Read PPM signals from RC receiver or Control

well, like part of my arduino UAVS project, i wrote a program to read (not write) PPM signals coming from a RC receirver or maybe from the remote control port (buddy port), works with futabas and walkeras.
To know more about PPM signals pleaseeeeee here:
http://www.mp.ttu.ee/risto/rc/electronics/radio/signal.htm

If you want to intercept the PPM signal from you receiver, please enter here:

http://paparazzi.enac.fr/wiki/index.php/Other_Hardware

To know more about the buddy port of the futaba PLEASE HERE:
http://users.belgacom.net/TX2TX/tx2tx/english/tx2txgb3.htm

You just conect the PPM signal out to the pin 4 of arduino and arduino ground with the ground of the device.

#define channumber 6 //Cuantos canales tiene tu radio???????/How many channels have your radio???
int channel[channumber]; //Valores de canales leidos/ readed Channel values 
int PPMin = 4;

void setup()
{
  Serial.begin(9600); //Iniciamos com serial/ 
  pinMode(PPMin, INPUT); //Patita 4 como entrada / Pin 4 as input
} 

void loop()
{
  //Espera hasta que la senal de sincronizacion llegue, debe ser > 4 milisegundos 
  //waits ultil synchronize arrives > 4 miliseconds
  if(pulseIn(PPMin , HIGH) > 4000); //Si el pulso del pin 4 es > que 4 msegundos continua /If pulse > 4 miliseconds, continues
  { 
    for(int i = 1; i <= channumber; i++) //lee los pulsos de los demas canales / Read the pulses of the remainig channels
    {
      channel[i-1]=pulseIn(PPMin, HIGH);
    }
    for(int i = 1; i <= channumber; i++) //Imprime los valores de todos los canales / Prints all the values readed
    {
      Serial.print("CH"); //Canal/Channel
      Serial.print(i); // Numero del canal / Channel number
      Serial.print(": "); // que te importa 
      Serial.println(channel[i-1]); // Imprime el valor/ Print the value
    }
    delay(200);//Le da tiempo para imprimir los valores en el puerto/ Give time to print values.
  }  
}

