要说蓝牙小车哪个模块最重要,多数人一定会以为是马达。 
之前说过,为了防止开发板被电流击穿,控制马达时要增加一块扩展板。 
所以,控制马达,只对扩展板编程,而不需要对马达编程。 
此外,扩展板厂家会提供通过扩展板控制马达的代码。
综上,对开发人员来说,马达,只要确认存在就可以了。
Arduino开发板只提供了一些基础、通用的接口,针对一些常见的特殊功能,Arduino专门为其推出了扩展板。
Arduino官方目前总共推出了5款扩展板。 
分别是 
Arduino Motor Shield





其中的Arduino Motor Shield就是专为马达设计的扩展板。
Arduino是开放平台,所以有不少第三方设计者为Arduino设计扩展板。 
我们今天要使用的是下面这款双L293D芯片的马达扩展板。

作为一个软件程序员,我们只需要知道L293D是一种“H桥电机驱动器”就足够了。 
如果你还有更多好奇心,可以参看L293D的datasheet文件
之所以选择这块马达扩展板,而没有选择官方推出的扩展板。 
一个原因是这块扩展板有两个L293D,它支持同时控制四个车轮。四轮驱动,好牛X的感觉:) 
另一个原因是这个开发板便宜。
马达采用比较常见的这种

车轮只要能和马达匹配就行

因为不会针对这两个设备编程,所以没有太多要求。
厂家提供了一些扩展板相关的代码,我把相关的三个文件打包放在安豆网方便大家下载。
下载解压后,打开MotorTest目录,可以看到三个文件。
AFMotor.cpp,AFMotor.h是扩展板的库文件。 
Arduino有两种方法使用库文件。
第一种方法是把它们加入Arduino库文件目录中。 
把库文件打成zip包,直接打包文件或放在目录下打包都可以。 
选择“菜单 项目->加载库->添加一个.ZIP库”,文件就被加到了”c:\Users\UserName\Documents\Arduino\libraries\”目录。 
所以你也可以直接拷贝这两个文件到以上目录下。
第二种方法是把这两个文件和使用他们的ino文件放在一起。 
使用时根据相对路径调用库文件。
所有arduino模块,厂家都会提供库文件,这个库文件相当于sdk。 
大多数时候,我们不需要了解它的详细实现过程,只要知道它提供哪些接口,怎么使用就可以了。
MotorTest.ino是这款马达扩展板的演示程序。 
我们需要详细了解这个文件。
第5行 
#include <AFMotor.h> 
如果你没把AFMotor.h放在arduino库文件目录下,这里要改成""引用头文件。

从这张图中可以看到,这款开发板可以控制的四个马达,接口分别被标注为M1、M2、M3、M4。 
第7行 
AF_DCMotor motor(4); 
生成一个控制M4号马达的对象。
第14行 
motor.setSpeed(200); 
从函数名判断是设置马达的速度,代码理解到这个程度就足够了。 
当然,如果你非常有好奇心,我还是有必要满足一下。
看看setSpeed函数的实现:
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;
  }
}
我们传入的参数是200,即speed=200。 
初始化AF_DCMotor对象时,指定了M4号马达,此处的motornum等于4。 
setSpeed最终执行的是case 4: setPWM4(200);。
再看看setPWM4函数的实现:
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
}
我手头这块Mega板对应的宏定义是__AVR_ATmega2560__,即执行了代码OCR3A = s;。 
你如果不确定哪个宏定义对应你的开发板,可以用这个方法。 
每一个#if下都胡乱写一些代码,不相同即可。
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;
 abc
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // on arduino mega, pin 6 is now PH3 (OC4A)
  OCR3A = s;
 def
#elif defined(__PIC32MX__)
  // Set the OC2 (pin 5) PMW duty cycle from 0 to 255
  OC2RS = s;
 ghi
#else
#error "This chip is not supported!"
#endif
}
编译一下,编译器会告诉你某行代码出错了。我这里提示def出错了。 
我就确定我的开发板对应的是__AVR_ATmega1280__或defined(__AVR_ATmega2560__。
OCR3A = s这行代码做了什么?简单说,就是告诉Arduino,输出电压按时间分成255份,s份输出1,其他的输出0。 
OCR3A = 200就是200份输出1,55份输出0。整体看,Arduino就输出了一个5(v)*200/255~=4(v)的电压。
还不满意我这个解释? 
那就自己学习Mega PinMapping和PWM两篇文档。
/*******************************************************************/ 
  * 版权声明 
  * 本教程只在CSDN和安豆网发布,其他网站出现本教程均属侵权。 
/*******************************************************************/
第16行 
motor.run(RELEASE); 
先看看RELEASE的定义,在AFMotor.h中一共定义了四条命令。
// Constants that the user passes in to the motor calls
#define FORWARD  1
#define BACKWARD 2
#define BRAKE    3
#define RELEASE  4
接着分析run函数的实现,先看函数的后半段。
void AF_DCMotor::run(uint8_t cmd) {
...
  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;
  }
}
先看看_BV是个啥东东。 
#define _BV(bit) (1 << (bit)),作用就是把1左移bit位。
我们继续分析刚才发出的RELEASE命令, 
latch_state &= ~_BV(a);,把latch_state的第a位清零。 
latch_state &= ~_BV(b);,把latch_state的第b位清零。 
MC.latch_tx();调用AFMotorController类latch_tx函数。
回过头再分析run函数的前半段
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;
  }
  ...
}
继续查看MOTOR1_A的定义
#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
结合这个定义,我们可以得出结论: 
latch_state变量的2,3位对应MOTOR1,也就是扩展板上看到的M1。 
1,4位对应M2, 
5,7位对应M3, 
0,6位对应M4。
继续分析latch_tx函数
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);
}
这段代码根据latch_state各个位的状态开或关MOTORDATA引脚。 
如果不详细学习这个硬件知识,完全搞不懂这是在做什么。 
目前只要知道通过这些操作,马达是可以被有效控制的就足够了。
  ...
  motor.run(FORWARD);
  for (i = 0; i < 255; i++) {
    motor.setSpeed(i);
    delay(10);
  }
  for (i = 255; i != 0; i--) {
    motor.setSpeed(i);
    delay(10);
  }
  ...
经过刚才的分析,这一块的代码就很简单了。 
motor.run(FORWARD)让车轮向前转 
第一个for循环i逐渐变大,motor.setSpeed(i)使车轮速度越来越快。 
第一个for循环i逐渐减小,motor.setSpeed(i)使车轮速度越来越慢到最后停止。
  motor.run(BACKWARD);
  for (i = 0; i < 255; i++) {
    motor.setSpeed(i);
    delay(10);
  }
  for (i = 255; i != 0; i--) {
    motor.setSpeed(i);
    delay(10);
  }
其他代码比较简单,就不再分析了。

蓝牙模块还是5.2节的连接方法。 
这里要注意扩展板和Mega的连接方式。扩展板没有Pin脚的这头和Mega没有Pin脚的这头放一边,扩展板0 Pin脚和Mege 0 Pin脚重合,图中黄线所示。
上传程序到开发板,可以观察到马达先向前转,速度从慢到快,又从快到慢。 
接着马达向后转,速度从慢到快,又从快到慢。
原文:http://blog.csdn.net/anddlecn/article/details/51724969