آموزش آردوینو پروژه های آردوینو پهپاد Drone

آموزش ساخت کوادکوپتر با آردوینو — جلسه ۴

نوشته شده توسط حسین فهیمی

کالیبره کردن تجهیزات کوادکوپتر یک مرحله مهم در فرآیند تنظیم و آماده‌سازی کوادکوپتر برای پرواز است. این کالیبره کردن به منظور اطمینان از عملکرد صحیح تجهیزاتی مانند ژیروسکوپ، شتاب‌سنج، قطب‌نما (Compass)، GPS و سایر سنسورها انجام می‌شود.

ژیروسکوپ (Gyroscope) و شتاب‌سنج (Accelerometer):

قبل از هر پرواز، کوادکوپتر باید بر روی یک سطح صاف و افقی قرار گیرد.
از طریق نرم‌افزار کنترل پرواز یا رادیوکنترل، دستور کالیبره کردن ژیروسکوپ و شتاب‌سنج را صادر کنید.
کوادکوپتر تجهیزات را کالیبره می‌کند و تنظیمات مرتبط با این سنسورها به روزرسانی می‌شود.

قطب‌نما (Compass) و GPS:

برای کالیبره کردن قطب‌نما و GPS، کوادکوپتر را به مکانی برده و آن را در یک جایی بی‌حرکت قرار دهید که از هیچ گونه تداخل مغناطیسی مانند فلزات نباشد.
از طریق نرم‌افزار کنترل پرواز، دستور کالیبره کردن قطب‌نما و GPS را صادر کنید.
کوادکوپتر سعی می‌کند جهتی مورد نظر را تشخیص دهد و مکان فعلی خود را به عنوان نقطه شروع برای محاسبه موقعیت GPS انتخاب کند.

میزان توازن پایه‌های پرواز:

پایه‌های پرواز (Stabilization Mode) کوادکوپتر باید تا حد ممکن در حالت عمودی و افقی باشند.
از طریق نرم‌افزار کنترل پرواز یا رادیوکنترل، میزان توازن پایه‌ها را تنظیم کنید تا کوادکوپتر به درستی در حالت عمودی باشد.

دیگر تنظیمات:

به تنظیمات دیگری مانند پرواز در حالت RTL (Return to Launch)، حالتی که بیشتر برای پرواز انتخاب می‌شود، و تنظیمات کنترل دوربین (اگر دارید) بپردازید.

تست پرواز تجربی:

پس از کالیبره کردن تجهیزات، یک تست پرواز تجربی انجام دهید.
این تست باید به شما امکان دهد تا مشکلات ممکن را شناسایی کنید و تنظیمات نهایی را تصحیح کنید.

توجه داشته باشید که روش‌های کالیبره کردن تجهیزات ممکن است بسته به نوع کوادکوپتر و سیستم کنترل متغیر باشد. بهتر است همواره به دفترچه راهنمای تولید کننده و منابع مرتبط با دستگاه خود مراجعه کنید تا راهنمایی‌های دقیقتر در خصوص کالیبره کردن تجهیزات خود کسب کنید.

در این پست برنامه ی مربوط به کالیبره کردن تجهیزات کوادکوپتر رو قدم به قدم براتون بزارم.  آموزش ها رو مرحله به مرحله انجام بدین. اول برنامه رو قرار بدم بعدش هم توضیحات رو میدم. اول برنامه Setup رو از قسمت زیر کپی و بعد روی بردتون آپلود کنید.

#include <Wire.h>            
#include <EEPROM.h>            

byte last_channel_1, last_channel_2, last_channel_3, last_channel_4;
byte lowByte, highByte, type, gyro_address, error, clockspeed_ok;
byte channel_1_assign, channel_2_assign, channel_3_assign, channel_4_assign;
byte roll_axis, pitch_axis, yaw_axis;
byte receiver_check_byte, gyro_check_byte;
int receiver_input_channel_1, receiver_input_channel_2, receiver_input_channel_3, receiver_input_channel_4;
int center_channel_1, center_channel_2, center_channel_3, center_channel_4;
int high_channel_1, high_channel_2, high_channel_3, high_channel_4;
int low_channel_1, low_channel_2, low_channel_3, low_channel_4;
int address, cal_int;
unsigned long timer, timer_1, timer_2, timer_3, timer_4, current_time;
float gyro_pitch, gyro_roll, gyro_yaw;
float gyro_roll_cal, gyro_pitch_cal, gyro_yaw_cal;


void setup(){
  pinMode(12, OUTPUT);
  PCICR |= (1 << PCIE0);    
  PCMSK0 |= (1 << PCINT0);  
  PCMSK0 |= (1 << PCINT1); 
  PCMSK0 |= (1 << PCINT2); 
  PCMSK0 |= (1 << PCINT3);  
  Wire.begin();            
  Serial.begin(57600);     
  delay(250);               
}