Right now im finishing my new invent:
Im writing an arduino code that is able to control 6 or more servos in parallel mode. What this mean?
Ok in normal mode, you need to pulse servo 1, then continue, pulse servo 2, then pulse servo 3, etc. etc. One by time.
But with my code you can control more than 6 servo just with one “pulse”. YEAHHH. how i do it? well… is easy, with a “For” cicle, with a 1 microsencond delay, and when the X channel rich the pulse length, they LOW the port with an IF condition (if(pulseLenght >= parallelPulse) { digitalWrite(pinServo, LOW)}. THAT ALLL!!! haha :stuck_out_tongue:

Another taste of my project, im waiting for my gyrocope sensor, to finish mi accelerometer+gyros+Kalman Filters, IMU. :slight_smile:
To do this:
http://tom.pycke.be/mav/92/kalman-demo-application

Better version with glitch filter:

#define channumber 6 //Cuantos canales tiene tu radio???????/How many channels have your radio???
#define filter 10 // Filtro anti salto/ Glitch Filter
int channel[channumber]; //Valores de canales leidos/ readed Channel values
int lastReadChannel[channumber]; //Ultima lectura obtenida/ Last  values readed
int conta=0; //Contador/couter


void setup()
{
  Serial.begin(9600); //Iniciamos com serial/ Serial Begin
  pinMode(4, INPUT); //Patita 4 como entrada / Pin 4 as input
  pinMode(13, OUTPUT); // Led pin 13
} 

void loop()
{

  if(pulseIn(4, HIGH) > 3000) //Si el pulso del pin 4 es > 3000 usegundos continua /If pulse > 3000 useconds, continues
  { 
    for(int i = 0; i <= channumber-1; i++) //lee los pulsos de los canales / Read the pulses of the channels
    {
      channel[i]=pulseIn(4, HIGH);
    }
    for(int i = 0; i <= channumber-1; i++) //Promedia los pulsos/Average the pulses
    {
      if((channel[i] > 2000) || (channel[i] <100))//Si se pasa del rango envia ultimo pulso/ If channel > max range, chage the value to the last pulse
      {
       channel[i]= lastReadChannel[i]; 
      }
      else
      { 
      channel[i]=(lastReadChannel[i]+channel[i])/2; //Promedio el pulso pasado con el nuevo pulso/Average the last pulse eith the current pulse
      conta++; //Incrementa el contador/ increment counter
      }
    }

    }
    if(conta > filter)//Si el contador es mayor al filtro imprime valores/ If counter is > than filter, then prints values
    {
      for(int i = 0; i <= channumber-1; i++) //Ciclo para imprimir valores/Cycle to print values 
      {
        Serial.print("CH"); //Canal/Channel
        Serial.print(i+1); // Numero del canal / Channel number
        Serial.print(": "); // que te importa 
        Serial.println(channel[i]);
        lastReadChannel[i]=channel[i];
      }
      if(channel[4] > 1000) //si el canal 5 tiene un rango mayor a 500 enciende el LED/ If channel 5 is > than 500 turn on the led
      {
        digitalWrite(13, HIGH);
      }
      else
      {
        digitalWrite(13, LOW);//Si no lo apaga/If not turn it off
      } 
      delay(400); //Delay
      conta=0;//Reinicia el contador/ Restart couter. 
    }
  }

It looks like that will be an interesting project, I hope you will post your progress.

BTW, pulseIn is a blocking function, if this causes you a problem, you may want to consider using the Atmega chips hardware support for input capture on digital pin 8. There is no high level Arduino support for this and it's a little tricky to get going but the Atmega168 datasheet does cover input capture and you may be able to find out more using google if you decide you want to pursue this route.

Yes i was thinking that, probably is going to be a big problem, if the receiver fails, the servos will be freeze and airplane BOOM!!!. I wish the arduino developers program a time out function: pulsein(Pin, HIGH, timeOut); thats would be pretty cool. Any ideas??? But think again... if the receiver fail, with arduino or not, it will crash... is the same. By the way, ill use TWO arduinos, one for read sensors, precess the data, send information by UArts to ground, and this data (few bytes) will be sended to arduino 2 by i2C, arduino 2 only read PPM signals, and control servos.. (Automatic Pilot). Is going to be DUAL CORE ;D I made some test and looks goods. The only real deal is the kalman filters, but yesterday i figure almost everthing out (12 am until 6 am, that was my new year).

No body know an external PPM signal reader??? There is a lots of components to pulse servos etc. But i want to read PPM signal.... And send the readed data by i2c or SPI, WHATEVER!!. And if the receiver fails, the Arduino wont freeze.

I was thinking on a physical component to switch the PPM signal between Arduino and an external servo control. If the second arduino detects something wrong i will return the manual control. :o

Maybe i can use a third Arduino :P ??????????????????????????????????????????????????????????????

I wish the arduino developers program a time out function: pulsein(Pin, HIGH, timeOut); thats would be pretty cool. Any ideas???

There are a number of ways you could implement a PulseIn with timeouts.

PulseIn counts the time it takes for a pin to change to a different state and back again. You would need to add a check to see if a given maximum time is exceeded. The disadvantage of this method is that timing errors are increased by the amount of time to do the additional check. Optimizations can be made to minimise this, such as only supporting 16 bit values rather then the 32 bits used by the standard PulseIn.

A more accurate method is to use a hardware clock to do the timing. There a are a number of ways of doing this but the most accurate would be to use input capture on timer1, either by polling for the register that indicates that a pulse has changed state or by using the capture interrupt.

But you may want stick with existing PulseIn implementation until you are clearer on how the overall system will behave. Your idea of separating out functionality for sensing pulse inputs, driving servos and other functions is a good one. You may find that you can achieve this on a single chip if you want to delve under the covers and take advantage of the timer hardware. Its not trivial, but nor is getting two or three processors reliably talking to each other.

Have fun!

Thanks for the information... I understand all you said, but i don't know exactly how to do it...Maybe i need to study more options. which library's or tutorials of arduino or AVR your recommend to start for??? :)

