Arduino Helicopter Autopilot

Hi all,

This is my first post on the Arduino forums, but i'd like to introduce you to one of my projects.

I have been developing a 'HeliShield' for the Duemilanove, along with the code to run full stabilisation of the helicopter, and mix the radio control signals etc.

I will soon be adding in autonomous features for dealing with loss of signal and suchlike.

There's a big write up which I am adding to as I progress with the work on my website, link in a minute, being the first post - it won't let me include the link.

I hope there are some Walkera and Piccolo users interested!

The current code and HeliShield are best suited to twin motor helicopters (one for the main rotor, one for the tail) although I am working on code for a 5 channel system (currently using 4) for a collective pitch heli, outputting all the control using servo pulses, thus doing away with the need for an onboard motor controller, as most people with a collective pitch heli will have a suitable ESC anyhow.

I hope someone will find this of interest!
Many thanks to the Arduino folk everywhere for all the demo code!!!

Ed
:slight_smile:

Here's the web address mentioned in the previous post.

http://www.eclipseaudioservices.co.uk/extras/helicopter.html

I'll be putting the code online as soon as I fix my CMS. It currently has a special 'code mangling' "feature"

Calling all Piccolo and Walkera pilots - development kits for arduino helicopter control!!

Looks good.
Now I only wish that I could fix the damage that my old heli took the last flight....

Nice idea you've got there, keep it up! :slight_smile:

@ Archive555, what's the heli? Cheers!! Let me know if you'd like a PCB, I have a few first run prototypes up for grabs! They're not the easiest boards to solder, there's no solder mask or through hole plating - and it's double sided. But aside from that - it might fly!!

The PCB is coming together nicely, more revisions have been made to the layout and I'm planning to etch more PCBs soon.

There is a full UAV development board in the works, all made on one PCB, with all the sensors and the micro being available as SMT it seems an obvious progression. I will post details when more progress has been made, and the article will also be on my website...

Code has been improved, both for the Arduino and the Processing sketch. The serial control is nearly complete, all the control data is sent in a string similar to GPS output and checked for validity. All suspect data is ignored and the last good values are repeated.
The task of designing an interface to first display the sensor data was not particularly easy, but I have now added code for control.
One click of the mouse enables control, another click holds the position of the mouse to free you to do other things with your mouse without crashing the heli.

So far so good, next is to integrate the data being sent into the flight algorithms...

Hi,

owning (and flying) 5 helicopter from 26g to 3800g I am very interested. However I don't think it will be that simple in the end. Tuning a helicopter for normal flight is complicated as hell, so such a system requires much work to get it right. There are some ready systems on the marked evolved over the last years (Helicommand, V-Stabi, GAUI GU-356, Gyrobot etc) so I guess you tackled a problem which will keep you busy some years. Also check the mikro copter project!

Best Regards,
Carsten

Can't remember what brand it was, it doesn't have any decals and I got it from a relative (second hand), and they didn't still have the manual or anything. It's a pretty standard-type heli, nothing special, just the basics.

How much are the PCBs? If they aren't too pricey, I might just grab a few... :slight_smile:

Hi All,

it's my first post here and i'm a newbie when it comes to programming arduinos (i havent received mine yet but im anxiously awaiting its arrival) but i have flown rc helicopters for about 4 years now. Currently my fleet consists of a trex 450, 2 trex 600ns and a raptor 50

Firstly, your project is very ambitious but it could make you popular in the rc world if you managed to create/market a working model :slight_smile:

just by looking at your photographs on your website, it looks like youre off to a good start. The one thing i noticed is you note in one of your pictures that the gyro is 150deg/sec. This may be good for your piccolo but not for a larger helicopter. I fly spartan 760 gyros in my helicopters and they have yaw rates of well over 700deg/sec.

Having your board output a pulse to control the tail (a c/p tail rotor) would be highly beneficial, I can think of very few helicopters which use a motor on the tail.

You might be best off using a mechanically mixed helicopter to test your design, that way you don't need to worry about mixing any of the outputs.

You seem to be worrying about yaw, it might be best to think about that in a later project. Nearly all helicopters today come with gyros as part of the electronics outfit, so concentrating an a stabilisation system and leaving out yaw would simplify things somewhat if you were running into problems.

Also one final thought, i'm not sure exactly what type of g forces the airframes undergo during flight, but theyre well above that of a regular airplane (My project is going to be to use an accelerometer to measure and record this).

I'm really interested to see how you progress with this, r/c helicopters are a passion of mine. Keep in touch.

Nick

Hi all,

Thanks for all the interest, questions and advice!

I've succeeded in getting the serial API working correctly, and there is now some autonomous code being tested.

I will soon have the code online, I'm tidying it up so as not to confuse, and inserting some much needed commenting.

I will be building the heli up in the next couple of days for some real testing, video will be on my site soon...

Re sensitivity of the gyro, i'm aware that the yaw rates of some helis can be huge, however for the most stable correction the more sensitive the sensor the better. I'll see what comes of it when i start flying it again.

Re servo pulse output for tail rotor control: I have made the pins controlling the two motor controllers on my current PCB also available on servo headers, this allows either use of the onboard speed controllers for a piccolo or walkera type heli, or output ESC/servos. All that is needed to change the code is to remove the commenting of one line, and comment out another.

I am going to buy a 'proper heli' in the very near future, this will be the test bed for the rest of the development work.

