- /*
- 【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
- 实验一百七十:L293D四路电机驱动板 motor control shield 马达板
- Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板
- 1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
- 2、实验之六:连接每转48步(7.5度)的步进电机,电机端口2#(M3和M4)
- */
- #include< AFMotor.h>
- // Connect a stepper motor with 48 steps per revolution (7.5 degree)
- // to motor port #2 (M3 and M4)
- AF_Stepper motor(48, 2);
- void setup() {
- Serial.begin(9600); // set up Serial library at 9600 bps
- Serial.println("Stepper test! 测试步进电机!");
- motor.setSpeed(10); // 10 rpm
- }
- void loop() {
- Serial.println("Single coil steps 单线圈步");
- motor.step(100, FORWARD, SINGLE);
- motor.step(100, BACKWARD, SINGLE);
- Serial.println("Double coil steps 双线圈步");
- motor.step(100, FORWARD, DOUBLE);
- motor.step(100, BACKWARD, DOUBLE);
-
Serial.println("Interleave coil steps 交错线圈台阶");
- motor.step(100, FORWARD, INTERLEAVE);
- motor.step(100, BACKWARD, INTERLEAVE);
-
Serial.println("Micrsostep steps 微步前进");
- motor.step(100, FORWARD, MICROSTEP);
- motor.step(100, BACKWARD, MICROSTEP);
- }
使用Arduino AFMotor驱动四只直流电机
复制代码
- /*
- 【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
- 实验一百七十:L293D四路电机驱动板 motor control shield 马达板
- Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板
- 1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
- 2、实验之七:使用Arduino AFMotor驱动四只直流电机
- */
- #include< AFMotor.h> // 本程序中使用AFMotor库
- AF_DCMotor motor1(1); // 这4条语句的作用是建立4个直流电机对象,它们的名称分别是:motor1/2/3/4.
- AF_DCMotor motor2(2); // 这四条语句括号中的数字代表各个电机对象所连接在AFMotor扩展板的电机端口号码。
- AF_DCMotor motor3(3); // AF_DCMotor motor1(1); 代表motor1对象连接在AFMotor扩展板的M1端口上。
- AF_DCMotor motor4(4); // AFMotor电机扩展板最多可以驱动4个直流电机,最少可以驱动1个直流电机。
- void setup() {
- motor1.setSpeed(200); // 这4条语句的作用是通过setSpped库函数设置电机运行速度。
- motor2.setSpeed(200); // setSpped库函数中的参数是运行速度参数。
- motor3.setSpeed(200); // 运行速度参数允许范围是0~255。
- motor4.setSpeed(200); // 速度参数越大,运转速度越快。参数为0时电机停止转动。
- motor1.run(RELEASE); // 这4条语句的作用是让4个电机在启动时停止转动
- motor2.run(RELEASE); // run库函数允许使用的关键字参数有RELEASE、FORWARD、BACKWARD
- motor3.run(RELEASE); // 使用关键字RELEASE作为参数使用时,run库函数将会让扩展板停止提供电机运转动力
- motor4.run(RELEASE); // 电机旋转一旦失去动力就会自然的停止转动。
- }
- void loop() {
- motor1.run(FORWARD); // 这4条语句的作用是利用run库函数控制4个电机"正向"旋转。
- motor2.run(FORWARD); // 这里所谓的“正向”旋转只是一种说法,假如您发现电机旋转方向和您所要的“正向”不一致。
- motor3.run(FORWARD); // 您可以将电机的两个引线从扩展板上断开,然后交换顺序再接到扩展板接口上
- motor4.run(FORWARD); // 这时您会看到同样使用FORWARD关键字作为run库函数的参数,电机的旋转方向却反过来了。
- for (int i = 0; i< = 255; i++) { // 这里使用for循环语句控制4个电机速度由停止逐步加速,最终电机运转达到最大速度。
- motor1.setSpeed(i); // 在for循环语句的作用下,setSpeed库函数的速度参数i由0逐渐增大,最终达到255。
- motor2.setSpeed(i); // 因此电机运行速度也是由停止逐渐加速,最终达到最大速度。
- motor3.setSpeed(i); // 对于一些模型电机来说,当速度参数小于一定数值以后就不能转动了。也就是说,也许您的电机
- motor4.setSpeed(i); // 在速度参数在小于某一个速度参数数值的时候就无法转动了。这属于正常现象。
- delay(10); // 具体这个最小值是多少,对于不同的电机来说是不同的。有的可能是50也有的可能是100。
- } // 换句话说,很可能您的某一个直流电机在速度参数小于50的情况下就无法转动了。
- // 也可能您的另一个直流电机在参数100以下的情况下就无法转动了。
- for (int i = 255; i >= 0; i--) { // 这里使用for循环语句控制4个电机由最大旋转速度逐步减速最终停止旋转。
- motor1.setSpeed(i); // 这一系列语句的操作与上一段for循环语句类似。唯一区别是上一段for循环控制速度参数i由0涨到255
- motor2.setSpeed(i); // 而这一段语句控制速度参数i由255减小到0。同样您可能会发现当速度参数没有减小到零的时候,电机就已经
- motor3.setSpeed(i); // 停止旋转了。这其中的原因在上一段for循环语句中已经介绍了。不在这里赘述了。
- motor4.setSpeed(i);
- delay(10);
- }
- motor1.run(BACKWARD); // 这4条语句的作用是利用run库函数控制4个电机"反向"旋转。
- motor2.run(BACKWARD); // 同样的,这里所谓的“反向”旋转也只是一种说法。这部分程序内容
- motor3.run(BACKWARD); // 与本程序33-36行中的内容十分类似。唯一区别就是使用了“BACKWARD”
- motor4.run(BACKWARD); // 关键字参数来通过库函数run控制电机“反向”旋转。
- for (int i = 0; i< = 255; i++) { // 利用for循环语句控制速度参数i由小到大
- motor1.setSpeed(i); // 电机也会以“反向”旋转的方式由停止逐步达到最大速度
- motor2.setSpeed(i);
- motor3.setSpeed(i);
- motor4.setSpeed(i);
- delay(10);
- }
- for (int i = 255; i >= 0; i--) { // 利用for循环语句控制速度参数i由大到小
- motor1.setSpeed(i); // 电机也会以“反向”旋转的方式由最大速度逐步减小到停止
- motor2.setSpeed(i);
- motor3.setSpeed(i);
- motor4.setSpeed(i);
- delay(10);
- }
- motor1.run(RELEASE); // 这四条语句作用是使用关键字RELEASE作为run函数的参数。
- motor2.run(RELEASE); // 在这种情况下,AFMotor扩展板将会停止为电机旋转提供动力。
- motor3.run(RELEASE); // 电机也就会自然的停止转动。
- motor4.run(RELEASE); // 本段程序后面的delay(1000)的作用就是让4个电机保持无旋转动力状态1秒钟
- delay(1000);
- }
附录:AFMotor.h库文件
目录—adafruit/Adafruit-Motor-Shield-library
链接—https://github.com/adafruit/Adaf ... ob/master/AFMotor.h
复制代码
目录—adafruit/Adafruit-Motor-Shield-library
链接—https://github.com/adafruit/Adaf ... ob/master/AFMotor.h
- // Adafruit Motor shield library
- // 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 (four 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>
- #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
- #define MOTOR2_B 4
- #define MOTOR4_A 0
- #define MOTOR4_B 6
- #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
- #define MICROSTEP 4
- /*
- #define LATCH 4
- #define LATCH_DDR DDRB
- #define LATCH_PORT PORTB
- #define CLK_PORT PORTD
- #define CLK_DDR DDRD
- #define CLK 4
- #define ENABLE_PORT PORTD
- #define ENABLE_DDR DDRD
- #define ENABLE 7
- #define SER 0
- #define SER_DDR DDRB
- #define SER_PORT PORTB
- */
- // Arduino pin names for interface to 74HCT595 latch
- #define MOTORLATCH 12
- #define MOTORCLK 4
- #define MOTORENABLE 7
- #define MOTORDATA 8
- class AFMotorController
- {
- public:
- AFMotorController(void);
- 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 = DC_MOTOR_PWM_RATE);
- void run(uint8_t);
- void setSpeed(uint8_t);
- private:
- uint8_t motornum, pwmfreq;
- };
- class AF_Stepper {
- public:
- AF_Stepper(uint16_t, uint8_t);
- void step(uint16_t steps, uint8_t dir, uint8_t style = SINGLE);
- void setSpeed(uint16_t);
- uint8_t onestep(uint8_t dir, uint8_t style);
- void release(void);
- uint16_t revsteps; // # steps per revolution
- uint8_t steppernum;
- uint32_t usperstep, steppingcounter;
- private:
- uint8_t currentstep;
- };
- uint8_t getlatchstate(void);
- #endif
附录:AFMotor.cpp库文件
目录—adafruit/Adafruit-Motor-Shield-library
链接—https://github.com/adafruit/Adaf ... /master/AFMotor.cpp
- // Adafruit Motor shield library
- // copyright Adafruit Industries LLC, 2009
- // this code is public domain, enjoy!
- #if (ARDUINO >= 100)
- #include "Arduino.h"
- #else
- #if defined(__AVR__)
- #include< avr/io.h>
- #endif
- #include "WProgram.h"
- #endif
- #include "AFMotor.h"
- static uint8_t latch_state;
- #if (MICROSTEPS == 8)
- uint8_t microstepcurve[] = {0, 50, 98, 142, 180, 212, 236, 250, 255};
- #elif (MICROSTEPS == 16)
- uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255};
- #endif
-
AFMotorController::AFMotorController(void) {
- TimerInitalized = false;
- }
-
void AFMotorController::enable(void) {
- // setup the latch
- /*
- LATCH_DDR |= _BV(LATCH);
- ENABLE_DDR |= _BV(ENABLE);
- CLK_DDR |= _BV(CLK);
- SER_DDR |= _BV(SER);
- */
- pinMode(MOTORLATCH, OUTPUT);
- pinMode(MOTORENABLE, OUTPUT);
- pinMode(MOTORDATA, OUTPUT);
- pinMode(MOTORCLK, OUTPUT);
- latch_state = 0;
- latch_tx(); // "reset"
- //ENABLE_PORT& = ~_BV(ENABLE); // enable the chip outputs!
- digitalWrite(MOTORENABLE, LOW);
- }
-
void AFMotorController::latch_tx(void) {
- uint8_t i;
- //LATCH_PORT& = ~_BV(LATCH);
- digitalWrite(MOTORLATCH, LOW);
- //SER_PORT& = ~_BV(SER);
- digitalWrite(MOTORDATA, LOW);
- for (i=0; i<8; i++) {
- //CLK_PORT& = ~_BV(CLK);
- digitalWrite(MOTORCLK, LOW);
- if (latch_state& _BV(7-i)) {
- //SER_PORT |= _BV(SER);
- digitalWrite(MOTORDATA, HIGH);
- } else {
- //SER_PORT& = ~_BV(SER);
- digitalWrite(MOTORDATA, LOW);
- }
- //CLK_PORT |= _BV(CLK);
- digitalWrite(MOTORCLK, HIGH);
- }
- //LATCH_PORT |= _BV(LATCH);
- digitalWrite(MOTORLATCH, HIGH);
- }
- static AFMotorController MC;
-
/******************************************
- MOTORS
-
******************************************/
- inline void initPWM1(uint8_t freq) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer2A on PB3 (Arduino pin #11)
- TCCR2A |= _BV(COM2A1) | _BV(WGM20) | _BV(WGM21); // fast PWM, turn on oc2a
- TCCR2B = freq& 0x7;
- OCR2A = 0;
-
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
- // on arduino mega, pin 11 is now PB5 (OC1A)
- 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
-
#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) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer2A on PB3 (Arduino pin #11)
- OCR2A = 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
- }
- inline void initPWM2(uint8_t freq) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer2B (pin 3)
- TCCR2A |= _BV(COM2B1) | _BV(WGM20) | _BV(WGM21); // fast PWM, turn on oc2b
- TCCR2B = freq& 0x7;
- OCR2B = 0;
-
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
- // on arduino mega, pin 3 is now PE5 (OC3C)
- 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
- pinMode(3, OUTPUT);
- }
- inline void setPWM2(uint8_t s) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer2A on PB3 (Arduino pin #11)
- OCR2B = 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
- }
- inline void initPWM3(uint8_t freq) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer0A / PD6 (pin 6)
- TCCR0A |= _BV(COM0A1) | _BV(WGM00) | _BV(WGM01); // fast PWM, turn on OC0A
- //TCCR0B = freq& 0x7;
- OCR0A = 0;
-
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
- // on arduino mega, pin 6 is now PH3 (OC4A)
- TCCR4A |= _BV(COM1A1) | _BV(WGM10); // fast PWM, turn on oc4a
- 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
- pinMode(6, OUTPUT);
- }
- inline void setPWM3(uint8_t s) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer0A on PB3 (Arduino pin #6)
- OCR0A = 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
- }
- inline void initPWM4(uint8_t freq) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer0B / PD5 (pin 5)
- TCCR0A |= _BV(COM0B1) | _BV(WGM00) | _BV(WGM01); // fast PWM, turn on oc0a
- //TCCR0B = freq& 0x7;
- OCR0B = 0;
-
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
- // on arduino mega, pin 5 is now PE3 (OC3A)
- TCCR3A |= _BV(COM1A1) | _BV(WGM10); // fast PWM, turn on oc3a
- 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
- pinMode(5, OUTPUT);
- }
- inline void setPWM4(uint8_t s) {
- #if defined(__AVR_ATmega8__) || \
- defined(__AVR_ATmega48__) || \
- defined(__AVR_ATmega88__) || \
-
defined(__AVR_ATmega168__) || \
-
defined(__AVR_ATmega328P__)
- // use PWM from timer0A on PB3 (Arduino pin #6)
- OCR0B = 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
- }
-
AF_DCMotor::AF_DCMotor(uint8_t num, uint8_t freq) {
- motornum = num;
- pwmfreq = freq;
- MC.enable();
- switch (num) {
- case 1:
- latch_state& = ~_BV(MOTOR1_A)& ~_BV(MOTOR1_B); // set both motor pins to 0
- MC.latch_tx();
- initPWM1(freq);
- break;
- case 2:
- latch_state& = ~_BV(MOTOR2_A)& ~_BV(MOTOR2_B); // set both motor pins to 0
- MC.latch_tx();
- initPWM2(freq);
- break;
- case 3:
- latch_state& = ~_BV(MOTOR3_A)& ~_BV(MOTOR3_B); // set both motor pins to 0
- MC.latch_tx();
- initPWM3(freq);
- break;
- case 4:
- latch_state& = ~_BV(MOTOR4_A)& ~_BV(MOTOR4_B); // set both motor pins to 0
- MC.latch_tx();
- initPWM4(freq);
- break;
- }
- }
- void AF_DCMotor::run(uint8_t cmd) {
- uint8_t a, b;
- switch (motornum) {
- case 1:
- a = MOTOR1_A; b = MOTOR1_B; break;
- case 2:
- a = MOTOR2_A; b = MOTOR2_B; break;
- case 3:
- a = MOTOR3_A; b = MOTOR3_B; break;
- case 4:
- a = MOTOR4_A; b = MOTOR4_B; break;
- default:
- return;
- }
-
- switch (cmd) {
- case FORWARD:
- latch_state |= _BV(a);
- latch_state& = ~_BV(b);
- MC.latch_tx();
- break;
- case BACKWARD:
- latch_state& = ~_BV(a);
- latch_state |= _BV(b);
- MC.latch_tx();
- break;
- case RELEASE:
- latch_state& = ~_BV(a); // A and B both low
- latch_state& = ~_BV(b);
- MC.latch_tx();
- break;
- }
- }
-
void AF_DCMotor::setSpeed(uint8_t speed) {
- switch (motornum) {
- case 1:
- setPWM1(speed); break;
- case 2:
- setPWM2(speed); break;
- case 3:
- setPWM3(speed); break;
- case 4:
- setPWM4(speed); break;
- }
- }
-
/******************************************
- STEPPERS
-
******************************************/
-
AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) {
- MC.enable();
- revsteps = steps;
- steppernum = num;
- currentstep = 0;
- if (steppernum == 1) {
- latch_state& = ~_BV(MOTOR1_A)& ~_BV(MOTOR1_B)&
- ~_BV(MOTOR2_A)& ~_BV(MOTOR2_B); // all motor pins to 0
- MC.latch_tx();
-
- // enable both H bridges
- pinMode(11, OUTPUT);
- pinMode(3, OUTPUT);
- digitalWrite(11, HIGH);
- digitalWrite(3, HIGH);
- // use PWM for microstepping support
-
initPWM1(STEPPER1_PWM_RATE);
-
initPWM2(STEPPER1_PWM_RATE);
- setPWM1(255);
- setPWM2(255);
- } else if (steppernum == 2) {
- latch_state& = ~_BV(MOTOR3_A)& ~_BV(MOTOR3_B)&
- ~_BV(MOTOR4_A)& ~_BV(MOTOR4_B); // all motor pins to 0
- MC.latch_tx();
- // enable both H bridges
- pinMode(5, OUTPUT);
- pinMode(6, OUTPUT);
- digitalWrite(5, HIGH);
- digitalWrite(6, HIGH);
- // use PWM for microstepping support
- // use PWM for microstepping support
-
initPWM3(STEPPER2_PWM_RATE);
-
initPWM4(STEPPER2_PWM_RATE);
- setPWM3(255);
- setPWM4(255);
- }
- }
-
void AF_Stepper::setSpeed(uint16_t rpm) {
- usperstep = 60000000 / ((uint32_t)revsteps * (uint32_t)rpm);
- steppingcounter = 0;
- }
- void AF_Stepper::release(void) {
- if (steppernum == 1) {
- latch_state& = ~_BV(MOTOR1_A)& ~_BV(MOTOR1_B)&
- ~_BV(MOTOR2_A)& ~_BV(MOTOR2_B); // all motor pins to 0
- MC.latch_tx();
- } else if (steppernum == 2) {
- latch_state& = ~_BV(MOTOR3_A)& ~_BV(MOTOR3_B)&
- ~_BV(MOTOR4_A)& ~_BV(MOTOR4_B); // all motor pins to 0
- MC.latch_tx();
- }
- }
- void AF_Stepper::step(uint16_t steps, uint8_t dir, uint8_t style) {
- uint32_t uspers = usperstep;
- uint8_t ret = 0;
- if (style == INTERLEAVE) {
- uspers /= 2;
- }
- else if (style == MICROSTEP) {
- uspers /= MICROSTEPS;
- steps *= MICROSTEPS;
- #ifdef MOTORDEBUG
- Serial.print("steps = "); Serial.println(steps, DEC);
- #endif
- }
- while (steps--) {
- ret = onestep(dir, style);
- delay(uspers/1000); // in ms
- steppingcounter += (uspers % 1000);
- if (steppingcounter >= 1000) {
- delay(1);
- steppingcounter -= 1000;
- }
- }
- if (style == MICROSTEP) {
- while ((ret != 0)&& (ret != MICROSTEPS)) {
- ret = onestep(dir, style);
- delay(uspers/1000); // in ms
- steppingcounter += (uspers % 1000);
- if (steppingcounter >= 1000) {
- delay(1);
- steppingcounter -= 1000;
- }
- }
- }
- }
-
uint8_t AF_Stepper::onestep(uint8_t dir, uint8_t style) {
- uint8_t a, b, c, d;
- uint8_t ocrb, ocra;
- ocra = ocrb = 255;
- if (steppernum == 1) {
- a = _BV(MOTOR1_A);
- b = _BV(MOTOR2_A);
- c = _BV(MOTOR1_B);
- d = _BV(MOTOR2_B);
- } else if (steppernum == 2) {
- a = _BV(MOTOR3_A);
- b = _BV(MOTOR4_A);
- c = _BV(MOTOR3_B);
- d = _BV(MOTOR4_B);
- } else {
- return 0;
- }
- // next determine what sort of stepping procedure we're up to
- if (style == SINGLE) {
-
if ((currentstep/(MICROSTEPS/2)) % 2) { // we're at an odd step, weird
- if (dir == FORWARD) {
- currentstep += MICROSTEPS/2;
- }
- else {
- currentstep -= MICROSTEPS/2;
- }
- } else { // go to the next even step
- if (dir == FORWARD) {
- currentstep += MICROSTEPS;
- }
- else {
- currentstep -= MICROSTEPS;
- }
- }
- } else if (style == DOUBLE) {
-
if (! (currentstep/(MICROSTEPS/2) % 2)) { // we're at an even step, weird
- if (dir == FORWARD) {
- currentstep += MICROSTEPS/2;
- } else {
- currentstep -= MICROSTEPS/2;
- }
- } else { // go to the next odd step
- if (dir == FORWARD) {
- currentstep += MICROSTEPS;
- } else {
- currentstep -= MICROSTEPS;
- }
- }
- } else if (style == INTERLEAVE) {
- if (dir == FORWARD) {
- currentstep += MICROSTEPS/2;
- } else {
- currentstep -= MICROSTEPS/2;
- }
- }
- if (style == MICROSTEP) {
- if (dir == FORWARD) {
- currentstep++;
- } else {
- // BACKWARDS
- currentstep--;
- }
- currentstep += MICROSTEPS*4;
- currentstep %= MICROSTEPS*4;
- ocra = ocrb = 0;
- if ( (currentstep >= 0)&& (currentstep< MICROSTEPS)) {
- ocra = microstepcurve[MICROSTEPS - currentstep];
-
ocrb = microstepcurve[currentstep];
- } else if ( (currentstep >= MICROSTEPS)&& (currentstep< MICROSTEPS*2)) {
-
ocra = microstepcurve[currentstep - MICROSTEPS];
-
ocrb = microstepcurve[MICROSTEPS*2 - currentstep];
- } else if ( (currentstep >= MICROSTEPS*2)&& (currentstep< MICROSTEPS*3)) {
-
ocra = microstepcurve[MICROSTEPS*3 - currentstep];
-
ocrb = microstepcurve[currentstep - MICROSTEPS*2];
- } else if ( (currentstep >= MICROSTEPS*3)&& (currentstep< MICROSTEPS*4)) {
-
ocra = microstepcurve[currentstep - MICROSTEPS*3];
-
ocrb = microstepcurve[MICROSTEPS*4 - currentstep];
- }
- }
- currentstep += MICROSTEPS*4;
- currentstep %= MICROSTEPS*4;
- #ifdef MOTORDEBUG
-
Serial.print("current step: "); Serial.println(currentstep, DEC);
- Serial.print(" pwmA = "); Serial.print(ocra, DEC);
- Serial.print(" pwmB = "); Serial.println(ocrb, DEC);
- #endif
- if (steppernum == 1) {
- setPWM1(ocra);
- setPWM2(ocrb);
- } else if (steppernum == 2) {
- setPWM3(ocra);
- setPWM4(ocrb);
- }
- // release all
- latch_state& = ~a& ~b& ~c& ~d; // all motor pins to 0
- //Serial.println(step, DEC);
- if (style == MICROSTEP) {
- if ((currentstep >= 0)&& (currentstep< MICROSTEPS))
- latch_state |= a | b;
- if ((currentstep >= MICROSTEPS)&& (currentstep< MICROSTEPS*2))
- latch_state |= b | c;
- if ((currentstep >= MICROSTEPS*2)&& (currentstep< MICROSTEPS*3))
- latch_state |= c | d;
- if ((currentstep >= MICROSTEPS*3)&& (currentstep< MICROSTEPS*4))
- latch_state |= d | a;
- } else {
-
switch (currentstep/(MICROSTEPS/2)) {
- case 0:
- latch_state |= a; // energize coil 1 only
- break;
- case 1:
- latch_state |= a | b; // energize coil 1+2
- break;
- case 2:
- latch_state |= b; // energize coil 2 only
- break;
- case 3:
- latch_state |= b | c; // energize coil 2+3
- break;
- case 4:
- latch_state |= c; // energize coil 3 only
- break;
- case 5:
- latch_state |= c | d; // energize coil 3+4
- break;
- case 6:
- latch_state |= d; // energize coil 4 only
- break;
- case 7:
- latch_state |= d | a; // energize coil 1+4
- break;
- }
- }
- MC.latch_tx();
- return currentstep;
- }
补充实验
复制代码
- /*
- 【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
- 实验一百七十:L293D四路电机驱动板 motor control shield 马达板
- Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板
- 1、安装库:IDE—工具—管理库—搜索“Servo”—安装
- 2、实验之八:测试M1M2电机
- */
- #include< AFMotor.h>
- AF_DCMotor motor1(1);
- AF_DCMotor motor2(2);
- void setup() {
- Serial.begin(9600);
- Serial.println("测试M1M2电机!");
- // turn on motor
- motor1.setSpeed(200);
- motor2.setSpeed(200);
- motor1.run(RELEASE);
- motor2.run(RELEASE);
- }
- void loop() {
- uint8_t i;
- Serial.println("正转");
- motor1.run(FORWARD);
- motor2.run(FORWARD);
- for (i = 0; i< 255; i++) {
- motor1.setSpeed(i);
- motor2.setSpeed(i);
- delay(10);
- }
- for (i = 255; i != 0; i--) {
- motor1.setSpeed(i);
- motor2.setSpeed(i);
- delay(10);
- }
- Serial.println("反转");
- motor1.run(BACKWARD);
- motor2.run(BACKWARD);
- for (i = 0; i< 255; i++) {
- motor1.setSpeed(i);
- motor2.setSpeed(i);
- delay(10);
- }
- for (i = 255; i != 0; i--) {
- motor1.setSpeed(i);
- motor2.setSpeed(i);
- delay(10);
- }
- Serial.println("断电一秒");
- motor1.run(RELEASE);
- motor2.run(RELEASE);
- delay(1000);
- }
Arduino AFMotor电机扩展板(上)
https://www.bilibili.com/video/BV1vb411q7xz?p=1
Arduino AFMotor电机扩展板(下)
https://www.bilibili.com/video/BV1vb411q7xz?p=2
https://www.bilibili.com/video/BV1vb411q7xz?p=1
Arduino AFMotor电机扩展板(下)
https://www.bilibili.com/video/BV1vb411q7xz?p=2
- /*
- 【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
- 实验一百七十:L293D四路电机驱动板 motor control shield 马达板
- Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板
- 1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
- 2、实验之九:测试M1M2M3M4电机前进与后退
- */
- #include< AFMotor.h>
- // 创建对象
- AF_DCMotor motor1(1);
- AF_DCMotor motor2(2);
- AF_DCMotor motor3(3);
- AF_DCMotor motor4(4);
- // 主程序开始
- void setup() {
- }
- void loop() {
- motor1.setSpeed(200);
- motor1.run(FORWARD);
- motor2.setSpeed(200);
- motor2.run(FORWARD);
- motor3.setSpeed(200);
- motor3.run(FORWARD);
- motor4.setSpeed(200);
- motor4.run(FORWARD);
- delay(2000);
-
- motor1.setSpeed(0);
- motor1.run(RELEASE);
- motor2.setSpeed(0);
- motor2.run(RELEASE);
- motor3.setSpeed(0);
- motor3.run(RELEASE);
- motor4.setSpeed(0);
- motor4.run(RELEASE);
- delay(1000);
-
- motor1.setSpeed(200);
- motor1.run(BACKWARD);
- motor2.setSpeed(200);
- motor2.run(BACKWARD);
- motor3.setSpeed(200);
- motor3.run(BACKWARD);
- motor4.setSpeed(200);
- motor4.run(BACKWARD);
- delay(2000);
-
- motor1.setSpeed(0);
- motor1.run(RELEASE);
- motor2.setSpeed(0);
- motor2.run(RELEASE);
- motor3.setSpeed(0);
- motor3.run(RELEASE);
- motor4.setSpeed(0);
- motor4.run(RELEASE);
- delay(1000);
- }
使用
AFMotor电机扩展板的麦克纳姆轮小车(视频)
https://v.youku.com/v_show/id_XNTAzNDYyMzE1Mg==.html?spm=a2hzp.8253869.0.0