Sunday 11 June 2017

Arduino DIY Transmitter & Receiver For Quadcopter/Drone/UAV (AT9)





Flight Test:

https://www.youtube.com/watch?v=Ogv1lEFTNxo



In this post, i just share an idea, not full toturial.


Bulan bulan puasa ni nak share sikit pasal DIY transmitter & receiver. Maybe dapat bantu korang budak budak RC atau student.

Sebernarnya kan, kalau korang dah boleh buat transmitter dengan receiver ni sendiri, bermakna korang boleh tukar drone korang jadi Autonomous Drone. Abenda tu? drone yang boleh terbang sendiri tanpa kita kawal. Kira nya automatik terbang sendiri. Macam mana? simple je, edit sikit sikit je lagi code yang aku share nanti.

Tapi aku tak buat lagi autonomous drone tu sebab laptop aku low spec. Tak cukup power nak buat image processing. Kalau korang nak tambah barometer ke, optic flow sensor ke, image processing ke, korang boleh celup idea atau code aku nak share ni.

Dalam post ni Bang Jaki guna transmitter brand RadioLink model AT9 yang rosak masa competition robotik dulu. Tak puas hati tak tahu kat mana rosak nya. Sekali main board dia yang rosak.

How its work?




Ni cara transmitter dan receiver ni berfungsi.

Transmitter:
-Potentiometer ni dari user lah. Kita gerak kan stick, nanti potentiometer keluarkan bacaan dan hantar bacaan tu ke Arduino Uno.
- Pastu Arduino Uno akan mula hantar bacaan tu ke NRF24L01 (SPI) untuk dihantar ke NRF24L01 yang kedua, iaitu receiver. 
-Dalam masa yang sama LED(indicator) akan berkelip untuk bagi tahu kita yang transmission sedang berlaku. Yang Vibrator Motor tu pulak akan gegar kan transmitter (vibrate/shaking) sebelum berlaku transmission.

Receiver:
-Lepas NRF24L01 pertama hantar bacaan, NRF24L01 yang kedua akan menerima bacaan tu, then dia hantar ke Arduino Nano.
-Arduino Nano ni lah yang convert bacaan dari potentiometer tadi ke bentuk Pulse Width Modulation (PWM). Untuk convert bacaan ni korang kena guna library servo. Library ni memang dah ada dalam Arduino. Tinggal nak call je. Pastu guna function .writeMicroseconds(); untuk convert.
-Lepas convert apa lagi, terus Arduino Nano keluarkan PWM value untuk send ke flight controller.
-Flight Controller yang Bang Jaki guna ni SP Racing Deluxe, setup dalam CleanFlight Configurator 2.0.3. Korang boleh guna apa apa jenis configurator atau apa apa brand FC asal kan support PWM. 

Kalau FC korang tak support PWM, cuma support SBUS/PPM cemana?
Dont worry, boleh guna signal converter dari PWM to PPM, SBUS! Ni Bang Jaki tunjuk salah satu converter yang OscarLiang rekemen kat blog dia.



1. Malas borak banyak, basically dalam remote ni ada Potentiometer

Potentiometer ni ada kat setiap stick untuk measure perubahan kedudukkan stick. Ni gambor potentiometer kalau korang buta elektronik sangat. Aku malas explaine detail sangat nanti panjang berjele jele.

Potentiometer ni akan keluar kan bacaan bila kita gerak kan stick. So dalam Arduino aku function analogRead();  untuk baca bacaan setiap stick.


Potentiometer



Inside Potentiometer


Haa ni pulak bahagian dalam AT9. Ni gambar masa lepas bukak hari tu. Hijau tu Main Board dia yang rosak tu. Dekat situ banyak wayar potentiometer disambung. Aku cabut semua nya






2. Lepas read bacaan dari potentiometer, aku send data tu guna NRF24L01 kepada receiver.

Lepas cabut semua aku try lah guna satu potentiometer untuk kawal throttle. Aku test satu per satu. control rudder, elevator etc.



NRF24L01 Module With Antena







Untuk baca bacaan dari potentiometer Bang Jaki attach kat pin Analog In Arduino Uno





Lepas test semua okay, solder semua cable ke pin Arduino supaya tak tertanggal/longgar.






Dah confident semua wiring okay, terus glue semua benda guna hot glue gun. Supaya tak
bergerak gerak, tercabut atau tertanggal nanti. Silap silap ada cable putus.








Lepas glue, guna cable tie untuk kemas kemas kan sikit wiring.






Lepas apa lagi, ikat semua skru. Then upload code untuk test!









3. Subtrim & End Point

Mari sini ajar sikit buat subtrim dengan End Point. Benda ni penting kalau tak, drone fly cam taik sikit. Benda ni Bro Macus yang ajar aku dulu. Tapi dia ajar guna AT9 betul, bukan AT9 Diy ni. Apa apa pun dia banyak ajar aku main benda ni :D



        Benda ni kalau nak senang buat dekat dalam program Receiver. Tapi kalau nak buat dalam

program transmitter pun boleh. Ni aku saja letak gambar program transmitter. Adjust lah sampai dapat macam mana korang setting dalam configurator.
Bang Jaki setting 1000, 1500, 2000









