Arduino+2.4G模块做航模遥控器

Arduino+2.4G模块做航模遥控器

萌新第一次发文,多多关照~
玩航模估计有七八年了,玩arduino和各类单片机也有一两年啦,今年回家以后因为疫情被困在家里回不去,就寻思着用arduino做个2.4g的遥控和接收。闲话不多说,开始正文。

2.4G模块

接线还有其他的基础介绍可以参考凌顺实验室的介绍和示意,我感觉很不错
Arduino 2.4G通信实验 nRF24L01模块的简单例子
我用的是两块Nano来做主板,接线与Uno基本相同。
库下载地址: https://github.com/nRF24/RF24

或者在Arduino IDE 的库管理器中搜索nrf24,作者为TMRh20
接线大致如下
Arduino+2.4G模块做航模遥控器_第1张图片
然后就是上程序。

发送部分

#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 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模块,接下来准备写几块板子做个好点的遥控器,就酱。

你可能感兴趣的:(Arduino+2.4G模块做航模遥控器)