diff options
author | Limor "Ladyada" Fried <limor@ladyada.net> | 2012-10-09 23:08:36 +0400 |
---|---|---|
committer | Limor "Ladyada" Fried <limor@ladyada.net> | 2012-10-09 23:08:36 +0400 |
commit | 4bd21ca41a4e64556bf0f217660571cfad453d24 (patch) | |
tree | 7f6184e496710dcfbdade05cc7d2b5a2b5452072 | |
parent | dd30da7ecb40581377dc4bb8fc9044a995ddb4d4 (diff) | |
parent | 33e4a2748d00be8a16b6c67890ed9e7ae29b4f0a (diff) |
Merge pull request #8 from EmbeddedMan/master
Add support for PIC32 architecture (fixes issue #7)
-rw-r--r-- | AFMotor.cpp | 123 | ||||
-rw-r--r-- | AFMotor.h | 109 | ||||
-rw-r--r-- | README.txt | 1 |
3 files changed, 207 insertions, 26 deletions
diff --git a/AFMotor.cpp b/AFMotor.cpp index 8ac0c08..c1f6482 100644 --- a/AFMotor.cpp +++ b/AFMotor.cpp @@ -4,11 +4,14 @@ #if (ARDUINO >= 100) - #include "Arduino.h" + #include "Arduino.h" #else - #include <avr/io.h> - #include "WProgram.h" + #if defined(__AVR__) + #include <avr/io.h> + #endif + #include "WProgram.h" #endif + #include "AFMotor.h" @@ -22,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) { @@ -75,7 +79,6 @@ void AFMotorController::latch_tx(void) { static AFMotorController MC; - /****************************************** MOTORS ******************************************/ @@ -94,10 +97,47 @@ inline void initPWM1(uint8_t freq) { TCCR1A |= _BV(COM1A1) | _BV(WGM10); // fast PWM, turn on oc1a TCCR1B = (freq & 0x7) | _BV(WGM12); OCR1A = 0; +#elif defined(__PIC32MX__) + #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) { @@ -111,6 +151,24 @@ inline void setPWM1(uint8_t s) { #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // on arduino mega, pin 11 is now PB5 (OC1A) OCR1A = s; +#elif defined(__PIC32MX__) + #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 @@ -131,6 +189,18 @@ inline void initPWM2(uint8_t freq) { TCCR3A |= _BV(COM1C1) | _BV(WGM10); // fast PWM, turn on oc3c TCCR3B = (freq & 0x7) | _BV(WGM12); OCR3C = 0; +#elif defined(__PIC32MX__) + 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 @@ -149,6 +219,9 @@ inline void setPWM2(uint8_t s) { #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // on arduino mega, pin 11 is now PB5 (OC1A) OCR3C = s; +#elif defined(__PIC32MX__) + // Set the OC1 (pin3) PMW duty cycle from 0 to 255 + OC1RS = s; #else #error "This chip is not supported!" #endif @@ -170,6 +243,18 @@ inline void initPWM3(uint8_t freq) { TCCR4B = (freq & 0x7) | _BV(WGM12); //TCCR4B = 1 | _BV(WGM12); OCR4A = 0; +#elif defined(__PIC32MX__) + 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 @@ -187,6 +272,9 @@ inline void setPWM3(uint8_t s) { #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // on arduino mega, pin 6 is now PH3 (OC4A) OCR4A = s; +#elif defined(__PIC32MX__) + // Set the OC3 (pin 6) PMW duty cycle from 0 to 255 + OC3RS = s; #else #error "This chip is not supported!" #endif @@ -210,6 +298,18 @@ inline void initPWM4(uint8_t freq) { TCCR3B = (freq & 0x7) | _BV(WGM12); //TCCR4B = 1 | _BV(WGM12); OCR3A = 0; +#elif defined(__PIC32MX__) + 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 @@ -227,6 +327,9 @@ inline void setPWM4(uint8_t s) { #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // on arduino mega, pin 6 is now PH3 (OC4A) OCR3A = s; +#elif defined(__PIC32MX__) + // Set the OC2 (pin 5) PMW duty cycle from 0 to 255 + OC2RS = s; #else #error "This chip is not supported!" #endif @@ -289,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; @@ -332,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); @@ -350,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,25 +2,99 @@ // 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_ #include <inttypes.h> -#include <avr/io.h> - -//#define MOTORDEBUG 1 - -#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 MOTOR34_64KHZ _BV(CS00) // no prescale -#define MOTOR34_8KHZ _BV(CS01) // divide by 8 -#define MOTOR34_1KHZ _BV(CS01) | _BV(CS00) // divide by 64 +#if defined(__AVR__) + #include <avr/io.h> + + //#define MOTORDEBUG 1 + + #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 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__) + //#define MOTORDEBUG 1 + + // 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 #define MOTOR1_A 2 #define MOTOR1_B 3 #define MOTOR2_A 1 @@ -30,11 +104,13 @@ #define MOTOR3_A 5 #define MOTOR3_B 7 +// Constants that the user passes in to the motor calls #define FORWARD 1 #define BACKWARD 2 #define BRAKE 3 #define RELEASE 4 +// Constants that the user passes in to the stepper calls #define SINGLE 1 #define DOUBLE 2 #define INTERLEAVE 3 @@ -58,7 +134,7 @@ #define SER_PORT PORTB */ -// Arduino pin names +// Arduino pin names for interface to 74HCT595 latch #define MOTORLATCH 12 #define MOTORCLK 4 #define MOTORENABLE 7 @@ -71,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/ |