Arduino Helicopter Autopilot

Hi,

I wrote the following code because I had looked (very briefly) for something similar and found nothing of any use so I coded a system myself.

The code I wrote for reading the pulses in PCM is as follows:

/*
PCM reading code for Arduino, by Ed Simmons
The aim of this code is to capture all the channels from an RC receiver on one pin.

Inside your TX, the control positions are coded together into a sequence of pulses(PCM), the rising edge of each pulse being the parts of the signal that convey the information.
This is the modulated with the carrier signal for transmission, when received by the RX it is de-modulated (the signal at this stage is the same PCM as in the TX - this is what we are interested in!)
before being sent to a some demux circuitry (usually very basic)

Find the pcm in your RX with a scope, verify you have the right place by adjusting the controls on the TX and looking for the changes in the pulse timings, solder a wire onto this point,
connect this to the arduino and off we go.

Theoretically, this code should be able to use any number of channels available on your radio gear, ie you need not specify that your 7ch set is 7ch if you only need 5ch... the
extra pulses will simply be ignored in the process of finding the framing period. However, the pulses must be sequential and starting immediately after the frame period.
*/

define NUM_CHANNELS 4 // the number of channels we are receiving

define FRAME 4000 // the length of the framing pause from the RC rx

int rcPin = 2; // the pin that the pcm is connected to

extern volatile unsigned long timer0_overflow_count = 0; // variable to store timer overflows...
unsigned long lastReadRC = 0;
unsigned long hptime = 0;
unsigned long time = 0;
unsigned long channel[NUM_CHANNELS] = {};
unsigned long on =0;
unsigned long lastWriteServos = 0;

unsigned long hpticks (void)
{
return (timer0_overflow_count << 8) + TCNT0;
// return TCNT0;
}

void setup()
{
Serial.begin(9600);
pinMode(rcPin, INPUT);
pinMode(19, OUTPUT);
}

void loop()
{

if(millis() - lastReadRC >= 100)
{
// Serial.print("hpticks*4 = ");Serial.println(hpticks()*4); // debug - test timers (will print time in microseconds since switched on every 100ms)

// mstime = millis();
while(!digitalRead(rcPin) == HIGH) // waits for signal to go high
{
continue;
}
hptime = hpticks()*4; //When the signal arrives, record the start time (in microseconds)
// mstime = millis();

while(!digitalRead(rcPin) == LOW) //Waits for signal to go low
{
continue;
}
while(!digitalRead(rcPin) == HIGH) // waits for signal to go high
{
continue;
}
time = (hpticks()*4) - hptime; //Here takes the differences of the start and finish times, the result is the length of the last off period.

if(time >= 5000) // if the last off period was the frame period - we are at the start of the sequence
{
// Serial.println(time);
for(int i = 0; i < NUM_CHANNELS;i++){ // step through the channels from 0 to 1 less than you specify in NUM_CHANNELS
channel = hpticks()*4; // record the start time for this channel

  • while(!digitalRead(rcPin) == LOW) //Waits for signal to go low*

  • {*

  • continue;*

  • }*

  • while(!digitalRead(rcPin) == HIGH) //Waits for signal to go high *

  • {*

  • continue;*

  • }*

channel = hpticks()4 - channel; // subtract the start time from the end time to get the duration*
* }*
* hptime = 0;*
* lastReadRC = millis();*
* time=0;*
* Serial.print("Results! 1= ");Serial.print(channel[0]);Serial.print(" 2= ");Serial.print(channel[1]);Serial.print(" 3= ");Serial.print(channel[2]);Serial.print(" 4= ");Serial.println(channel[3]);*

* }*
* }*
}
I hope this proves to be of some use to people, I'm looking into making the needed changes to enable a failsafe action.