Arduino+2.4G模块做航模遥控器
萌新第一次发文,多多关照~
玩航模估计有七八年了,玩arduino和各类单片机也有一两年啦,今年回家以后因为疫情被困在家里回不去,就寻思着用arduino做个2.4g的遥控和接收。闲话不多说,开始正文。
2.4G模块
接线还有其他的基础介绍可以参考凌顺实验室的介绍和示意,我感觉很不错
Arduino 2.4G通信实验 nRF24L01模块的简单例子
我用的是两块Nano来做主板,接线与Uno基本相同。
库下载地址: https://github.com/nRF24/RF24
或者在Arduino IDE 的库管理器中搜索nrf24,作者为TMRh20
接线大致如下
然后就是上程序。
发送部分
#include "SPI.h" //24L01库文件
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
int a; //定义一个变量储存前一次通道参数;
int aa; //改变后的通道参数;
int b;
int bb;
int c;
int cc;
int d;
int dd;
int e;
int ee;
int x=2; //开关通道;
int y=3;
int z=4;
int f=4001;
int g=4002;
int h=4003;
int i = 4005;
int data;
void setup(){
Mirf.spi = &MirfHardwareSpi; //加载24L01 SPI
Mirf.init(); //开始
Mirf.setTADDR((byte *)"serv1");//发送到"接收地址"
Mirf.payload = sizeof(int); //将数据类型定义为整型;
Mirf.config();
Serial.begin(9600);
pinMode(x,INPUT);
pinMode(y,INPUT);
pinMode(z,INPUT);
}
void loop(){
a=analogRead(A7); //读取电位器电平(0至1023),一定要是模拟接口才可以。
b=analogRead(A6);
c=analogRead(A2);
d=analogRead(A3);
e=analogRead(A1);
a=map(a,0,1023,0,999) ; //map函数将读取到的数据转换成不同区间的数,加以区分;
b=map(b,0,1023,1000,1999) ;
c=map(c,0,1023,2000,2999) ;
d=map(d,0,1023,3000,3999) ;
e=map(e,0,1023,5000,5999) ;
Mirf.send((byte *)&a); //向接收机发送数据;
while(Mirf.isSending()){ //等待发送完毕;
}
Mirf.send((byte *)&b);
while(Mirf.isSending()){
}
Mirf.send((byte *)&c);
while(Mirf.isSending()){
}
Mirf.send((byte *)&d);
while(Mirf.isSending()){
}
Mirf.send((byte *)&e);
while(Mirf.isSending()){
}
if (a !=aa) { //如果数值改变,则参数发生改变,aa是一个中间变量;
aa=a;
}
if (b !=bb) {
bb=b;
}
if (c !=cc) {
cc=c;}
if (d !=dd) {
dd=d;}
if (e !=ee) {
ee=e;
}
int x_1 = digitalRead(x); //读取开关通道的电平;
if (x_1==0)
{
Mirf.send((byte *)&f); //若开关通道为低电平,则发送数据;开关通道我接了个1k的上拉电阻(连接5v),不接有干扰;
while(Mirf.isSending()){
}
}
int y_1 = digitalRead(y);
Serial.println(y_1);
if (y_1==0)
{
Mirf.send((byte *)&g);
while(Mirf.isSending()){
}
}
if (y_1==1)
{
Mirf.send((byte *)&i);
while(Mirf.isSending()){
}
}
int z_1 = digitalRead(z);
if (z_1==0)
{
Mirf.send((byte *)&h);
while(Mirf.isSending()){
}
}
delay(10); // 等待0.01秒,等待接收部分清理缓存;
}
接收部分
#include "SPI.h" //24L01库文件
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
#include <Servo.h>
Servo myservo1; // 定义舵机,使用舵机库;
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;
Servo myservo6;
int data;
int a;
int b;
int c;
int d;
int e;
int h = 1000;
int pin3=3;
int pin4=4;
int pin5=5;
int pin6=6;
int pin10=10;
int pin2=2;
int pin9=9;
void setup(){
myservo1.attach(pin3,1000,2000); // 定义舵机通道,还有转动角度;
myservo2.attach(pin4,1000,2000);
myservo3.attach(pin5,1000,2000);
myservo4.attach(pin6,1000,2000);
myservo5.attach(pin9,1000,2000);
myservo6.attach(pin2,1000,2000);
Mirf.spi = &MirfHardwareSpi; //加载24L01 SPI
Mirf.init();
Mirf.setRADDR((byte *)"serv1"); //接收地址" ",一定要与发送端地址相同;
Mirf.payload = sizeof(int); //定义数据类型为整型;
Mirf.config();
Serial.begin(9600);
pinMode(pin10,OUTPUT); //开关通道定为输出通道,要接一个继电器用于点燃拉烟器。
}
void loop(){
digitalWrite(pin10,LOW);
analogWrite(A1,0); //数字IO口不足,用模拟接口代替;
analogWrite(A2,0);
analogWrite(A3,0);
if(Mirf.dataReady()){ //如果接收到数据则执行
Mirf.getData((byte *)&data); //接收数据
if (data>=0&&data<=999) //如果数据处于此区间,则说明数据是发送部分的a;
{
a=map(data,0,999,2000,1000); //将a的数据转变为舵机转动的角度;
myservo1.writeMicroseconds(a); //舵机转动;因为输出的是pwm信号,所以也可以直接接电调;
}
if (data>=1000&&data<=1999)
{
b=map(data,1000,1999,1000,2000);
myservo2.writeMicroseconds(b);
}
if (data>=2000&&data<=2999)
{
c=map(data,2000,2999,1200,1800); //这个通道被我拿来当升降舵通道,我觉得舵量太高就改小了,方法是将1000,2000同时减去一个数,如果要通道反向就将两个数位置调换即可;
myservo3.writeMicroseconds(c);
}
if (data>=3000&&data<=3999)
{
d=map(data,3000,3999,1200,1800);
myservo4.writeMicroseconds(d);
}
if (data>=5000&&data<=5999)
{
e=map(data,5000,5999,1314,1800);
myservo5.writeMicroseconds(e);
}
if(data==4001)
{
digitalWrite(pin10,HIGH); //开关通道为高电平;
}
if(data==4002)
{
myservo6.writeMicroseconds(1000);
}
if(data==4005)
{
myservo6.writeMicroseconds(1500);
}
if(data==4006)
{
myservo6.writeMicroseconds(2000); //我做的三段开关;
}
if(data==4003)
{
analogWrite(A1,1023); //模拟通道高电平;
}
if(data==4004)
{
analogWrite(A2,1023);
}
Mirf.rxFifoEmpty(); //清理24L01援存
}
}
总结
这样做出来的遥控器大概是八通道,对于航模来说已经绰绰有余了,因为我买的是半双工的2.4g,所以无法实现数据回传,或者说数据回传会造成很高的数据延迟,就没有加到程序里。如果要拓展通道的话直接增加区间减小区间就可以了,理论上可以做无数个通道只要io口足够,不过并不推荐,够用就行,否则延迟增高。前几天买了个曼塔K3的遥控器,看着挺高级的才花了八十,上面有一个大功率的2.4g和5.8g模块,接下来准备写几块板子做个好点的遥控器,就酱。