diff options
author | Brian Schmalz <brian@schmalzhaus.com> | 2012-09-22 20:50:31 +0400 |
---|---|---|
committer | Brian Schmalz <brian@schmalzhaus.com> | 2012-09-22 20:50:31 +0400 |
commit | 33e4a2748d00be8a16b6c67890ed9e7ae29b4f0a (patch) | |
tree | 7f6184e496710dcfbdade05cc7d2b5a2b5452072 | |
parent | c7189c22ea7a027dfcecd0fb89bae5189f5a9d69 (diff) |
Added support for cipKIT/MPIDE (PIC32 architecture) boards. Please see AFMotor.h for usage notes and workarounds for 2 minor issues.
Tested with all examples (and AccelStepper) and all work properly with the exception of the Motor Party example. (See AFMotor.h for reason why not.)
Tested all 4 DC motor ouptuts (with PWM) and 2 stepper outputs (with microstepping) and all work properly.
-rw-r--r-- | AFMotor.cpp | 114 | ||||
-rw-r--r-- | AFMotor.h | 95 | ||||
-rw-r--r-- | README.txt | 1 |
3 files changed, 175 insertions, 35 deletions
diff --git a/AFMotor.cpp b/AFMotor.cpp index 220e066..c1f6482 100644 --- a/AFMotor.cpp +++ b/AFMotor.cpp @@ -25,6 +25,7 @@ uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225 #endif AFMotorController::AFMotorController(void) { + TimerInitalized = false; } void AFMotorController::enable(void) { @@ -78,7 +79,6 @@ void AFMotorController::latch_tx(void) { static AFMotorController MC; - /****************************************** MOTORS ******************************************/ @@ -98,11 +98,46 @@ inline void initPWM1(uint8_t freq) { TCCR1B = (freq & 0x7) | _BV(WGM12); OCR1A = 0; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + #if defined(PIC32_USE_PIN9_FOR_M1_PWM) + // Make sure that pin 11 is an input, since we have tied together 9 and 11 + pinMode(9, OUTPUT); + pinMode(11, INPUT); + if (!MC.TimerInitalized) + { // Set up Timer2 for 80MHz counting fro 0 to 256 + T2CON = 0x8000 | ((freq & 0x07) << 4); // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=<freq>, T32=0, TCS=0; // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=0, T32=0, TCS=0 + TMR2 = 0x0000; + PR2 = 0x0100; + MC.TimerInitalized = true; + } + // Setup OC4 (pin 9) in PWM mode, with Timer2 as timebase + OC4CON = 0x8006; // OC32 = 0, OCTSEL=0, OCM=6 + OC4RS = 0x0000; + OC4R = 0x0000; + #elif defined(PIC32_USE_PIN10_FOR_M1_PWM) + // Make sure that pin 11 is an input, since we have tied together 9 and 11 + pinMode(10, OUTPUT); + pinMode(11, INPUT); + if (!MC.TimerInitalized) + { // Set up Timer2 for 80MHz counting fro 0 to 256 + T2CON = 0x8000 | ((freq & 0x07) << 4); // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=<freq>, T32=0, TCS=0; // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=0, T32=0, TCS=0 + TMR2 = 0x0000; + PR2 = 0x0100; + MC.TimerInitalized = true; + } + // Setup OC5 (pin 10) in PWM mode, with Timer2 as timebase + OC5CON = 0x8006; // OC32 = 0, OCTSEL=0, OCM=6 + OC5RS = 0x0000; + OC5R = 0x0000; + #else + // If we are not using PWM for pin 11, then just do digital + digitalWrite(11, LOW); + #endif #else #error "This chip is not supported!" #endif - pinMode(11, OUTPUT); + #if !defined(PIC32_USE_PIN9_FOR_M1_PWM) && !defined(PIC32_USE_PIN10_FOR_M1_PWM) + pinMode(11, OUTPUT); + #endif } inline void setPWM1(uint8_t s) { @@ -117,7 +152,23 @@ inline void setPWM1(uint8_t s) { // on arduino mega, pin 11 is now PB5 (OC1A) OCR1A = s; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + #if defined(PIC32_USE_PIN9_FOR_M1_PWM) + // Set the OC4 (pin 9) PMW duty cycle from 0 to 255 + OC4RS = s; + #elif defined(PIC32_USE_PIN10_FOR_M1_PWM) + // Set the OC5 (pin 10) PMW duty cycle from 0 to 255 + OC5RS = s; + #else + // If we are not doing PWM output for M1, then just use on/off + if (s > 127) + { + digitalWrite(11, HIGH); + } + else + { + digitalWrite(11, LOW); + } + #endif #else #error "This chip is not supported!" #endif @@ -139,7 +190,17 @@ inline void initPWM2(uint8_t freq) { TCCR3B = (freq & 0x7) | _BV(WGM12); OCR3C = 0; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + if (!MC.TimerInitalized) + { // Set up Timer2 for 80MHz counting fro 0 to 256 + T2CON = 0x8000 | ((freq & 0x07) << 4); // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=<freq>, T32=0, TCS=0; // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=0, T32=0, TCS=0 + TMR2 = 0x0000; + PR2 = 0x0100; + MC.TimerInitalized = true; + } + // Setup OC1 (pin3) in PWM mode, with Timer2 as timebase + OC1CON = 0x8006; // OC32 = 0, OCTSEL=0, OCM=6 + OC1RS = 0x0000; + OC1R = 0x0000; #else #error "This chip is not supported!" #endif @@ -159,7 +220,8 @@ inline void setPWM2(uint8_t s) { // on arduino mega, pin 11 is now PB5 (OC1A) OCR3C = s; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + // Set the OC1 (pin3) PMW duty cycle from 0 to 255 + OC1RS = s; #else #error "This chip is not supported!" #endif @@ -182,7 +244,17 @@ inline void initPWM3(uint8_t freq) { //TCCR4B = 1 | _BV(WGM12); OCR4A = 0; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + if (!MC.TimerInitalized) + { // Set up Timer2 for 80MHz counting fro 0 to 256 + T2CON = 0x8000 | ((freq & 0x07) << 4); // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=<freq>, T32=0, TCS=0; // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=0, T32=0, TCS=0 + TMR2 = 0x0000; + PR2 = 0x0100; + MC.TimerInitalized = true; + } + // Setup OC3 (pin 6) in PWM mode, with Timer2 as timebase + OC3CON = 0x8006; // OC32 = 0, OCTSEL=0, OCM=6 + OC3RS = 0x0000; + OC3R = 0x0000; #else #error "This chip is not supported!" #endif @@ -201,7 +273,8 @@ inline void setPWM3(uint8_t s) { // on arduino mega, pin 6 is now PH3 (OC4A) OCR4A = s; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + // Set the OC3 (pin 6) PMW duty cycle from 0 to 255 + OC3RS = s; #else #error "This chip is not supported!" #endif @@ -226,7 +299,17 @@ inline void initPWM4(uint8_t freq) { //TCCR4B = 1 | _BV(WGM12); OCR3A = 0; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + if (!MC.TimerInitalized) + { // Set up Timer2 for 80MHz counting fro 0 to 256 + T2CON = 0x8000 | ((freq & 0x07) << 4); // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=<freq>, T32=0, TCS=0; // ON=1, FRZ=0, SIDL=0, TGATE=0, TCKPS=0, T32=0, TCS=0 + TMR2 = 0x0000; + PR2 = 0x0100; + MC.TimerInitalized = true; + } + // Setup OC2 (pin 5) in PWM mode, with Timer2 as timebase + OC2CON = 0x8006; // OC32 = 0, OCTSEL=0, OCM=6 + OC2RS = 0x0000; + OC2R = 0x0000; #else #error "This chip is not supported!" #endif @@ -245,7 +328,8 @@ inline void setPWM4(uint8_t s) { // on arduino mega, pin 6 is now PH3 (OC4A) OCR3A = s; #elif defined(__PIC32MX__) -/// TODO: Fill this in for PIC32 + // Set the OC2 (pin 5) PMW duty cycle from 0 to 255 + OC2RS = s; #else #error "This chip is not supported!" #endif @@ -308,7 +392,7 @@ void AF_DCMotor::run(uint8_t cmd) { MC.latch_tx(); break; case RELEASE: - latch_state &= ~_BV(a); + latch_state &= ~_BV(a); // A and B both low latch_state &= ~_BV(b); MC.latch_tx(); break; @@ -351,8 +435,8 @@ AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) { digitalWrite(3, HIGH); // use PWM for microstepping support - initPWM1(MOTOR12_64KHZ); - initPWM2(MOTOR12_64KHZ); + initPWM1(STEPPER1_PWM_RATE); + initPWM2(STEPPER1_PWM_RATE); setPWM1(255); setPWM2(255); @@ -369,8 +453,8 @@ AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) { // use PWM for microstepping support // use PWM for microstepping support - initPWM3(1); - initPWM4(1); + initPWM3(STEPPER2_PWM_RATE); + initPWM4(STEPPER2_PWM_RATE); setPWM3(255); setPWM4(255); } @@ -2,8 +2,33 @@ // copyright Adafruit Industries LLC, 2009 // this code is public domain, enjoy! +/* + * Usage Notes: + * For PIC32, all features work properly with the following two exceptions: + * + * 1) Because the PIC32 only has 5 PWM outputs, and the AFMotor shield needs 6 + * to completely operate (for for motor outputs and two for RC servos), the + * M1 motor output will not have PWM ability when used with a PIC32 board. + * However, there is a very simple workaround. If you need to drive a stepper + * or DC motor with PWM on motor output M1, you can use the PWM output on pin + * 9 or pin 10 (normally use for RC servo outputs on Arduino, not needed for + * RC servo outputs on PIC32) to drive the PWM input for M1 by simply putting + * a jumber from pin 9 to pin 11 or pin 10 to pin 11. Then uncomment one of the + * two #defines below to activate the PWM on either pin 9 or pin 10. You will + * then have a fully functional microstepping for 2 stepper motors, or four + * DC motor outputs with PWM. + * + * 2) There is a conflict between RC Servo outputs on pins 9 and pins 10 and + * the operation of DC motors and stepper motors as of 9/2012. This issue + * will get fixed in future MPIDE releases, but at the present time it means + * that the Motor Party example will NOT work properly. Any time you attach + * an RC servo to pins 9 or pins 10, ALL PWM outputs on the whole board will + * stop working. Thus no steppers or DC motors. + * + */ // <BPS> 09/15/2012 Modified for use with chipKIT boards + #ifndef _AFMotor_h_ #define _AFMotor_h_ @@ -13,31 +38,60 @@ //#define MOTORDEBUG 1 - #define MICROSTEPS 16 // 8 or 16 + #define MICROSTEPS 16 // 8 or 16 - #define MOTOR12_64KHZ _BV(CS20) // no prescale - #define MOTOR12_8KHZ _BV(CS21) // divide by 8 - #define MOTOR12_2KHZ _BV(CS21) | _BV(CS20) // divide by 32 - #define MOTOR12_1KHZ _BV(CS22) // divide by 64 + #define MOTOR12_64KHZ _BV(CS20) // no prescale + #define MOTOR12_8KHZ _BV(CS21) // divide by 8 + #define MOTOR12_2KHZ _BV(CS21) | _BV(CS20) // divide by 32 + #define MOTOR12_1KHZ _BV(CS22) // divide by 64 - #define MOTOR34_64KHZ _BV(CS00) // no prescale - #define MOTOR34_8KHZ _BV(CS01) // divide by 8 + #define MOTOR34_64KHZ _BV(CS00) // no prescale + #define MOTOR34_8KHZ _BV(CS01) // divide by 8 #define MOTOR34_1KHZ _BV(CS01) | _BV(CS00) // divide by 64 + #define DC_MOTOR_PWM_RATE MOTOR34_8KHZ // PWM rate for DC motors + #define STEPPER1_PWM_RATE MOTOR12_64KHZ // PWM rate for stepper 1 + #define STEPPER2_PWM_RATE MOTOR34_64KHZ // PWM rate for stepper 2 + #elif defined(__PIC32MX__) - /// TODO: Update this for PIC32 microstepping //#define MOTORDEBUG 1 - - #define MICROSTEPS 16 // 8 or 16 - - #define MOTOR12_64KHZ 1 // no prescale - #define MOTOR12_8KHZ 2 // divide by 8 - #define MOTOR12_2KHZ 3 // divide by 32 - #define MOTOR12_1KHZ 4// divide by 64 - - #define MOTOR34_64KHZ 5 // no prescale - #define MOTOR34_8KHZ 6 // divide by 8 - #define MOTOR34_1KHZ 7 // divide by 64 + + // Uncomment the one of following lines if you have put a jumper from + // either pin 9 to pin 11 or pin 10 to pin 11 on your Motor Shield. + // Either will enable PWM for M1 + //#define PIC32_USE_PIN9_FOR_M1_PWM + //#define PIC32_USE_PIN10_FOR_M1_PWM + + #define MICROSTEPS 16 // 8 or 16 + + // For PIC32 Timers, define prescale settings by PWM frequency + #define MOTOR12_312KHZ 0 // 1:1, actual frequency 312KHz + #define MOTOR12_156KHZ 1 // 1:2, actual frequency 156KHz + #define MOTOR12_64KHZ 2 // 1:4, actual frequency 78KHz + #define MOTOR12_39KHZ 3 // 1:8, acutal frequency 39KHz + #define MOTOR12_19KHZ 4 // 1:16, actual frequency 19KHz + #define MOTOR12_8KHZ 5 // 1:32, actual frequency 9.7KHz + #define MOTOR12_4_8KHZ 6 // 1:64, actual frequency 4.8KHz + #define MOTOR12_2KHZ 7 // 1:256, actual frequency 1.2KHz + #define MOTOR12_1KHZ 7 // 1:256, actual frequency 1.2KHz + + #define MOTOR34_312KHZ 0 // 1:1, actual frequency 312KHz + #define MOTOR34_156KHZ 1 // 1:2, actual frequency 156KHz + #define MOTOR34_64KHZ 2 // 1:4, actual frequency 78KHz + #define MOTOR34_39KHZ 3 // 1:8, acutal frequency 39KHz + #define MOTOR34_19KHZ 4 // 1:16, actual frequency 19KHz + #define MOTOR34_8KHZ 5 // 1:32, actual frequency 9.7KHz + #define MOTOR34_4_8KHZ 6 // 1:64, actual frequency 4.8KHz + #define MOTOR34_2KHZ 7 // 1:256, actual frequency 1.2KHz + #define MOTOR34_1KHZ 7 // 1:256, actual frequency 1.2KHz + + // PWM rate for DC motors. + #define DC_MOTOR_PWM_RATE MOTOR34_39KHZ + // Note: for PIC32, both of these must be set to the same value + // since there's only one timebase for all 4 PWM outputs + #define STEPPER1_PWM_RATE MOTOR12_39KHZ + #define STEPPER2_PWM_RATE MOTOR34_39KHZ + #endif // Bit positions in the 74HCT595 shift register output @@ -93,12 +147,13 @@ class AFMotorController void enable(void); friend class AF_DCMotor; void latch_tx(void); + uint8_t TimerInitalized; }; class AF_DCMotor { public: - AF_DCMotor(uint8_t motornum, uint8_t freq = MOTOR34_8KHZ); + AF_DCMotor(uint8_t motornum, uint8_t freq = DC_MOTOR_PWM_RATE); void run(uint8_t); void setSpeed(uint8_t); @@ -1,4 +1,5 @@ This is the August 12, 2009 Adafruit Motor shield firmware with basic Microstepping support. Works with all Arduinos and the Mega +Updated in September 2012 for use on PIC32 architecture (chipKIT/MPIDE) For more information on the shield, please visit http://www.ladyada.net/make/mshield/ |