Adjust benda ni sama je macam korang adjust subtrim & endpoint kat transmitter biasa.
Cuma kat sini korang trim kat dalam program. Nampak baris yang highlight tu? 

pwm1.writeMicroseconds(pwmE+4);

Kalau subtrim korang kurang, korang tambah dalam bracket tu. Kalau lebih tolak
Contoh:

pwm1.writeMicroseconds(pwmE-8);
pwm2.writeMicroseconds(pwmA-5);
pwm3.writeMicroseconds(pwmR+10);
pwm4.writeMicroseconds(pwmT+2);

Lagi satu nak pesan, nak buat Subtrim dengan End Point, better refer reading kat dalam configurator. Sebab ada sedikit berbeza. Contoh alam gambar bawah ni. Dalam Arduino lain, kat configurator lain bacaan. tapi tak banyak pun beza nya.







4. Untuk Receiver pulak korang follow je wiring ni

Untuk connection Arduino dengan NRF24L01
Selebih nya wiring ke flight controller, korang follow je dalam program. Dah penat malas nak taip atau lukis wiring untuk korang.

pwm1.attach(2);    = Elevator pin at FC connect to pin 2 Arduino 
pwm2.attach(3);
pwm3.attach(4);    = Throttle pin at FC connect to pin 4 Arduino 
pwm4.attach(5);
AUX1.attach(6);
AUX2.attach(9)
AUX3.attach(10);
pinMode(A0, OUTPUT);  = LED to pin A0 on Arduino

BEC 5v from PDB connect to pin VIN
GND to GND








5. Code

NOTE: i found many library for NRF24L01, and not all library can compile this code!





For Transmitter :



/*
 * this code written by zaki zakaria on 26/05/2017
 * how ? visit ohhmyproject.blogspot.com
 * maybe useful in certain situation
   Arduino pin freqeuncy run at 490Hz on pin 3,9,10,11  || run on 976Hz pin 5,6
*/

#include <SPI.h>
#include <nRF24L01p.h>

//AERT
int AIL = A0; int ELE = A1; int RUD = A3; int THRO = A2; int AUX1 = A4; int AUX2 = A5; //pin
#define vibrator 9
#define indicator 6
nRF24L01p transmitter(7, 8); //CSN,CE
nRF24L01p transmitter2(7, 8); //create second line transmission


void setup() {
  delay(150);
  Serial.begin(115200);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  transmitter.channel(90);
  transmitter2.channel(90);
  transmitter.TXaddress("ALL");
  transmitter2.TXaddress("ALL");
  transmitter.init();
  transmitter2.init(); //create 2nd line transmission
  pinMode(AIL, INPUT); pinMode(ELE, INPUT); pinMode(RUD, INPUT); pinMode(THRO, INPUT); pinMode(AUX1, INPUT); pinMode(AUX2, INPUT);
  pinMode(vibrator, OUTPUT); pinMode(indicator, OUTPUT);
  //Turn ON vibrator motor & led on transmitter 
  analogWrite(vibrator, 100); digitalWrite(indicator, HIGH); delay(800); analogWrite(vibrator, 0); digitalWrite(indicator, LOW); delay(200);
  analogWrite(vibrator, 100); digitalWrite(indicator, HIGH); delay(800); analogWrite(vibrator, 0); delay(200); digitalWrite(indicator, LOW);
  Serial.setTimeout(10);
}
String fromSerial; String pWm, Aux, ch1, ch2, ch3, ch4, ch5, ch6;

void loop() {
  digitalWrite(indicator, HIGH); delay(10); //blink led
  int AIL_VAL = analogRead(AIL); int ELE_VAL = analogRead(ELE); int RUD_VAL = analogRead(RUD); int THRO_VAL = analogRead(THRO);
  int AUX1_VAL = analogRead(AUX1); int AUX2_VAL = analogRead(AUX2);

  AIL_VAL = map(AIL_VAL, 35, 1023, 1000, 2000)+30;  //subtrim & end point
  ELE_VAL = map(ELE_VAL, 30, 960, 1000, 2000)-10;  //subtrim & end point
  RUD_VAL = map(RUD_VAL, 27, 970, 1000, 2000)+30;  //subtrim & end point
  THRO_VAL = map(THRO_VAL, 70, 970, 1000, 2000);  //subtrim & end point
  AUX1_VAL = map(AUX1_VAL, 0, 1023, 1000, 2000);  //subtrim & end point
  AUX2_VAL = map(AUX2_VAL, 0, 1023, 1000, 2000);  //subtrim & end point

  if(ELE_VAL > 2000){ELE_VAL=2000;} if(ELE_VAL <1000){ELE_VAL= 1000;}
  if(AIL_VAL > 2000){AIL_VAL=2000;} if(AIL_VAL <1000){AIL_VAL= 1000;}
  if(RUD_VAL > 2000){RUD_VAL=2000;} if(RUD_VAL <1000){RUD_VAL= 1000;}
  if(THRO_VAL > 2000){THRO_VAL=2000;} if(THRO_VAL < 1000){THRO_VAL=1000;}

  ch1=String(ELE_VAL); ch2=String(AIL_VAL); ch4=String(RUD_VAL); ch3=String(THRO_VAL); ch5=String(AUX1_VAL); ch6=String(AUX2_VAL);

  pWm=String('A'+ch1+'E'+ch2+'R'+ch4+'T'+ch3);  //convert pwm value (AERT) to string before send to RX
  Aux=String('L'+ch5+'M'+ch6);  //convert aux1 and aux2 value to string before send to RX
  
  Serial.print("toSendpWm: "); Serial.print(pWm); Serial.print("       "); 
  Serial.print("toSendAux: "); Serial.println(Aux);
  //Serial.print("ELE_VAL: ");Serial.print(ch1); Serial.print("   "); Serial.print("AIL_VAL: ");Serial.print(ch2); Serial.print("   ");
  //Serial.print("RUD_VAL: ");Serial.print(ch4); Serial.print("   "); Serial.print("THRO_VAL: ");Serial.print(ch3); Serial.print("   ");
  //Serial.print("AUX1_VAL: ");Serial.print(ch5); Serial.print("   "); Serial.print("AUX2_VAL: ");Serial.println(ch6);
  transmitter.txPL(pWm);
  transmitter.send(FAST);
  digitalWrite(indicator, LOW); delay(20); //blink led
  //transmitter2.txPL(Aux);
  //transmitter2.send(FAST);
  
} //closing for void loop


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