void loop(){
  intro();
  Serial.println(F(""));
  Serial.println(F("==================================================="));
  Serial.println(F("System check"));
  Serial.println(F("==================================================="));
  delay(1000);
  Serial.println(F("Checking I2C clock speed."));
  delay(1000); 
  #if F_CPU == 16000000L         
    clockspeed_ok = 1;           
  #endif                         
  if(TWBR == 12 && clockspeed_ok){
    Serial.println(F("I2C clock speed is correctly set to 400kHz."));
  }
  else{
    Serial.println(F("I2C clock speed is not set to 400kHz. (ERROR 8)"));
    error = 1;
  }
  
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F("==================================================="));
    Serial.println(F("Transmitter setup"));
    Serial.println(F("==================================================="));
    delay(1000);
    Serial.print(F("Checking for valid receiver signals."));
    wait_for_receiver();
    Serial.println(F(""));
  }
  if(error == 0){
    delay(2000);
    Serial.println(F("Place all sticks and subtrims in the center position within 10 seconds."));
    for(int i = 9;i > 0;i--){
      delay(1000);
      Serial.print(i);
      Serial.print(" ");
    }
    Serial.println(" ");
    center_channel_1 = receiver_input_channel_1;
    center_channel_2 = receiver_input_channel_2;
    center_channel_3 = receiver_input_channel_3;
    center_channel_4 = receiver_input_channel_4;
    Serial.println(F(""));
    Serial.println(F("Center positions stored."));
    Serial.print(F("Digital input 08 = "));
    Serial.println(receiver_input_channel_1);
    Serial.print(F("Digital input 09 = "));
    Serial.println(receiver_input_channel_2);
    Serial.print(F("Digital input 10 = "));
    Serial.println(receiver_input_channel_3);
    Serial.print(F("Digital input 11 = "));
    Serial.println(receiver_input_channel_4);
    Serial.println(F(""));
    Serial.println(F(""));
  }
  if(error == 0){  
    Serial.println(F("Move the throttle stick to full throttle and back to center"));
    check_receiver_inputs(1);
    Serial.print(F("Throttle is connected to digital input "));
    Serial.println((channel_3_assign & 0b00000111) + 7);
    if(channel_3_assign & 0b10000000)Serial.println(F("Channel inverted = yes"));
    else Serial.println(F("Channel inverted = no"));
    wait_sticks_zero();
    
    Serial.println(F(""));
    Serial.println(F(""));
    Serial.println(F("Move the roll stick to simulate left wing up and back to center"));
    check_receiver_inputs(2);
    Serial.print(F("Roll is connected to digital input "));
    Serial.println((channel_1_assign & 0b00000111) + 7);
    if(channel_1_assign & 0b10000000)Serial.println(F("Channel inverted = yes"));
    else Serial.println(F("Channel inverted = no"));
    wait_sticks_zero();
  }
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F(""));
    Serial.println(F("Move the pitch stick to simulate nose up and back to center"));
    check_receiver_inputs(3);
    Serial.print(F("Pitch is connected to digital input "));
    Serial.println((channel_2_assign & 0b00000111) + 7);
    if(channel_2_assign & 0b10000000)Serial.println(F("Channel inverted = yes"));
    else Serial.println(F("Channel inverted = no"));
    wait_sticks_zero();
  }
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F(""));
    Serial.println(F("Move the yaw stick to simulate nose right and back to center"));
    check_receiver_inputs(4);
    Serial.print(F("Yaw is connected to digital input "));
    Serial.println((channel_4_assign & 0b00000111) + 7);
    if(channel_4_assign & 0b10000000)Serial.println(F("Channel inverted = yes"));
    else Serial.println(F("Channel inverted = no"));
    wait_sticks_zero();
  }
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F(""));
    Serial.println(F("Gently move all the sticks simultaneously to their extends"));
    Serial.println(F("When ready put the sticks back in their center positions"));
    register_min_max();
    Serial.println(F(""));
    Serial.println(F(""));
    Serial.println(F("High, low and center values found during setup"));
    Serial.print(F("Digital input 08 values:"));
    Serial.print(low_channel_1);
    Serial.print(F(" - "));
    Serial.print(center_channel_1);
    Serial.print(F(" - "));
    Serial.println(high_channel_1);
    Serial.print(F("Digital input 09 values:"));
    Serial.print(low_channel_2);
    Serial.print(F(" - "));
    Serial.print(center_channel_2);
    Serial.print(F(" - "));
    Serial.println(high_channel_2);
    Serial.print(F("Digital input 10 values:"));
    Serial.print(low_channel_3);
    Serial.print(F(" - "));
    Serial.print(center_channel_3);
    Serial.print(F(" - "));
    Serial.println(high_channel_3);
    Serial.print(F("Digital input 11 values:"));
    Serial.print(low_channel_4);
    Serial.print(F(" - "));
    Serial.print(center_channel_4);
    Serial.print(F(" - "));
    Serial.println(high_channel_4);
    Serial.println(F("Move stick 'nose up' and back to center to continue"));
    check_to_continue();
  }
    
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F("==================================================="));
    Serial.println(F("Gyro search"));
    Serial.println(F("==================================================="));
    delay(2000);
    
    Serial.println(F("Searching for MPU-6050 on address 0x68/104"));
    delay(1000);
    if(search_gyro(0x68, 0x75) == 0x68){
      Serial.println(F("MPU-6050 found on address 0x68"));
      type = 1;
      gyro_address = 0x68;
    }
    
    if(type == 0){
      Serial.println(F("Searching for MPU-6050 on address 0x69/105"));
      delay(1000);
      if(search_gyro(0x69, 0x75) == 0x68){
        Serial.println(F("MPU-6050 found on address 0x69"));
        type = 1;
        gyro_address = 0x69;
      }
    }
    
    if(type == 0){
      Serial.println(F("Searching for L3G4200D on address 0x68/104"));
      delay(1000);
      if(search_gyro(0x68, 0x0F) == 0xD3){
        Serial.println(F("L3G4200D found on address 0x68"));
        type = 2;
        gyro_address = 0x68;
      }
    }
    
    if(type == 0){
      Serial.println(F("Searching for L3G4200D on address 0x69/105"));
      delay(1000);
      if(search_gyro(0x69, 0x0F) == 0xD3){
        Serial.println(F("L3G4200D found on address 0x69"));
        type = 2;
        gyro_address = 0x69;
      }
    }
    
    if(type == 0){
      Serial.println(F("Searching for L3GD20H on address 0x6A/106"));
      delay(1000);
      if(search_gyro(0x6A, 0x0F) == 0xD7){
        Serial.println(F("L3GD20H found on address 0x6A"));
        type = 3;
        gyro_address = 0x6A;
      }
    }
    
    if(type == 0){
     Serial.println(F("Searching for L3GD20H on address 0x6B/107"));
      delay(1000);
      if(search_gyro(0x6B, 0x0F) == 0xD7){
        Serial.println(F("L3GD20H found on address 0x6B"));
        type = 3;
        gyro_address = 0x6B;
      }
    }
    
    if(type == 0){
      Serial.println(F("No gyro device found!!! (ERROR 3)"));
      error = 1;
    }
    
    else{
      delay(3000);
      Serial.println(F(""));
      Serial.println(F("==================================================="));
      Serial.println(F("Gyro register settings"));
      Serial.println(F("==================================================="));
      start_gyro();
    }
  }
  
  if(error == 0){
    delay(3000);
    Serial.println(F(""));
    Serial.println(F("==================================================="));
    Serial.println(F("Gyro calibration"));
    Serial.println(F("==================================================="));
    Serial.println(F("Don't move the quadcopter!! Calibration starts in 3 seconds"));
    delay(3000);
    Serial.println(F("Calibrating the gyro, this will take +/- 8 seconds"));
    Serial.print(F("Please wait"));
    for (cal_int = 0; cal_int < 2000 ; cal_int ++){             
      if(cal_int % 100 == 0)Serial.print(F("."));               
      gyro_signalen();                                           
      gyro_roll_cal += gyro_roll;                               
      gyro_pitch_cal += gyro_pitch;                             
      gyro_yaw_cal += gyro_yaw;                                  
      delay(4);                                                
    }
    gyro_roll_cal /= 2000;                                     
    gyro_pitch_cal /= 2000;                                  
    gyro_yaw_cal /= 2000;                                     
    
    Serial.println(F(""));
    Serial.print(F("Axis 1 offset="));
    Serial.println(gyro_roll_cal);
    Serial.print(F("Axis 2 offset="));
    Serial.println(gyro_pitch_cal);
    Serial.print(F("Axis 3 offset="));
    Serial.println(gyro_yaw_cal);
    Serial.println(F(""));
    
    Serial.println(F("==================================================="));
    Serial.println(F("Gyro axes configuration"));
    Serial.println(F("==================================================="));
    
    Serial.println(F("Lift the left side of the quadcopter to a 45 degree angle within 10 seconds"));
    check_gyro_axes(1);
    if(error == 0){
      Serial.println(F("OK!"));
      Serial.print(F("Angle detection = "));
      Serial.println(roll_axis & 0b00000011);
      if(roll_axis & 0b10000000)Serial.println(F("Axis inverted = yes"));
      else Serial.println(F("Axis inverted = no"));
      Serial.println(F("Put the quadcopter back in its original position"));
      Serial.println(F("Move stick 'nose up' and back to center to continue"));
      check_to_continue();

      Serial.println(F(""));
      Serial.println(F(""));
      Serial.println(F("Lift the nose of the quadcopter to a 45 degree angle within 10 seconds"));
      check_gyro_axes(2);
    }
    if(error == 0){
      Serial.println(F("OK!"));
      Serial.print(F("Angle detection = "));
      Serial.println(pitch_axis & 0b00000011);
      if(pitch_axis & 0b10000000)Serial.println(F("Axis inverted = yes"));
      else Serial.println(F("Axis inverted = no"));
      Serial.println(F("Put the quadcopter back in its original position"));
      Serial.println(F("Move stick 'nose up' and back to center to continue"));
      check_to_continue();
      
      Serial.println(F(""));
      Serial.println(F(""));
      Serial.println(F("Rotate the nose of the quadcopter 45 degree to the right within 10 seconds"));
      check_gyro_axes(3);
    }
    if(error == 0){
      Serial.println(F("OK!"));
      Serial.print(F("Angle detection = "));
      Serial.println(yaw_axis & 0b00000011);
      if(yaw_axis & 0b10000000)Serial.println(F("Axis inverted = yes"));
      else Serial.println(F("Axis inverted = no"));
      Serial.println(F("Put the quadcopter back in its original position"));
      Serial.println(F("Move stick 'nose up' and back to center to continue"));
      check_to_continue();
    }
  }
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F("==================================================="));
    Serial.println(F("LED test"));
    Serial.println(F("==================================================="));
    digitalWrite(12, HIGH);
    Serial.println(F("The LED should now be lit"));
    Serial.println(F("Move stick 'nose up' and back to center to continue"));
    check_to_continue();
    digitalWrite(12, LOW);
  }
  
  Serial.println(F(""));
  
  if(error == 0){
    Serial.println(F("==================================================="));
    Serial.println(F("Final setup check"));
    Serial.println(F("==================================================="));
    delay(1000);
    if(receiver_check_byte == 0b00001111){
      Serial.println(F("Receiver channels ok"));
    }
    else{
      Serial.println(F("Receiver channel verification failed!!! (ERROR 6)"));
      error = 1;
    }
    delay(1000);
    if(gyro_check_byte == 0b00000111){
      Serial.println(F("Gyro axes ok"));
    }
    else{
      Serial.println(F("Gyro exes verification failed!!! (ERROR 7)"));
      error = 1;
    }
  }     
  
  if(error == 0){
    Serial.println(F(""));
    Serial.println(F("==================================================="));
    Serial.println(F("Storing EEPROM information"));
    Serial.println(F("==================================================="));
    Serial.println(F("Writing EEPROM"));
    delay(1000);
    Serial.println(F("Done!"));
    EEPROM.write(0, center_channel_1 & 0b11111111);
    EEPROM.write(1, center_channel_1 >> 8);
    EEPROM.write(2, center_channel_2 & 0b11111111);
    EEPROM.write(3, center_channel_2 >> 8);
    EEPROM.write(4, center_channel_3 & 0b11111111);
    EEPROM.write(5, center_channel_3 >> 8);
    EEPROM.write(6, center_channel_4 & 0b11111111);
    EEPROM.write(7, center_channel_4 >> 8);
    EEPROM.write(8, high_channel_1 & 0b11111111);
    EEPROM.write(9, high_channel_1 >> 8);
    EEPROM.write(10, high_channel_2 & 0b11111111);
    EEPROM.write(11, high_channel_2 >> 8);
    EEPROM.write(12, high_channel_3 & 0b11111111);
    EEPROM.write(13, high_channel_3 >> 8);
    EEPROM.write(14, high_channel_4 & 0b11111111);
    EEPROM.write(15, high_channel_4 >> 8);
    EEPROM.write(16, low_channel_1 & 0b11111111);
    EEPROM.write(17, low_channel_1 >> 8);
    EEPROM.write(18, low_channel_2 & 0b11111111);
    EEPROM.write(19, low_channel_2 >> 8);
    EEPROM.write(20, low_channel_3 & 0b11111111);
    EEPROM.write(21, low_channel_3 >> 8);
    EEPROM.write(22, low_channel_4 & 0b11111111);
    EEPROM.write(23, low_channel_4 >> 8);
    EEPROM.write(24, channel_1_assign);
    EEPROM.write(25, channel_2_assign);
    EEPROM.write(26, channel_3_assign);
    EEPROM.write(27, channel_4_assign);
    EEPROM.write(28, roll_axis);
    EEPROM.write(29, pitch_axis);
    EEPROM.write(30, yaw_axis);
    EEPROM.write(31, type);
    EEPROM.write(32, gyro_address);
    EEPROM.write(33, 'J'); 
    EEPROM.write(34, 'M');
    EEPROM.write(35, 'B');
        
    
    Serial.println(F("Verify EEPROM data"));
    delay(1000);
    if(center_channel_1 != ((EEPROM.read(1) << 8) | EEPROM.read(0)))error = 1;
    if(center_channel_2 != ((EEPROM.read(3) << 8) | EEPROM.read(2)))error = 1;
    if(center_channel_3 != ((EEPROM.read(5) << 8) | EEPROM.read(4)))error = 1;
    if(center_channel_4 != ((EEPROM.read(7) << 8) | EEPROM.read(6)))error = 1;
    
    if(high_channel_1 != ((EEPROM.read(9) << 8) | EEPROM.read(8)))error = 1;
    if(high_channel_2 != ((EEPROM.read(11) << 8) | EEPROM.read(10)))error = 1;
    if(high_channel_3 != ((EEPROM.read(13) << 8) | EEPROM.read(12)))error = 1;
    if(high_channel_4 != ((EEPROM.read(15) << 8) | EEPROM.read(14)))error = 1;
    
    if(low_channel_1 != ((EEPROM.read(17) << 8) | EEPROM.read(16)))error = 1;
    if(low_channel_2 != ((EEPROM.read(19) << 8) | EEPROM.read(18)))error = 1;
    if(low_channel_3 != ((EEPROM.read(21) << 8) | EEPROM.read(20)))error = 1;
    if(low_channel_4 != ((EEPROM.read(23) << 8) | EEPROM.read(22)))error = 1;
    
    if(channel_1_assign != EEPROM.read(24))error = 1;
    if(channel_2_assign != EEPROM.read(25))error = 1;
    if(channel_3_assign != EEPROM.read(26))error = 1;
    if(channel_4_assign != EEPROM.read(27))error = 1;
    
    if(roll_axis != EEPROM.read(28))error = 1;
    if(pitch_axis != EEPROM.read(29))error = 1;
    if(yaw_axis != EEPROM.read(30))error = 1;
    if(type != EEPROM.read(31))error = 1;
    if(gyro_address != EEPROM.read(32))error = 1;
    
    if('J' != EEPROM.read(33))error = 1;
    if('M' != EEPROM.read(34))error = 1;
    if('B' != EEPROM.read(35))error = 1;
  
    if(error == 1)Serial.println(F("EEPROM verification failed!!! (ERROR 5)"));
    else Serial.println(F("Verification done"));
  }
  
  
  if(error == 0){
    Serial.println(F("Setup is finished."));
    Serial.println(F("You can now calibrate the esc's and upload the YMFC-3D V2 code."));
  }
  else{
   Serial.println(F("The setup is aborted due to an error."));
   Serial.println(F("Check the Q and A page of the YMFC-3D V2 project on:"));
   Serial.println(F("www.brokking.net for more information about this error."));
  }
  while(1);
}

