标题: 【Arduino】168种传感器系列实验(170)---L293D四路电机驱动板 [打印本页]

作者: eagler8    时间: 2020-10-26 18:53
标题: 【Arduino】168种传感器系列实验(170)---L293D四路电机驱动板
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试做实验,不管成功与否,都会记录下来---小小的进步或是搞不定的问题,希望能够抛砖引玉。

【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
实验一百七十:L293D四路电机驱动模块 扩展板 motor control shield 马达板








作者: eagler8    时间: 2020-10-27 10:26
L293D
L293D是ST公司生产的一种高电压、小电流电机驱动芯片,其设计用于在4.5 V至36 V的电压下提供高达600 mA的双向驱动电流。可以用于驱动电感性负载,例如继电器,螺线管,DC和双极步进电机,以及在正电源应用中的其他大电流/高压负载。

每个输出都是一个完整的图腾柱驱动电路,带有一个达林顿晶体管沉和一个伪达林顿源。驱动程序成对启用,驱动程序1和2由1,2EN启用,驱动程序3和4由3,4EN启用。

L293D的工作温度范围为0°C至70°C。





作者: eagler8    时间: 2020-10-27 10:55
L293D特性
电源电压范围:4.5V至36V
单独的输入逻辑电源
内部ESD保护
热关断
高噪声抗扰度输入的
通标L293和L293DSGS的功能替代
输出电流1A每通道(600毫安L293D)
峰值输出电流每通道2A(1.2 L293D)
输出钳位二极管的感性瞬态抑制(L293D)

L293D参数
制造商: STMicroelectronics
产品种类: 电机/运动控制器和驱动器
类型: Driver
工作电源电压: 4.5 V to 36 V
封装 / 箱体: POWERDIP
封装: Tube





作者: eagler8    时间: 2020-10-27 11:06
该器件是单片集成的高电压,高电流的四通道驱动器,旨在接受标准的DTL或TTL逻辑电平并驱动感性负载(例如继电器螺线管,直流和步进电机)和开关功率晶体管。为了简化用作两个桥接器的使用,每对通道都配备了一个使能输入。 独立为逻辑电路提供了电源输入,允许在较低电压下工作,并包括内部钳位二极管。该设备适合在高达5 kHz的频率下切换应用。L293D用16引线塑料组装具有4个中心引脚连接到gether并用于散热的包装L293DD装配在20引线表面中具有8个中心引脚连接到gether并用于散热的安装座。

内部电路框图




作者: eagler8    时间: 2020-10-27 12:40
L293D引脚图






作者: eagler8    时间: 2020-10-27 13:04
本帖最后由 eagler8 于 2020-10-27 17:49 编辑


1,2EN:启用驱动器通道1和2(高可用有效输入)
<1-4> A:驱动器输入,同相
<1-4>Y:驱动输出
3,4EN:启用驱动器通道3和4(高允许有效输入)
4、5、12、13:设备接地和散热器引脚。通过多个实心通孔连接到印刷电路板接地层
V CC1:用于内部逻辑转换的5V电源
V CC2:驱动器的电源VCC 4.5 V至36 V


作者: eagler8    时间: 2020-10-27 13:11
L293D电气特性
(对于每个通道,VS = 24 V,VSS = 5 V,Tamb = 25°C,除非另有规定)





作者: eagler8    时间: 2020-10-27 13:14


作者: eagler8    时间: 2020-10-27 15:28


作者: eagler8    时间: 2020-10-27 15:30


作者: eagler8    时间: 2020-10-27 15:32


作者: eagler8    时间: 2020-10-27 15:35




作者: eagler8    时间: 2020-10-27 15:37


作者: eagler8    时间: 2020-10-27 16:30
本帖最后由 eagler8 于 2020-10-28 10:46 编辑

L293D(双H桥路)工作原理(视频21分钟)

https://www.bilibili.com/video/B ... 6911526506650231789



作者: eagler8    时间: 2020-10-27 16:51
L293D四路电机驱动模块 扩展板 motor control shield 马达板




作者: eagler8    时间: 2020-10-27 16:55
这是一款常用的直流电机驱动模块,采用293D芯片小电流直流电机驱动芯片。管脚被做成了rduino兼容的,也方便了爱好者快速的基于rduino的开发。

rduino 是一款很好的电子制作入门,有了电机扩展板可以很好的成为机器人开发平台。这里介绍一款能驱动各种简单到稍复杂项目的全功能的电机扩展板。

适用范围:rduino初学者,rduino实验器材平台,rduino互动电子,Arduino机器人等。

特点:功能多,操作方便,有强大的驱动库支持及功能更新。

缺点:I/O占用较多在同时驱动四路电机的情况下(相对rduino I/O少的版本而言),小功率。

可驱动4路直流电机或者2路步进电机的同时还能驱动2路舵机,支持最新rduino UNO, rduino Mega 2560

可以这样搭配:
驱动四路直流电机和两路舵机
驱动两路直流电机和一路步进电机和两路舵机
驱动两路步进电机和两路舵机





作者: eagler8    时间: 2020-10-27 17:00
L293D四路电机扩展板特点
    * 2个5V伺服电机(舵机)端口 联接到Arduino的高解析高精度的定时器-无抖动!
    * 多达4个双向直流电机及4路PWM调速(大约0.5%的解析度)
    * 多达2个步进电机正反转控制,单/双步控制,交错或微步及旋转角度控制。
    * 4路H-桥:L293D 芯片每路桥提供.0.6A(峰值1.2A)电流并且带有热断电保护,4.5V to 36V。
    * 下拉电阻保证在上电时电机保持停止状态。
    * 大终端接线端子使接线更容易(10 - 22AWG)和电源。
    * 带有Arduino复位按钮。
    * 2个大终端外部电源接线端子 保证逻辑和电机驱动电源分离。
    * 兼容Mega, Diecimila, & Duemilanove。
    *下载方便使用的Arduino软件库快速进行项目开发。





作者: eagler8    时间: 2020-10-27 18:19
本帖最后由 eagler8 于 2020-10-28 13:18 编辑

L293D四路电机扩展板电原理图






作者: eagler8    时间: 2020-10-28 10:55
本帖最后由 eagler8 于 2020-10-28 13:19 编辑

L293D四路电机扩展板模块原理
使用L293D来驱动电机的,中间有一个74HC595芯片,是将串行信号转为并行信号的,因为该模块是为arduino设计的,arduino的I/O口较少,控制4个直流电机需要12个引脚,使用74HC595可以减少4个引脚的使用,也可以取掉74HC595芯片,焊接接线,直接使用51单片机并行控制2个L293D芯片从而控制电机。

74HC595
74HC595是一个8位串行输入、并行输出的位移缓存器:并行输出为三态输出。在SCK 的上升沿,串行数据由SDL输入到内部的8位位移缓存器,并由Q7'输出,而并行输出则是在LCK的上升沿将在8位位移缓存器的数据存入到8位并行输出缓存器。当串行数据输入端OE的控制信号为低使能时,并行输出端的输出值等于并行输出缓存器所存储的值。简单的说,先将模块的引脚7置0,然后模块的引脚4(74HC595芯片的数据输入时钟端)接受到一个上升沿,就将芯片中的8位数据左移一位,空出低位将引脚8(74HC595芯片的串行数据输入端)的0或1信号写入低位,写入八次就将控制4个电机的8位信号写入74HC595的芯片中了(M3M4M3M2M1M1M2M4),然后在给引脚12一个上升沿,就将芯片中的数据输出在芯片的引脚上(Q0~Q7)。



程序计数器——74HC595(视频6分32秒)
https://www.bilibili.com/video/BV1ME411T7EY?from=search&seid=17494597794294138238


作者: eagler8    时间: 2020-10-28 11:28
本帖最后由 eagler8 于 2020-10-29 05:10 编辑

电机和驱动器
电机是许多机器人和电子项目不可分割的一部分,根据应用的不同,它们可以使用不同的类型。以下是有关不同类型电机的一些信息:

直流电机(DC Motor):直流电机是最常见的电机,可用于许多应用。我们可以在遥控车、机器人等中看到它。这种电机结构简单。它将通过向其端部施加适当的电压并通过切换电压极性来改变其方向来开始滚动。直流电机的速度由施加的电压直接控制。当电压电平小于最大容许电压时,速度会降低。

步进电机(Stepper Motor):在一些项目中,如3D打印机、扫描仪和数控机床,我们需要准确了解电机旋转步数。在这些情况下,我们使用步进电机。步进电机可将整个旋转分成多个相等的步长。每步的旋转量由电机结构决定。这些电机具有非常高的精度。

伺服电机(Servo Motor):伺服电机是一种简单的直流电机,带有位置控制服务。通过使用伺服电机,您将能够控制轴的旋转量并将其移动到特定位置。它们通常尺寸小,是机器人手臂的最佳选择。

这里做实验准备使用TT马达





TT马达直流减速电机,作为一款被广泛应用于电子DIY,机器人制作,智能车制作环节重点动力装置,以其组装简单,扩展性能强,价格低廉等诸多特点受到广大师生和电子爱好者的喜欢。

主要参数
额定电压:4.5-6V
空载转速:90±10rpm (具体视减速比而定)
负载电流:190mA(250mA 最大)
最大扭矩:0.8Kg·cm


作者: eagler8    时间: 2020-10-28 14:29
本帖最后由 eagler8 于 2020-10-29 04:51 编辑

为什么用L293D驱动电机?
驱动电动机需要大电流。另外,旋转方向和速度是两个需要控制的重要参数。这些要求可以通过使用微控制器(或像Arduino这样的开发板)来处理。但有个问题;微控制器无法提供足够的电流来运行电机,如果直接将电机连接到微控制器,可能会损坏微控制器。例如,Arduino UNO引脚限制为40mA电流,远小于控制小型电机所需的100-200mA电流。要解决这个问题,我们应该使用电机驱动器。电机驱动器可以连接到微控制器以接收命令并以高电流运行电机。L293D是最受欢迎的电机驱动器之一,可驱动直流电机,电流负载高达1A.L293D有4个输出,适用于4线步进电机。 L293D也可用于驱动伺服电机。






L293D四路电机扩展板支持Arduino UNO. Arduino Mega2560
可以这样搭配
驱动四路直流电机和两路舵机
驱动两路直流电机和一路步进电机和两路舵机
驱动两路步进电机和两路舵机
可以同时控制4个直流电机和2个步进电机和两个伺服电机(舵
机)。有专门的代码库。导入库后,简单使用。



作者: eagler8    时间: 2020-10-29 04:58
L293D四路电机扩展板接线图




作者: eagler8    时间: 2020-10-29 17:34
本帖最后由 eagler8 于 2020-10-29 17:41 编辑

在L293D上哪些引脚我们可以使用呢?
所有的六个模拟输入引脚都是可用的。它们也可以当做数字芯片来使用。(引脚14到19),数字引脚2和13可用。