For Receiver:


/*
 * this code written by zaki zakaria on 26/05/2017
 * how ? visit ohhmyproject.blogspot.com
 * maybe useful in certain situation
   Arduino pin freqeuncy run at 490Hz on pin 3,9,10,11  || run on 976Hz pin 5,6
*/


#include <SPI.h>
#include <nRF24L01p.h>
#include <Servo.h>

int minThrottleWrite = 980;  // for arming

Servo pwm1; Servo pwm2; Servo pwm3; Servo pwm4; Servo AUX1; Servo AUX2; Servo AUX3;

String A;
String E;
String R;
String T;

nRF24L01p receiver(7, 8); //CSN,CE
//nRF24L01p receiver2(7, 8); //2nd receiver

void setup() {
  delay(150);
  Serial.begin(115200);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  receiver.channel(90);
  //receiver2.channel(90);
  receiver.RXaddress("ALL");
  //receiver2.RXaddress("ALL");
  receiver.init();
  //receiver2.init();
  pwm1.attach(2); pwm2.attach(3); pwm3.attach(4); pwm4.attach(5); AUX1.attach(6); AUX2.attach(9); AUX3.attach(10);
  pinMode(A0, OUTPUT);
  Serial.setTimeout(10);

  pwm1.writeMicroseconds(1504);   //default setup
  pwm2.writeMicroseconds(1504);
  pwm3.writeMicroseconds(minThrottleWrite); 
  pwm4.writeMicroseconds(1504);
  AUX1.writeMicroseconds(1000);
  AUX2.writeMicroseconds(1900);  
  //AUX3.writeMicroseconds(1900);
  digitalWrite(A0, HIGH); delay(2000);
  digitalWrite(A0, LOW); delay(2000);
  digitalWrite(A0, HIGH); delay(2000);  //waiting for fc, esc ready before arming
  digitalWrite(A0, LOW); delay(2000);
  digitalWrite(A0, HIGH); delay(2000);
  digitalWrite(A0, LOW); delay(2000);
  AUX1.writeMicroseconds(1900);  //arming
  Serial.println("Ready..");
}

String message;

void loop() {
  if (receiver.available()) {
    receiver.read();
    receiver.rxPL(message);
    //Serial.print("Message: "); Serial.print(message);
    digitalWrite(A0, HIGH);  //signal status
    delay(20);
    digitalWrite(A0, LOW);  //signal status
    delay(20);


    A = message.substring(1, 5);
    E = message.substring(6, 10);
    R = message.substring(11, 15);
    T = message.substring(16, 20);

    int pwmA = (A.toInt()-3000)*-1;
    int pwmE = E.toInt();
    int pwmR = (R.toInt()-3000)*-1;
    int pwmT = T.toInt();

    pwm1.writeMicroseconds(pwmE+4);  //pitch min=1004  mid=  max=2004
    pwm2.writeMicroseconds(pwmA+4);  //roll min=1004   mid=1504   max=2004
    pwm3.writeMicroseconds((pwmT+4)-10);  //throttle value
    pwm4.writeMicroseconds(pwmR+4);  //yaw min=1004   mid=1504    max=2004
    //AUX1.writeMicroseconds(1900);  //on barometer. range 1750-2000
    //AUX2.writeMicroseconds(1100);  //flight mode || angle 900-1400 || Horizon 1600-2100
    //AUX3.writeMicroseconds(1800);  //arming range 1700-2100

    Serial.print("   E: "); Serial.print(pwmA); Serial.print("   A: "); Serial.print(pwmE);
    Serial.print("   R: "); Serial.print(pwmR); Serial.print("   T: "); Serial.println(pwmT);
    message = "";
  }

  else
  {
    digitalWrite(A0, LOW);
  }
}

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