byte search_gyro(int gyro_address, int who_am_i){
  Wire.beginTransmission(gyro_address);
  Wire.write(who_am_i);
  Wire.endTransmission();
  Wire.requestFrom(gyro_address, 1);
  timer = millis() + 100;
  while(Wire.available() < 1 && timer > millis());
  lowByte = Wire.read();
  address = gyro_address;
  return lowByte;
}

void start_gyro(){
  if(type == 2 || type == 3){
    Wire.beginTransmission(address);                        
    Wire.write(0x20);                                           
    Wire.write(0x0F);                                        
    Wire.endTransmission();                                    

    Wire.beginTransmission(address);                            
    Wire.write(0x20);                                            
    Wire.endTransmission();                                   
    Wire.requestFrom(address, 1);                               
    while(Wire.available() < 1);                                 
    Serial.print(F("Register 0x20 is set to:"));
    Serial.println(Wire.read(),BIN);

    Wire.beginTransmission(address);                            
    Wire.write(0x23);                                          
    Wire.write(0x90);                                           
    Wire.endTransmission();                                   
    
    Wire.beginTransmission(address);                           
    Wire.write(0x23);                                           
    Wire.endTransmission();                                    
    Wire.requestFrom(address, 1);                               
    while(Wire.available() < 1);                                 
    Serial.print(F("Register 0x23 is set to:"));
    Serial.println(Wire.read(),BIN);

  }
  if(type == 1){
    
    Wire.beginTransmission(address);                             
    Wire.write(0x6B);                                            
    Wire.write(0x00);                                           
    Wire.endTransmission();                                      
    
    Wire.beginTransmission(address);                            
    Wire.write(0x6B);                                            
    Wire.endTransmission();                                     
    Wire.requestFrom(address, 1);                               
    while(Wire.available() < 1);                               
    Serial.print(F("Register 0x6B is set to:"));
    Serial.println(Wire.read(),BIN);
    
    Wire.beginTransmission(address);                           
    Wire.write(0x1B);                                            
    Wire.write(0x08);                                          
    Wire.endTransmission();                                     
    
    Wire.beginTransmission(address);                             
    Wire.write(0x1B);                                          
    Wire.endTransmission();                                      
    Wire.requestFrom(address, 1);                                
    while(Wire.available() < 1);                               
    Serial.print(F("Register 0x1B is set to:"));
    Serial.println(Wire.read(),BIN);

  }
}