下面的引脚只有在下面提到的直流或者步进电机工作时才会被用到
       数字引脚11: 1号直流电机或者1号步进电机
       数字引脚3: 2号直流电机或者1号步进电机
       数字引脚5: 3号直流电机或者2号步进电机
       数字引脚6:4号直流电机或者2号步进电机

下面的引脚只有在下面的直流或者步进电机工作时才会被用到
       数字信号4,7,8,和12通过74hc595(serial-to-parallel)来驱动直流或者步进电机

数字引脚4:DIR CLK触发
数字引脚7:DIR EN指令的允许端EN
数字引脚8:DIR SER
数字引脚12:DIR ATCH中断连接

下面的引脚只有在舵机工作时才会被用到
       数字信号9:1号舵机
       数字信号10: 2号舵机

所以只要相应的引脚没被L293D驱动板使用到,你也是可以拿来用的但前提是你得自己焊出引脚来。另外,GND、5V引脚必须也要连接,否则的话就无法稳定地控制直流电动机。






作者: eagler8    时间: 2020-11-3 20:22
外接电源供电
如下图所示,AFMotor电机扩展板上配有外接电源接口。该接口所连接的直流电源可以为电机和Arduino开发板供电。



使用AFMotor电机扩展板驱动电机时,首要考虑的问题就是如何为扩展板供电。如果电源输出功率达不到驱动电机的要求,那么电机是无法正常工作的。在考虑如何选择电源时,我们需要重点关注两个方面 ,一个是电源电压,一个是电源电流。

注意:外接电源极性千万不要接反,否则会对扩展板造成损坏!

外接电源电压要求
AFMotor扩展板中起关键作用的芯片是L293D。该芯片所允许的直流电源电压范围是4.5V ~25V。因此AFMotor扩展板外接电源接口允许我们连接的电源也是4.5V ~25V。请注意:这是一个很宽泛的电压指标。具体我们应该连接的电源电压有多大,这是由被驱动的电机工作电压来决定的。

外接电源电流要求
与上面提到的电源电压要求相同,外接电源的电流要求也是由被驱动的电机来决定的。通常我们使用AFMotor电机扩展板所驱动的电机就是普通的模型电机(如以上电源讲解中的图片所示)。对于这一类型的电机,它们的工作电流大约是500mA左右,因此我们只要为扩展板配一个500 mA~1000 mA的外接电源就足够了。请注意,假如您所驱动的电机工作电流超过500mA,那么就要考虑为扩展板上的L293D加装芯片了。

作者: eagler8    时间: 2020-11-4 05:04
电源使用
为直流电动机,电压和电流需求供电电动机需要大量能量,尤其是便宜的电动机,因为它们的效率较低。首先要弄清楚电动机要使用的电压。如果幸运的话,您的电动机带有一些规格。一些小型的业余电动机仅打算以1.5V的电压运行,但6-12V电动机的使用却一样普遍。该屏蔽罩的电机控制器设计为在 4.5V至25V 范围内运行。

MOST 1.5-3V电动机将无法工作
电流要求:要弄清的第二件事是电动机需要多少电流。该套件随附的电机驱动器芯片旨在为每个电机提供高达600 mA的电流,峰值电流为1.2A。请注意,一旦接近1A,您可能会希望在电机驱动器上放一个散热器,否则会出现热故障,从而可能烧坏芯片。

使用SN754410
某些人使用SN754410电机驱动器芯片是因为它与引脚兼容,具有输出二极管,每个电机可提供1A电流,峰值2A电流。在仔细阅读数据表并与TI技术支持和电源工程师进行讨论之后,看来输出二极管仅设计用于ESD保护,并且将其用作反冲保护是一种黑客行为,并且不能保证性能。因此,该套件不随SN754410一起提供,而是使用带有集成反冲保护二极管的L293D。如果您愿意冒险,并且需要额外的流动资金,请随时购买SN754410并更换提供的芯片。

需要更多电源吗?请购买另一组L293D驱动器并将其焊接在板上的顶部(背负式)。瞧,当前功能加倍!您可以在顶部再焊接2个芯片,否则可能不会为您带来很多好处

您不能用9V电池来驱动电动机,因此甚至不浪费时间/电池! 使用大号铅酸或镍氢电池。它还非常建议您设置两个电源(分离电源),一个用于Arduino,另一个用于电机。 99%的“怪异电机问题” 是由于共享电源线上的噪声引起的供应和/或没有足够的供应!

如何设置Arduino + Shield来为电机供电 Servos的电源是与Arduino使用的相同的5V电压。建议使用小型业余伺服器。如果您想要更好的东西,请切断去往伺服连接器上+的走线,并为您自己的5-6V电源接线!

直流电动机由“高压电源”供电,而不是经过调节的5V电源。请勿将电动机电源连接到5V线。除非您确定自己知道自己在做什么,否则这是一个非常非常糟糕的主意!

可以在两个地方获得电动机的“高压电源”。一个是Arduino板上的DC插孔,另一个是屏蔽板上标有 EXT_PWR 的2端子块.Arduino上的DC插孔具有保护二极管,因此您将无法弄乱如果插入错误的电源,情况可能会变得非常糟糕。但是,屏蔽层上的 EXT_PWR端子没有保护二极管(出于相当充分的理由)。请小心不要将其向后插入,否则您将破坏电机护罩和/或Arduino!

这是它的工作方式:




如果您想要一个为Arduino和电机提供单个DC电源,只需将其插入Arduino的DC插孔或屏蔽板上的2针PWR_EXT模块。将电源跳线放在电动机的护罩上。

如果您有Diecimila Arduino,请将Arduino电源跳线设置为EXT。

请注意,如果电池电源无法提供恒定的电源,您可能会遇到Arduino重置问题,但这不是建议您为电机项目供电的方法

如果您想让 Arduino的USB电源关闭,而电机的电源是直流电源,插入USB电缆。然后将电动机电源连接到屏蔽板上的PWR_EXTblock。请勿将跳线放在防护罩上。这是为电机项目供电的建议方法

