Tripple Controller for the TLE5206 H Bridge motor controller
Revision 0:e2433ca2ce59, committed 2011-07-05
- Comitter:
- AjK
- Date:
- Tue Jul 05 07:43:28 2011 +0000
- Child:
- 1:e6f43157c7db
- Commit message:
- 0.2 Beta
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/SimpleTLE5206.h Tue Jul 05 07:43:28 2011 +0000 @@ -0,0 +1,62 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef AJK_SIMPLETLE5206_H +#define AJK_SIMPLETLE5206_H + +#include "LPC17xx.h" +#include "SimpleTLE5206Output.h" + +namespace AjK { + +class SimpleTLE5206 { + +public: + enum PwmCh { NoPwm0, Pwm1, Pwm2, Pwm3, Pwm4, Pwm5, Pwm6, NumOfPwms }; + +protected: + uint32_t _duty; + + SimpleTLE5206Output *_in1; + SimpleTLE5206Output *_in2; + + void setDuty(uint32_t u); + + void setMRx(PwmCh ch, uint32_t value); + + void init(void); + +public: + + SimpleTLE5206() { error("We require two pins!\n"); } + + SimpleTLE5206(SimpleTLE5206Output *in1, SimpleTLE5206Output *in2); + + void setSpeed(double d); + +}; /* class SimpleTLE5206 ends. */ + +}; /* namespace AjK ends. */ + +using namespace AjK; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/SimpleTLE5206Mbed.h Tue Jul 05 07:43:28 2011 +0000 @@ -0,0 +1,85 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef AJK_SIMPLETLE5206MBED_H +#define AJK_SIMPLETLE5206MBED_H + +#ifndef MBED_PINNAMES_H +#define MBED_PINNAMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + P0_0 = LPC_GPIO0_BASE, P0_1, P0_2, P0_3, P0_4, P0_5, P0_6, P0_7 + , P0_8, P0_9, P0_10, P0_11, P0_12, P0_13, P0_14, P0_15 + , P0_16, P0_17, P0_18, P0_19, P0_20, P0_21, P0_22, P0_23 + , P0_24, P0_25, P0_26, P0_27, P0_28, P0_29, P0_30, P0_31 + , P1_0, P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7 + , P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15 + , P1_16, P1_17, P1_18, P1_19, P1_20, P1_21, P1_22, P1_23 + , P1_24, P1_25, P1_26, P1_27, P1_28, P1_29, P1_30, P1_31 + , P2_0, P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7 + , P2_8, P2_9, P2_10, P2_11, P2_12, P2_13, P2_14, P2_15 + , P2_16, P2_17, P2_18, P2_19, P2_20, P2_21, P2_22, P2_23 + , P2_24, P2_25, P2_26, P2_27, P2_28, P2_29, P2_30, P2_31 + , P3_0, P3_1, P3_2, P3_3, P3_4, P3_5, P3_6, P3_7 + , P3_8, P3_9, P3_10, P3_11, P3_12, P3_13, P3_14, P3_15 + , P3_16, P3_17, P3_18, P3_19, P3_20, P3_21, P3_22, P3_23 + , P3_24, P3_25, P3_26, P3_27, P3_28, P3_29, P3_30, P3_31 + , P4_0, P4_1, P4_2, P4_3, P4_4, P4_5, P4_6, P4_7 + , P4_8, P4_9, P4_10, P4_11, P4_12, P4_13, P4_14, P4_15 + , P4_16, P4_17, P4_18, P4_19, P4_20, P4_21, P4_22, P4_23 + , P4_24, P4_25, P4_26, P4_27, P4_28, P4_29, P4_30, P4_31 + + // Mbed DIP Pin Names + , p5 = P0_9, p6 = P0_8, p7 = P0_7, p8 = P0_6, p9 = P0_0, p10 = P0_1 + , p11 = P0_18, p12 = P0_17, p13 = P0_15, p14 = P0_16, p15 = P0_23 + , p16 = P0_24, p17 = P0_25, p18 = P0_26, p19 = P1_30, p20 = P1_31 + , p21 = P2_5, p22 = P2_4, p23 = P2_3, p24 = P2_2, p25 = P2_1 + , p26 = P2_0, p27 = P0_11, p28 = P0_10, p29 = P0_5, p30 = P0_4 + + // Other Mbed Pin Names + , LED1 = P1_18, LED2 = P1_20, LED3 = P1_21, LED4 = P1_23 + , USBTX = P0_2, USBRX = P0_3 + + // Not connected + , NC = (int)0xFFFFFFFF + +} PinName; + +typedef enum { + PullUp = 0 + , Repeater = 1 + , PullNone = 2 + , PullDown = 3 + , OpenDrain = 4 +} PinMode; + +#ifdef __cplusplus +} +#endif + +#endif /* MBED_PINNAMES_H */ + +#endif /* AJK_SIMPLETLE5206MBED_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/SimpleTLE5206Output.h Tue Jul 05 07:43:28 2011 +0000 @@ -0,0 +1,476 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef AJK_SIMPLETLE5206OUTPUT_H +#define AJK_SIMPLETLE5206OUTPUT_H + +#ifndef __ARMCC_VERSION +#include "SimpleTLE5206Mbed.h" +#define error(...) +#else +#include "mbed.h" +#endif + + +namespace AjK { + +/** SimpleTLE5206Output - Adds pin output objects. + * + * The Mbed library supplies the DigitalIn and DigitalOut objects to allow you + * to specify ins and outs. + * + * SimpleTLE5206Output allows library objects to implement pins without the requirement + * to link against the Mbed library. This increase portability when using + * alternate compilers (such as the Code Red GCC C++ compiler for LPCXpresso). + * + * Additionally, this class allows the pin to be configured as a GPIO output or swapped + * to PWM output mode. + * + * Note, this class can only be used for pins p21 through p26 as these are used for PWM pins. + * Trying to set this to any other pin will result in a fatal error() call. + * + * @ingroup SimpleTLE5206Output + */ +class SimpleTLE5206Output { +public: + enum Direction { + Out = 0 + , In + }; + + enum PinType { + IsGPIO = 0 + , IsPWM + }; + +protected: + PinName pin; + uint32_t mask; + uint32_t fiodir; + uint32_t fiomask; + uint32_t fiopin; + uint32_t fioset; + uint32_t fioclr; + + PinType pin_type; + + inline void setpin(PinName p) { pin = p; } + inline void setmask(PinName p) { mask = (uint32_t)(1UL << ((uint32_t)p & 0x1F)); } + inline void setDir(PinName p) { fiodir = (uint32_t)(p & ~0x1F) + 0x00; } + inline void setMask(PinName p) { fiomask = (uint32_t)(p & ~0x1F) + 0x10; } + inline void setPin(PinName p) { fiopin = (uint32_t)(p & ~0x1F) + 0x14; } + inline void setSet(PinName p) { fioset = (uint32_t)(p & ~0x1F) + 0x18; } + inline void setClr(PinName p) { fioclr = (uint32_t)(p & ~0x1F) + 0x1C; } + + inline void pinUp() { *((volatile uint32_t *)fioset) = mask; } + inline void pinDn() { *((volatile uint32_t *)fioclr) = mask; } + inline uint32_t pinIs() { return *((volatile uint32_t *)(fiopin)) & mask; } + +public: + + /** Constructor + * @ingroup SimpleTLE5206Output + */ + SimpleTLE5206Output(PinName p, Direction d = Out, PinMode m = PullDown) { + + if (p == p21 || p == p22 || p == p23 || p == p24 || p == p25 || p == p26 || p == LED1 || p == LED2 || p == LED3 || p == LED4) { + init(p, d, m); + } + else { + error("Invalid pin supplied.\n"); + } + }; + + /** write + * + * Writes a value to the pin. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @param i Zero makes the pin 0v, non-zero makes the pin 1. + */ + void write(int i) { if (i!=0) { pinUp(); } else { pinDn(); } } + + /** read + * + * Reads the value on the pin. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return int 0v returns zero, otherwise returns 1. + */ + int read(void) { return pinIs() ? 1 : 0; }; + + /** output + * + * Setup the pin to be an output. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @ingroup API + * @return int 0v returns zero, otherwise returns 1. + */ + void output(void) { *((volatile uint32_t *)fiodir) |= mask; } + + /** input + * + * Setup the pin to be an input. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return int 0v returns zero, otherwise returns 1. + */ + void input(void) { *((volatile uint32_t *)fiodir) &= ~mask; } + + /** getPin + * + * Get the PinName this object is operating on. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return int 0v returns zero, otherwise returns 1. + */ + PinName getPin(void) { return pin; } + + /** getDirection + * + * Get the operational direction this pin is setup for. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return int 0v returns zero, otherwise returns 1. + */ + int getDirection(void) { return *((volatile uint32_t *)fiomask) & mask ? 1 : 0; } + + /** operator int() + * + * Reads the value on the pin. + * + * @see read + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return int 0v returns zero, otherwise returns 1. + */ + operator int() { return read(); } + + /** operator= + * + * Writes a value to the pin. + * + * @see write + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + */ + SimpleTLE5206Output& operator= (int value) { write(value); return *this; } + + /** operator= + * + * Writes a value to the pin. + * + * @see write + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + */ + SimpleTLE5206Output& operator= (SimpleTLE5206Output& rhs) { write(rhs.read()); return *this; } + + /** getMask + * + * Get the mask value for this pin. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return uint32_t The mask value used by this pin. + */ + uint32_t getMask(void) { return mask; } + + /** getFiodir + * + * Get the FIODIR register for the port the pin is on. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return uint32_t The register value. + */ + uint32_t getFiodir(void) { return fiodir; } + + /** getFiomask + * + * Get the FIOMASK register for the port the pin is on. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return uint32_t The register value. + */ + uint32_t getFiomask(void) { return fiomask; } + + /** getFiopin + * + * Get the FIOPIN register for the port the pin is on. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return uint32_t The register value. + */ + uint32_t getFiopin(void) { return fiopin; } + + /** getFioset + * + * Get the FIOSET register for the port the pin is on. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return uint32_t The register value. + */ + uint32_t getFioset(void) { return fioset; } + + /** getFioclr + * + * Get the FIOCLR register for the port the pin is on. + * + * @see http://cornflakes.wikidot.com/lib17:core:lib17-dio + * @ingroup SimpleTLE5206Output + * @return uint32_t The register value. + */ + uint32_t getFioclr(void) { return fioclr; } + + +protected: + void init(PinName p, Direction d, PinMode m) + { + // We rely on the fact that by default the LPC1768 + // sets all pins to be GPIO. The user will change + // that if they need to. So we don't bother trying + // to setup PINSELx + + // psel(); // Not used, see above. + + setpin(p); + setmask(p); + setDir(p); + setMask(p); + setPin(p); + setSet(p); + setClr(p); + + if (d == Out) output(); + else mode( m ); + + pin_type = IsGPIO; // GPIO. + } + +public: + void as_gpio(void) + { + pin_type = IsGPIO; + + switch(pin) { + case P2_0: + LPC_PINCON->PINSEL4 &= ~(3UL << 0); // Mbed p26 P2.0 clr bits + return; + case P1_18: // Mbed LED1 + LPC_PINCON->PINSEL3 &= ~(3UL << 4); // Mbed LED2 P1.18 clr bits + return; + } + + switch(pin) { + case P2_1: + LPC_PINCON->PINSEL4 &= ~(3UL << 2); // Mbed p25 P2.1 clr bits + return; + case P1_20: // Mbed LED2 + LPC_PINCON->PINSEL3 &= ~(3UL << 8); // Mbed LED2 P1.20 clr bits + return; + } + + switch(pin) { + case P2_2: + LPC_PINCON->PINSEL4 &= ~(3UL << 4); // Mbed p24 P2.2 clr bits + return; + case P1_21: // Mbed LED3 + LPC_PINCON->PINSEL3 &= ~(3UL << 10); // Mbed LED3 P1.21 clr bits + return; + } + + switch(pin) { + case P2_3: + LPC_PINCON->PINSEL4 &= ~(3UL << 6); // Mbed p23 P2.3 clr bits + return; + case P1_23: // Mbed LED4 + LPC_PINCON->PINSEL3 &= ~(3UL << 14); // Mbed LED4 P1.23 clr bits + return; + } + + switch(pin) { + case P2_4: // Mbed p22 + LPC_PINCON->PINSEL4 &= ~(3UL << 8); // Mbed p22 P2.4 clr bits + return; + case P1_24: + LPC_PINCON->PINSEL3 &= ~(3UL << 16); // P1.24 clr bits + return; + } + + switch(pin) { + case P2_5: // Mbed p21 + LPC_PINCON->PINSEL4 &= ~(3UL << 10); // Mbed p21 P2.5 clr bits + return; + case P1_26: + LPC_PINCON->PINSEL3 &= ~(3UL << 20); // P1.26 clr bits + return; + } + } + + void as_pwm(void) + { + pin_type = IsPWM; + + switch(pin) { + case P2_0: + LPC_PINCON->PINSEL4 &= ~(3UL << 0); // Mbed p26 P2.0 clr bits + LPC_PINCON->PINSEL4 |= (1UL << 0); // Mbed p26 P2.0 set bits + LPC_PWM1->PCR |= (1UL << 9); + return; + case P1_18: // Mbed LED1 + LPC_PINCON->PINSEL3 &= ~(3UL << 4); // Mbed LED2 P1.18 clr bits + LPC_PINCON->PINSEL3 |= (2UL << 4); // Mbed LED2 P1.18 set bits + LPC_PWM1->PCR |= (1UL << 9); + return; + } + + switch(pin) { + case P2_1: + LPC_PINCON->PINSEL4 &= ~(3UL << 2); // Mbed p25 P2.1 clr bits + LPC_PINCON->PINSEL4 |= (1UL << 2); // Mbed p25 P2.1 set bits + LPC_PWM1->PCR |= (1UL << 10); + return; + case P1_20: // Mbed LED2 + LPC_PINCON->PINSEL3 &= ~(3UL << 8); // Mbed LED2 P1.20 clr bits + LPC_PINCON->PINSEL3 |= (2UL << 8); // Mbed LED2 P1.20 set bits + LPC_PWM1->PCR |= (1UL << 10); + return; + } + + switch(pin) { + case P2_2: + LPC_PINCON->PINSEL4 &= ~(3UL << 4); // Mbed p24 P2.2 clr bits + LPC_PINCON->PINSEL4 |= (1UL << 4); // Mbed p24 P2.2 set bits + LPC_PWM1->PCR |= (1UL << 11); + return; + case P1_21: // Mbed LED3 + LPC_PINCON->PINSEL3 &= ~(3UL << 10); // Mbed LED3 P1.21 clr bits + LPC_PINCON->PINSEL3 |= (2UL << 10); // Mbed LED3 P1.21 set bits + LPC_PWM1->PCR |= (1UL << 11); + return; + } + + switch(pin) { + case P2_3: + LPC_PINCON->PINSEL4 &= ~(3UL << 6); // Mbed p23 P2.3 clr bits + LPC_PINCON->PINSEL4 |= (1UL << 6); // Mbed p23 P2.3 set bits + LPC_PWM1->PCR |= (1UL << 12); + return; + case P1_23: // Mbed LED4 + LPC_PINCON->PINSEL3 &= ~(3UL << 14); // Mbed LED4 P1.23 clr bits + LPC_PINCON->PINSEL3 |= (2UL << 14); // Mbed LED4 P1.23 set bits + LPC_PWM1->PCR |= (1UL << 12); + return; + } + + switch(pin) { + case P2_4: // Mbed p22 + LPC_PINCON->PINSEL4 &= ~(3UL << 8); // Mbed p22 P2.4 clr bits + LPC_PINCON->PINSEL4 |= (1UL << 8); // Mbed p22 P2.4 set bits + LPC_PWM1->PCR |= (1UL << 13); + return; + case P1_24: + LPC_PINCON->PINSEL3 &= ~(3UL << 16); // P1.24 clr bits + LPC_PINCON->PINSEL3 |= (2UL << 16); // P1.24 set bits + LPC_PWM1->PCR |= (1UL << 13); + return; + } + + switch(pin) { + case P2_5: // Mbed p21 + LPC_PINCON->PINSEL4 &= ~(3UL << 10); // Mbed p21 P2.5 clr bits + LPC_PINCON->PINSEL4 |= (1UL << 10); // Mbed p21 P2.5 set bits + LPC_PWM1->PCR |= (1UL << 14); + return; + case P1_26: + LPC_PINCON->PINSEL3 &= ~(3UL << 20); // P1.26 clr bits + LPC_PINCON->PINSEL3 |= (2UL << 20); // P1.26 set bits + LPC_PWM1->PCR |= (1UL << 14); + return; + } + +/* + uint32_t ppsel, pumask; + + if (pin >= P2_0 && pin <= P2_5) { + ppsel = (uint32_t)(&LPC_PINCON->PINSEL4); + pumask = ~(3UL << ((pin & 0x1F)>>1)); + *((volatile uint32_t *)ppsel) &= pumask; + pumask = (1UL << ((pin & 0x1F)>>1)); + *((volatile uint32_t *)ppsel) |= pumask; + } + else if (pin >= LED1 && pin <= LED4) { + ppsel = (uint32_t)(&LPC_PINCON->PINSEL3); + pumask = ~(3UL << ((pin & 0x1F)>>1)); + *((volatile uint32_t *)ppsel) &= pumask; + pumask = (2UL << ((pin & 0x1F)>>1)); + *((volatile uint32_t *)ppsel) |= pumask; + } + else return; +*/ + + } + + PinType get_pin_type(void) { return pin_type; } + + void mode(PinMode m) + { + uint32_t ppmod, pumask; + + if (m == OpenDrain) { + openDrain(1); + } + else { + if (pin >= P2_0 && pin <= P2_5) { + ppmod = (uint32_t)(&LPC_PINCON->PINMODE4); + pumask = ((m & 0x3) << ( ((pin & 0x1F)-0)*2) ); + } + else return; + + *((volatile uint32_t *)ppmod) |= pumask; + } + } + +public: + void openDrain(int i = 1) + { + if (pin >= P2_0 && pin <= P2_5) { if (i) LPC_PINCON->PINMODE_OD2 |= mask; else LPC_PINCON->PINMODE_OD2 &= ~mask; } + } + +}; + +}; /* namespace AjK ends. */ + +using namespace AjK; + +#endif /* AJK_SIMPLETLE5206OUTPUT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/example1.h Tue Jul 05 07:43:28 2011 +0000 @@ -0,0 +1,107 @@ + +#include "mbed.h" +#include "SimpleTLE5206.h" + +Serial pc(USBTX, USBRX); + +/* NOTE! The SimpleTLE5206 library supports the TLE5206 in + * Mode 2 Sign/Magnitude Control using two PWM outputs to + * control speed and direction. + * + * Pins that be be used are p21, p22, p23, p24, p25 and/or p26 + * in pairs. So the library supports upto 3 TLE5206 devices/motors. + * + * All PWM outputs use a common duty cycle which defaults to 100Hz/10ms. + * There is no way to have differing duty cycles for different output + * pin pairs as the hardware only supports a common duty cycle in single + * ended mode. It may be possible to refactor the library to use a different + * duty cycle system (paired outputs). But single/common duty cycle was the + * easiest and simplest way to get the library done in a short period of time. + * + * Additionally you can use LED1, LED2, LED3 and.or LED4 as mimics. + * However, if using:- + * LED1 you cannot use p26 to drive an in to TLE5206 + * LED2 you cannot use p25 to drive an in to TLE5206 + * LED3 you cannot use p24 to drive an in to TLE5206 + * LED4 you cannot use p23 to drive an in to TLE5206 + * + * The function SimpleTLE5206::setSpeed() takes a single arg, a double, + * and should be in the range +1.0 to -1.0 where +1.0 is full speed in + * a CW direction, -1.0 is full speed in a CCW direction and 0 is stopped. + */ + +// Create a motor "A" driven by a TLE5206 on pins 21 and 22. +SimpleTLE5206Output Ain1(p21); // TLE5206 In1 is connected to p21 +SimpleTLE5206Output Ain2(p22); // TLE5206 In2 is connected to p22 +SimpleTLE5206 motorA(&Ain1, &Ain2); // Create the TLE5206 controller using these pins. + +// Create a motor "B" driven by a TLE5206 but on LEDs as a mimic. +SimpleTLE5206Output Bin1(LED3); // TLE5206 In1 is connected to LED3 +SimpleTLE5206Output Bin2(LED4); // TLE5206 In2 is connected to LED4 +SimpleTLE5206 motorB(&Bin1, &Bin2); // Create the TLE5206 controller using these pins. + +DigitalOut myled(LED1); + +Ticker myLedFlasher; + +void myLedFlasherCallback(void) { + myled = !myled; +} + +int main() { + double speed; + + pc.baud(115200); + + // Just flashes LED1 similar to a normal initial Mbed program. + myLedFlasher.attach(myLedFlasherCallback, 0.2); + + // The main loop just demos a linear ramp up/ramp down repeatedly. + while(1) { + motorA.setSpeed(0); + motorB.setSpeed(0); + + wait(2); + + // Go from zero to +1.0 (+1.0 is full speed) + pc.printf("Going from zero to full CW speed..."); + for(speed = 0.0; speed <= 1.0; speed += 0.005) { + if (speed > 1.0) speed = 1.0; // Never let the speed go over 1! + if (speed < -1.0) speed = -1.0; // Never let the speed go below -1! + motorA.setSpeed(speed); + motorB.setSpeed(speed); + wait(0.05); + } + pc.printf(" done.\n"); + + // Hold the motor at full speed for 5seconds. + wait(2); + + // Now slow the motor down to zero and then reverse direction to -1.0 + pc.printf("Going from full CW speed to full CCW speed..."); + for( ; speed >= -1.0; speed -= 0.005) { + if (speed > 1.0) speed = 1.0; // Never let the speed go over 1! + if (speed < -1.0) speed = -1.0; // Never let the speed go below -1! + motorA.setSpeed(speed); + motorB.setSpeed(speed); + wait(0.05); + } + pc.printf(" done.\n"); + + // Hold the motor at full speed in ccw for 5seconds. + wait(2); + + // Now bring the motor to a stop. + pc.printf("Bringing the motor to a halt..."); + for( ; speed <= 0.0; speed += 0.005) { + if (speed > 1.0) speed = 1.0; // Never let the speed go over 1! + if (speed < -1.0) speed = -1.0; // Never let the speed go below -1! + motorA.setSpeed(speed); + motorB.setSpeed(speed); + wait(0.05); + } + pc.printf(" done.\n"); + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/SimpleTLE5206.cpp Tue Jul 05 07:43:28 2011 +0000 @@ -0,0 +1,139 @@ +/* + Copyright (c) 2011 Andy Kirkham + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + + +#include "mbed.h" +#include "SimpleTLE5206.h" + +namespace AjK { + +SimpleTLE5206::SimpleTLE5206(SimpleTLE5206Output *in1, SimpleTLE5206Output *in2) +{ + // Start initially as GPIO and both on (no drive, no speed). + _in1 = in1; + _in2 = in2; + init(); +} + +void +SimpleTLE5206::init() +{ + setDuty(240000UL); + setSpeed(0.0); +} + +void +SimpleTLE5206::setDuty(uint32_t duty) +{ + // Ensure powered up (default is 1) + LPC_SC->PCONP |= (1UL << 6); + + // CCLK/4 = 24MHz + LPC_SC->PCLKSEL0 &= ~(3UL << 12); + + // Reset. + LPC_PWM1->TCR = 2; + + _duty = duty; + + LPC_PWM1->PR = 0; + LPC_PWM1->MR0 = _duty; + LPC_PWM1->MR1 = 0; + LPC_PWM1->MR2 = 0; + LPC_PWM1->MR3 = 0; + LPC_PWM1->MR4 = 0; + LPC_PWM1->MR5 = 0; + LPC_PWM1->MR6 = 0; + + LPC_PWM1->MCR = 2; // MR0 resets TC. + + LPC_PWM1->TCR = 9; // Enable. +} + +void +SimpleTLE5206::setSpeed(double speed) +{ + uint32_t value; + + // Ensure we cap the speed to +/-1.0 + if (speed > +1.0) speed = +1.0; + if (speed < -1.0) speed = -1.0; + + if (speed == 0) { + _in1->as_gpio(); + _in2->as_gpio(); + _in1->write(1); + _in2->write(1); + } + else { + if (speed > 0.0) { + // Check the outputs are configured for the direction requested. + if (_in1->get_pin_type() != SimpleTLE5206Output::IsGPIO) _in1->as_gpio(); + if (_in2->get_pin_type() != SimpleTLE5206Output::IsPWM) _in2->as_pwm(); + } + + if (speed < 0.0) { + // Check the outputs are configured for the direction requested. + if (_in1->get_pin_type() != SimpleTLE5206Output::IsPWM) _in1->as_pwm(); + if (_in2->get_pin_type() != SimpleTLE5206Output::IsGPIO) _in2->as_gpio(); + speed *= -1; // invert sign. + } + + value = (uint32_t)(speed * _duty); // Scale for requested speed. + if (value >= _duty) value = _duty - 1; // Don't allow the value to overrun the duty. + value = _duty - value; // Invert logic sense. + + switch(_in1->getPin()) { + case p21: setMRx(Pwm6, value); break; + case p22: setMRx(Pwm5, value); break; + case p23: case LED4: setMRx(Pwm4, value); break; + case p24: case LED3: setMRx(Pwm3, value); break; + case p25: case LED2: setMRx(Pwm2, value); break; + case p26: case LED1: setMRx(Pwm1, value); break; + } + + switch(_in2->getPin()) { + case p21: setMRx(Pwm6, value); break; + case p22: setMRx(Pwm5, value); break; + case p23: case LED4: setMRx(Pwm4, value); break; + case p24: case LED3: setMRx(Pwm3, value); break; + case p25: case LED2: setMRx(Pwm2, value); break; + case p26: case LED1: setMRx(Pwm1, value); break; + } + } +} + +void +SimpleTLE5206::setMRx(PwmCh ch, uint32_t value) +{ + switch(ch) { + case Pwm1: LPC_PWM1->MR1 = value; break; + case Pwm2: LPC_PWM1->MR2 = value; break; + case Pwm3: LPC_PWM1->MR3 = value; break; + case Pwm4: LPC_PWM1->MR4 = value; break; + case Pwm5: LPC_PWM1->MR5 = value; break; + case Pwm6: LPC_PWM1->MR6 = value; break; + } + LPC_PWM1->LER |= (1UL << ch); +} + +}; // namespace AjK ends.