void gyro_signalen(){
  if(type == 2 || type == 3){
    Wire.beginTransmission(address);                             
    Wire.write(168);                                            
    Wire.endTransmission();                                     
    Wire.requestFrom(address, 6);                               
    while(Wire.available() < 6);                                
    lowByte = Wire.read();                                      
    highByte = Wire.read();                                     
    gyro_roll = ((highByte<<8)|lowByte);                        
    if(cal_int == 2000)gyro_roll -= gyro_roll_cal;               
    lowByte = Wire.read();                                      
    highByte = Wire.read();                                     
    gyro_pitch = ((highByte<<8)|lowByte);                       
    if(cal_int == 2000)gyro_pitch -= gyro_pitch_cal;            
    lowByte = Wire.read();                                     
    highByte = Wire.read();                                     
    gyro_yaw = ((highByte<<8)|lowByte);                          
    if(cal_int == 2000)gyro_yaw -= gyro_yaw_cal;                 
  }
  if(type == 1){
    Wire.beginTransmission(address);                             
    Wire.write(0x43);                                         
    Wire.endTransmission();                                     
    Wire.requestFrom(address,6);                                
    while(Wire.available() < 6);                                 
    gyro_roll=Wire.read()<<8|Wire.read();                        
    if(cal_int == 2000)gyro_roll -= gyro_roll_cal;             
    gyro_pitch=Wire.read()<<8|Wire.read();                       
    if(cal_int == 2000)gyro_pitch -= gyro_pitch_cal;            
    gyro_yaw=Wire.read()<<8|Wire.read();                         
    if(cal_int == 2000)gyro_yaw -= gyro_yaw_cal;               
  }
}