(如果您有Diecimila Arduino,请不要忘记将Arduino电源跳线设置为USB。如果您有Diecimila,则可以交替执行以下操作:将DC电源插入

如果您要 2个用于Arduino和电机的独立直流电源。请插入Arduino的电源插入DC插孔,然后将电动机电源连接到PWR_EXT块。确保将跳线从电动机护罩上卸下。

如果您有Diecimila Arduino,请将Arduino跳线设置为EXT。这是为电动机项目供电的建议方法。

无论哪种方式,如果要使用直流电动机/步进系统,电动机的护罩LED均应点亮,指示电动机功率良好。


作者: eagler8    时间: 2020-11-4 05:12
安装AFMotor电机库
使用AFMotor电机扩展板驱动电机以前,需要先将AFMotor库安装到Arduino IDE中。如果您不知道如何进行操作,请点击这里进入Arduino IDE安装库的说明页面(http://www.taichi-maker.com/home ... ll-arduino-library/)。

在这里我们向您推荐两个电机程序库。一个是必须安装的,一个是可按您需要选择安装的。

必装的库是AFMotor库。这个库是AFMotor扩展板的开发团队Adafruit专门为该扩展板编写的。它的优点是非常简单易用,但是功能相对单一。假如您只是驱动直流模型电机,那么这个AFMotor库就足够了。

但是如果您还想用AFMotor扩展板驱动28BYJ-48步进电机的话,AFMotor库虽然也可以实现这一功能,但是它的功能太简单了。所以我们建议您使用AccelStepper库来控制步进电机。请注意:AccelStepper库本身不能配合AFMotor电机扩展板工作。只有安装了AFMotor库以后,AccelStepper库在AFMotor库的配合下才能用于AFMotor电机扩展板驱动步进电机。这也就是说,无论您是否使用AccelStepper库,都要首先安装AFMotor库。

以下是这两个库的下载链接:

下载 AFMotor库(https://pan.baidu.com/s/1xVViDOb_VIb0qenXVdGErw
下载 AccelStepper库(https://pan.baidu.com/s/1PXKIEiSYR-P_3IpY5cs7tw




作者: eagler8    时间: 2020-11-4 14:52
本帖最后由 eagler8 于 2020-11-4 16:17 编辑
  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
  6.   2、实验之一:测试驱动M2直流电机
  7. */

  8. #include <AFMotor.h>

  9. AF_DCMotor motor(2, MOTOR12_64KHZ);

  10. void setup() {
  11.   motor.setSpeed(200);
  12. }

  13. void loop() {
  14.   motor.run(FORWARD);
  15.   delay(1000);
  16.   motor.run(BACKWARD);
  17.   delay(1000);
  18.   motor.run(RELEASE);
  19.   delay(1000);
  20. }
复制代码


作者: eagler8    时间: 2020-11-4 14:52
本帖最后由 eagler8 于 2020-11-5 19:32 编辑
  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
  6.   2、实验之二:引擎测试—用串口查看2号直流电机运转情况
  7. */

  8. #include "AFMotor.h"

  9. AF_DCMotor motor(2);

  10. void setup() {
  11.   Serial.begin(9600);           // set up Serial library at 9600 bps
  12.   Serial.println("引擎测试 Motor test!");

  13.   // turn on motor
  14.   motor.setSpeed(200);

  15.   motor.run(RELEASE);
  16. }

  17. void loop() {
  18.   uint8_t i;

  19.   Serial.println("向前 FORWARD!");

  20.   motor.run(FORWARD);
  21.   for (i = 0; i < 255; i++) {
  22.     motor.setSpeed(i);
  23.     delay(10);
  24.   }

  25.   for (i = 255; i != 0; i--) {
  26.     motor.setSpeed(i);
  27.     delay(10);
  28.   }

  29.   Serial.println("向后 BACKWARD!");

  30.   motor.run(BACKWARD);
  31.   for (i = 0; i < 255; i++) {
  32.     motor.setSpeed(i);
  33.     delay(10);
  34.   }

  35.   for (i = 255; i != 0; i--) {
  36.     motor.setSpeed(i);
  37.     delay(10);
  38.   }


  39.   Serial.println("停止 RELEASE!");
  40.   motor.run(RELEASE);
  41.   delay(1000);
  42. }
复制代码


作者: eagler8    时间: 2020-11-4 16:16
本帖最后由 eagler8 于 2020-11-5 19:34 编辑


作者: eagler8    时间: 2020-11-6 11:16
AF_DCMotor 类函数
AFMotor类配合Adafruit Motor Shied可以最多同时控制4个直流电机的速度和方向。要使用这些功能,首先要在开头添加库文件:
#include <AFMotor.h>

AF_DCMotor motorname(portnum,freq)
这是一个建立一个直流电机的函数。在程序中需要声明每个电机各一次。像下面的例子中一样,每个电机必须使用不同的名字。
参数:
port num - 选择你的电机连接到电机驱动板上的接口(1-4)
freq - 选择PWM频率。如果你没有选择这个选项,默认设置为1KHZ。
适用于通道1和2的频率:
MOTOR12_64KHZ
MOTOR12_8KHZ
MOTOR12_2KHZ
MOTOR12_1KHZ
适用于通道3和4的频率:
MOTOR34_64KHZ
MOTOR34_8KHZ
MOTOR34_1KHZ
例如:
AF_DCMotor motor4(4);//通道4,默认1KHZ频率
AF_DCMotor left_motor(1,MOTOR12_64KHZ);//通道1,64KHZ频率
注意:更高的频率会减小电机在运动过程中的噪音,但同时也会降低扭矩。

setSpeed(speed)
设置电机的速度
参数:
speed-范围为0到255,0代表停止,255代表全速。
注意:直流电机的回馈并不是典型线性的,所以真正的转速并不会与程序中设定的速度成正比。

run(cmd)
设置电机的运转模式
参数:
cmd - 选择你想要的电机运转模式
可选择的模式:
FORWARD - 正转(真正的转动方向取决于你电机的连线)
BACKWARD - 反转 (转动方向与正转相反)
RELEASE - 停止。使电机断电,与setSpeed(0)函数功能相同。调用了这个函数后,电机需要一定时间才能彻底停止。


作者: eagler8    时间: 2020-11-11 11:03
驱动直流电机




作者: eagler8    时间: 2020-11-11 11:26
驱动伺服电机(舵机)

首先需要安装库:IDE—工具—管理库—搜索“servo”—安装




作者: eagler8    时间: 2020-11-11 16:37
本帖最后由 eagler8 于 2020-11-11 16:51 编辑

实验之三:驱动单只伺服电机(2号舵机)

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:IDE—工具—管理库—搜索“Servo”—安装
  6.   2、实验之三:驱动单只伺服电机(2号舵机)
  7. */

  8. #include <Servo.h>

  9. Servo myservo;  // create servo object to control a servo
  10. // twelve servo objects can be created on most boards

  11. int pos = 0;    // variable to store the servo position

  12. void setup() {
  13.   myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  14. }

  15. void loop() {
  16.   for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
  17.     // in steps of 1 degree
  18.     myservo.write(pos);              // tell servo to go to position in variable 'pos'
  19.     delay(15);                       // waits 15ms for the servo to reach the position
  20.   }
  21.   for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
  22.     myservo.write(pos);              // tell servo to go to position in variable 'pos'
  23.     delay(15);                       // waits 15ms for the servo to reach the position
  24.   }
  25. }
复制代码




作者: eagler8    时间: 2020-11-11 16:55
实验之四:驱动二只伺服电机(1号与2号舵机)

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:IDE—工具—管理库—搜索“Servo”—安装
  6.   2、实验之四:驱动二只伺服电机(1号与2号舵机)
  7. */

  8. #include <Servo.h>

  9. Servo servo1;   //建立舵机对象servo1
  10. Servo servo2;   //建立舵机对象servo2

  11. int pos = 0;   
  12. void setup() {
  13.   servo1.attach(10);    //servo1对象接在扩展板servo1端口。
  14.                         //servo1端口是由Arduino的10号引脚来控制的。
  15.   servo2.attach(9);     //servo2对象接在扩展板servo2端口。
  16.                         //servo2端口是由Arduino的9号引脚来控制的。
  17. }

  18. void loop() {
  19.   //以下程序将控制servo1输出轴左右旋转180度
  20.   for (pos = 0; pos <= 180; pos += 1) {
  21.     servo1.write(pos);              
  22.     delay(15);                       
  23.   }
  24.   for (pos = 180; pos >= 0; pos -= 1) {
  25.     servo1.write(pos);   
  26.     delay(15);      
  27.   }
  28.   
  29.   //以下程序将控制servo2输出轴左右旋转180度
  30.   for (pos = 0; pos <= 180; pos += 1) {
  31.     servo2.write(pos);              
  32.     delay(15);                       
  33.   }
  34.   for (pos = 180; pos >= 0; pos -= 1) {
  35.     servo2.write(pos);   
  36.     delay(15);      
  37.   }  
  38. }
复制代码




作者: eagler8    时间: 2020-11-11 17:12
Servo库
允许Arduino / Genuino开发板控制各种伺服电机(舵机)。 该库可以控制大量的伺服器。它仔细使用了计时器:该库仅使用1个计时器就可以控制12个伺服器。在Arduino Due上,最多可以控制60个伺服器。
该库与avr,megaavr,sam,samd,nrf52,stm32f4,mbed 架构兼容。要使用此库,请在Arduino IDE中打开库管理器,然后从那里安装它。

该库允许Arduino开发板控制RC(业余)伺服电机。伺服系统具有集成的齿轮和可精确控制的轴。标准伺服器允许将轴以各种角度定位,通常在0到180度之间。连续旋转伺服器允许将轴的旋转设置为各种速度。

伺服库在大多数Arduino板上最多支持12个电机,在Arduino Mega上最多支持48个电机。在Mega以外的板上,使用该库会禁用analogWrite()引脚9和10上的(PWM)功能,无论这些引脚上是否有Servo。在Mega上,最多可以使用12个伺服器,而不会影响PWM功能。使用12到23个电机将禁用引脚11和12上的PWM。

要使用此库:

#include <Servo.h>

电路图
伺服电机(舵机)有三根电线:电源线,地线和信号线。电源线通常为红色,应连接至Arduino板上的5V引脚。接地线通常为黑色或棕色,应连接至Arduino板上的接地引脚。信号引脚通常为黄色,橙色或白色,应连接至Arduino板上的数字引脚。请注意,伺服器消耗的功率很大,因此如果需要驱动一两个以上,则可能需要使用单独的电源(即,不是Arduino上的+ 5V引脚)为它们供电。确保将Arduino的接地和外部电源连接在一起。





作者: eagler8    时间: 2020-11-11 18:39
使用Servo库
1、Servo-attach()函数(连接)
将伺服变量附加到引脚上。请注意,在Arduino 0016及更早版本中,Servo库仅在两个引脚上仅支持舵机:9和10。

句法
servo.attach(pin)
servo.attach(pin, min, max)

参量
伺服:类型变量Servo
pin:伺服器连接的引脚号
min(可选):脉冲宽度(以微秒为单位),对应于伺服器上的最小(0度)角度(默认为544)
最大(可选):脉冲宽度(以微秒为单位),对应于伺服器上的最大(180度)角度(默认为2400)


#include <Servo.h>
Servo myservo;
void setup()
{
  myservo.attach(9);
}
void loop() {}

2、Servo-write(x)函数(写入)
将值写入伺服器,从而相应地控制轴。在标准伺服器上,这将设置轴的角度(以度为单位),将轴移动到该方向。在连续旋转伺服系统(360度舵机)上,这将设置伺服系统的速度(0表示一个方向的全速,180表示另一方向的全速,而90左右的值表示无运动)。

句法
servo.write(angle)

参量
伺服:伺服类型的变量
angle:写入伺服的值,从0到180


#include <Servo.h>
Servo myservo;
void setup()
{
  myservo.attach(9);
  myservo.write(90);  // set servo to mid-point
}
void loop() {}


作者: eagler8    时间: 2020-11-11 18:40
3、Servo-writeMicroseconds()函数(精确控制)
以微秒(uS)为单位写入一个值,从而相应地控制轴。在标准伺服系统上,这将设置轴的角度。在标准伺服器上,参数值1000完全是逆时针方向,2000完全是顺时针方向,中间是1500。

请注意,某些制造商并未非常严格地遵循此标准,因此,伺服器通常会对700到2300之间的值做出响应。可以随意增加这些端点,直到伺服器不再继续增加其范围为止。但是请注意,尝试将伺服驱动器驱动通过其端点(通常由嘶嘶声表示)是高电流状态,应避免使用。连续旋转伺服器将以类似于写入功能的方式响应writeMicrosecond功能。

句法
servo.writeMicroseconds(uS)

参量
伺服:伺服类型的变量
us:参数值(以微秒为单位)(int)


#include <Servo.h>

Servo myservo;

void setup()
{
  myservo.attach(9);
  myservo.writeMicroseconds(1500);  // set servo to mid-point
}

void loop() {}


4、Servo-read()函数(读取)
读取伺服器的当前角度(该值传递给对write()的最后一次调用)。

句法
servo.read()

参量
伺服:类型变量Servo
反馈
伺服角度为0到180度。


5、Servo-Attached()函数(附加)
检查是否将Servo变量附加到引脚上。

句法
servo.attached()

参量
伺服:类型变量Servo
反馈
true如果伺服系统连接到引脚上;false除此以外。

6、Servo-detach()函数(分离)
从其引脚上拆下伺服变量。如果所有伺服变量均已分离,则可以使用AnalogWrite()将引脚9和10用于PWM输出。

句法
servo.detach()

参量
伺服:类型变量Servo


作者: eagler8    时间: 2020-11-11 19:16
驱动28BYJ-48步进电机
AFMotor电机扩展板最多可以驱动2个28BYJ-48步进电机。以下我们将给您介绍两种电机扩展板的使用方法。第一种是在您开发项目时的使用方法,第二种是项目开发完毕后,在使用扩展板驱动电机工作时的方法。这两种方法最大的区别在于:开发时的Arduino开发板是通过USB数据线连接在电脑上的。但是在工作时开发板是不连接电脑的。

步进电机可以用来精确控制,很适合用于许多机器人或者CNC制作。这个电机驱动板做多支持2个步进电机。双极性和单极性电机都适合这个库。对于双极性电机(42二相四线电机):其中由两相,相1的两线连接到驱动板上的M1或者M3,相2的两线连接到驱动板上对于的M2或者M4上。运转一个步进电机比运转一个直流电机稍微复杂些,但总体还是比较简单的。





作者: eagler8    时间: 2020-11-11 19:30
  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
  6.   2、实验之五:驱动28BYJ-48步进电机
  7. */

  8. #include <AFMotor.h> // 本程序中使用AFMotor库

  9. AF_Stepper motor1(2048, 1);  // 这2条语句的作用是建立2个步进电机对象,它们的名称分别是:motor1/2。
  10. AF_Stepper motor2(2048, 2);  // 对象名称后面括号中的两个参数分别代表了步进电机旋转一周的步数以及
  11.                               // 步进电机连接在扩展板上的端口号。如AF_Stepper motor1(2048, 1)语句中
  12.                               // 参数2048代表motor1旋转一周需要走2048步。假如您的电机旋转一周需要32步,
  13.                               // 那么请在第一个参数位置输入32这一数字参数。
  14.                               // 括号中第二个参数1代表motor1连接在M1和M2端口。
  15.                               // 对于motor2对象,它括号中的参数2代表该电机连接在M3和M4端口。

  16. void setup() {
  17.   Serial.begin(9600);         //启动串口通讯
  18.   
  19.   motor1.setSpeed(10);        // 这2条语句的作用是通过setSpped库函数设置电机运行速度。
  20.   motor2.setSpeed(10);        // setSpped库函数中的参数是运行速度参数。
  21.                               // 速度参数越大,运转速度越快。参数为0时电机停止转动。
  22. }

  23. /*
  24. 以下的loop函数中有4段程序语句。它们的内容十分类似,主要语句都是是通过step库函数来控制
  25. 步进电机的运行模式。step库函数一共有3个参数。如loop函数的第二行语句:motor1.step(2048, FORWARD, SINGLE)。
  26. 括号中的第一个参数是控制电机走的步数,这里的参数2048就是让电机走2048步。
  27. 接下来的关键字参数"FORWARD"作用是控制电机旋转方向。"FORWARD"是控制电机"正转",
  28. 这里也可以使用关键字"BACKWARD"让电机"反转"。
  29. 最后一个关键字参数是用于控制步进电机运转模式的。这里可选的关键字参数有:
  30. SINGLE - 全步进模式(单线圈)。电机每走一步,扩展板只给一相线圈供电。
  31. DOUBLE - 全步进模式(双线圈)。电机每走一步,扩展板会同时给两相线圈供电。
  32.          此模式运行的电机比SINGLE模式下的扭矩要更大,但是电机耗电也会更多。
  33. INTERLEAVE - 半步进模式。这种模式是SINGLE和DOUBLE的混合。电机每走一步,扩展板对线圈供电方式
  34.              在一相和两相之间交替切换。举例来说,电机走第一步时,只有一相线圈通电。
  35.              走第二步时,会有两相线圈供电,然后又是一相,再两相......这样交替通电。
  36.              这种控制模式的优点是电机运行更流畅,但是缺点是运行速度大打折扣。
  37. MICROSTEP - 微步进模式。此模式下的电机运行更光滑,但缺点是扭矩会打折扣。   
  38. */

  39. void loop() {
  40.   Serial.println("Single Mode");        //串口监视器输出当前运行模式为“Single”
  41.   motor1.step(2048, FORWARD, SINGLE);    //步进电机以SINGLE模式"正转"2048步
  42.   motor1.step(2048, BACKWARD, SINGLE);   //步进电机以SINGLE模式"反转"2048步

  43.   Serial.println("Double Mode");        //串口监视器输出当前运行模式为“Double”
  44.   motor2.step(2048, FORWARD, DOUBLE);    //步进电机以DOUBLE模式"正转"2048步
  45.   motor2.step(2048, BACKWARD, DOUBLE);   //步进电机以DOUBLE模式"反转"2048步

  46.   Serial.println("Interleave Mode");        //串口监视器输出当前运行模式为“Interleave”
  47.   motor1.step(2048, FORWARD, INTERLEAVE);    //步进电机以INTERLEAVE模式"正转"2048步
  48.   motor1.step(2048, BACKWARD, INTERLEAVE);   //步进电机以INTERLEAVE模式"反转"2048步

  49.   Serial.println("Micrsostep Mode");         //串口监视器输出当前运行模式为“Micrsostep”
  50.   motor2.step(2048, FORWARD, MICROSTEP);      //步进电机以MICROSTEP模式"正转"2048步
  51.   motor2.step(2048, BACKWARD, MICROSTEP);     //步进电机以MICROSTEP模式"反转"2048步
  52. }
复制代码



作者: eagler8    时间: 2020-11-11 19:37
与步进电机有关的函数
确保导入AFMotor库文件并#include < AFMotor.h>后,有这么几个函数需要用到

1、AF_Stepper steppername(steps,portnumber)
(1)steppername
给电机起个名字,然后这个名字就是此电机在程序中的代号了
(2)steps
设置电机每转的步数,比如设置36,则每步走1/36转
(3)portnumber
选择电机的通道,范围为1(通道1,2)和2(通道3和4)

2、Step(steps,direction,style)
(1)step
转动的步数
(2)direction
转动的方向FORWARD 或者 BACKWARD
(3)style
步进的模式,可以选择的参数:
a\SINGLE - 一次只给一相线圈供电
b\DOUBLE - 一次给两项项圈都供电,得到更大的扭矩
c\INTERLEAVE - 电机会运转得更柔滑,因为步数增加了一倍,同时速度也减小一半
d\MICROSTEP - 电机会运转的更柔滑,精度更高,但扭矩也会减小

如果想更精细地控制步进电机,可以使用AccelStepper library,这个库带有电机加减速度功能。


作者: eagler8    时间: 2020-11-12 19:38
  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
  6.   2、实验之六:连接每转48步(7.5度)的步进电机,电机端口2#(M3和M4)
  7. */

  8. #include <AFMotor.h>

  9. // Connect a stepper motor with 48 steps per revolution (7.5 degree)
  10. // to motor port #2 (M3 and M4)
  11. AF_Stepper motor(48, 2);

  12. void setup() {
  13.   Serial.begin(9600);           // set up Serial library at 9600 bps
  14.   Serial.println("Stepper test! 测试步进电机!");

  15.   motor.setSpeed(10);  // 10 rpm
  16. }

  17. void loop() {
  18.   Serial.println("Single coil steps 单线圈步");
  19.   motor.step(100, FORWARD, SINGLE);
  20.   motor.step(100, BACKWARD, SINGLE);

  21.   Serial.println("Double coil steps 双线圈步");
  22.   motor.step(100, FORWARD, DOUBLE);
  23.   motor.step(100, BACKWARD, DOUBLE);

  24.   Serial.println("Interleave coil steps 交错线圈台阶");
  25.   motor.step(100, FORWARD, INTERLEAVE);
  26.   motor.step(100, BACKWARD, INTERLEAVE);

  27.   Serial.println("Micrsostep steps 微步前进");
  28.   motor.step(100, FORWARD, MICROSTEP);
  29.   motor.step(100, BACKWARD, MICROSTEP);
  30. }
复制代码



作者: eagler8    时间: 2020-11-12 19:41


作者: eagler8    时间: 2020-11-12 20:26
使用Arduino AFMotor驱动四只直流电机

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
  6.   2、实验之七:使用Arduino AFMotor驱动四只直流电机
  7. */

  8. #include <AFMotor.h> // 本程序中使用AFMotor库

  9. AF_DCMotor motor1(1); // 这4条语句的作用是建立4个直流电机对象,它们的名称分别是:motor1/2/3/4.
  10. AF_DCMotor motor2(2); // 这四条语句括号中的数字代表各个电机对象所连接在AFMotor扩展板的电机端口号码。
  11. AF_DCMotor motor3(3); // AF_DCMotor motor1(1); 代表motor1对象连接在AFMotor扩展板的M1端口上。
  12. AF_DCMotor motor4(4); // AFMotor电机扩展板最多可以驱动4个直流电机,最少可以驱动1个直流电机。

  13. void setup() {
  14.   motor1.setSpeed(200); // 这4条语句的作用是通过setSpped库函数设置电机运行速度。
  15.   motor2.setSpeed(200); // setSpped库函数中的参数是运行速度参数。
  16.   motor3.setSpeed(200); // 运行速度参数允许范围是0~255。
  17.   motor4.setSpeed(200); // 速度参数越大,运转速度越快。参数为0时电机停止转动。

  18.   motor1.run(RELEASE); // 这4条语句的作用是让4个电机在启动时停止转动
  19.   motor2.run(RELEASE); // run库函数允许使用的关键字参数有RELEASE、FORWARD、BACKWARD
  20.   motor3.run(RELEASE); // 使用关键字RELEASE作为参数使用时,run库函数将会让扩展板停止提供电机运转动力
  21.   motor4.run(RELEASE); // 电机旋转一旦失去动力就会自然的停止转动。
  22. }

  23. void loop() {
  24.   motor1.run(FORWARD); // 这4条语句的作用是利用run库函数控制4个电机"正向"旋转。
  25.   motor2.run(FORWARD); // 这里所谓的“正向”旋转只是一种说法,假如您发现电机旋转方向和您所要的“正向”不一致。
  26.   motor3.run(FORWARD); // 您可以将电机的两个引线从扩展板上断开,然后交换顺序再接到扩展板接口上
  27.   motor4.run(FORWARD); // 这时您会看到同样使用FORWARD关键字作为run库函数的参数,电机的旋转方向却反过来了。

  28.   for (int i = 0; i <= 255; i++) { // 这里使用for循环语句控制4个电机速度由停止逐步加速,最终电机运转达到最大速度。
  29.     motor1.setSpeed(i);          // 在for循环语句的作用下,setSpeed库函数的速度参数i由0逐渐增大,最终达到255。
  30.     motor2.setSpeed(i);          // 因此电机运行速度也是由停止逐渐加速,最终达到最大速度。
  31.     motor3.setSpeed(i);          // 对于一些模型电机来说,当速度参数小于一定数值以后就不能转动了。也就是说,也许您的电机
  32.     motor4.setSpeed(i);          // 在速度参数在小于某一个速度参数数值的时候就无法转动了。这属于正常现象。
  33.     delay(10);                   // 具体这个最小值是多少,对于不同的电机来说是不同的。有的可能是50也有的可能是100。
  34.   }                               // 换句话说,很可能您的某一个直流电机在速度参数小于50的情况下就无法转动了。
  35.   // 也可能您的另一个直流电机在参数100以下的情况下就无法转动了。

  36.   for (int i = 255; i >= 0; i--) { // 这里使用for循环语句控制4个电机由最大旋转速度逐步减速最终停止旋转。
  37.     motor1.setSpeed(i);          // 这一系列语句的操作与上一段for循环语句类似。唯一区别是上一段for循环控制速度参数i由0涨到255
  38.     motor2.setSpeed(i);          // 而这一段语句控制速度参数i由255减小到0。同样您可能会发现当速度参数没有减小到零的时候,电机就已经
  39.     motor3.setSpeed(i);          // 停止旋转了。这其中的原因在上一段for循环语句中已经介绍了。不在这里赘述了。
  40.     motor4.setSpeed(i);
  41.     delay(10);
  42.   }

  43.   motor1.run(BACKWARD); // 这4条语句的作用是利用run库函数控制4个电机"反向"旋转。
  44.   motor2.run(BACKWARD); // 同样的,这里所谓的“反向”旋转也只是一种说法。这部分程序内容
  45.   motor3.run(BACKWARD); // 与本程序33-36行中的内容十分类似。唯一区别就是使用了“BACKWARD”
  46.   motor4.run(BACKWARD); // 关键字参数来通过库函数run控制电机“反向”旋转。

  47.   for (int i = 0; i <= 255; i++) { // 利用for循环语句控制速度参数i由小到大
  48.     motor1.setSpeed(i);          // 电机也会以“反向”旋转的方式由停止逐步达到最大速度
  49.     motor2.setSpeed(i);
  50.     motor3.setSpeed(i);
  51.     motor4.setSpeed(i);
  52.     delay(10);
  53.   }

  54.   for (int i = 255; i >= 0; i--) { // 利用for循环语句控制速度参数i由大到小
  55.     motor1.setSpeed(i);          // 电机也会以“反向”旋转的方式由最大速度逐步减小到停止
  56.     motor2.setSpeed(i);
  57.     motor3.setSpeed(i);
  58.     motor4.setSpeed(i);
  59.     delay(10);
  60.   }

  61.   motor1.run(RELEASE);   // 这四条语句作用是使用关键字RELEASE作为run函数的参数。
  62.   motor2.run(RELEASE);   // 在这种情况下,AFMotor扩展板将会停止为电机旋转提供动力。
  63.   motor3.run(RELEASE);   // 电机也就会自然的停止转动。
  64.   motor4.run(RELEASE);   // 本段程序后面的delay(1000)的作用就是让4个电机保持无旋转动力状态1秒钟

  65.   delay(1000);
  66. }
复制代码




作者: eagler8    时间: 2020-11-13 08:07
Arduino AFMotor 电机扩展板实验场景图




作者: eagler8    时间: 2020-11-13 08:59
附录:AFMotor.h库文件
目录—adafruit/Adafruit-Motor-Shield-library
链接—https://github.com/adafruit/Adaf ... ob/master/AFMotor.h

  1. // Adafruit Motor shield library
  2. // copyright Adafruit Industries LLC, 2009
  3. // this code is public domain, enjoy!

  4. /*
  5. * Usage Notes:
  6. * For PIC32, all features work properly with the following two exceptions:
  7. *
  8. * 1) Because the PIC32 only has 5 PWM outputs, and the AFMotor shield needs 6
  9. *    to completely operate (four for motor outputs and two for RC servos), the
  10. *    M1 motor output will not have PWM ability when used with a PIC32 board.
  11. *    However, there is a very simple workaround. If you need to drive a stepper
  12. *    or DC motor with PWM on motor output M1, you can use the PWM output on pin
  13. *    9 or pin 10 (normally use for RC servo outputs on Arduino, not needed for
  14. *    RC servo outputs on PIC32) to drive the PWM input for M1 by simply putting
  15. *    a jumber from pin 9 to pin 11 or pin 10 to pin 11. Then uncomment one of the
  16. *    two #defines below to activate the PWM on either pin 9 or pin 10. You will
  17. *    then have a fully functional microstepping for 2 stepper motors, or four
  18. *    DC motor outputs with PWM.
  19. *
  20. * 2) There is a conflict between RC Servo outputs on pins 9 and pins 10 and
  21. *    the operation of DC motors and stepper motors as of 9/2012. This issue
  22. *    will get fixed in future MPIDE releases, but at the present time it means
  23. *    that the Motor Party example will NOT work properly. Any time you attach
  24. *    an RC servo to pins 9 or pins 10, ALL PWM outputs on the whole board will
  25. *    stop working. Thus no steppers or DC motors.
  26. *
  27. */
  28. // <BPS> 09/15/2012 Modified for use with chipKIT boards


  29. #ifndef _AFMotor_h_
  30. #define _AFMotor_h_

  31. #include <inttypes.h>
  32. #if defined(__AVR__)
  33.     #include <avr/io.h>

  34.     //#define MOTORDEBUG 1

  35.     #define MICROSTEPS 16                       // 8 or 16

  36.     #define MOTOR12_64KHZ _BV(CS20)             // no prescale
  37.     #define MOTOR12_8KHZ _BV(CS21)              // divide by 8
  38.     #define MOTOR12_2KHZ _BV(CS21) | _BV(CS20)  // divide by 32
  39.     #define MOTOR12_1KHZ _BV(CS22)              // divide by 64

  40.     #define MOTOR34_64KHZ _BV(CS00)             // no prescale
  41.     #define MOTOR34_8KHZ _BV(CS01)              // divide by 8
  42.     #define MOTOR34_1KHZ _BV(CS01) | _BV(CS00)  // divide by 64
  43.    
  44.     #define DC_MOTOR_PWM_RATE   MOTOR34_8KHZ    // PWM rate for DC motors
  45.     #define STEPPER1_PWM_RATE   MOTOR12_64KHZ   // PWM rate for stepper 1
  46.     #define STEPPER2_PWM_RATE   MOTOR34_64KHZ   // PWM rate for stepper 2
  47.    
  48. #elif defined(__PIC32MX__)
  49.     //#define MOTORDEBUG 1
  50.    
  51.     // Uncomment the one of following lines if you have put a jumper from
  52.     // either pin 9 to pin 11 or pin 10 to pin 11 on your Motor Shield.
  53.     // Either will enable PWM for M1
  54.     //#define PIC32_USE_PIN9_FOR_M1_PWM
  55.     //#define PIC32_USE_PIN10_FOR_M1_PWM

  56.     #define MICROSTEPS 16       // 8 or 16

  57.     // For PIC32 Timers, define prescale settings by PWM frequency
  58.     #define MOTOR12_312KHZ  0   // 1:1, actual frequency 312KHz
  59.     #define MOTOR12_156KHZ  1   // 1:2, actual frequency 156KHz
  60.     #define MOTOR12_64KHZ   2   // 1:4, actual frequency 78KHz
  61.     #define MOTOR12_39KHZ   3   // 1:8, acutal frequency 39KHz
  62.     #define MOTOR12_19KHZ   4   // 1:16, actual frequency 19KHz
  63.     #define MOTOR12_8KHZ    5   // 1:32, actual frequency 9.7KHz
  64.     #define MOTOR12_4_8KHZ  6   // 1:64, actual frequency 4.8KHz
  65.     #define MOTOR12_2KHZ    7   // 1:256, actual frequency 1.2KHz
  66.     #define MOTOR12_1KHZ    7   // 1:256, actual frequency 1.2KHz

  67.     #define MOTOR34_312KHZ  0   // 1:1, actual frequency 312KHz
  68.     #define MOTOR34_156KHZ  1   // 1:2, actual frequency 156KHz
  69.     #define MOTOR34_64KHZ   2   // 1:4, actual frequency 78KHz
  70.     #define MOTOR34_39KHZ   3   // 1:8, acutal frequency 39KHz
  71.     #define MOTOR34_19KHZ   4   // 1:16, actual frequency 19KHz
  72.     #define MOTOR34_8KHZ    5   // 1:32, actual frequency 9.7KHz
  73.     #define MOTOR34_4_8KHZ  6   // 1:64, actual frequency 4.8KHz
  74.     #define MOTOR34_2KHZ    7   // 1:256, actual frequency 1.2KHz
  75.     #define MOTOR34_1KHZ    7   // 1:256, actual frequency 1.2KHz
  76.    
  77.     // PWM rate for DC motors.
  78.     #define DC_MOTOR_PWM_RATE   MOTOR34_39KHZ
  79.     // Note: for PIC32, both of these must be set to the same value
  80.     // since there's only one timebase for all 4 PWM outputs
  81.     #define STEPPER1_PWM_RATE   MOTOR12_39KHZ
  82.     #define STEPPER2_PWM_RATE   MOTOR34_39KHZ
  83.    
  84. #endif

  85. // Bit positions in the 74HCT595 shift register output
  86. #define MOTOR1_A 2
  87. #define MOTOR1_B 3
  88. #define MOTOR2_A 1
  89. #define MOTOR2_B 4
  90. #define MOTOR4_A 0
  91. #define MOTOR4_B 6
  92. #define MOTOR3_A 5
  93. #define MOTOR3_B 7

  94. // Constants that the user passes in to the motor calls
  95. #define FORWARD 1
  96. #define BACKWARD 2
  97. #define BRAKE 3
  98. #define RELEASE 4

  99. // Constants that the user passes in to the stepper calls
  100. #define SINGLE 1
  101. #define DOUBLE 2
  102. #define INTERLEAVE 3
  103. #define MICROSTEP 4

  104. /*
  105. #define LATCH 4
  106. #define LATCH_DDR DDRB
  107. #define LATCH_PORT PORTB
  108. #define CLK_PORT PORTD
  109. #define CLK_DDR DDRD
  110. #define CLK 4
  111. #define ENABLE_PORT PORTD
  112. #define ENABLE_DDR DDRD
  113. #define ENABLE 7
  114. #define SER 0
  115. #define SER_DDR DDRB
  116. #define SER_PORT PORTB
  117. */

  118. // Arduino pin names for interface to 74HCT595 latch
  119. #define MOTORLATCH 12
  120. #define MOTORCLK 4
  121. #define MOTORENABLE 7
  122. #define MOTORDATA 8

  123. class AFMotorController
  124. {
  125.   public:
  126.     AFMotorController(void);
  127.     void enable(void);
  128.     friend class AF_DCMotor;
  129.     void latch_tx(void);
  130.     uint8_t TimerInitalized;
  131. };

  132. class AF_DCMotor
  133. {
  134. public:
  135.   AF_DCMotor(uint8_t motornum, uint8_t freq = DC_MOTOR_PWM_RATE);
  136.   void run(uint8_t);
  137.   void setSpeed(uint8_t);

  138. private:
  139.   uint8_t motornum, pwmfreq;
  140. };

  141. class AF_Stepper {
  142. public:
  143.   AF_Stepper(uint16_t, uint8_t);
  144.   void step(uint16_t steps, uint8_t dir,  uint8_t style = SINGLE);
  145.   void setSpeed(uint16_t);
  146.   uint8_t onestep(uint8_t dir, uint8_t style);
  147.   void release(void);
  148.   uint16_t revsteps; // # steps per revolution
  149.   uint8_t steppernum;
  150.   uint32_t usperstep, steppingcounter;
  151. private:
  152.   uint8_t currentstep;

  153. };

  154. uint8_t getlatchstate(void);

  155. #endif
复制代码





作者: eagler8    时间: 2020-11-13 09:04

附录:AFMotor.cpp库文件
目录—adafruit/Adafruit-Motor-Shield-library
链接—https://github.com/adafruit/Adaf ... /master/AFMotor.cpp


  1. // Adafruit Motor shield library
  2. // copyright Adafruit Industries LLC, 2009
  3. // this code is public domain, enjoy!


  4. #if (ARDUINO >= 100)
  5.   #include "Arduino.h"
  6. #else
  7.   #if defined(__AVR__)
  8.     #include <avr/io.h>
  9.   #endif
  10.   #include "WProgram.h"
  11. #endif

  12. #include "AFMotor.h"



  13. static uint8_t latch_state;

  14. #if (MICROSTEPS == 8)
  15. uint8_t microstepcurve[] = {0, 50, 98, 142, 180, 212, 236, 250, 255};
  16. #elif (MICROSTEPS == 16)
  17. uint8_t microstepcurve[] = {0, 25, 50, 74, 98, 120, 141, 162, 180, 197, 212, 225, 236, 244, 250, 253, 255};
  18. #endif

  19. AFMotorController::AFMotorController(void) {
  20.     TimerInitalized = false;
  21. }

  22. void AFMotorController::enable(void) {
  23.   // setup the latch
  24.   /*
  25.   LATCH_DDR |= _BV(LATCH);
  26.   ENABLE_DDR |= _BV(ENABLE);
  27.   CLK_DDR |= _BV(CLK);
  28.   SER_DDR |= _BV(SER);
  29.   */
  30.   pinMode(MOTORLATCH, OUTPUT);
  31.   pinMode(MOTORENABLE, OUTPUT);
  32.   pinMode(MOTORDATA, OUTPUT);
  33.   pinMode(MOTORCLK, OUTPUT);

  34.   latch_state = 0;

  35.   latch_tx();  // "reset"

  36.   //ENABLE_PORT &= ~_BV(ENABLE); // enable the chip outputs!
  37.   digitalWrite(MOTORENABLE, LOW);
  38. }


  39. void AFMotorController::latch_tx(void) {
  40.   uint8_t i;

  41.   //LATCH_PORT &= ~_BV(LATCH);
  42.   digitalWrite(MOTORLATCH, LOW);

  43.   //SER_PORT &= ~_BV(SER);
  44.   digitalWrite(MOTORDATA, LOW);

  45.   for (i=0; i<8; i++) {
  46.     //CLK_PORT &= ~_BV(CLK);
  47.     digitalWrite(MOTORCLK, LOW);

  48.     if (latch_state & _BV(7-i)) {
  49.       //SER_PORT |= _BV(SER);
  50.       digitalWrite(MOTORDATA, HIGH);
  51.     } else {
  52.       //SER_PORT &= ~_BV(SER);
  53.       digitalWrite(MOTORDATA, LOW);
  54.     }
  55.     //CLK_PORT |= _BV(CLK);
  56.     digitalWrite(MOTORCLK, HIGH);
  57.   }
  58.   //LATCH_PORT |= _BV(LATCH);
  59.   digitalWrite(MOTORLATCH, HIGH);
  60. }

  61. static AFMotorController MC;

  62. /******************************************
  63.                MOTORS
  64. ******************************************/
  65. inline void initPWM1(uint8_t freq) {
  66. #if defined(__AVR_ATmega8__) || \
  67.     defined(__AVR_ATmega48__) || \
  68.     defined(__AVR_ATmega88__) || \
  69.     defined(__AVR_ATmega168__) || \
  70.     defined(__AVR_ATmega328P__)
  71.     // use PWM from timer2A on PB3 (Arduino pin #11)
  72.     TCCR2A |= _BV(COM2A1) | _BV(WGM20) | _BV(WGM21); // fast PWM, turn on oc2a
  73.     TCCR2B = freq & 0x7;
  74.     OCR2A = 0;
  75. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  76.     // on arduino mega, pin 11 is now PB5 (OC1A)
  77.     TCCR1A |= _BV(COM1A1) | _BV(WGM10); // fast PWM, turn on oc1a
  78.     TCCR1B = (freq & 0x7) | _BV(WGM12);
  79.     OCR1A = 0;
  80. #elif defined(__PIC32MX__)
  81.     #if defined(PIC32_USE_PIN9_FOR_M1_PWM)
  82.         // Make sure that pin 11 is an input, since we have tied together 9 and 11
  83.         pinMode(9, OUTPUT);
  84.         pinMode(11, INPUT);
  85.         if (!MC.TimerInitalized)
  86.         {   // Set up Timer2 for 80MHz counting fro 0 to 256
  87.             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
  88.             TMR2 = 0x0000;
  89.             PR2 = 0x0100;
  90.             MC.TimerInitalized = true;
  91.         }
  92.          // Setup OC4 (pin 9) in PWM mode, with Timer2 as timebase
  93.         OC4CON = 0x8006;    // OC32 = 0, OCTSEL=0, OCM=6
  94.         OC4RS = 0x0000;
  95.         OC4R = 0x0000;
  96.     #elif defined(PIC32_USE_PIN10_FOR_M1_PWM)
  97.         // Make sure that pin 11 is an input, since we have tied together 9 and 11
  98.         pinMode(10, OUTPUT);
  99.         pinMode(11, INPUT);
  100.         if (!MC.TimerInitalized)
  101.         {   // Set up Timer2 for 80MHz counting fro 0 to 256
  102.             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
  103.             TMR2 = 0x0000;
  104.             PR2 = 0x0100;
  105.             MC.TimerInitalized = true;
  106.         }
  107.          // Setup OC5 (pin 10) in PWM mode, with Timer2 as timebase
  108.         OC5CON = 0x8006;    // OC32 = 0, OCTSEL=0, OCM=6
  109.         OC5RS = 0x0000;
  110.         OC5R = 0x0000;
  111.     #else
  112.         // If we are not using PWM for pin 11, then just do digital
  113.         digitalWrite(11, LOW);
  114.     #endif
  115. #else
  116.    #error "This chip is not supported!"
  117. #endif
  118.     #if !defined(PIC32_USE_PIN9_FOR_M1_PWM) && !defined(PIC32_USE_PIN10_FOR_M1_PWM)
  119.         pinMode(11, OUTPUT);
  120.     #endif
  121. }

  122. inline void setPWM1(uint8_t s) {
  123. #if defined(__AVR_ATmega8__) || \
  124.     defined(__AVR_ATmega48__) || \
  125.     defined(__AVR_ATmega88__) || \
  126.     defined(__AVR_ATmega168__) || \
  127.     defined(__AVR_ATmega328P__)
  128.     // use PWM from timer2A on PB3 (Arduino pin #11)
  129.     OCR2A = s;
  130. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  131.     // on arduino mega, pin 11 is now PB5 (OC1A)
  132.     OCR1A = s;
  133. #elif defined(__PIC32MX__)
  134.     #if defined(PIC32_USE_PIN9_FOR_M1_PWM)
  135.         // Set the OC4 (pin 9) PMW duty cycle from 0 to 255
  136.         OC4RS = s;
  137.     #elif defined(PIC32_USE_PIN10_FOR_M1_PWM)
  138.         // Set the OC5 (pin 10) PMW duty cycle from 0 to 255
  139.         OC5RS = s;
  140.     #else
  141.         // If we are not doing PWM output for M1, then just use on/off
  142.         if (s > 127)
  143.         {
  144.             digitalWrite(11, HIGH);
  145.         }
  146.         else
  147.         {
  148.             digitalWrite(11, LOW);
  149.         }
  150.     #endif
  151. #else
  152.    #error "This chip is not supported!"
  153. #endif
  154. }

  155. inline void initPWM2(uint8_t freq) {
  156. #if defined(__AVR_ATmega8__) || \
  157.     defined(__AVR_ATmega48__) || \
  158.     defined(__AVR_ATmega88__) || \
  159.     defined(__AVR_ATmega168__) || \
  160.     defined(__AVR_ATmega328P__)
  161.     // use PWM from timer2B (pin 3)
  162.     TCCR2A |= _BV(COM2B1) | _BV(WGM20) | _BV(WGM21); // fast PWM, turn on oc2b
  163.     TCCR2B = freq & 0x7;
  164.     OCR2B = 0;
  165. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  166.     // on arduino mega, pin 3 is now PE5 (OC3C)
  167.     TCCR3A |= _BV(COM1C1) | _BV(WGM10); // fast PWM, turn on oc3c
  168.     TCCR3B = (freq & 0x7) | _BV(WGM12);
  169.     OCR3C = 0;
  170. #elif defined(__PIC32MX__)
  171.     if (!MC.TimerInitalized)
  172.     {   // Set up Timer2 for 80MHz counting fro 0 to 256
  173.         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
  174.         TMR2 = 0x0000;
  175.         PR2 = 0x0100;
  176.         MC.TimerInitalized = true;
  177.     }
  178.     // Setup OC1 (pin3) in PWM mode, with Timer2 as timebase
  179.     OC1CON = 0x8006;    // OC32 = 0, OCTSEL=0, OCM=6
  180.     OC1RS = 0x0000;
  181.     OC1R = 0x0000;
  182. #else
  183.    #error "This chip is not supported!"
  184. #endif

  185.     pinMode(3, OUTPUT);
  186. }

  187. inline void setPWM2(uint8_t s) {
  188. #if defined(__AVR_ATmega8__) || \
  189.     defined(__AVR_ATmega48__) || \
  190.     defined(__AVR_ATmega88__) || \
  191.     defined(__AVR_ATmega168__) || \
  192.     defined(__AVR_ATmega328P__)
  193.     // use PWM from timer2A on PB3 (Arduino pin #11)
  194.     OCR2B = s;
  195. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  196.     // on arduino mega, pin 11 is now PB5 (OC1A)
  197.     OCR3C = s;
  198. #elif defined(__PIC32MX__)
  199.     // Set the OC1 (pin3) PMW duty cycle from 0 to 255
  200.     OC1RS = s;
  201. #else
  202.    #error "This chip is not supported!"
  203. #endif
  204. }

  205. inline void initPWM3(uint8_t freq) {
  206. #if defined(__AVR_ATmega8__) || \
  207.     defined(__AVR_ATmega48__) || \
  208.     defined(__AVR_ATmega88__) || \
  209.     defined(__AVR_ATmega168__) || \
  210.     defined(__AVR_ATmega328P__)
  211.     // use PWM from timer0A / PD6 (pin 6)
  212.     TCCR0A |= _BV(COM0A1) | _BV(WGM00) | _BV(WGM01); // fast PWM, turn on OC0A
  213.     //TCCR0B = freq & 0x7;
  214.     OCR0A = 0;
  215. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  216.     // on arduino mega, pin 6 is now PH3 (OC4A)
  217.     TCCR4A |= _BV(COM1A1) | _BV(WGM10); // fast PWM, turn on oc4a
  218.     TCCR4B = (freq & 0x7) | _BV(WGM12);
  219.     //TCCR4B = 1 | _BV(WGM12);
  220.     OCR4A = 0;
  221. #elif defined(__PIC32MX__)
  222.     if (!MC.TimerInitalized)
  223.     {   // Set up Timer2 for 80MHz counting fro 0 to 256
  224.         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
  225.         TMR2 = 0x0000;
  226.         PR2 = 0x0100;
  227.         MC.TimerInitalized = true;
  228.     }
  229.     // Setup OC3 (pin 6) in PWM mode, with Timer2 as timebase
  230.     OC3CON = 0x8006;    // OC32 = 0, OCTSEL=0, OCM=6
  231.     OC3RS = 0x0000;
  232.     OC3R = 0x0000;
  233. #else
  234.    #error "This chip is not supported!"
  235. #endif
  236.     pinMode(6, OUTPUT);
  237. }

  238. inline void setPWM3(uint8_t s) {
  239. #if defined(__AVR_ATmega8__) || \
  240.     defined(__AVR_ATmega48__) || \
  241.     defined(__AVR_ATmega88__) || \
  242.     defined(__AVR_ATmega168__) || \
  243.     defined(__AVR_ATmega328P__)
  244.     // use PWM from timer0A on PB3 (Arduino pin #6)
  245.     OCR0A = s;
  246. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  247.     // on arduino mega, pin 6 is now PH3 (OC4A)
  248.     OCR4A = s;
  249. #elif defined(__PIC32MX__)
  250.     // Set the OC3 (pin 6) PMW duty cycle from 0 to 255
  251.     OC3RS = s;
  252. #else
  253.    #error "This chip is not supported!"
  254. #endif
  255. }



  256. inline void initPWM4(uint8_t freq) {
  257. #if defined(__AVR_ATmega8__) || \
  258.     defined(__AVR_ATmega48__) || \
  259.     defined(__AVR_ATmega88__) || \
  260.     defined(__AVR_ATmega168__) || \
  261.     defined(__AVR_ATmega328P__)
  262.     // use PWM from timer0B / PD5 (pin 5)
  263.     TCCR0A |= _BV(COM0B1) | _BV(WGM00) | _BV(WGM01); // fast PWM, turn on oc0a
  264.     //TCCR0B = freq & 0x7;
  265.     OCR0B = 0;
  266. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  267.     // on arduino mega, pin 5 is now PE3 (OC3A)
  268.     TCCR3A |= _BV(COM1A1) | _BV(WGM10); // fast PWM, turn on oc3a
  269.     TCCR3B = (freq & 0x7) | _BV(WGM12);
  270.     //TCCR4B = 1 | _BV(WGM12);
  271.     OCR3A = 0;
  272. #elif defined(__PIC32MX__)
  273.     if (!MC.TimerInitalized)
  274.     {   // Set up Timer2 for 80MHz counting fro 0 to 256
  275.         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
  276.         TMR2 = 0x0000;
  277.         PR2 = 0x0100;
  278.         MC.TimerInitalized = true;
  279.     }
  280.     // Setup OC2 (pin 5) in PWM mode, with Timer2 as timebase
  281.     OC2CON = 0x8006;    // OC32 = 0, OCTSEL=0, OCM=6
  282.     OC2RS = 0x0000;
  283.     OC2R = 0x0000;
  284. #else
  285.    #error "This chip is not supported!"
  286. #endif
  287.     pinMode(5, OUTPUT);
  288. }

  289. inline void setPWM4(uint8_t s) {
  290. #if defined(__AVR_ATmega8__) || \
  291.     defined(__AVR_ATmega48__) || \
  292.     defined(__AVR_ATmega88__) || \
  293.     defined(__AVR_ATmega168__) || \
  294.     defined(__AVR_ATmega328P__)
  295.     // use PWM from timer0A on PB3 (Arduino pin #6)
  296.     OCR0B = s;
  297. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  298.     // on arduino mega, pin 6 is now PH3 (OC4A)
  299.     OCR3A = s;
  300. #elif defined(__PIC32MX__)
  301.     // Set the OC2 (pin 5) PMW duty cycle from 0 to 255
  302.     OC2RS = s;
  303. #else
  304.    #error "This chip is not supported!"
  305. #endif
  306. }

  307. AF_DCMotor::AF_DCMotor(uint8_t num, uint8_t freq) {
  308.   motornum = num;
  309.   pwmfreq = freq;

  310.   MC.enable();

  311.   switch (num) {
  312.   case 1:
  313.     latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B); // set both motor pins to 0
  314.     MC.latch_tx();
  315.     initPWM1(freq);
  316.     break;
  317.   case 2:
  318.     latch_state &= ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // set both motor pins to 0
  319.     MC.latch_tx();
  320.     initPWM2(freq);
  321.     break;
  322.   case 3:
  323.     latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B); // set both motor pins to 0
  324.     MC.latch_tx();
  325.     initPWM3(freq);
  326.     break;
  327.   case 4:
  328.     latch_state &= ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); // set both motor pins to 0
  329.     MC.latch_tx();
  330.     initPWM4(freq);
  331.     break;
  332.   }
  333. }

  334. void AF_DCMotor::run(uint8_t cmd) {
  335.   uint8_t a, b;
  336.   switch (motornum) {
  337.   case 1:
  338.     a = MOTOR1_A; b = MOTOR1_B; break;
  339.   case 2:
  340.     a = MOTOR2_A; b = MOTOR2_B; break;
  341.   case 3:
  342.     a = MOTOR3_A; b = MOTOR3_B; break;
  343.   case 4:
  344.     a = MOTOR4_A; b = MOTOR4_B; break;
  345.   default:
  346.     return;
  347.   }
  348.   
  349.   switch (cmd) {
  350.   case FORWARD:
  351.     latch_state |= _BV(a);
  352.     latch_state &= ~_BV(b);
  353.     MC.latch_tx();
  354.     break;
  355.   case BACKWARD:
  356.     latch_state &= ~_BV(a);
  357.     latch_state |= _BV(b);
  358.     MC.latch_tx();
  359.     break;
  360.   case RELEASE:
  361.     latch_state &= ~_BV(a);     // A and B both low
  362.     latch_state &= ~_BV(b);
  363.     MC.latch_tx();
  364.     break;
  365.   }
  366. }

  367. void AF_DCMotor::setSpeed(uint8_t speed) {
  368.   switch (motornum) {
  369.   case 1:
  370.     setPWM1(speed); break;
  371.   case 2:
  372.     setPWM2(speed); break;
  373.   case 3:
  374.     setPWM3(speed); break;
  375.   case 4:
  376.     setPWM4(speed); break;
  377.   }
  378. }

  379. /******************************************
  380.                STEPPERS
  381. ******************************************/

  382. AF_Stepper::AF_Stepper(uint16_t steps, uint8_t num) {
  383.   MC.enable();

  384.   revsteps = steps;
  385.   steppernum = num;
  386.   currentstep = 0;

  387.   if (steppernum == 1) {
  388.     latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) &
  389.       ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // all motor pins to 0
  390.     MC.latch_tx();
  391.    
  392.     // enable both H bridges
  393.     pinMode(11, OUTPUT);
  394.     pinMode(3, OUTPUT);
  395.     digitalWrite(11, HIGH);
  396.     digitalWrite(3, HIGH);

  397.     // use PWM for microstepping support
  398.     initPWM1(STEPPER1_PWM_RATE);
  399.     initPWM2(STEPPER1_PWM_RATE);
  400.     setPWM1(255);
  401.     setPWM2(255);

  402.   } else if (steppernum == 2) {
  403.     latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) &
  404.       ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); // all motor pins to 0
  405.     MC.latch_tx();

  406.     // enable both H bridges
  407.     pinMode(5, OUTPUT);
  408.     pinMode(6, OUTPUT);
  409.     digitalWrite(5, HIGH);
  410.     digitalWrite(6, HIGH);

  411.     // use PWM for microstepping support
  412.     // use PWM for microstepping support
  413.     initPWM3(STEPPER2_PWM_RATE);
  414.     initPWM4(STEPPER2_PWM_RATE);
  415.     setPWM3(255);
  416.     setPWM4(255);
  417.   }
  418. }

  419. void AF_Stepper::setSpeed(uint16_t rpm) {
  420.   usperstep = 60000000 / ((uint32_t)revsteps * (uint32_t)rpm);
  421.   steppingcounter = 0;
  422. }

  423. void AF_Stepper::release(void) {
  424.   if (steppernum == 1) {
  425.     latch_state &= ~_BV(MOTOR1_A) & ~_BV(MOTOR1_B) &
  426.       ~_BV(MOTOR2_A) & ~_BV(MOTOR2_B); // all motor pins to 0
  427.     MC.latch_tx();
  428.   } else if (steppernum == 2) {
  429.     latch_state &= ~_BV(MOTOR3_A) & ~_BV(MOTOR3_B) &
  430.       ~_BV(MOTOR4_A) & ~_BV(MOTOR4_B); // all motor pins to 0
  431.     MC.latch_tx();
  432.   }
  433. }

  434. void AF_Stepper::step(uint16_t steps, uint8_t dir,  uint8_t style) {
  435.   uint32_t uspers = usperstep;
  436.   uint8_t ret = 0;

  437.   if (style == INTERLEAVE) {
  438.     uspers /= 2;
  439.   }
  440. else if (style == MICROSTEP) {
  441.     uspers /= MICROSTEPS;
  442.     steps *= MICROSTEPS;
  443. #ifdef MOTORDEBUG
  444.     Serial.print("steps = "); Serial.println(steps, DEC);
  445. #endif
  446.   }

  447.   while (steps--) {
  448.     ret = onestep(dir, style);
  449.     delay(uspers/1000); // in ms
  450.     steppingcounter += (uspers % 1000);
  451.     if (steppingcounter >= 1000) {
  452.       delay(1);
  453.       steppingcounter -= 1000;
  454.     }
  455.   }
  456.   if (style == MICROSTEP) {
  457.     while ((ret != 0) && (ret != MICROSTEPS)) {
  458.       ret = onestep(dir, style);
  459.       delay(uspers/1000); // in ms
  460.       steppingcounter += (uspers % 1000);
  461.       if (steppingcounter >= 1000) {
  462.         delay(1);
  463.         steppingcounter -= 1000;
  464.       }
  465.     }
  466.   }
  467. }

  468. uint8_t AF_Stepper::onestep(uint8_t dir, uint8_t style) {
  469.   uint8_t a, b, c, d;
  470.   uint8_t ocrb, ocra;

  471.   ocra = ocrb = 255;

  472.   if (steppernum == 1) {
  473.     a = _BV(MOTOR1_A);
  474.     b = _BV(MOTOR2_A);
  475.     c = _BV(MOTOR1_B);
  476.     d = _BV(MOTOR2_B);
  477.   } else if (steppernum == 2) {
  478.     a = _BV(MOTOR3_A);
  479.     b = _BV(MOTOR4_A);
  480.     c = _BV(MOTOR3_B);
  481.     d = _BV(MOTOR4_B);
  482.   } else {
  483.     return 0;
  484.   }

  485.   // next determine what sort of stepping procedure we're up to
  486.   if (style == SINGLE) {
  487.     if ((currentstep/(MICROSTEPS/2)) % 2) { // we're at an odd step, weird
  488.       if (dir == FORWARD) {
  489.         currentstep += MICROSTEPS/2;
  490.       }
  491.       else {
  492.         currentstep -= MICROSTEPS/2;
  493.       }
  494.     } else {           // go to the next even step
  495.       if (dir == FORWARD) {
  496.         currentstep += MICROSTEPS;
  497.       }
  498.       else {
  499.         currentstep -= MICROSTEPS;
  500.       }
  501.     }
  502.   } else if (style == DOUBLE) {
  503.     if (! (currentstep/(MICROSTEPS/2) % 2)) { // we're at an even step, weird
  504.       if (dir == FORWARD) {
  505.         currentstep += MICROSTEPS/2;
  506.       } else {
  507.         currentstep -= MICROSTEPS/2;
  508.       }
  509.     } else {           // go to the next odd step
  510.       if (dir == FORWARD) {
  511.         currentstep += MICROSTEPS;
  512.       } else {
  513.         currentstep -= MICROSTEPS;
  514.       }
  515.     }
  516.   } else if (style == INTERLEAVE) {
  517.     if (dir == FORWARD) {
  518.        currentstep += MICROSTEPS/2;
  519.     } else {
  520.        currentstep -= MICROSTEPS/2;
  521.     }
  522.   }

  523.   if (style == MICROSTEP) {
  524.     if (dir == FORWARD) {
  525.       currentstep++;
  526.     } else {
  527.       // BACKWARDS
  528.       currentstep--;
  529.     }

  530.     currentstep += MICROSTEPS*4;
  531.     currentstep %= MICROSTEPS*4;

  532.     ocra = ocrb = 0;
  533.     if ( (currentstep >= 0) && (currentstep < MICROSTEPS)) {
  534.       ocra = microstepcurve[MICROSTEPS - currentstep];
  535.       ocrb = microstepcurve[currentstep];
  536.     } else if  ( (currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2)) {
  537.       ocra = microstepcurve[currentstep - MICROSTEPS];
  538.       ocrb = microstepcurve[MICROSTEPS*2 - currentstep];
  539.     } else if  ( (currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3)) {
  540.       ocra = microstepcurve[MICROSTEPS*3 - currentstep];
  541.       ocrb = microstepcurve[currentstep - MICROSTEPS*2];
  542.     } else if  ( (currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4)) {
  543.       ocra = microstepcurve[currentstep - MICROSTEPS*3];
  544.       ocrb = microstepcurve[MICROSTEPS*4 - currentstep];
  545.     }
  546.   }

  547.   currentstep += MICROSTEPS*4;
  548.   currentstep %= MICROSTEPS*4;

  549. #ifdef MOTORDEBUG
  550.   Serial.print("current step: "); Serial.println(currentstep, DEC);
  551.   Serial.print(" pwmA = "); Serial.print(ocra, DEC);
  552.   Serial.print(" pwmB = "); Serial.println(ocrb, DEC);
  553. #endif

  554.   if (steppernum == 1) {
  555.     setPWM1(ocra);
  556.     setPWM2(ocrb);
  557.   } else if (steppernum == 2) {
  558.     setPWM3(ocra);
  559.     setPWM4(ocrb);
  560.   }


  561.   // release all
  562.   latch_state &= ~a & ~b & ~c & ~d; // all motor pins to 0

  563.   //Serial.println(step, DEC);
  564.   if (style == MICROSTEP) {
  565.     if ((currentstep >= 0) && (currentstep < MICROSTEPS))
  566.       latch_state |= a | b;
  567.     if ((currentstep >= MICROSTEPS) && (currentstep < MICROSTEPS*2))
  568.       latch_state |= b | c;
  569.     if ((currentstep >= MICROSTEPS*2) && (currentstep < MICROSTEPS*3))
  570.       latch_state |= c | d;
  571.     if ((currentstep >= MICROSTEPS*3) && (currentstep < MICROSTEPS*4))
  572.       latch_state |= d | a;
  573.   } else {
  574.     switch (currentstep/(MICROSTEPS/2)) {
  575.     case 0:
  576.       latch_state |= a; // energize coil 1 only
  577.       break;
  578.     case 1:
  579.       latch_state |= a | b; // energize coil 1+2
  580.       break;
  581.     case 2:
  582.       latch_state |= b; // energize coil 2 only
  583.       break;
  584.     case 3:
  585.       latch_state |= b | c; // energize coil 2+3
  586.       break;
  587.     case 4:
  588.       latch_state |= c; // energize coil 3 only
  589.       break;
  590.     case 5:
  591.       latch_state |= c | d; // energize coil 3+4
  592.       break;
  593.     case 6:
  594.       latch_state |= d; // energize coil 4 only
  595.       break;
  596.     case 7:
  597.       latch_state |= d | a; // energize coil 1+4
  598.       break;
  599.     }
  600.   }


  601.   MC.latch_tx();
  602.   return currentstep;
  603. }