I have 5 pcbs for £10 each, this will help me cover the costs of the next batch of prototypes aimed at bigger helicopters, more channels of radio etc etc.

If you are interested in the PCBs please email info(at)eclipseaudioservices(dot)co(dot)uk

A small breakthrough has been made! I have coded the ability to read the PCM baseband signal from the RC rx - all the channels of data can be captured on one pin of the arduino, just by soldering one wire onto the RX all the info is available on one pin.

Efficiency of the system has been improved as a result of the way the pulses are read, instead of waiting for a pulse on each pin of the RX separately (introducing a delay before each value is read) the code waits for only once for the framing pulse and then reads all the values of all channels at once.

This code should also prove an easier system to adjust to make it time out when RC signal is lost.

If anyone is interested in how to do this, please email me and I can send you the code, I still have to solve a code mangling problem on my website.

All the code will be available very soon, I'm quite eager to make it stable before releasing it...

Hi Ed, good to hear you are making progress.

I presume the code is not very big, why not post it here? I am wondering how different it is from the code I posted in this thread: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1228137503

So am I. MEM, your library has been working very well for me.

Jim

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.

Hi Ed, thanks for posting.

The advantage of your implementation over the ServoDecode library linked in post #9 above is that it doesn't grab timer1, so PWM outputs on pins 9 and 10 are available. But your code has some drawbacks that may limit its use.

Your decoding is done in software so the application can't do anything else while waiting for the channel pulses. There may only be three or four milliseconds between frames so 80% of the available processing time is not available for running application code. ServoDecode does all the pulse counting in hardware using Timer1 so practically all of the available processing power is available to run the application.

Also, it appears that the code above is measuring to an accuracy of 4 hpticks. I think each hptick is 4 microseconds so your accuracy is to 16 microseconds, which would give around 64 discrete steps between 1ms and 2ms, this is less than the resolution of the rc systems I have looked at. TheServoDecode library clocks timer1 at 0.5microseconds which is 8 times faster than an hptick, 64 times higher resolution than the 4xhptick code.

Other advantages of ServoDecode are that it automatically detects positive or negative going pulses and the number of channels. It has failsafe supporting preset or last good value. And it s library that is easy to integrate into an application.

I don't want to discourage you in enhancing your code, but knowing what else is out there may help you decide where best to apply your efforts.

Have fun!

Re timings etc, the RC pulse train is only read every 100ms, which is fine for the moment (it's causing no problems in testing) and this bit of code runs plenty fast enough for the moment.

I would like to look into using the other timer - this has proved perfectly reliable so far, but the increase in resolution would be nice.

I'll look into it.

Cheers,
Ed

Nice job, i didn't have time to read all the comments, but i like your work =), please keep going...

check this out:
http://diydrones.com/profiles/blogs/705844:BlogPost:38393

But i suggest to use external interrupts with a hardware timer to count the pulses... Without wasting CPU power, the secret is never use pulseIn and delays, NEVER! ::slight_smile:

I been working on ArduCopter V2, using better Kalman Filters and a real accelerometer (no more Wii).. It uses zero delays and is very efficient... I also rewrite the Labview grounds station.. I want to use it also to mount it in the new helicopters without fly bar...

But i'm busy here doing other tasks...

Take care.

Hi,

Firstly, the code I borrowed some of the kalman filtering was based on the Wii nunchuck, but this code uses the Sparkfun accel and gyros.

I'm constantly omptimising the code, and yes delay is bad, I never use pulse in.

I am interested in looking at some of the other hardware timers, but for the moment I'm concentrating on getting the hardware smaller and well integrated into the helicopter. I have a collective pitch version too now, there are two platforms to build.

Cheers for all the support!

But i suggest to use external interrupts with a hardware timer to count the pulses... Without wasting CPU power, the secret is never use pulseIn

Hi jordi,

The most recent ardupilot [u]code[/u] I could find does use pulseIn, have you posted a version of the code that uses the timer?

Hi all,

Once again, thanks for all your input and interest.

The code is now online and both Collective pitch and fixed pitch development code-bases are available.

The serial API has been implemented with control input from the processing sketch.

Come and get it from www.eclipseaudioservices.co.uk/extras/helicopter.html

Have fun!

Hi Ed, interesting writup – I would love to see the helicopter in flight – have you posted a video?

BTW, I see that your RC signal decode and servo output code are both done in the foreground. This eats into the number of sensor readings you can process. You may want to consider using code that does the decoding and servo driving in background using the ATmega168 hardware timers to do the work.

The RC decoder is here : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1228137503
it uses pin 8 as input and has failsafe that can be set to last good signal or any preset

The servo driver code is here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1230479947/13

PM me if you would like help integrating the code into your app.

Hi mem,

I'd like to work on integrating these, I've looked at both libraries in an effort to understand the timer functions etc. I'd be interested in trying to now that I've got my tax return out of the way.

The servo outputs seem to have the biggest impact on performance, it would be great to get that going in the background. I also like the idea of the preset values on signal loss, given that there is mixing between RC and Serial control it would not be good to include noise from the RC when flying on the serial 'line'.

I've upped the sensor count too, I now have the code ready for 6 degrees of freedom, but there's a few little issues to iron out.

There will be some video soon, but the hardware needs some more work before I risk actually flying properly. It's dangerous enough on a tether! (For a little while, it was over-reacting to movements)

Cheers,

Ed