void check_receiver_inputs(byte movement){
  byte trigger = 0;
  int pulse_length;
  timer = millis() + 30000;
  while(timer > millis() && trigger == 0){
    delay(250);
    if(receiver_input_channel_1 > 1750 || receiver_input_channel_1 < 1250){
      trigger = 1;
      receiver_check_byte |= 0b00000001;
      pulse_length = receiver_input_channel_1;
    }
    if(receiver_input_channel_2 > 1750 || receiver_input_channel_2 < 1250){
      trigger = 2;
      receiver_check_byte |= 0b00000010;
      pulse_length = receiver_input_channel_2;
    }
    if(receiver_input_channel_3 > 1750 || receiver_input_channel_3 < 1250){
      trigger = 3;
      receiver_check_byte |= 0b00000100;
      pulse_length = receiver_input_channel_3;
    }
    if(receiver_input_channel_4 > 1750 || receiver_input_channel_4 < 1250){
      trigger = 4;
      receiver_check_byte |= 0b00001000;
      pulse_length = receiver_input_channel_4;
    } 
  }
  if(trigger == 0){
    error = 1;
    Serial.println(F("No stick movement detected in the last 30 seconds!!! (ERROR 2)"));
  }
  else{
    if(movement == 1){
      channel_3_assign = trigger;
      if(pulse_length < 1250)channel_3_assign += 0b10000000;
    }
    if(movement == 2){
      channel_1_assign = trigger;
      if(pulse_length < 1250)channel_1_assign += 0b10000000;
    }
    if(movement == 3){
      channel_2_assign = trigger;
      if(pulse_length < 1250)channel_2_assign += 0b10000000;
    }
    if(movement == 4){
      channel_4_assign = trigger;
      if(pulse_length < 1250)channel_4_assign += 0b10000000;
    }
  }
}

