Arduino to Radio-Control Transmitter Interface

Blogged by Mathieu as Diary, Electronics — Mathieu Thu 1 Nov 2007 9:11

I whipped up a little interface yesterday, to connect an Arduino to a Radio Control Transmitter (a Multiplex Royal Evo 12, in my case). This can be used to send commands from the Arduino to the transmitter, which will mix them with the manual input and radio them to the radio-controlled model.

Arduino Controlled RC Transmitter
Channels 1, 2, 4 and 5 are moving, sticks centered.

The first application I want this for is to pan a video camera with two servos on the model, with input from head motion tracking on the Arduino, i.e. see from the model’s cockpit. (Yes, I know, it’s been done… but not by me and not on Arduino AFAIK.) I’ve got the video goggles, camera and video transmitter/receiver from the Spy Gear RC car Jack of All Trades has made famous.

It could also be used as a PC-to-RC interface, using Arduino as a USB-to-RC bridge. Any kind of processing could be done on land, and the resulting commands sent to the model. Ultimately, you could close the loop with a data transmitter on board, but that is beyond the scope of this little hack…

First off, had to make a trainer cable for the RC transmitter, which would normally be used to connect a student’s radio to a teacher’s, in order to share control of the model. For Multiplex Royal Evos, the best info I found was here, but you should be able to google for whatever works for your radio.

RC Trainer Plug
Need to buffer the 5V signal from the Arduino to the 7.2V of the radio with a transistor.

Next, made a little connector from some headers, perfboard and shrinkwrap for the Arduino end of the cable.

RC Trainer Cable for Arduino
Quick and dirty connector at the Arduino end. Center pin not connected.

Last, needed to write some code to generate the PPM frames, which consist of a series of pulses, one per channel, rounded out by a synchronization pulse to a 20ms frame. The pulses are very similar to servo control pulses, which are a well treated subject in Arduino lore. I started out with todbot’s Serial_Servo_Better and added the frame wrapper around the pulses, some dirty code to sweep values and some cryptic code comments.

The basic idea is that the Arduino is busy doing precise timing with delayMicroseconds() while the pulses are being sent, but you can do whatever you want for the remainder of the 20ms frame, i.e. the synchronization pulse. If you need more than that to get stuff done (lots of processing, or lots of channels leaving a small synch pulse), I guess this would need to be written with interrupts to make it more ‘fire and forget’. Never done interrupts, so will try that later.

Here’s the code:

/*
* Trainer PPM Interface
* -------------------
*
*
* Created 31 October 2007
* copyleft 2007 Mathieu Glachant
* http://ban-sidhe.com/
*
* adapted from todbot's Serial-Servo-Better
*/

#define channelNumber 2 // Number of channels to send (keep below frameLength/pulseMax)

int servoPin = 12; // Control pin for trainer interface

// A pulse starts with a low signal of fixed width (0.3ms),
// followed by a high signal for the remainder of the pulse.
// Total pulse width is proportional to servo position (1 to 2ms)
int pulseStart = 300; // pulse start width in microseconds
int pulseMin = 724; // pulse minimum width minus start in microseconds
int pulseMax = 2048; // pulse maximum width in microseconds
int conversionFactor = 57; // (pulseMax - pulseMin - pulseStart)/18 (will divide by 10, wante two digits without using a float)

// A frame is a succession of pulses, in order of channels,
// followed by a synchronisation pulse to fill out the frame.
// A frame's total length is fixed (20ms)
int frameLength = 20; // The duration in millisecs of a frame

long lastFrame = 0; // The time in millisecs of the last frame
int servo[channelNumber]; // Values to set for the servos in degrees
int channel[channelNumber]; // Values to send on channels (duration of pulse minus start, in microseconds)
int i; // Counter in for loop
int j = 0; // Counter for servo updates

void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
Serial.begin(9600); // connect to the serial port
for ( i = 0; i < channelNumber; i = i + 1 ) {servo[i] = 0;}
for ( i = 0; i < channelNumber; i = i + 1 ) {channel[i] = pulseMin;}
Serial.println("Trainer_PPM_Interface ready");
}

void loop() {

// Save the time of frame start
lastFrame = millis();

// This for loop generates the pulse train, one per channel
for ( i = 0; i < channelNumber; i = i + 1 ) {
digitalWrite(servoPin, LOW); // Initiate pulse start
delayMicroseconds(pulseStart); // Duration of pulse start
digitalWrite(servoPin, HIGH); // Stop pulse start
delayMicroseconds(channel[i]); // Finish off pulse
}
digitalWrite(servoPin, LOW); // Initiate synchronisation pulse
delayMicroseconds(pulseStart); // Duration of start of synchronisation pulse
digitalWrite(servoPin, HIGH); // Stop synchronisation pulse start

// We're done generating pulses and using delayMicroseconds()
// Time to do some other processing before the next frame
// How much time depends on how many channels you are running

// Let's change the servo positions
j=j+1;
if (j==4) {j=0;}

if (j==0) {
for ( i = 0; i < channelNumber; i = i + 1 ) {
servo[i] = servo[i]+1;
if (servo[i] >= 360) {servo[i]=0;}
}
}

// Calculate pulse durations from servo positions
for ( i = 0; i < channelNumber; i = i + 1 ) {
channel[i] = abs(servo[i]-180);
channel[i] = int(channel[i]*conversionFactor/10)+pulseMin;
}

//if (j==0) { Serial.println(channel[0]+pulseStart); } //debug console output, normally commented out

// We're ready to wait for the next frame
// Some jitter is allowed, so to the closest ms
while (millis() - lastFrame < frameLength) {
delay(1);
}
}