复制代码




作者: eagler8    时间: 2020-11-13 09:51
补充实验

  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:IDE—工具—管理库—搜索“Servo”—安装
  6.   2、实验之八:测试M1M2电机
  7. */

  8. #include <AFMotor.h>

  9. AF_DCMotor motor1(1);
  10. AF_DCMotor motor2(2);

  11. void setup() {
  12.   Serial.begin(9600);
  13.   Serial.println("测试M1M2电机!");

  14.   // turn on motor
  15.   motor1.setSpeed(200);
  16.   motor2.setSpeed(200);

  17.   motor1.run(RELEASE);
  18.   motor2.run(RELEASE);
  19. }

  20. void loop() {
  21.   uint8_t i;

  22.   Serial.println("正转");

  23.   motor1.run(FORWARD);
  24.   motor2.run(FORWARD);
  25.   for (i = 0; i < 255; i++) {
  26.     motor1.setSpeed(i);
  27.     motor2.setSpeed(i);
  28.     delay(10);
  29.   }

  30.   for (i = 255; i != 0; i--) {
  31.     motor1.setSpeed(i);
  32.     motor2.setSpeed(i);
  33.     delay(10);
  34.   }

  35.   Serial.println("反转");

  36.   motor1.run(BACKWARD);
  37.   motor2.run(BACKWARD);

  38.   for (i = 0; i < 255; i++) {
  39.     motor1.setSpeed(i);
  40.     motor2.setSpeed(i);
  41.     delay(10);
  42.   }

  43.   for (i = 255; i != 0; i--) {
  44.     motor1.setSpeed(i);
  45.     motor2.setSpeed(i);
  46.     delay(10);
  47.   }

  48.   Serial.println("断电一秒");
  49.   motor1.run(RELEASE);
  50.   motor2.run(RELEASE);
  51.   delay(1000);
  52. }