void check_to_continue(){
  byte continue_byte = 0;
  while(continue_byte == 0){
    if(channel_2_assign == 0b00000001 && receiver_input_channel_1 > center_channel_1 + 150)continue_byte = 1;
    if(channel_2_assign == 0b10000001 && receiver_input_channel_1 < center_channel_1 - 150)continue_byte = 1;
    if(channel_2_assign == 0b00000010 && receiver_input_channel_2 > center_channel_2 + 150)continue_byte = 1;
    if(channel_2_assign == 0b10000010 && receiver_input_channel_2 < center_channel_2 - 150)continue_byte = 1;
    if(channel_2_assign == 0b00000011 && receiver_input_channel_3 > center_channel_3 + 150)continue_byte = 1;
    if(channel_2_assign == 0b10000011 && receiver_input_channel_3 < center_channel_3 - 150)continue_byte = 1;
    if(channel_2_assign == 0b00000100 && receiver_input_channel_4 > center_channel_4 + 150)continue_byte = 1;
    if(channel_2_assign == 0b10000100 && receiver_input_channel_4 < center_channel_4 - 150)continue_byte = 1;
    delay(100);
  }
  wait_sticks_zero();
}

void wait_sticks_zero(){
  byte zero = 0;
  while(zero < 15){
    if(receiver_input_channel_1 < center_channel_1 + 20 && receiver_input_channel_1 > center_channel_1 - 20)zero |= 0b00000001;
    if(receiver_input_channel_2 < center_channel_2 + 20 && receiver_input_channel_2 > center_channel_2 - 20)zero |= 0b00000010;
    if(receiver_input_channel_3 < center_channel_3 + 20 && receiver_input_channel_3 > center_channel_3 - 20)zero |= 0b00000100;
    if(receiver_input_channel_4 < center_channel_4 + 20 && receiver_input_channel_4 > center_channel_4 - 20)zero |= 0b00001000;
    delay(100);
  }
}

void wait_for_receiver(){
  byte zero = 0;
  timer = millis() + 10000;
  while(timer > millis() && zero < 15){
    if(receiver_input_channel_1 < 2100 && receiver_input_channel_1 > 900)zero |= 0b00000001;
    if(receiver_input_channel_2 < 2100 && receiver_input_channel_2 > 900)zero |= 0b00000010;
    if(receiver_input_channel_3 < 2100 && receiver_input_channel_3 > 900)zero |= 0b00000100;
    if(receiver_input_channel_4 < 2100 && receiver_input_channel_4 > 900)zero |= 0b00001000;
    delay(500);
    Serial.print(F("."));
  }
  if(zero == 0){
    error = 1;
    Serial.println(F("."));
    Serial.println(F("No valid receiver signals found!!! (ERROR 1)"));
  }
  else Serial.println(F(" OK"));
}

void register_min_max(){
  byte zero = 0;
  low_channel_1 = receiver_input_channel_1;
  low_channel_2 = receiver_input_channel_2;
  low_channel_3 = receiver_input_channel_3;
  low_channel_4 = receiver_input_channel_4;
  while(receiver_input_channel_1 < center_channel_1 + 20 && receiver_input_channel_1 > center_channel_1 - 20)delay(250);
  Serial.println(F("Measuring endpoints...."));
  while(zero < 15){
    if(receiver_input_channel_1 < center_channel_1 + 20 && receiver_input_channel_1 > center_channel_1 - 20)zero |= 0b00000001;
    if(receiver_input_channel_2 < center_channel_2 + 20 && receiver_input_channel_2 > center_channel_2 - 20)zero |= 0b00000010;
    if(receiver_input_channel_3 < center_channel_3 + 20 && receiver_input_channel_3 > center_channel_3 - 20)zero |= 0b00000100;
    if(receiver_input_channel_4 < center_channel_4 + 20 && receiver_input_channel_4 > center_channel_4 - 20)zero |= 0b00001000;
    if(receiver_input_channel_1 < low_channel_1)low_channel_1 = receiver_input_channel_1;
    if(receiver_input_channel_2 < low_channel_2)low_channel_2 = receiver_input_channel_2;
    if(receiver_input_channel_3 < low_channel_3)low_channel_3 = receiver_input_channel_3;
    if(receiver_input_channel_4 < low_channel_4)low_channel_4 = receiver_input_channel_4;
    if(receiver_input_channel_1 > high_channel_1)high_channel_1 = receiver_input_channel_1;
    if(receiver_input_channel_2 > high_channel_2)high_channel_2 = receiver_input_channel_2;
    if(receiver_input_channel_3 > high_channel_3)high_channel_3 = receiver_input_channel_3;
    if(receiver_input_channel_4 > high_channel_4)high_channel_4 = receiver_input_channel_4;
    delay(100);
  }
}

