本文共 8461 字,大约阅读时间需要 28 分钟。
NRF24L01 控制电舵机
目录
一、控制舵机
二、控制步进舵机
(一)控制舵机
下面,我们主要介绍如何使用 NRF24L01 和 Arduino 控制伺服电机。我们在发送端移动操纵杆,使用 NRF24L01,将操纵杆移动的值发送到接收侧,然后在接收侧接收该值,使用此值移动伺服电机。模块简介
1
材料准备
Arduino UNO 开发板NRF24L01 模块操纵杆模块伺服电机杜邦线2
NRF24L01引脚说明
该模块的 功耗非常低。它在传输过程中消耗大约 12mA 的功率,甚至低于 LED。该模块工作在 3.3V,因此不要将其直接连接到 5V 的 Arduino,因为它可能会损坏。NRF24L01 模块的其他引脚具有 5V 容限,因此您可以将它们直接连接到Arduino。SCK、MOSI 和 MISO 引脚用于 SPI 通信,CSN 和 CE 引脚用于设置待机或活动模式以及设置发送或命令模式。3
RF遥感模块
RF 摇杆模块非常简单,我们需要从摇杆读取 X 值和 Y 值,然后通过 nRF24L01 将其发送到接收模块。工作原理
伺服电机控制工作在发送侧,我们有一个操纵杆模块、Arduino 和 NRF24L01,而在接收侧,我们有一个 NRF24L01、Arduino 和一个伺服电机。当我们在水平方向上移动操纵杆时,操纵杆模块将向 Arduino 发送模拟值。我们已将 NRF24L01 模块设置为发送模式,并将操纵杆移动值发送到特定地址。在接收侧,将 NRF24L01 模块设置为接收模式。我们在接收端给出了相同的地址,其他 NRF24L01 模块正在传输数据。因此,只要模块接收到数据,Arduino就会读取数据并根据它移动伺服电机。用法用例
1
硬件原理图
连接有点冗长,因此我将分别介绍发送器和接收器的连接。在发送器侧,NRF24L01 与 Arduino 的连接如下:将 NRF24L01 的 3.3V 引脚与 Arduino 的 3.3V 连接 将 NRF24L01 的 GND 引脚与 Arduino 的 GND 连接将 NRF24L01 的 CSN 引脚与 Arduino 的引脚 8 连接 将 NRF24L01 的 CE 引脚与 Arduino 的引脚 7 连接 将 NRF24L01 的 SCK 引脚与 Arduino 的引脚 13 连接将 NRF24L01 的 MOSI 引脚与 Arduino 的引脚 11 连接 将 NRF24L01 的 MISO 引脚与 Arduino 的引脚 12 连接然后将操纵杆模块与 Arduino 连接如下:操纵杆模块的 VCC 到 Arduino 的 5V操纵杆模块的 GND 到 Arduino 的 GND操纵杆模块的 VER 到 Arduino 的 A1操纵杆模块的 HOR 到 Arduino 的 A0在接收器侧,NRF24L01 与 Arduino 的连接与发送器侧的连接相同。使用Arduino 连接伺服电机如下:红线到 Arduino 的 5V棕色线到 Arduino 的 GND黄色线到 Arduino 的引脚 62
示例代码
//reciver#include //包含头文件#include #include #include Servo servo;//创建一个舵机对象RF24 radio(7, 8);//两个参数分别为 Arduino 连接 CE 和 CSN 的引脚const byte address[6] = "00001"; //定义发送数据的地址int servo_pin = 6;//将舵机控制引脚连接到 Arduino 的数字引脚 6void setup() { Serial.begin(9600); //初始化串口,设定串口通信速率为 9600(波特) radio.begin(); //初始化 NRF24L01 servo.attach (servo_pin ) ;//设定舵机的接口 radio.openReadingPipe(0, address); //传输发送数据的地址 radio.setPALevel(RF24_PA_MIN); //设置通信功率 radio.startListening(); }void loop() { if (radio.available()) { int x_pos ;//发射数据口 radio.read(&x_pos, sizeof(x_pos)); //读取数据 Serial.println(x_pos); x_pos = map(x_pos, 0, 1023, 0, 180);//遥感映射函数 servo.write (x_pos) ; } }//Transimitter#include //包含头文件#include #include RF24 radio(7, 8);//两个参数分别为 Arduino 连接 CE 和 CSN 的引脚const byte address[6] = "00001"; //定义接收数据的地址int x_key = A1;//发射数据口int y_key = A0;//接收数据口int x_pos;int y_pos;void setup() { radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); //设置通信功率 radio.stopListening();//设置接收器 pinMode (x_key, INPUT) ; //将引脚设置为输入状态 pinMode (y_key, INPUT) ;//将引脚设置为输入状态 }void loop() { x_pos = analogRead (x_key) ; //读取数据口 y_pos = analogRead (y_key) ; radio.write(&x_pos, sizeof(x_pos));//控制舵机旋转 delay(100); }首先,包括 NRF24L01和伺服电机的库
#include #include #include #include然后,定义我们连接 NRF24L01 的 CSN 和 CE 引脚的引脚。之后,我们初始化将发送和接收数据的地址。该地址在发射机和接收机侧应该相同。该地址可以是任何五个字母的字符串。
RF24 radio(7, 8); // CSN, CE const byte address[6] = "00001";在发送器的 setup()函数中,我们设置了发送数据的地址。然后将功率放大范围设置为最小,因为模块彼此很接近。
radio.openWritingPipe(address);radio.setPALevel(RF24_PA_MIN);在接收器侧,我们使用以下命令并设置模块以从该地址接收数据。
radio.openReadingPipe(0, address);在发送器的 loop()函数中,我们从操纵杆模块读取并在我们之前设置的地址发送值。
radio.write(&x_pos, sizeof(x_pos));接收器侧的以下命令将从发送器获取数据,并且在将数据映射到 0-180 之后,我们将移动伺服电机。
radio.read(&x_pos, sizeof(x_pos));
(二)控制步进电机
下面,我们将使用 Arduino 和 nRF24L01 RF 模块进行远程控制驱动无芯直流电机。这些电机通常用于无人机,额定功率为 39000 RPM,足以满足速度要求。该小车将使用小型锂电池供电。模块简介
无芯直流电机
直流电机存在一些不足。它的速度,难以处理 39000 RPM,因此我们需要在 Arduino 端使用MOSFET 构建的速度控制电路。这些电动机将由工作电压在3.6V 至 4.2V 之间的单个锂聚合物电池供电,因此我们必须将电路设计为在 3.3V 电压下工作。这就是为什么我们将 3.3V Arduino Promini 用来控制电机的原因。1
材料准备
Arduino nano 开发板3.3V Arduino Pro Mini 开发板NRF24L01 模块操纵杆模块无芯无刷直流电机杜邦线锂聚合物电池2
硬件原理图
发射模块
3
引脚说明
nRF24L01 模块在 3.3V 电压下运行,因此我们在 Arduino 上使用了 3.3V 引脚。驱动模块
4
实物链截图
直流电机由连接到 P1 的锂电池供电。AMS117-3.3V 用于为我们的 nRF24L01 和 Mini开发板调节 3.3V。我们还可以直接在插针上为 Arduino 开发板供电,但是 pro mini 上的板载 3.3V 稳压器将无法为我们的 RF 模块提供足够的电流,因此我们使用了外部电源。示例代码
RF驱动代码
#include //包含头文件#include "RF24.h" RF24 myRadio (7, 8); //两个参数分别为 Arduino 连接 CE 和 CSN 的引脚struct package { intmsg=0; }; byte addresses[6] = { "00001"}; //定义发送数据的地址typedef struct package Package; //定义结构体 Package data;void setup() { Serial.begin(9600);//初始化串口,设定串口通信速率为 9600(波特) myRadio.begin(); //初始化 NRF myRadio.setChannel(115); //WIFI 信号上方 115 频段 myRadio.setPALevel(RF24_PA_MAX);//最大功率远射 myRadio.setDataRate( RF24_250KBPS ) ; //最低速度 delay(500); Serial.print("Remote Initialized");//初始化成功int forward;int reverse; }void loop() { int xValue = analogRead(A0);//读取 JoyX 值int yValue = analogRead(A1); //读取 JoyY 值 Serial.print(xValue); Serial.print(" , "); Serial.println(yValue);if (xValue>560 && xValue<1000) //筛选 JoyX { forward = map (xValue, 560, 1000, 1, 10); //将 Joyx-up 转换为 0-10 Serial.print("F="); Serial.println(forward); data.msg = forward; //保存数据 WriteData(); delay(50); }if (xValue<500 && xValue > 10) //筛选 JoyX { reverse = map (xValue, 10, 500, 20, 11); //将 JoyX-down 转换为 11-20 Serial.print("B="); Serial.println(reverse); data.msg = reverse; WriteData(); delay(50); }else { Serial.println("Rest"); data.msg = 0;//更新数据 WriteData(); delay(50); } }void WriteData() //输入函数{ myRadio.stopListening(); //停止接收并开始传送 myRadio.openWritingPipe( 0xF0F0F0F0AA);//在此 20 位地址上发送数据 myRadio.write(&data, sizeof(data)); delay(50); }void ReadData() //读取函数{ myRadio.openReadingPipe(1, 0xF0F0F0F066);//读取哪个管道,20 位地址 myRadio.startListening(); //停止发送并开始接收 if (myRadio.available()) { while (myRadio.available()) { myRadio.read( &data, sizeof(data) ); } Serial.print("\nReceived:"); Serial.println(data.msg); } }
电机驱动代码
/*CE-7 MISO-12 MOSI-11 SCK-13 CS-8*/#define R_IR 3//定义输入输出引脚#define L_IR 4#define L_MR 5 #define R_MR 6 #define min_speed 200 //定义速度#define max_speed 800 #include #include "RF24.h"RF24 myRadio (7, 8);struct package { intmsg; };typedef struct package Package; Package data; byte addresses[6] = { "00001"}; void setup() { pinMode(R_IR, INPUT);//将电机引脚设置为输入状态 pinMode(L_IR, INPUT); pinMode(L_MR, OUTPUT);//将电机引脚设置为输出状态 pinMode(R_MR, OUTPUT); Serial.begin (9600); myRadio.begin(); myRadio.setChannel(115); //WIFI 信号上方 115 频段 myRadio.setPALevel(RF24_PA_MIN); //最小功率 myRadio.setDataRate( RF24_250KBPS ) ; //最低速度int received; }void loop(){ ReadData(); }void Control() //前进后退控制{ if (received>=1 && received <=10) // 向前 { int PWM_Value = map (received, 1, 10, min_speed, max_speed); analogWrite(R_MR,PWM_Value); analogWrite(L_MR,PWM_Value); }else if (received>=11 && received <=20) //向后 { int PWM_Value = map (received, 11, 20, min_speed, max_speed); analogWrite(R_MR,0); analogWrite(L_MR,0); } }void ReadData(){ myRadio.openReadingPipe(1, 0xF0F0F0F0AA); //读取哪个管道,20 位地址 myRadio.startListening(); //停止发送并开始接收if ( myRadio.available()) //有来自 RF 的数据 { while (myRadio.available()) { myRadio.read( &data, sizeof(data) ); } Serial.print("\nReceived:"); Serial.println(data.msg); received = data.msg; Control_Car(); } }void WriteData() { //向电机输入转动方向 myRadio.stopListening(); //停止接收并开始传送 myRadio.openWritingPipe(0xF0F0F0F066);//在此 20 位地址上发送数据 myRadio.write(&data, sizeof(data)); Serial.print("\nSent:"); Serial.println(data.msg); delay(300); }接下来,在 loop 函数中,我们将仅执行 ReadData 函数,通过该函数我们将不断读取从发送器摇杆模块发送的值。请注意,程序中提到的管道地址应与发送器程序中提到的管道地址相同。我们还打印了我们收到的用于调试的值。成功读取该值后,我们将执行 Control 函数,根据从 RF 模块接收到的值来控制直流电机。
void ReadData() { myRadio.openReadingPipe(1,0xF0F0F0F0AA); myRadio.startListening();if ( myRadio.available()) { while (myRadio.available()) { myRadio.read( &data, sizeof(data) ); } Serial.print("\nReceived:"); Serial.println(data.msg); received = data.msg; Control_Car(); } }
在 Control 函数内,我们将使用模拟写入功能来控制连接到 PWM 引脚的电机。在我们的发送器程序中,我们已将 Nano 的 A0 和 A1 引脚的模拟值转换为 1 到 10、11 到 20,以分别控制电机向前、向后。以下程序用于控制向前 if (received>=1 && received <=10) // Move Forward { int PWM_Value = map (received, 1, 10, min_speed, max_speed); analogWrite(R_MR,PWM_Value);analogWrite(L_MR,PWM_Value); }完成代码后,将其上传到 pro mini 开发板。通过 FTDI 模块取出电池和电路板进行测试。启动代码,打开串口监视器,您应该从发送器的摇杆模块接收到该值。连接电池,电动机也应开始旋转。
以上代码文件及使用的库可以到以下QQ群统一下载
机甲学院技术交流QQ群
931630584
转载地址:http://sfevl.baihongyu.com/