Open source self-made 6-channel model remote controller, ultra simple and no more than 100 lines of code

Foreword

Some time ago, I followed the LOLI Great God's tutorial to make LOLI three generations of control, and the effect was very good. However, since the receiver of the third generation of LOLI has a data backhaul function, that is, the wireless module of the receiver also undertakes the function of transmitting data, so the receiver must also use the NRF24L01 module with a power amplification chip to achieve long-distance communication This not only increases the cost but also increases the volume. So the author intends to make a simpler 6-channel model remote controller, and just happens to have a Tiandifei-06X without a receiver, and decides to transform it. After consulting the data, he realized the basic functions with the Arduino Pro Mini development board. , The effect is not bad.

1. Bill of Materials

USB to TTL module * 1

Arduino Pro Mini development board * 2

NRF24L01 wireless communication module * 2

1 ams1117-3.3 voltage conversion chip

 

100uF electrolytic capacitor * 2

104 capacitance * 2

Tripod switch * 4

10k resistance * 1, 20k resistance * 1

Wires and pins

2. Hardware

Solder the circuit according to the schematic diagram and enjoy the flying wire horn. If you have the conditions, you can design the PCB to do a better look.

a) Remote control

The remote controller is responsible for sending data, so use the NRF24L01 wireless communication module that can wirelessly transmit 2000m;

The author's flying line can't bear to look directly, the 100m NRF24L01 module is not enough, and the decisive change was 2000m.

 

b) receiver

The receiver is responsible for receiving data. It is enough to use the 100m NRF24L01 wireless communication module.

3. Software part

a) Remote control

Connect the USB to TTL module to the computer, the pin wiring is as follows:

TX0--RXD
RX1--TXD
VCC--3V3
GND--GND

Open the Arduino IDE, select the remote control program to open, here to download the RF24 package library, the download method is as follows:

Project "Load library" Manage library, open the library manager

Enter RF24 to search, select the library in the figure to install, and click close after installation; 

Before programming the program, you must first select your own development board model, as shown in the figure below, the processor selects your own development board type, and the port selects the port number where USB to TTL is located 

Click upload to program

After waiting for the upload to complete, open the serial monitor to view the values ​​of the 4 ADCs;

The communication address can be changed to your favorite address, each digit is hexadecimal (0 ~ 9, A ~ F);

Move the joystick in all directions to view the output value through the serial port monitor, then fill the minimum, median, and maximum values ​​of each channel into the program, and finally upload the code again.

 The complete Arduino code is as follows:

/* ArduinoProMini-6通道发射器 
 *     by Bilibili 蔡子CaiZi
 *     
 * A0~5 -> 模拟输入,2~5 -> 通道正反开关
 * A6 -> 电压检测
 * 6 -> 蜂鸣器
 * 
 * NRF24L01 | Arduino
 * CE    -> 7
 * CSN   -> 8
 * MOSI  -> 11
 * MISO  -> 12
 * SCK   -> 13
 * IRQ   -> 无连接
 * VCC   -> 小于3.6V
 * GND   -> GND
 */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
const uint64_t pipeOut = 0xBBBBBBBBB;   //为何这么多B币?与接收器中相同的地址进行通信
RF24 radio(7, 8); // SPI通信,引脚对应关系:CE ->7,CSN ->8
struct Signal {
  byte roll;
  byte pitch;
  byte throttle;
  byte yaw;
  byte gyr;
  byte pit;
};
Signal data;
void ResetData() 
{
  data.roll = 127; // 横滚通道AIL(中心点127)
  data.pitch = 127; // 俯仰通道ELE
  data.throttle = 0; // 信号丢失时,关闭油门THR
  data.yaw = 127; // 航向通道RUD
  data.gyr = 0; //第五通道
  data.pit = 0; //第六通道
}
void setup()
{
  radio.begin();
  radio.openWritingPipe(pipeOut);//pipeOut通信地址
  radio.stopListening(); //发射模式
  ResetData();//初始化6个通道值
  Serial.begin(115200);
  pinMode(2,INPUT);//正反通道开关为数字输入
  pinMode(3,INPUT);
  pinMode(4,INPUT);
  pinMode(5,INPUT);
  pinMode(6,OUTPUT);//蜂鸣器推挽输出
  if (analogRead(A6)*3.28*3/1023<5){//调整3校准电压检测,5为报警电压
    for(int i=0;i<3;i++){
      digitalWrite(6,HIGH);//蜂鸣器响
      delay(100);
      digitalWrite(6,LOW);
      delay(100);
    }
  }
  else{
    digitalWrite(6,HIGH);//蜂鸣器响
    delay(100);
    digitalWrite(6,LOW);
  }
}

// 将ADC获取的0~1023转换到0~255
int chValue(int val, int lower, int middle, int upper, bool reverse)
{
  val = constrain(val, lower, upper);//将val限制在lower~upper范围内
  if ( val < middle )
    val = map(val, lower, middle, 0, 128);
  else
    val = map(val, middle, upper, 128, 255);
  return ( reverse ? 255 - val : val );
}