void check_gyro_axes(byte movement){
  byte trigger_axis = 0;
  float gyro_angle_roll, gyro_angle_pitch, gyro_angle_yaw;
  //Reset all axes
  gyro_angle_roll = 0;
  gyro_angle_pitch = 0;
  gyro_angle_yaw = 0;
  gyro_signalen();
  timer = millis() + 10000;    
  while(timer > millis() && gyro_angle_roll > -30 && gyro_angle_roll < 30 && gyro_angle_pitch > -30 && gyro_angle_pitch < 30 && gyro_angle_yaw > -30 && gyro_angle_yaw < 30){
    gyro_signalen();
    if(type == 2 || type == 3){
      gyro_angle_roll += gyro_roll * 0.00007;             
      gyro_angle_pitch += gyro_pitch * 0.00007;
      gyro_angle_yaw += gyro_yaw * 0.00007;
    }
    if(type == 1){
      gyro_angle_roll += gyro_roll * 0.0000611;         
      gyro_angle_pitch += gyro_pitch * 0.0000611;
      gyro_angle_yaw += gyro_yaw * 0.0000611;
    }
    
    delayMicroseconds(3700); 
  }
  if((gyro_angle_roll < -30 || gyro_angle_roll > 30) && gyro_angle_pitch > -30 && gyro_angle_pitch < 30 && gyro_angle_yaw > -30 && gyro_angle_yaw < 30){
    gyro_check_byte |= 0b00000001;
    if(gyro_angle_roll < 0)trigger_axis = 0b10000001;
    else trigger_axis = 0b00000001;
  }
  if((gyro_angle_pitch < -30 || gyro_angle_pitch > 30) && gyro_angle_roll > -30 && gyro_angle_roll < 30 && gyro_angle_yaw > -30 && gyro_angle_yaw < 30){
    gyro_check_byte |= 0b00000010;
    if(gyro_angle_pitch < 0)trigger_axis = 0b10000010;
    else trigger_axis = 0b00000010;
  }
  if((gyro_angle_yaw < -30 || gyro_angle_yaw > 30) && gyro_angle_roll > -30 && gyro_angle_roll < 30 && gyro_angle_pitch > -30 && gyro_angle_pitch < 30){
    gyro_check_byte |= 0b00000100;
    if(gyro_angle_yaw < 0)trigger_axis = 0b10000011;
    else trigger_axis = 0b00000011;
  }
  
  if(trigger_axis == 0){
    error = 1;
    Serial.println(F("No angular motion is detected in the last 10 seconds!!! (ERROR 4)"));
  }
  else
  if(movement == 1)roll_axis = trigger_axis;
  if(movement == 2)pitch_axis = trigger_axis;
  if(movement == 3)yaw_axis = trigger_axis;
  
}

ISR(PCINT0_vect){
  current_time = micros();
  //Channel 1=========================================
  if(PINB & B00000001){                                      
    if(last_channel_1 == 0){                                   
      last_channel_1 = 1;                                     
      timer_1 = current_time;                                 
    }
  }
  else if(last_channel_1 == 1){                               
    last_channel_1 = 0;                                       
    receiver_input_channel_1 = current_time - timer_1;         
  }
  //Channel 2=========================================
  if(PINB & B00000010 ){                                    
    if(last_channel_2 == 0){                                  
      last_channel_2 = 1;                                      
      timer_2 = current_time;                                  
    }
  }
  else if(last_channel_2 == 1){                                
    last_channel_2 = 0;                                        
    receiver_input_channel_2 = current_time - timer_2;        
  }
  //Channel 3=========================================
  if(PINB & B00000100 ){                                      
    if(last_channel_3 == 0){                                   
      last_channel_3 = 1;                                      
      timer_3 = current_time;                                 
    }
  }
  else if(last_channel_3 == 1){                                
    last_channel_3 = 0;                                        
    receiver_input_channel_3 = current_time - timer_3;       

  }
  //Channel 4=========================================
  if(PINB & B00001000 ){                                      
    if(last_channel_4 == 0){                                  
      last_channel_4 = 1;                                      
      timer_4 = current_time;                                 
    }
  }
  else if(last_channel_4 == 1){                                
    last_channel_4 = 0;                                        
    receiver_input_channel_4 = current_time - timer_4;      
  }
}

//Intro subroutine
void intro(){
  Serial.println(F("==================================================="));
  delay(1500);
  Serial.println(F(""));
  Serial.println(F("Your"));
  delay(500);
  Serial.println(F("  Multicopter"));
  delay(500);
  Serial.println(F("    Flight"));
  delay(500);
  Serial.println(F("      Controller"));
  delay(1000);
  Serial.println(F(""));
  Serial.println(F("V         V     22222                "));
  delay(200);
  Serial.println(F(" V       V     2     2             "));
  delay(200);
  Serial.println(F("  V     V          2             "));
  delay(200);
  Serial.println(F("   V   V         2              "));
  delay(200);
  Serial.println(F("    V V        2                  "));
  delay(200);
  Serial.println(F("     V        22222222                  "));
  delay(500);
  Serial.println(F(""));
  Serial.println(F("==================================================="));
  delay(1500);
  Serial.println(F("Have fun!"));
}

 

بعد از آپلود برنامه سریال مانیتور رو باز کنید. (رنج کاری سریال مانتور هم یادتون نره یکی باشه. در حلقه ی Setup هر برنامه متغییر هست)