复制代码




作者: eagler8    时间: 2020-11-13 10:40


作者: eagler8    时间: 2020-11-13 11:01
太极创客团队制作的B站视频,相当不错的视频教程

B站太极创客官方站:https://space.bilibili.com/10358 ... _765f7570696e666f.2






作者: eagler8    时间: 2020-11-13 11:05
Arduino AFMotor电机扩展板(上)
https://www.bilibili.com/video/BV1vb411q7xz?p=1

Arduino AFMotor电机扩展板(下)
https://www.bilibili.com/video/BV1vb411q7xz?p=2

作者: eagler8    时间: 2020-11-13 13:22
AFMotor电机驱动扩展板使用图形编程
【mind+用户库】第三方库方案

先下载安装Mind+(目前版本V1.6.5 RC3.0)
链接(自行替换.):mindplus点cc/download.html






作者: eagler8    时间: 2020-11-13 13:38
打开Mind+,进入“扩展”




作者: eagler8    时间: 2020-11-13 13:42
进入“用户库”




作者: eagler8    时间: 2020-11-13 13:45
在用户库中搜索“hockel”即可




作者: eagler8    时间: 2020-11-13 13:48
添加的 AFMotor模块




作者: eagler8    时间: 2020-11-13 14:04
AFMotor电机驱动扩展板积木列表




