Quadcopter safety

Hi veryone, i'm building a quadcopter, and i want to do a last thing. i want to cut off motors when a lose communication. i'm using arduino uno. is there a trick to cut off the motors when receiver does'nt receive signal from RC, i have a flysky t6.
Thanks

You are measuring the width of pulses. If you also measure the time between pulses you can detect when that time exceeds a threshold and shut down the motors.

Of course this will cause your quadcopter to tumble out of the sky.

Thanks Mr Johnwasser,
Could you explan more. me i measur time with interruption. the problem is when i shutdown the communication from my RC. the quadcopter keep the last signal.

I thought that johnwasser did a very good job explaining, especially since there was no code to help with the explanation.

Please post your code and wiring. When you do…

  1. Use CTRL-T in the Arduino IDE to autoformat your complete code.
  2. Paste the complete autoformatted code between code tags (the </> button)
    so that we can easily see and deal with your code.
    3) Paste the complete error message between code tags (the </> button)
    ~~ so that we can easily see and deal with your messages.~~
    4) If you already posted without code tags, you may add the code tags by
    ~~ editing your post.~~ Do not change your existing posts in any other way.
    You may make additional posts as needed.

Before posting again, you should read the three locked topics at the top of the Programming Questions forum, and any links to which these posts point.

If your project involves wiring, please provide a schematic and/or a wiring diagram and/or a clear photograph of the wiring.

Good Luck!

Here is tte code in the loop() function i get the value of my 4 channel min valu 1000 max value 2000
ans there is an ISR function that calculate the puls