وقتی سریال مانیتور رو باز کردین به ترتیب مراحل زیر براتون نمایش داده میشه :

  • ۱ – لوگوی کواد کوپتر – V2
  • ۲ -در ابتدا میاد ارتباط I2c سنسور رو چک میکنه و اگه اشتباه باشه Eror میده و باید درستش کنید.
  • برای درست کردن اون باید به مسیر نصب آردوینو برید (arduino-1.6.10\hardware\arduino\avr\libraries\Wire\utility\twi.h) – فایل twi.h رو باز کنید و ۱۰۰۰۰۰ رو به ۴۰۰۰۰۰ تغییر بدین.
  • ۳ – فلایت کنترل ، پالس های دریافتی از گیرنده رادیو کنترل رو چک میکنه که روشن هست یا خاموش ، در این قسمت فرستنده رو هم روشن کنید.
  • ۴ – بعد ۱۰ ثانیه صبر میکنه تا جوی استیک های فرستنده رو در وسط قرار بدین.
  • ۵ – تراتل (throttle) را بالا ببرید و به وسط برگردانید.
  • ۶ – رول (roll)  را به سمت راست ببرید و به وسط برگردانید.
  • ۷ – پیتچ (pitch) را به پایین ببرید و به وسط برگردانید.
  • ۸ – یاو (yaw)  را به راست ببرید و به وسط برگردانید.
  • ۹ – حالا هر دو جوی استیک را در تمام نقاط بچرخانید تا مینیمم و ماکزیمم آن را برنامه تشخیص دهد.
  • ۱۰- پیتچ (pitch) رو پایین ببرید و برگردانید .
  • ۱۱ – gyro search —- برنامه به صورت خودکار به دنبال سنسور ی که استفاده کردین میگرده و تشخیص میده.
  • ۱۲- بعد از تشخیص دادن ازتون میخواد که کواد رو تکون ندید چون داره کالیبره میکنه سنسوتون رو .
  • ۱۳ – کواد رو ۴۵ درجه به سمت راست بلند کنید و پیتچ را به پایین ببرید و برگردانید.
  • ۱۴ – کواد رو ۴۵ درجه به سمت جلو بلند کنید و پیتچ را به پایین ببرید و برگردانید.
  • ۱۵ – کواد رو ۴۵ درچه به سمت چپ بپیچانید و پیتچ را به پایین ببرید و برگردانید.
  • ۱۶- LED روشن میشود که با پایین دادن پیتچ (pitch) خاموش میشود.
  • ۱۷- در آخر تنظیمات به صورت خودکار در eeprom ذخیره میشود و همه چی تمام میشه.
  • ۱۸- حالا شما باید اسپید کنترل هاتون رو کالیبره کنید که در پست بعدی آموزش اون رو براتون قرار میدم.

 

این مراحل رو هم میتونید از طریق دیدن فیلم انجام دهید.

فیلم مراحل کانفیگ کردن کوادکوپتر : کلیک کنید

 

درباره نویسنده

حسین فهیمی

تبادل نظر و رفع عیب با ثبت دیدگاه

۲۴ دیدگاه

  • سلام خسته نباشید تورو خدا جواب بدین من همه کار را انجام دادم ولی وقتی که کد های بالا رو اپلود میکنم و سریال مانیتور را بازمیکنم ارور i2c clock speed is not set to 400 khz. (error 8) رفتم داخل فایل twi.h و ۱۰۰۰۰۰ را به۴۰۰۰۰۰ تغییر دادم ولی درست نشد
    لطفا راهنمایی کنین؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟

  • سلام من با این خطا مواجه میشوم
    I2C clock speed is not set to 400kHz. (ERROR 8)
    رفتم داخل فایل twi.h 100000 را به ۴۰۰۰۰۰ تغییردادم ولی درست نشد
    لطفا کمکم کنید

  • با سلام و خسته نباشیدی جانانه برای کد بالا، ولی فقط ای کاش این همه رو به یک یا چند کتابخانه تبدیل کنید تا با نوشتن یه چن تا دستور ساده تو برنامه بشه راحت تر ازش استفاده کرد-اینطوری کاربردی ترهم میشه؛

  • سلام من نرم افزار آردینو ای دی ای رو نصب کردم این کد رو وقتی میخوام آپلود کنم یه ارور خیلی طولانی میده مشکل چیه
    باید از قبل چه کتابخونه ای رو نصب کنیم؟

  • سلام ببخشید در نوشته بالا گفتید که بعد از آپلو برنامه رو در سریال مانیتور اجرا کنید.یعنی چی؟تو کدوم مانیتور

    • با سلام
      کاربر گرامی، در نرم افزار آردوینو یک بخشی جهت نمایش وضعیت ارتباطات با ماژول وجود دارد تحت عنوان سریال مانیتور، از طریق این بخش میبایست اقدامات لازم را انجام داد.

  • سلام من آردینو رو وصل کردم وقتی برنامه شما رو داخل آپلود کردم تو سریال مانیتور
    (⸮⸮⸮⸮⸮⸮p⸮⸮)اینجوری نشون میده اینو چطور درست کنم

  • سلام تو سریال مانیتور
    No valid receiver signals found!!! (ERROR 1)
    این رو مینویسه تو یکی از خط هاش
    ریسیور هم وصله و روشن

    • رسیورم رادیولینک AT 9 هست آیا باید کدی رو تغییر بدم
      وقتی پین ۸ تا ۱۱ رو از رسیسور جدا میکنم ارور نمیده وقتی وصل میکنم ارور میده
      Checking for valid receiver signals………………………
      No valid receiver signals found!!! (ERROR 1)
      ؟
      میشه تو ایمیل در ارتباط باشیم

      • با سلام
        متاسفانه بنده با این ماژول کار نکرده‌ام، از اینرو نمیتوانم راهنمایی کنم. از دیگر کاربرانی که با این رادیو کار کرده‌اند، تقاضا دارم تا در این بحث شرکت کنند.

  • سلام
    روبروی هر خط کد فارسی توضیح بدین خیلی بهتره تا بعد از کل کدها
    هی باید بریم بالا هی بیاییم پایین

  • سلام.
    خسته نباشید من با خطای I2C clock speed is not set to 400kHz. (ERROR 8)
    رفتم داخل فایل و twi.h 100000 را به ۴۰۰۰۰۰ تغییردادم شاید بیش از ۱۰ باز این کار را انجام دادم ولی درست نشد با یک سنسور ۶۰۵۰ تست کردم نشد با سنسور l3g هم تست کردم باز این خطا را میده هر کاری میشده انجام دادم ولی بازم ارور دارم اگه میشه راهنمایی کنید

    • با سلام
      در خصوص مشکلتان، بنده اطلاعی ندارم، سوال شما منتشر شده است و در صورتی که دیگر کاربران اطلاعی داشته باشند، از همین طریق به شما کمک خواهند کرد.