作者: eagler8    时间: 2020-11-13 16:54
用图形编程驱动四只直流电机




作者: eagler8    时间: 2020-11-13 16:55


作者: eagler8    时间: 2020-11-13 17:38
  1. /*
  2.   【Arduino】168种传感器模块系列实验(资料+代码+图形+仿真)
  3.   实验一百七十:L293D四路电机驱动板 motor control shield 马达板
  4.   Adafruit Motor Shield模块 Arduino AFMotor 电机扩展板

  5.   1、安装库:百度搜索“AFMotor库”— 下载 — 拷贝到Arduino-libraries 文件夹中
  6.   2、实验之九:测试M1M2M3M4电机前进与后退
  7. */

  8. #include <AFMotor.h>

  9. // 创建对象
  10. AF_DCMotor motor1(1);
  11. AF_DCMotor motor2(2);
  12. AF_DCMotor motor3(3);
  13. AF_DCMotor motor4(4);


  14. // 主程序开始
  15. void setup() {

  16. }
  17. void loop() {
  18.   motor1.setSpeed(200);
  19.   motor1.run(FORWARD);
  20.   motor2.setSpeed(200);
  21.   motor2.run(FORWARD);
  22.   motor3.setSpeed(200);
  23.   motor3.run(FORWARD);
  24.   motor4.setSpeed(200);
  25.   motor4.run(FORWARD);
  26.   delay(2000);
  27.   
  28.   motor1.setSpeed(0);
  29.   motor1.run(RELEASE);
  30.   motor2.setSpeed(0);
  31.   motor2.run(RELEASE);
  32.   motor3.setSpeed(0);
  33.   motor3.run(RELEASE);
  34.   motor4.setSpeed(0);
  35.   motor4.run(RELEASE);
  36.   delay(1000);
  37.   
  38.   motor1.setSpeed(200);
  39.   motor1.run(BACKWARD);
  40.   motor2.setSpeed(200);
  41.   motor2.run(BACKWARD);
  42.   motor3.setSpeed(200);
  43.   motor3.run(BACKWARD);
  44.   motor4.setSpeed(200);
  45.   motor4.run(BACKWARD);
  46.   delay(2000);
  47.   
  48.   motor1.setSpeed(0);
  49.   motor1.run(RELEASE);
  50.   motor2.setSpeed(0);
  51.   motor2.run(RELEASE);
  52.   motor3.setSpeed(0);
  53.   motor3.run(RELEASE);
  54.   motor4.setSpeed(0);
  55.   motor4.run(RELEASE);
  56.   delay(1000);
  57. }
复制代码



作者: eagler8    时间: 2020-12-29 20:38

实验开源仿真编程(linkboy V4.1)




作者: eagler8    时间: 2020-12-30 17:06
用这款电机驱动扩展板做了一辆麦克纳姆轮小车







作者: eagler8    时间: 2020-12-30 18:04
麦克纳姆轮车子运动模式图






作者: eagler8    时间: 2020-12-30 18:06
实验仿真编程(linkboy V4.1)之二





作者: eagler8    时间: 2020-12-30 18:16
使用
AFMotor电机扩展板的麦克纳姆轮小车(视频)



https://v.youku.com/v_show/id_XNTAzNDYyMzE1Mg==.html?spm=a2hzp.8253869.0.0



https://v.youku.com/v_show/id_XNTAzNDYyMzE1Mg==.html







欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1