I was looking over the R/C Receiver hacks to try to get the ppm single from it and i cam across this little cord that looks like it can do the job for those people that don't want to take the chance of messing up there receivers.

http://www.mftech.de/catalog/product_info.php?cPath=23&products_id=44

You plug the cords into the receiver and it outputs the ppm signal for you.

I was looking over the R/C Receiver hacks to try to get the ppm single from it and i cam across this little cord that looks like it can do the job for those people that don't want to take the chance of messing up there receivers.

http://www.mftech.de/catalog/product_info.php?cPath=23&products_id=44

You plug the cords into the receiver and it outputs the ppm signal for you.

If you can access the composite signal from your receiver then you don't need any external hardware. It is discussed in a (long) thread, but the code for the library to decode the signal starts here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1204020386/156#156

Has anyone used the Arduino to split out the stream from a VEX add on TX/RX set up? I have seen people do it with PIC and DIOS, just wondered if anyone has used the Arduino to do it?

Fantastic project. One disagreement:

Yes i was thinking that, probably is going to be a big problem, if the receiver fails, the servos will be freeze and airplane BOOM!!!.

Wouldn’t this be a great place for a failsafe command set?

Certainly, it depends on what sensors are aboard (horizon detector can tell you “up”, compass direction, GPS location, etc.)

At a minimum: If you lose the receiver, neutralize elevator & ailerons, idle throttle (or 1/2, or?). If your aircraft is semi-stable it should return to a flight attitude on its own. If you have a horizon detector, you can be even more sure of it.

Got more sensors? Fly to a GPS coordinate (your flying field?) and circle, again waiting for a signal. If no signal after orbiting the field for 2 minutes, fly to a coordinate downwind of the runway, turn to runway heading, cut throttle to idle. With a little luck your hardware ends up in just a few pieces at your flying field rather than a bajillion pieces lost in a lake, highway, forest…

Or, more lazily, if you lose the receiver switch off engine, pop parachute, and it all floats gently downward... to land on a road and be mangled by a passing truck. :)

Wouldn't this be a great place for a failsafe command set?

The code linked in reply 8 above should do what you want. Each channel can be individually set to a user defined failsafe value which will be returned on detection of loss of a valid signal. (Alternatively, any channel can be set to use the last good value received.)

The fail-safe could trigger an autopilot in a plane, but simpler is to just idle the motor and set the controls for a gentle turn so hopefully the plane will circle, gliding down to land somewhere near the pilot.

I am trying to find some time to do write-up on this library for the playground. Hopefully I will get to it this weekend, but the most recent code posted at the end of the thread does have that fails-safe capability.

The code linked in reply 8 above should do what you want. Each channel can be individually set to a user defined failsafe value which will be returned on detection of loss of a valid signal. (Alternatively, any channel can be set to use the last good value received.)

(peeking at other thread)

Oh, now that is just sweet, being able to set failsafe per channel in setup()...or not set it!

For a battlebot or something, last good value before you were jammed may be OK. For an aircraft that may not be good. (Imagines the beginning of an outside loop...)

Or, more lazily, if you lose the receiver switch off engine, pop parachute, and it all floats gently downward... to land on a road and be mangled by a passing truck. :)

:) :) :)

When I was a teenager there was a guy at the local flying field who landed that way.

Instead of landing in the usual manner, he would fly ~50 feet over the field, then when he pulled both the throttle trim and throttle all the way back the engine would cut off, and (what would be on full scale aircraft) the engine cowling and part of the windshield were released and a parachute, tied to the wing spar, came out.

First time I saw it I thought it was a great trick. Soon discovered he always landed that way. Wasn't till much later I learned that he crashed so much on landing, that one time he blew such a fit, stomping the poo out of his aircraft that he injured his foot (control rod went through the sole of his shoe into his foot). While waiting in the ER he had the idea to rig his next plane to eject the cowling (held down in front by an extra tab on the throttle servo control wire). A 2 or 3 foot nylon chute was folded and mashed against some open cell foam on top of the fuel tank, and held in by the cowling.