Feel free to reuse, modify, etc… to your heart’s content. Please acknowledge me with due credit if you do, and have fun!

UPDATE: Corrected a couple rookie mistakes in the original code, like defining 5.7 as an integer or not using declared constants. No changes to how it works, but cleaner code (I hope).

UPDATE2: If you got here via the mention on the Make Magazine Blog, there is a small discussion going on over at the Arduino forums, with a bit more explanation of how and why this works…

13 Comments »

  1. Comment by Matt Swann — November 1, 2007 at 10:01

    Very nice! Interrupts aren’t so bad, they’re just hard to debug…

  2. Comment by Mathieu — November 1, 2007 at 10:44

    Thanks!

    Did some timing tests, the inclinometer code runs in about one millisecond, so I may not have to master interrupts just yet…

  3. Pingback by Blog de Daniel Bernat » Conociendo Arduino (II) — December 12, 2007 at 19:02

    [...] INTERFACE: a nice blog post with some pretty pictures showing how to [...]

  4. Pingback by Arduino to radio-control transmitter interface » Developages - Development and Technology Blog — January 25, 2008 at 11:45

    [...] Arduino to radio-control transmitter interface – Link (and code). [...]

  5. Pingback by Electronics-Lab.com Blog » Blog Archive » Arduino to radio-control transmitter interface — January 25, 2008 at 12:13

    [...] Arduino to radio-control transmitter interface – [Link] [...]

  6. Pingback by Arduino to radio-control transmitter interface — January 25, 2008 at 15:37

    [...] You can see on the transmitter’s display that channels 1, 2, 4 and 5 are broadcasting values while the sticks are centered. If I had video, you could see them change over time under the Arduino’s control.Arduino to radio-control transmitter interface – Link (and code). [...]

  7. Pingback by Arduino to radio-control transmitter interface at Cool Electronic projects blog — January 26, 2008 at 2:39

    [...] 12, in this case), which mixes them with manual input and radios them to the radio-controlled model.Link google_color_link = “0000FF”; google_color_url = “777777″; google_color_text = “333333″; //–> [...]

  8. Comment by JOrdi — February 2, 2008 at 5:21

    You can improve your system adding some gyros and kalman filters, like my arduino project:

    http://diydrones.com/profiles/blog/show?id=705844%3ABlogPost%3A23188

    Nice work!! d

  9. Comment by Mitch — April 14, 2008 at 3:18

    Jordi, he has a SparkFun 5DOF plugged in there.

    Im more interested in that, have you any code or details how to interface Arduino with it? I dont have a 5DOF, but im keen on getting one soon.

  10. Comment by Mathieu — April 14, 2008 at 8:23

    Hi Mitch, you should find the code in this other post:

    http://ban-sidhe.com/blog/?p=1467

  11. Comment by Steve — June 8, 2008 at 11:31

    Hi there, my name is Steve and I am very new to micro controllers. I have been reading madly on programming in C and must admit I am so far completely hopeless at it but I am sure it will come with time.

    I really am glad to have found your project. I want to do something very similar but wish to take four analog inputs (potentiometers) and send them to Arduino, convert to PPM and send into my trainer port just as you have.

    After that is complete I want to add a 2 axis gyro (or accelerometer not sure which is best) for head tracking.

    I have ordered the Arduino and hope to get working on code right away.

    If you don’t mind I will borrow your code as a starting point but honestly I could use some help in converting it to what I need… if you would not mind emailing me at the address I supplied here that would be really gret!

    If not no worries and thanks for the starter code!

  12. Comment by Mathieu — June 14, 2008 at 20:35

    I’ll try to help but would readily admit I’m not an expert at head tracking by any means. I think you need to filter the gyro inputs just right, etc… Just bought a three axis magnetometer recently and was hoping to use that to get an absolute heading reference rather than the gyro readings… or on top of the gyro reading. Am away for the rest of the week, tho.

    In any case, happy to write you to establish contact at least.

  13. Pingback by Arduino - Interfaccia per Radiocomandi - Elettronica Faidate — March 12, 2009 at 18:20

    [...] maggiori informazioni cliccare qui. Mentre nei forum arduino c’è un thread interessante su questo progetto che unisce [...]

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Click on smiley to insert!

) (w) (u) p (y) (n) d (*) o) 8) ( (f) (g) (t) o (8) (l) (i) x (~) (e) $ (&amp) (c) ( s (d) (o) (@) (p) (^) (b) [

Proudly powered by wordpress - Theme Back in Black 2 by neuro