void loop()
{
///
//

loop_timer = micros();                                                    //Set the timer for the next loop.

  PORTD |= B11110000;                                                       //Set digital outputs 4,5,6 and 7 high.
  timer_channel_1 = esc_1 + loop_timer;                                     //Calculate the time of the faling edge of the esc-1 pulse.
  timer_channel_2 = esc_2 + loop_timer;                                     //Calculate the time of the faling edge of the esc-2 pulse.
  timer_channel_3 = esc_3 + loop_timer;                                     //Calculate the time of the faling edge of the esc-3 pulse.
  timer_channel_4 = esc_4 + loop_timer;                                     //Calculate the time of the faling edge of the esc-4 pulse.
  

  while(PORTD >= 16){                                                       //Stay in this loop until output 4,5,6 and 7 are low.
    esc_loop_timer = micros();                                              //Read the current time.
    if(timer_channel_1 <= esc_loop_timer)PORTD &= B11101111;                //Set digital output 4 to low if the time is expired.
    if(timer_channel_2 <= esc_loop_timer)PORTD &= B11011111;                //Set digital output 5 to low if the time is expired.
    if(timer_channel_3 <= esc_loop_timer)PORTD &= B10111111;                //Set digital output 6 to low if the time is expired.
    if(timer_channel_4 <= esc_loop_timer)PORTD &= B01111111;                //Set digital output 7 to low if the time is expired.
  }
///
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//This routine is called every time input 8, 9, 10 or 11 changed state. This is used to read the receiver signals. 
//More information about this subroutine can be found in this video:

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ISR(PCINT0_vect){
  current_time = micros();
  //Channel 1=========================================
  if(PINB & B00000001){                                                     //Is input 8 high?
    if(last_channel_1 == 0){                                                //Input 8 changed from 0 to 1.
      last_channel_1 = 1;                                                   //Remember current input state.
      timer_1 = current_time;                                               //Set timer_1 to current_time.
    }
  }
  else if(last_channel_1 == 1){                                             //Input 8 is not high and changed from 1 to 0.
    last_channel_1 = 0;                                                     //Remember current input state.
    receiver_input[1] = current_time - timer_1;                             //Channel 1 is current_time - timer_1.
  }
  //Channel 2=========================================
  if(PINB & B00000010 ){                                                    //Is input 9 high?
    if(last_channel_2 == 0){                                                //Input 9 changed from 0 to 1.
      last_channel_2 = 1;                                                   //Remember current input state.
      timer_2 = current_time;                                               //Set timer_2 to current_time.
    }
  }
  else if(last_channel_2 == 1){                                             //Input 9 is not high and changed from 1 to 0.
    last_channel_2 = 0;                                                     //Remember current input state.
    receiver_input[2] = current_time - timer_2;                             //Channel 2 is current_time - timer_2.
  }
  //Channel 3=========================================
  if(PINB & B00000100 ){                                                    //Is input 10 high?
    if(last_channel_3 == 0){                                                //Input 10 changed from 0 to 1.
      last_channel_3 = 1;                                                   //Remember current input state.
      timer_3 = current_time;                                               //Set timer_3 to current_time.
    }
  }
  else if(last_channel_3 == 1){                                             //Input 10 is not high and changed from 1 to 0.
    last_channel_3 = 0;                                                     //Remember current input state.
    receiver_input[3] = current_time - timer_3;                             //Channel 3 is current_time - timer_3.

  }
  //Channel 4=========================================
  if(PINB & B00001000 ){                                                    //Is input 11 high?
    if(last_channel_4 == 0){                                                //Input 11 changed from 0 to 1.
      last_channel_4 = 1;                                                   //Remember current input state.
      timer_4 = current_time;                                               //Set timer_4 to current_time.
    }
  }
  else if(last_channel_4 == 1){                                             //Input 11 is not high and changed from 1 to 0.
    last_channel_4 = 0;                                                     //Remember current input state.
    receiver_input[4] = current_time - timer_4;                             //Channel 4 is current_time - timer_4.
  }
}

My recommendation is outside of what you asked, but rather than having the motors programmed to shutdown , have the copter reverse course to get back in range. There's so many places you wouldn't want the copter to fall, such as water, people, road, etc.

There are other circumstances in which you also want instant emergency cut.
It is usual to have some sort of current-to-motors monitoring so that any sudden surge not resulting from user control increase, which usually meant that a twig or finger had jammed rotation of one of the blades, must always cut all motors. That way the maximum injury to a finger is the rotational kinetic energy in the blade. They all seem to have implemented that one.

thanks for the answer, my first idea is to cut of motor, by the way i have to do some code that detect that o lose communicaion. after it will be easy. i will devlope return home with the gps. but i should program the losing communication function

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ISR(PCINT0_vect){
  LastInputChangeTime = millis();
  current_time = micros();
  //Channel 1=========================================
unsigned long LastInputChangeTime;
void loop()
{
unsigned long lastChangeTime;
noInterrupts();
lastChangeTime = LastInputChangeTime;
interrupts()
if (millis() - lastChangeTime  > 100) {
    // PANIC!  No pulses from radio receiver
    // Shut down the motors
    while (1) {
        PORTB |= 0xF0;  // HIGH to all four ESC's
        delayMicroseconds(900);  // Throttle minimum
        PORTB &= 0x0F;  // LOW to all four ESC's
        delay(20);  // Time between pulses
    }
  }
///
//

Thanks a lot master :slight_smile:

Oops. That technically should have been "volatile unsigned long LastInputChangeTime;" because it is changed in the ISR.

If your "receiver_input" array contains values larger than a byte (and it must to store values in the 1000 to 2000 range) you should probably copy the array to a local array with the interrupts disabled. Imagine the processor fetches one byte of the value and in interrupt comes by an changes the other byte(s) of the value.

That technically should have been "volatile unsigned long

is it dangerouse if the variable not volatile ?? and what does mean volatile ?

If your "receiver_input" array contains values larger than a byte (and it must to store values in the 1000 to 2000 range) you should probably copy the array to a local array with the interrupts disabled. Imagine the processor fetches one byte of the value and in interrupt comes by an changes the other byte(s) of the value.

i don't understand you sir, could you give me more detail
thanks

jone31:
Hi veryone, i'm building a quadcopter, and i want to do a last thing. i want to cut off motors when a lose communication. i'm using arduino uno. is there a trick to cut off the motors when receiver does'nt receive signal from RC, i have a flysky t6.
Thanks

What is controlling the Quad.

Most have powerful processors , far more so than Arduino.

They should have inbuilt protection for this.Common setting is to go to low power for a controlled descent,
no idea where it lands but impact energy is limited.

I have seen this work, Quad was recovered intact although it took a couple of days to find it.

ad2049q:
They all seem to have implemented that one.

Yep , if you do not cut the grass they do not take off. :slight_smile:

"volatile" tells the compiler that the variable may change at any time because it is changed in an ISR. I keeps the compiler from optimizing away access to the variable. If you don't use "volatile" the compiler might copy the value to a register and never look at the actual variable again.

Thanks :slight_smile: