Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/adafruit/Adafruit-Motor-Shield-library.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLimor "Ladyada" Fried <limor@ladyada.net>2012-10-09 23:08:36 +0400
committerLimor "Ladyada" Fried <limor@ladyada.net>2012-10-09 23:08:36 +0400
commit4bd21ca41a4e64556bf0f217660571cfad453d24 (patch)
tree7f6184e496710dcfbdade05cc7d2b5a2b5452072
parentdd30da7ecb40581377dc4bb8fc9044a995ddb4d4 (diff)
parent33e4a2748d00be8a16b6c67890ed9e7ae29b4f0a (diff)
Merge pull request #8 from EmbeddedMan/master
Add support for PIC32 architecture (fixes issue #7)
-rw-r--r--AFMotor.cpp123
-rw-r--r--AFMotor.h109
-rw-r--r--README.txt1
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);
}
diff --git a/AFMotor.h b/AFMotor.h
index 3b954a5..0362211 100644
--- a/AFMotor.h
+++ b/AFMotor.h
@@ -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);
diff --git a/README.txt b/README.txt
index dfc5765..00cc0e9 100644
--- a/README.txt
+++ b/README.txt
@@ -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/