欢迎光临散文网 会员登陆 & 注册

丐版3通道带屏体感遥控器制作

2023-10-04 12:23 作者:暖风新叶柳  | 我要投稿

仅供学习使用,请勿用于飞行,否则失控炸机后果自负。。。

https://www.bilibili.com/video/BV1n8411C7We/?vd_source=0f4ae06f18a4b63b55bb17a7500b26e3

老外的开源程序,经过删减和修改,使用JY-61等模块制作。

遥控器可接一个0.91inch OLED屏,显示出3轴欧拉角。

接收机可带3个舵机。


遥控器:

#include <SPI.h> // 加载SPI库

#include <Wire.h>

#include <JY901.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <nRF24L01.h>                     //使用NRF24L01需要用到的库

#include <RF24.h>         

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define CE_pin 7                          //NRF24L01 CE引脚连接10号引脚(RFnano旧版)D7(RFnano V3)

#define CSN_pin 8                         //NRF24L01 CSN引脚接9号引脚(RFnano旧版)D8(RFnano V3)

/////////////////////

float anglex, angley, anglez;

float accx, accy, accz;

float wx, wy, wz;

float accx0, accy0, accz0;

float anglex0, angley0, anglez0;

float wx0, wy0, wz0;

float accAngleX, accAngleY;

float gyrodriftx,gyrodrifty,gyrodriftz;

float elapsedTime, currentTime, previousTime;

int i=1;

struct Data_Package {

  byte j1PotX;//byte

  byte j1PotY;

  byte j1PotZ;

};

Data_Package data; //Create a variable with the above structure

const byte addresses[][6] = {"00001", "00002"};  //NRF24L01地址


RF24 radio(CE_pin, CSN_pin);              //配置NRF24L01 CE和CSN引脚

///////////////////////

void setup() 

{

  

   Serial.begin(115200);

   radio.begin();                          //开启NRF24L01通信

   radio.openWritingPipe(addresses[1]);    //规定NRF24L01地址,发送端和接收端设置相同的地址,并以此方式启用两个模块之间的通信。

   radio.setPALevel(RF24_PA_MAX);          //设置功率放大器电平

   radio.stopListening();                  //停止NRF24L01的接收,作为发送端

   delay(10);

    

   display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

   display.clearDisplay();

   while (Serial.available()) 

  {

    JY901.CopeSerialData(Serial.read()); //Call JY901 data cope function

  } 

    delay(2000);  

 for (i=1;i<=50;i+=1)

  {

    accx0=(float)JY901.stcAcc.a[0]/32768*16+accx0;

    accy0=(float)JY901.stcAcc.a[1]/32768*16+accy0;

    accz0=(float)JY901.stcAcc.a[2]/32768*16+accz0;

    anglex0=(float)JY901.stcAngle.Angle[0]/32768*180+anglex0;

    angley0=(float)JY901.stcAngle.Angle[1]/32768*180+angley0;

    anglez0=(float)JY901.stcAngle.Angle[2]/32768*180+anglez0;

    wx0=(float)JY901.stcGyro.w[0]/32768*2000;

    wy0=(float)JY901.stcGyro.w[1]/32768*2000;

    wz0=(float)JY901.stcGyro.w[2]/32768*2000;  

     delay(50);

  }

   accx0=accx0/50;

   accy0=accy0/50;

   accz0=accz0/50;

   anglex0=anglex0/50;

   angley0=angley0/50;

   anglez0=anglez0/50;

   display.setTextSize(1.2); // Draw 2X-scale text 2倍字体

   display.setTextColor(SSD1306_WHITE);

   display.setCursor(0, 0); //显示的坐标位置

   display.print("drift wx:");

   display.println(wx0);

   display.print("drift wy:");

   display.println(wy0); 

   display.print("drift wz:");

   display.println(wz0); 

   display.display();

   delay(3000);

   display.clearDisplay();

}


void loop() 