void loop()
{
  Serial.print("\t");Serial.print(analogRead(A0));//将数据通过串口输出
  Serial.print("\t");Serial.print(analogRead(A1));
  Serial.print("\t");Serial.print(analogRead(A2));
  Serial.print("\t");Serial.println(analogRead(A3));
  // 需要对摇杆的最值、中值进行设置
  data.roll     = chValue( analogRead(A0), 59,  517, 882, digitalRead(2));
  data.pitch    = chValue( analogRead(A1), 115, 525, 896, digitalRead(3));
  data.throttle = chValue( analogRead(A2), 145, 522, 920, digitalRead(4));
  data.yaw      = chValue( analogRead(A3), 70,  530, 925, digitalRead(5));
  data.gyr      = chValue( analogRead(A4), 0,   510, 1020, false ); 
  data.pit      = chValue( analogRead(A5), 0,   510, 1020, false );  
  radio.write(&data, sizeof(Signal));//将数据发送出去
//  Serial.print("\t");Serial.print(data.roll);
//  Serial.print("\t");Serial.print(data.pitch);
//  Serial.print("\t");Serial.print(data.throttle);
//  Serial.print("\t");Serial.print(data.yaw);
//  Serial.print("\t");Serial.print(data.gyr);
//  Serial.print("\t");Serial.println(data.pit);
}

b) receiver

The download operation on the receiver side is basically the same as the operation on the remote control side, which is not repeated here. The complete code is as follows:

/* ArduinoProMini-6通道接收机 
 *     by Bilibili 蔡子CaiZi
 *     
 * PWM输出 -> 引脚2~6、9
 * 
 * NRF24L01 | Arduino
 * CE    -> 7
 * CSN   -> 8
 * MOSI  -> 11
 * MISO  -> 12
 * SCK   -> 13
 * IRQ   -> 无连接
 * VCC   -> 小于3.6V
 * GND   -> GND
 */
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
int ch_width_1 = 0, ch_width_2 = 0, ch_width_3 = 0, ch_width_4 = 0, ch_width_5 = 0, ch_width_6 = 0;
Servo ch1; Servo ch2; Servo ch3; Servo ch4; Servo ch5; Servo ch6;
struct Signal {    
  byte roll;
  byte pitch;
  byte throttle;  
  byte yaw;
  byte gyr;
  byte pit;
};
Signal data;
const uint64_t pipeIn = 0xBBBBBBBBB;//与发射端地址相同
RF24 radio(7, 8); 
void ResetData()
{
  data.roll = 127; // 横滚通道中心点(254/2 = 127)
  data.pitch = 127; // 俯仰通道
  data.throttle = 0; // 信号丢失时,关闭油门
  data.yaw = 127; // 航向通道
  data.gyr = 0; //第五通道
  data.pit = 0; //第六通道
}
void setup()
{
  //设置PWM信号输出引脚
  ch1.attach(2);
  ch2.attach(3);
  ch3.attach(4);
  ch4.attach(5);
  ch5.attach(6);
  ch6.attach(9);
  //配置NRF24L01模块
  ResetData();
  radio.begin();
  radio.openReadingPipe(1,pipeIn);//与发射端地址相同
  radio.startListening(); //接收模式
  pinMode(LED_BUILTIN,OUTPUT);//LED推挽输出
  digitalWrite(LED_BUILTIN,HIGH);
  Serial.begin(115200);
}
unsigned long lastRecvTime = 0;
void recvData()
{
  while ( radio.available() ) {
    radio.read(&data, sizeof(Signal));//接收数据
    lastRecvTime = millis();   //当前时间ms
  }
}
void loop()
{
  recvData();
  unsigned long now = millis();
  if ( now - lastRecvTime > 1000 ) {
    ResetData(); //两次接收超过1s表示失去信号,输出reset值
//    Serial.print("无信号");
    digitalWrite(LED_BUILTIN,HIGH);
  }
  else{
    digitalWrite(LED_BUILTIN,LOW);
    }
  ch_width_1 = map(data.roll,     0, 255, 1000, 2000);// 将0~255映射到1000~2000,即1ms~2ms/20ms的PWM输出
  ch_width_2 = map(data.pitch,    0, 255, 1000, 2000);
  ch_width_3 = map(data.throttle, 0, 255, 1000, 2000);
  ch_width_4 = map(data.yaw,      0, 255, 1000, 2000);
  ch_width_5 = map(data.gyr,      0, 255, 1000, 2000);
  ch_width_6 = map(data.pit,      0, 255, 1000, 2000);
  Serial.print("\t");Serial.print(ch_width_1);
  Serial.print("\t");Serial.print(ch_width_2);
  Serial.print("\t");Serial.print(ch_width_3);
  Serial.print("\t");Serial.print(ch_width_4);
  Serial.print("\t");Serial.print(ch_width_5);
  Serial.print("\t");Serial.println(ch_width_6);
  // 将PWM信号输出至引脚
  ch1.writeMicroseconds(ch_width_1);//写入us值
  ch2.writeMicroseconds(ch_width_2);
  ch3.writeMicroseconds(ch_width_3);
  ch4.writeMicroseconds(ch_width_4);
  ch5.writeMicroseconds(ch_width_5);
  ch6.writeMicroseconds(ch_width_6);
}

4. Achieve the effect

The video has been uploaded to station B : https://www.bilibili.com/video/BV1Wk4y1R7N3/

In the actual distance test, there is no pressure for wireless transmission of 1000m. At present, only the basic 6-channel remote control function has been realized. Later, it will continue to optimize and improve, and plans to improve the direction:

  1. On the remote control side, OLED display + key detection is added to facilitate human-computer interaction;
  2. At the receiver, add SBUS output and PPM output.

Reference link

http://www.rcpano.net/2020/04/09/how-to-make-6-channel-radio-control-for-models-diy-proportional-rc/

Published 18 original articles · praised 34 · 40,000+ views

Guess you like

Origin blog.csdn.net/weixin_42268054/article/details/105536264