本文翻译自DronebotWorkshop.com译者:DIY百事
目录

1 简介

2 无线通讯
3 2.4 GHz 频段
4 nRF24L01+
5 nRF24L01 连接
5.1 SPI 总线
5.2模块连接
5.3电源把稳事变
5.4 nRF24L01 适配器模块
6 nRF24L01+ 和 Arduino
6.1 Arduino 库和连接
6.2 RadioHead 库
6.3连接 Arduinos
6.4 RadioHead 示例代码 – 客户端和做事器
6.5 RadioHead 示例代码——可靠的数据报
7操纵杆演示
8机器人汽车遥控器
8.1利用仿照引脚作为数字引脚
8.2操纵杆发射器示意图
8.3操纵杆吸收器示意图
9结论
先容图1
nRF24L01+ 模块。这是一种利用 2.4 GHz 频段供应 2 路通信的廉价模块。该频段无需容许即可免用度于低功率设备,并且在某些情形下有效间隔长达一公里。
nRF24L01+ 有多种不同的配置可供选择,在本文中,我将先容几个比较盛行的配置。我们会将它们连接起来并利用一个非常广泛的库来促进它们之间的通信。
图2
在我们让它们事情后,我们将利用它们来构建一些有趣的东西——我们之前开拓的机器人汽车底座的无线操纵杆掌握。
在我们开始之前,让我们检讨一下 nRF24L01+ 以及您在设计无线设备时须要考虑的一些成分。
无线通讯自 1880 年代后期以来,我们一贯在以无线办法发送信息,托马斯爱迪生利用电磁感应系统将电报旗子暗记从移动的火车发送到轨道阁下的一组电线。无线设备是我们生活的一部分,大多数事情利用以下方法之一:
旗子暗记通过红外线光束发送利用无线电波发送旗子暗记与红外线光束比较,无线电波具有许多上风,最明显的是无线电波可以(在一定程度上)穿过墙壁和大多数其他障碍物。
无线电波绝不是一种完美的通信办法,它们会受到许多来源的滋扰,并且可能会被金属或厚墙阻挡。但它们确实在许多低速数据运用程序中发挥浸染,因此非常适宜想要构建远程掌握设备或须要无线发送数据的 Arduino 和 Raspberry Pi 实验者。
无线电旗子暗记基于改变或“调制”无线传输到吸收器的“载波”的观点。在吸收端,载波被分离,旗子暗记被“解调”以从中提取原始信息。
由于这些载波会相互滋扰,因此它们的分配受到严格掌握,每个国家都有一个政府部门卖力管理它们。造孽利用无线电载波频率会导致非常严厉的罚款,以是不要这样做。
像我们这样的实验者可以利用很多频率,个中最受欢迎的频率之一是 2.4 GHz 频段。
2.4 GHz 频段2.4 GHz 工业、科学和医疗 (ISM) 频段已保留用于未经容许的低功耗设备,这使其非常适宜构建远程掌握的 Arduino 设备。当然,它还非常适宜您家中的许多其他设备,如无线路由器、无绳电话、蓝牙小玩意和其他无线设备。
谈论的频段从 2.400.0 GHz 到 2.483.5 GHz,为了让多个设备共存成为可能,它被分解为多个通道。只管有 14 个频道可用,但并非每个频道在每个地区都是合法的。频道 1 到 11 在世界的大多数地方都是合法的,因此建议您将实验限定在这些频道中。
由于在 2.4 GHz 频段上进行通信是一项非常常见的功能,因此有许多模块专门用于此目的。我们本日要玩的可能是最受欢迎的,它可以在 网上以几元或更少的价格购买。
nRF24L01+nRF24L01+ 是用于构建 2.4 GHz 发射器和吸收器或“收发器”的通用芯片的部件号。该芯片已被用于创建一些大略且廉价的模块,这些模块可用于利用 2.4 GHz 频段传输和吸收数据。
有多种基于 nRF24L01 的模块可用,我将在本文中利用两个非常常见的模块。如果您有不同的模块,它该当可以正常事情,请务必把稳接线,尤其是电源哀求。
我利用的两个模块非常相似并且可以互换,它们之间的差异在于个中一个具有内置低噪声放大器 (LNA) 和外部天线连接。我更喜好这个,纵然它有点贵,由于它可以用于在相称长的间隔内进行可靠的数据通信。除非你住在城堡里,否则它可能足以覆盖你的全体屋子。
所有实验,包括无线操纵杆,都可以利用任一模块构建(它们共享相同的引脚),但利用带有外部天线的模型可以得到更好的范围。
nRF24L01 连接nRF24L01 有一个 8 针连接器,可与外界连接。此连接器在两种类型的 nRF24L01 模块之间通用。只管 nRF24L01 由 1.9 至 3.9 伏电源供电,但逻辑引脚可承受 5 伏电压,因此它们可以直接与 Arduino 或其他 5 伏逻辑微掌握器一起利用。
SPI总线nRF24L01 利用串行外设接口或 SPI 总线进行通信。这是许多微掌握器和微型打算机(包括 Arduino 和 Raspberry Pi)利用的标准总线。
SPI 总线利用主从的观点,在大多数常见运用中,微掌握器或微机是主,nRF24L01 是从。与 I2C 总线不同,SPI 总线上的从机数量是有限的,在 Arduino Uno 上,您最多可以利用两个 SPI 从机。
SPI 总线是双向总线,这意味着主机和从机可以同时发送和吸收,但是我们将与 nRF24L01 一起利用的库不会这样做。
每个从设备都须要由主设备选择才能进行通信。在任何给定时间,只有一个从站可以通信。nRF24L01 和其他从设备有一个中断引脚,可以在须要通信时提醒主设备,但我们本日将利用的库忽略了这一点,因此在我们的运用程序中,我们不会将中断引脚连接到 Arduino。
模块连接与 nRF24L01 模块的连接如下:
图3
GND地。这是接地引脚。它常日通过将引脚包裹在一个正方形中来标记,因此它可以用作识别其他引脚的参考。VCC逻辑电平。正电压。这可以是 1.9 到 3.9 伏之间的任何电压。它不耐受 5 伏电压!CE片选。Chip Enable,高电平有效引脚。选择后,nRF24L01 将发送或吸收,详细取决于它当前处于哪种模式。CSN。片选否。这是一个低电平有效的引脚,它是 SPI 总线用来选择 nRF24L01 从机的引脚。SCK 。时钟引脚,SPI 总线 Master 供应的外部时钟源。MOSI。主出从入。nRF24L01 的输入。MISO。主入从出。nRF24L01 的输出。IRQ中断要求。中断输出引脚。
利用外部天线的 nRF24L01 样式也有用于连接天线的 SMA 连接器。
电源把稳事变由于 nRF24L01 的电源范围为 1.9 – 3.9 伏,因此它可以由电池供电。利用 3.3 伏电源为模块供电也很常见。
选择电源时,应把稳 nRF24L01 在以最高功率传输时会花费相称多的电流。您的电源该当能够供应至少 300 mA 的电流。
电源上的噪声也会导致 nRF24L01 涌现问题。建议在电源线上放置一个滤波电容器(100 微法是空想的),尽可能靠近 nRF24L01 模块,以肃清电源噪声。
办理电源问题的另一种方法,也是我建议您采取的方法,是为您的 nRF24L01 利用适配器模块。
nRF24L01 适配器模块nRF24L01 适配器模块是一种非常便宜的原型开拓板,可简化 nRF24L01 的事情。我建议你利用一个,我在本文中包含的所有事理图中都展示了它。
适配器模块有一个 8 针母连接器,许可您插入 nRF24L01,它可以容纳带有集成或外部天线的模块。它还具有用于 SPI 和中断连接的 6 针公连接器和用于电源输入的 2 针连接器。
适配器模块有自己的 3.3 伏稳压器和一组滤波电容器,因此您可以利用 5 伏电源为其供电。假设您的电源具有所需的电流能力,适配器模块将办理上述所有电源问题。
由于这些模块的售价便宜,因此推举利用它们。它们可以方便您的 nRF24L01 设计。
nRF24L01+ 和 Arduino在我们的实验中,我们将利用两个 nRF24L01 模块和几个 Arduino Uno。您当然可以利用其他型号的 Arduino,但如果您这样做,您可能须要变动引脚排列,由于不同的 Arduino 型号对 SPI 总线利用不同的引脚。
我将在这里描述 Arduino Uno 和 Arduino Mega 2560 的引脚排列。后面(在事理图中)我将只利用 Arduino Uno,因此如果您利用的是 Mega 2560,则须要相应地更换引脚编号。我们的 Robot Car 项目基于 Arduino Uno,我们将修正该项目以利用无线操纵杆。
Arduino 库和连接与其他无线电模块一样,nRf24L01 有许多可用的库。利用库将真正简化利用这些模块创建项目的过程。
以下库均适用于 nRF24L01+ 模块:
TMRh20 – 这个库已经存在好几年了。它非常适宜创建安全的无线通信设备。您可以在TMRh20 项目博客上阅读更多内容,并在Arduino 设备的TMRh20 GitHub 存储库分支上获取最新版本。RF24 – 这是一个旧标准,已在许多 nRF24L01 项目中利用。它已被 RadioHead 和 TMRh20 库取代。Mirf 库——基于Tinkerer库。这是一个更古老的库,因此您不会再找到太多基于它的项目。RadioHead - 这是一个具有许多高等功能的当代库,能够支持许多 RF 模块。在我们将要实行的实验中,对付我们的无线游戏杆项目,我们将利用 RadioHead 库。
请把稳,并非上面列出的所有库都是Arduino 自带的。
RadioHead 库RadioHead 是 Mike McCauley 为 Airspayce 公司编写的库。我在之前的一篇文章中利用过它,将廉价的 433MHz 发送和吸收模块与 Arduino 结合利用。
这是一个高等库,它许可在诸如 nRF24L01 之类的 RF 模块之间进行多种分组无线电通信方法。它包含用于不同射频模块的许多不同驱动程序,nRF24L01 的驱动程序是RH_NRF24 驱动程序。
您可以在RadioHead 网站上理解有关 RadioHead 库的更多信息并下载您须要在 Arduino IDE 中安装的 ZIP 文件。在页面描述顶部附近查找指向 ZIP 文件的链接。
下载 ZIP 文件后,您须要将其安装在 Arduino IDE 中。这是一个非常大略的过程:
打开 Arduino IDE。从顶部菜单栏中选择Sketch,从代码菜单下拉菜单中选择包括库。从包含库子菜单中选择添加 .ZIP 库。利用对话框选择您下载的 ZIP 文件。将安装 RadioHead 库。在您的 Arduino IDE 中安装 RadioHead 库后,您就可以开始利用 nRF24L01 进行实验了。
连接 ArduinoRadioHead 库附带了许多示例代码,用于解释其用法。我们将从这些代码中的一些代码开始我们的实验,然后我们将为我们的操纵杆项目修正个中的一些代码。
以下是您须要为 Arduino Uno 进行的连接:
图4
请把稳,您须要制作个中两个电路!
我们将个中一个电路称为做事器,另一个称为客户端。两者的接线是相同的。
另请把稳,我利用 nRF24L01 适配器模块来解释事理图,该模块具有自己的稳压器,可为 nRF24L01 供应 3.3 伏电压。如果您乐意,您可以直接连接到 nRF24L01 本身,但您须要利用 Arduino 的 3.3 伏输出,而不是 5 伏输出(这可能会毁坏您的 nRF24L01 模块)。
请把稳,许多 Arduino 仿制板在 nRF24L01 的 3.3 伏输出上没有足够的电流。纵然你的有,建议在电源线上利用一个滤波电容器。但是,您最好的选择还是大略地利用 nRF24L01 适配器模块,这样您就可以避免很多问题!
如果您利用的是 Arduino Mega 2560,那么 RadioHead 库的引脚分配会有所不同:
GND。当然,这仍旧是接地,因此它连接到 Mega 2560 接地引脚之一。VCC。同样,这仍旧是电源连接。请参阅上面有关利用哪种电压的解释。CE。这与 Arduino Uno 相同,它连接到 Mega 2560 上的引脚 8。CSN。将此连接到 Mega 2560 上的输出引脚 53。SCK。将此连接到 Mega 2560 上的输出引脚 52。MOSI。这转到 Mega 2560 上的引脚 51。MISO。末了,这是 Mega 2560 上的引脚 50。请把稳,nRF24L01 上的 IRQ 引脚未与任一 Arduino 板一起利用,由于它被 RadioHead 库忽略。
统统就绪后,您就可以开始运行第一个代码了。
RadioHead 示例代码 – 客户端和做事器我们将运行的第一个代码是 RadioHead 库中包含的基本客户端和做事器示例。您可以按如下办法找到并加载它们:
打开 Arduino IDE(您可能已经这样做了)。从顶部菜单栏中打开文件菜单。选择示例。将显示一个子菜单。向下滚动示例子菜单到底部标题为来自自定义库的示例的部分。从菜单中选择RadioHead。此菜单阁下将涌现另一个子菜单。从 RadioHead 子菜单中选择nrf24。将显示 RadioHead RH_NRF24 驱动程序的示例代码列表。我们须要加载两个代码,每个 Arduino 上一个。如果您没有拥有两台打算机的奢侈,那么您可以利用一台打算机单独完成这些操作。
我们须要的代码如下:
在做事器 Arduino 上加载nrf24_server代码。在客户端打算机上加载nrf24_client代码。代码得到了很好的评论,因此我将仅先容此处的一些基本要素。
每个代码都包括 RadioHead RH_NRF24 库以及 Arduino SPI 库。然后他们都声明了一个无线电驱动程序的实例。如果您想变动接线或利用不同类型的 Arduino,您可以在声明驱动程序时添加可选参数。
之后,它们都进入设置例程,从设置串口监视器和初始化驱动程序开始。然后调用setChannel方法将无线电信道从默认信道(即信道 2)变动为信道 1。如果您创造任何 2.4 GHz 设备(即无线鼠标)滋扰实验,您可以考试测验不同的信道。
您还可以添加参数来变动模块的数据速率和发射功率。较慢的数据速率将导致更长的操作范围。只要确保在做事器和客户端之间保持相同的数据速率和通道。
然后我们连续循环。
在做事器端,循环从探求来自客户真个开始。如果收到,则将其放入缓冲区,然后输出到串口监视器。之后,回答“And hello back to you”被放入一个数组并发送给客户端。
在客户端,循环以相反的办法开始。一条“Hello World”被放入一个数组并发送到做事器。然后我们等待吸收来自客户真个(“And hello back to you”)。如果/当我们收到时,它会被输出到串口监视器上。
如果您有幸拥有两台打算机,则可以同时打开串口监视器并不雅观察做事器和客户端之间的交互。如果您只有一台打算机,那么我建议您利用电池或 USB 电源为一台 Arduino 供电,同时利用打算机为另一台打算机供电和监控。
虽然这是一个非常基本的代码,但它确实解释了 RadioHead 库如何使 nRF24L01 的事情变得随意马虎。它还有一个实际用场——您可以利用它(用一个 Arduino 电池供电)来确定利用两个模块可以达到的范围。如果您同时拥有带集整天线的模块和带外置天线的模块,您很快就会看到外置天线模块的真正上风。
RadioHead 示例代码 – 可靠的数据传送以前的代码效果很好,对付许多运用程序,它们都是您所须要的。但是,如果您碰着的情形是您传输的数据必须精确无误地吸收,那么您将须要查看另一种方法。
当您将一个大文件分成几个小部分时,这可能是一个哀求。发送端须要确保吸收端完全地吸收到每一位。如果不是,则须要重新发送数据。
Internet 上的数据传输利用此事理。
交流数据的 RadioHead 可靠数据传送方法也利用这种验证数据完全性的方法。它不须要任何分外编码,由于 Reliable Datagram 库在后台为您完成所有事情。我们现在来看看。
对付此实验,您无需进行任何接线变动,由于连接与之前的实验相同。
返回到Radiohead的库的例子代码nrf24并选择以下两个代码:
在做事器 Arduino 上加载nrf24_reliable_datagram_server代码。在客户端 Arduino 上加载nrf24_reliable_datagram_client代码。同样,这些代码得到了很好的评论,它们与我们刚刚看到的代码也有很多相似之处,以是我将在这里紧张谈论不同之处。
除了在前面的代码中加载的两个库之外,这些代码还加载了 RadioHead RHReliableDatagram库。
然后定义了两个常量,一个 CLIENT_ADDRESS 和 SERVER_ADDRESS。这些地址不是无线电信道,而是在做事器和客户端之间交流的数据报包中利用的地址。
创建无线电驱动程序的实例后,每个代码都利用上面定义的地址之一设置数据报管理器(这是做事器和客户真个不同之处)。
在设置例程中,设置串口监视器并初始化数据报管理器。
在设置例程之外和循环之前,利用要发送的数据定义一个数组并定义一个缓冲区。
在循环中,操作与之前的代码非常相似。做事器等待从客户端吸收到,将其输出到串口监视器,然后发送自己的。客户端反过来做同样的事情。
您会在串口监视器中把稳到的一件事是双方都打印出吸收到的数据包中包含的地址。
试用演示并查当作果。在远间隔,您偶尔会把稳到吸收数据时会涌现轻微延迟,这会在数据包丢失并须要重新发送时发生。
与之前的代码一样,这个效果很好。我们现在将修正此代码以发送一些操纵杆数据,然后利用它来构建我们的无线操纵杆。
操纵杆演示前两组代码解释了如何交流文本数据,如“Hello World”和“And hello back to you”,这本身就很有用。但在许多情形下,您会希望在两个 Arduino 之间无线交流数字数据。这方面的一个例子是从远程传感器向基站发送数据。
在我们的下一个实验中,我们将从操纵杆发送数据到远程吸收器。操纵杆的每个轴都将作为单个字节与“虚拟字节”一起发送,我将在适当的时候阐明其用场。根据操纵杆的位置,轴数据的值范围为 0 到 255。
您当然可以利用此代码发送其他传感器数据,它不须要来自操纵杆。你的想象力是这里唯一的限定。
每个代码都是我们之前看到的可靠数据报代码的修正版本,您会识别出很多代码。重新发明轮子毫无意义!
在我们开始之前,您须要拿一个 Arduinos 并为其添加一个操纵杆。连线如下图:
图5
如您所见,操纵杆连接非常大略。如果您没有操纵杆,只需利用两个电位计,由于这便是仿照操纵杆的全部功能——一个用于 x 轴的电位器,另一个用于 y 轴的电位器。每个控件都连接到 Arduino 的仿照输入之一。
在另一端,将 Arduino 和 nRF24L01 保持原样连接,您唯一须要变动的便是代码。
这是操纵杆方面的代码。请把稳,它基于 RadioHead Reliable Datagram Client 代码,这只是我的任意选择,由于我可以轻松地利用做事器代码。
/nRF24L01+ Joystick Transmitternrf24l01-joy-xmit-demo.inonRF24L01+ Transmitter with JoystickUse with Joystick Receiver DemoDroneBot Workshop 2018https://dronebotworkshop.com/// Include RadioHead ReliableDatagram & NRF24 Libraries#include <RHReliableDatagram.h>#include <RH_NRF24.h>// Include dependant SPI Library#include <SPI.h>// Define Joystick Connections#define JoyStick_X_PIN A0#define JoyStick_Y_PIN A1// Define addresses for radio channels#define CLIENT_ADDRESS 1#define SERVER_ADDRESS 2// Create an instance of the radio driverRH_NRF24 RadioDriver;// Sets the radio driver to NRF24 and the client address to 1RHReliableDatagram RadioManager(RadioDriver, CLIENT_ADDRESS);// Declare unsigned 8-bit joystick arrayuint8_t joystick[3];// Define the Message Bufferuint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];void setup(){// Setup Serial MonitorSerial.begin(9600);// Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBmif (!RadioManager.init())Serial.println("init failed");}void loop(){// Print to Serial MonitorSerial.println("Reading joystick values ");// Read Joystick values and map to values of 0 - 255joystick[0] = map(analogRead(JoyStick_X_PIN), 0, 1023, 0, 255);joystick[1] = map(analogRead(JoyStick_Y_PIN), 0, 1023, 0, 255);joystick[2] = 100;//Display the joystick values in the serial monitor.Serial.println("-----------");Serial.print("x:");Serial.println(joystick[0]);Serial.print("y:");Serial.println(joystick[1]);Serial.println("Sending Joystick data to nrf24_reliable_datagram_server");//Send a message containing Joystick data to manager_serverif (RadioManager.sendtoWait(joystick, sizeof(joystick), SERVER_ADDRESS)){// Now wait for a reply from the serveruint8_t len = sizeof(buf);uint8_t from;if (RadioManager.recvfromAckTimeout(buf, &len, 2000, &from)){Serial.print("got reply from : 0x");Serial.print(from, HEX);Serial.print(": ");Serial.println((char)buf);}else{Serial.println("No reply, is nrf24_reliable_datagram_server running?");}}elseSerial.println("sendtoWait failed");delay(100);// Wait a bit before next transmission}
代码以与 RadioHead Reliable Datagram 代码相同的办法开始,它加载所需的库。我们还定义了操纵杆利用的输入,以及可靠数据报包的客户端和做事器地址。
然后,我们定义了一个名为“joystick”的 8 位无符号整数数组,个中包含三个元素:
操纵杆 [0]是 x 轴值。操纵杆 [1]是 y 轴值。操纵杆 [2]是“虚拟”值。发送“虚拟”值的唯一缘故原由是要有第三个字节,由于我们终极的无线操纵杆代码将利用这个字节来指示电机方向。通过在这个演示代码中定义它,我们可以在必要时利用我们在这里构建的吸收器对终极产品进行故障打消。
我为虚拟值指定了 100 的值,您可以很好地指定 0 到 255 之间的任何值。它现在只是为了测试数据完全性。
设置例程与 RadioHead Reliable Datagram 示例相同。
在循环中,我们启动串口监视器,由于我们将利用它来监视操纵杆值。然后,我们连续在每个操纵杆仿照输入上利用 Arduino仿照读取函数获取这些操纵杆值。
由于 Arduino 的模数转换器是 10 位转换器,我们将从每个操纵杆返回 0 到 1023 的值。我们利用 Arduino map命令将其转换为 0 到 255 的范围。每个 hvalues 被分配给操纵杆数组中的相应元素。
代码的别的部分与可靠数据报代码非常相似。数组被发送到做事器端,我们等待看看是否得到回答。然后我们再做一遍。
另一端(即“操纵杆吸收器”)乃至更大略。这是代码:
/nRF24L01+ Joystick Receiver Demonrf24l01-joy-rcv-demo.inonRF24L01+ Receiver with Joystick DecodeUse with Joystick Transmitter DemoDroneBot Workshop 2018https://dronebotworkshop.com/// Include RadioHead ReliableDatagram & NRF24 Libraries#include <RHReliableDatagram.h>#include <RH_NRF24.h>// Include dependant SPI Library#include <SPI.h>// Define addresses for radio channels#define CLIENT_ADDRESS 1#define SERVER_ADDRESS 2// Create an instance of the radio driverRH_NRF24 RadioDriver;// Sets the radio driver to NRF24 and the server address to 2RHReliableDatagram RadioManager(RadioDriver, SERVER_ADDRESS);// Define a message to return if values receiveduint8_t ReturnMessage[] = "JoyStick Data Received";// Define the Message Bufferuint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];void setup(){// Setup Serial MonitorSerial.begin(9600);// Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBmif (!RadioManager.init())Serial.println("init failed");}void loop(){if (RadioManager.available()){// Wait for a message addressed to us from the clientuint8_t len = sizeof(buf);uint8_t from;if (RadioManager.recvfromAck(buf, &len, &from))//Serial Print the values of joystick{Serial.print("got request from : 0x");Serial.print(from, HEX);Serial.print(": X = ");Serial.print(buf[0]);Serial.print(" Y = ");Serial.print(buf[1]);Serial.print(" Z = ");Serial.println(buf[2]);// Send a reply back to the originator client, check for errorif (!RadioManager.sendtoWait(ReturnMessage, sizeof(ReturnMessage), from))Serial.println("sendtoWait failed");}}}
此代码与 RadioHead Reliable Datagram 做事器代码之间的唯一差异是我们在吸收到的数据数组中显示数值而不是文本。我们将它们标记为 X、Y 和 Z:
X 是 x 轴读数。Y 是 y 轴读数。Z 是“虚拟值”。加载 bnoth 代码后运行它们,至少将吸收器连接到打算机,以便您可以不雅观察串口监视器。当您移动操纵杆时,您该当不雅观察值的变革。
机器人汽车遥控器以是现在我们可以看到我们如何发送操纵杆值。是时候把它们放在一起创建我们的机器人汽车遥控操纵杆了。
在操纵杆一侧,您已经完成接线,您须要变动的只是代码。在另一端,虽然你须要一辆机器人汽车!
如果您按照上一篇文章“利用速率传感器构建机器人汽车”中的解释进行操作,那么您已经拥有一辆机器人汽车。如果没有,那么去看看那篇文章,理解如何利用便宜的套件组装机器人汽车。
由于该项目不该用速率传感器,因此您可以忽略该部分。如果您已经建造了机器人汽车,那么就让它保持原样,您不须要移除速率传感器。
如果您确实制造了原车,则须要进行一些变动,特殊是 L298N H 桥电机掌握器的连接办法。原始设计利用了 nRF24L01 所需的一些引脚,因此须要它。
这是新的机器人汽车示意图:
图6
与 nRF24L01 模块的连接与我们其他实验中的连接完备相同,这并不奇怪。您可以利用任何类型的 nRF24L01 模块,但我强烈建议利用带有外部天线的模型以提高性能,至少在汽车方面是这样。
利用仿照引脚作为数字引脚在电机方面,您会把稳到与原始设计比较,电机 A 的引脚已移动。个中之一可能会让您感到惊异——L289N H 桥IN1引脚连接到 Arduino 仿照引脚 A0。为什么是仿照引脚?
如果您查看作为 Arduino Uno 核心的 ATMega328 的规格,您就会明白我为什么利用 A0。事实证明,Arduino 上的“仿照”引脚也可以很好地用作数字 I/O 引脚。
我的 L298N 电机掌握器须要一个额外的引脚,我有几个选择:
我不想利用引脚 2 或 3,由于机器人汽车将这些用于速率传感器。纵然传感器不是这个设计的一部分,我也想让它们自由。引脚 1 和 2 可能看起来很有出息,但它们也是分外引脚——它们用作串行接口的 RX 和 TX 线。我想让它们免费,也是由于内部缘故原由,它们无论如何都不会在这个运用程序中很好地事情。我选择利用引脚 A0。它和仿照引脚,但它也是 Arduino Uno 上的数字 I/O 引脚 #14。只要引脚在代码中定义为输出,它就可以正常事情。
连接好汽车后,剩下的便是加载代码。我们将首先查看操纵杆代码。
操纵杆发射器示意图如您所料,远程操纵杆代码与我们之前看到的操纵杆演示代码非常相似。她在它的所有光彩中:
/nRF24L01+ Joystick Transmitternrf24l01-joy-xmit-car.inonRF24L01+ Transmitter with Joystick for Robot CarUse with Joystick Receiver for Robot CarDroneBot Workshop 2018https://dronebotworkshop.com/// Include RadioHead ReliableDatagram & NRF24 Libraries#include <RHReliableDatagram.h>#include <RH_NRF24.h>// Include dependant SPI Library#include <SPI.h>// Define Joystick Connections#define joyVertA0#define joyHorzA1// Define Joystick Values - Start at 512 (middle position)int joyposVert = 512;int joyposHorz = 512;// Define addresses for radio channels#define CLIENT_ADDRESS 1#define SERVER_ADDRESS 2// Create an instance of the radio driverRH_NRF24 RadioDriver;// Sets the radio driver to NRF24 and the client address to 1RHReliableDatagram RadioManager(RadioDriver, CLIENT_ADDRESS);// Declare unsigned 8-bit motorcontrol array// 2 Bytes for motor speeds plus 1 byte for direction controluint8_t motorcontrol[3];// Define the Message Bufferuint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];void setup(){// Setup Serial MonitorSerial.begin(9600);// Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBmif (!RadioManager.init())Serial.println("init failed");// Set initial motor direction as forwardmotorcontrol[2] = 0;}void loop(){// Print to Serial MonitorSerial.println("Reading motorcontrol values ");// Read the Joystick X and Y positionsjoyposVert = analogRead(joyVert);joyposHorz = analogRead(joyHorz);// Determine if this is a forward or backward motion// Do this by reading the Verticle Value// Apply results to MotorSpeed and to Directionif (joyposVert < 460){// This is Backward// Set Motors backwardmotorcontrol[2] = 1;//Determine Motor Speeds// As we are going backwards we need to reverse readingsmotorcontrol[0] = map(joyposVert, 460, 0, 0, 255);motorcontrol[1] = map(joyposVert, 460, 0, 0, 255);}else if (joyposVert > 564){// This is Forward// Set Motors forwardmotorcontrol[2] = 0;//Determine Motor Speedsmotorcontrol[0] = map(joyposVert, 564, 1023, 0, 255);motorcontrol[1] = map(joyposVert, 564, 1023, 0, 255);}else{// This is Stoppedmotorcontrol[0] = 0;motorcontrol[1] = 0;motorcontrol[2] = 0;}// Now do the steering// The Horizontal position will "weigh" the motor speed// Values for each motorif (joyposHorz < 460){// Move Left// As we are going left we need to reverse readings// Map the number to a value of 255 maximumjoyposHorz = map(joyposHorz, 460, 0, 0, 255);motorcontrol[0] = motorcontrol[0] - joyposHorz;motorcontrol[1] = motorcontrol[1] + joyposHorz;// Don't exceed range of 0-255 for motor speedsif (motorcontrol[0] < 0)motorcontrol[0] = 0;if (motorcontrol[1] > 255)motorcontrol[1] = 255;}else if (joyposHorz > 564){// Move Right// Map the number to a value of 255 maximumjoyposHorz = map(joyposHorz, 564, 1023, 0, 255);motorcontrol[0] = motorcontrol[0] + joyposHorz;motorcontrol[1] = motorcontrol[1] - joyposHorz;// Don't exceed range of 0-255 for motor speedsif (motorcontrol[0] > 255)motorcontrol[0] = 255;if (motorcontrol[1] < 0)motorcontrol[1] = 0;}// Adjust to prevent "buzzing" at very low speedif (motorcontrol[0] < 8)motorcontrol[0] = 0;if (motorcontrol[1] < 8)motorcontrol[1] = 0;//Display the Motor Control values in the serial monitor.Serial.print("Motor A: ");Serial.print(motorcontrol[0]);Serial.print(" - Motor B: ");Serial.print(motorcontrol[1]);Serial.print(" - Direction: ");Serial.println(motorcontrol[2]);//Send a message containing Motor Control data to manager_serverif (RadioManager.sendtoWait(motorcontrol, sizeof(motorcontrol), SERVER_ADDRESS)){// Now wait for a reply from the serveruint8_t len = sizeof(buf);uint8_t from;if (RadioManager.recvfromAckTimeout(buf, &len, 2000, &from)){Serial.print("got reply from : 0x");Serial.print(from, HEX);Serial.print(": ");Serial.println((char)buf);}else{Serial.println("No reply, is nrf24_reliable_datagram_server running?");}}elseSerial.println("sendtoWait failed");delay(100);// Wait a bit before next transmission}
那些阅读过“利用 L298N 双 H 桥和 Arduino 掌握直流电机”文章的人可能会认出这里的一些代码,由于它取自我用来演示带有机器人汽车的操纵杆的代码(那个利用一条电线)。
我们首先像以前一样定义我们的库。然后我们定义用于操纵杆输入的仿照引脚以及几个保存这些输入值的变量。
这个代码的真正差异在于我们如何处理这些值。我们希望操纵杆按如下办法操作:
如果我们向前推动操纵杆,汽车该当向前行驶。我们推得越远,它该当走得越快。如果我们将操纵杆向后拉向我们,汽车该当倒车。我们拉得越远,它该当走得越快。如果我们将其向左移动,汽车该当向左转向。如果我们将它向右移动,汽车该当向右转向。如果我们将操纵杆留在中间位置,那么汽车根本不会移动。我建立了操纵杆水平和垂直行程的“中间值”,使其值在 460 和 564 之间。确切的中间值当然是 511.5,但我们利用的是整数,我们还必须考虑到两美元操纵杆不是大多数精密仪器可用。
如果您按照代码进行操作,您该当会看到个中的逻辑。我们确定垂直操纵杆是否在 564 以上,如果是,我们将向前行驶。因此,我们将motorcontrol[2]变量设置为 0 值,在此代码中表示“提高”。
如果我们的垂直操纵杆低于 460,那么我们将motorcontrol[2]设置为 1 以表示我们想要倒退。
然后,我们利用 Arduino 映射函数将操纵杆值映射到 0 到 255 范围内的电机速率值,这些值分配给motorcontrol[0]和motorcontrol[1]变量。
水平掌握以相同的办法起浸染,不同之处在于它对速率值运用偏移量以使一个电机比另一个电机旋转得更快。
然后我们将数组中的三个变量发送到发射器,就像我们在操纵杆演示代码中所做的那样。
操纵杆吸收器代码吸收器代码,即在汽车本身上运行的代码,实际上非常大略。这里是:
/nRF24L01+ Joystick Receiver for Robot Carnrf24l01-joy-rcv-car.inonRF24L01+ Receiver and L298N driver for Robot CarUse with Joystick Transmitter for Robot CarDroneBot Workshop 2018https://dronebotworkshop.com/// Include RadioHead ReliableDatagram & NRF24 Libraries#include <RHReliableDatagram.h>#include <RH_NRF24.h>// Include dependant SPI Library#include <SPI.h>// Define addresses for radio channels#define CLIENT_ADDRESS 1#define SERVER_ADDRESS 2// Motor A Connectionsint enA = 9;int in1 = 14;int in2 = 4;// Motor B Connectionsint enB = 5;int in3 = 7;int in4 = 6;// Create an instance of the radio driverRH_NRF24 RadioDriver;// Sets the radio driver to NRF24 and the server address to 2RHReliableDatagram RadioManager(RadioDriver, SERVER_ADDRESS);// Define a message to return if values receiveduint8_t ReturnMessage[] = "JoyStick Data Received";// Define the Message Bufferuint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];void setup(){// Setup Serial MonitorSerial.begin(9600);// Set all the motor control pins to outputspinMode(enA, OUTPUT);pinMode(enB, OUTPUT);pinMode(in1, OUTPUT);pinMode(in2, OUTPUT);pinMode(in3, OUTPUT);pinMode(in4, OUTPUT);// Initialize RadioManager with defaults - 2.402 GHz (channel 2), 2Mbps, 0dBmif (!RadioManager.init())Serial.println("init failed");}void loop(){if (RadioManager.available()){// Wait for a message addressed to us from the clientuint8_t len = sizeof(buf);uint8_t from;if (RadioManager.recvfromAck(buf, &len, &from)){//Serial Print the values of joystick//Serial.print("got request from : 0x");//Serial.print(from, HEX);//Serial.print(": MotorA = ");//Serial.print(buf[0]);//Serial.print(" MotorB = ");//Serial.print(buf[1]);//Serial.print(" Dir = ");//Serial.println(buf[2]);// Set Motor Directionif (buf[2] == 1){// Motors are backwardsdigitalWrite(in1, LOW);digitalWrite(in2, HIGH);digitalWrite(in3, LOW);digitalWrite(in4, HIGH);}else{// Motors are forwardsdigitalWrite(in1, HIGH);digitalWrite(in2, LOW);digitalWrite(in3, HIGH);digitalWrite(in4, LOW); }// Drive MotorsanalogWrite(enA, buf[1]);analogWrite(enB, buf[0]);// Send a reply back to the originator client, check for errorif (!RadioManager.sendtoWait(ReturnMessage, sizeof(ReturnMessage), from))Serial.println("sendtoWait failed");}}}
实质上,这与我们在上一个演示中利用的吸收器代码相同,但添加了用于定义电机连接的变量。请把稳,我们利用 Arduino 引脚“14”作为变量in1,这当然是仿照 A0 引脚。如果你乐意,你实际上可以在这里更换一个“A0”,它会事情得很好。
在设置中,我们将电机掌握器引脚定义为输出。请把稳,用于两条 L298N 使能线的引脚须要能够进行 PWM,由于这是调节电机速率的办法。
您可能会把稳到我已经注释掉了所有的串口监视器语句。它们并不是真正必要的,只是在汽车运行时挡路,但如果您须要对汽车进行故障打消,则可以“不加把稳”。
缓冲器值对应于我们在发射器中利用的电机掌握值。以是buf[2]掌握电机方向,buf[0]和buf[1]处理电机速率。
电机利用 Arduino 仿照写入功能通过 PWM 进行掌握。
加载代码并启动统统。你现在该当有一辆遥控机器人车了!
如您所见,由于 RadioHead 库,nRF24L01 可用于创建一些非常有用的无线项目,只需很少的代码。如果您不喜好建造机器人汽车,您仍旧可以找到这种强大组合的很多用场