{

  accx=(float)JY901.stcAcc.a[0]/32768*16-accx0;

  accy=(float)JY901.stcAcc.a[1]/32768*16-accy0;

  accz=(float)JY901.stcAcc.a[2]/32768*16-accz0;

 

  wx=(float)JY901.stcGyro.w[0]/32768*2000-wx0;

  wy=(float)JY901.stcGyro.w[1]/32768*2000-wy0;

  wz=(float)JY901.stcGyro.w[2]/32768*2000-wz0;


  previousTime = currentTime;        // Previous time is stored before the actual time read

  currentTime = millis();            // Current time actual time read

  elapsedTime = (currentTime - previousTime) / 1000;   // Divide by 1000 to get seconds

  gyrodriftx = wx0 * elapsedTime;

  gyrodrifty = wy0 * elapsedTime;

  gyrodriftz = wz0 * elapsedTime;

 

  anglex=(float)JY901.stcAngle.Angle[0]/32768*180-anglex0;

  angley=(float)JY901.stcAngle.Angle[1]/32768*180-angley0;

  anglez=(float)JY901.stcAngle.Angle[2]/32768*180-anglez0;

  if (anglez<=-180)

  {anglez=360+anglez;}

  accAngleX = (-atan(accy / sqrt(pow(accx, 2) + pow(accz, 2))) * 180 / PI) ;

  accAngleY = (atan(accx / sqrt(pow(accy, 2) + pow(accz, 2))) * 180 / PI);

  anglex=(anglex +  gyrodriftx)*0.98 + 0.02 * accAngleX;

  angley=(angley +  gyrodrifty)*0.98 + 0.02 * accAngleY;

  anglez= anglez +  gyrodriftz;

  display.clearDisplay();

  display.setTextSize(1.2); // Draw 2X-scale text 2倍字体

  display.setTextColor(SSD1306_WHITE);

  display.setCursor(0, 0); //显示的坐标位置

  display.print("GY:");

  display.print(wx);

  display.print(",");

  display.print(wy);

  display.print(",");

  display.println(wz);     

  display.print("AC:");

  display.print(accx);

  display.print(",");

  display.print(accy);

  display.print(",");

  display.println(accz);

  display.print("Angle:");

  display.print(anglex);

  display.print(",");

  display.print(angley);

  display.print(",");

  display.println(anglez);

  display.display();  

  


  if (anglex<-90){anglex=-90;

  }

  if (anglex>90){anglex=90;} 

  if (anglez<-90){anglez=-90;}

  if (anglez>90){anglez=90;} 


  data.j1PotX = map(anglex, -100, +100, 0, 255);

  data.j1PotY = map(angley, -100, +100, 0, 255);

  data.j1PotZ = map(anglez, -120, +120, 0, 255);

  radio.write(&data, sizeof(Data_Package));          //radio.write()函数,将消息发送给接收器,第一个参数是想要发送的变量,通过在变量名之前使用“&”,设置一个指针用于存储我们想要发送的数据的变量,第二个参数设置了我们想要从该变量中获取的字节数。

  //radio.write(&anglez, sizeof(anglez));   

}



/*

  SerialEvent occurs whenever a new data comes in the

 hardware serial RX.  This routine is run between each

 time loop() runs, so using delay inside loop can delay

 response.  Multiple bytes of data may be available.

 */

void serialEvent() 

{

  while (Serial.available()) 

  {

    JY901.CopeSerialData(Serial.read()); //Call JY901 data cope function

  }

}


接收机:

/*

   Arduino RC Airplane

   == Receiver Code =

  by Dejan, www.HowToMechatronics.com

  Library: TMRh20/RF24, https://github.com/tmrh20/RF24/

*/

#include <SPI.h>

#include <nRF24L01.h>

#include <RF24.h>

#include <Servo.h>



RF24 radio(7, 8);   // nRF24L01 (CE, CSN)

const byte addresses[][6] = {"00001", "00002"};

unsigned long lastReceiveTime = 0;

unsigned long currentTime = 0;


Servo rudderServo;

Servo elevatorServo;

Servo aileron1Servo;


int rudderValue, elevatorValue, aileron1Value;

// Max size of this struct is 32 bytes - NRF24L01 buffer limit

struct Data_Package {

  byte j1PotX;

  byte j1PotY;

  byte j1PotZ;

};

Data_Package data; //Create a variable with the above structure

void setup() {

  Serial.begin(9600);

  radio.begin();

  radio.openReadingPipe(1, addresses[1]);  

  radio.setPALevel(RF24_PA_MAX);

  radio.startListening(); //  Set the module as receiver

  resetData(); 

  rudderServo.attach(6);   // CH1

  elevatorServo.attach(5); // CH2

  aileron1Servo.attach(4); // CH3


}

void loop() {

  // Check whether we keep receving data, or we have a connection between the two modules

  currentTime = millis();

  if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection

    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function

  }

  // Check whether there is data to be received

  if (radio.available()) {

    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure

    lastReceiveTime = millis(); // At this moment we have received the data

  }

 

  // Elevator control

  elevatorValue = map(data.j1PotY, 0, 255, 0, 100);

  elevatorServo.write(elevatorValue);

  

  // Ailerons control

  aileron1Value = map(data.j1PotX, 0, 255, 0, 100);

  aileron1Servo.write(aileron1Value);



  // Rudder control

  rudderValue = map(data.j1PotZ, 0, 255, 0, 100);

  rudderServo.write(rudderValue);


 

}

void resetData() {

  // Reset the values when there is no radio connection - Set initial default values

  data.j1PotX = 127;

  data.j1PotY = 127;

  data.j1PotZ = 127;

}


丐版3通道带屏体感遥控器制作的评论 (共 条)

分享到微博请遵守国家法律