Arduino Forum

Forum 2005-2010 (read only) => General => Exhibition => Topic started by: Syvwlch on Nov 01, 2007, 03:29 pm

Title: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Nov 01, 2007, 03:29 pm
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.

(http://farm3.static.flickr.com/2099/1813373215_888b4e3f2e.jpg)
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 here: http://jakeofalltrades.wordpress.com/2007/09/30/25-head-mounted-display/.

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: http://www.designsoft.com.au/ahome/rc/EVOtraining/, but you should be able to google for whatever works for your radio.

(http://farm3.static.flickr.com/2307/1813030879_1c9ce5cd01.jpg)
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.

(http://farm3.static.flickr.com/2232/1813030953_3a5c489c4a.jpg)
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 (http://todbot.com/blog/spookyarduino/) 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.

I've run out of characters, so I will post the code in a reply to this post.
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Nov 01, 2007, 03:31 pm
As promised, here it is, in all its quick and dirty glory!

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

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 = 5.7;   // (pulseMax - pulseMin - pulseStart)/180

                            // 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 channelNumber = 2;       // Number of channels to send (keep below frameLength/pulseMax)
int servo[2];                // Values to set for the servos in degrees
int channel[2];              // 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)+pulseMin;
 }  
 
 //if (j==0) {
 //  Serial.println(channel[0]+pulseStart);
 //}
 
 // We're ready to wait for the next frame
 // Some jitter is allowed, so to the closest ms
 while (millis() - lastFrame < frameLength) {  
   delay(1);
 }
}
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Nov 01, 2007, 07:02 pm
Mashed it up with some code I'd made to generate the pitch and bank angles from an accelerometer (based off of Dave Mellis Smoothing Tutorial) and I can now control two servos on the model by tilting the arduino forwards/backwards or left/right.

Also cleaned up the ugly bit where I defined 5.7 as an integer in the previous code  :-[ and made better use of defined constants in my variable declarations.

The new code doesn't fit in 5500 characters, so I can't quote it here, but I posted it here instead: http://ban-sidhe.com/blog/?p=1467
Title: Re: Arduino-Controlled RC Transmitter
Post by: Skylord123 on Dec 28, 2007, 07:14 am
Whoa, Nice job buddy  :) i like it lol. It will be more then i will ever do =D

Nice job again btw :)
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Dec 28, 2007, 02:45 pm
Thank you :-)
Title: Re: Arduino-Controlled RC Transmitter
Post by: aballen on Jan 05, 2008, 04:13 am
Awesome! :D I've been looking for something exactly like this.

I'll be expanding on your brilliant code.

What I want to do is use the wii nunchuck to control one of my helicopters.

On my futaba running mode 2.

The wii nunchuck tophat for cyclic, channels 1 and 2.

The nunchuck C and Z buttons for channel 3(throttle)

Tilt from the nunchuck for channel 4(rudder)

I'm already able to read in the nunchuk data, now to pair the two!!!
Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Jan 05, 2008, 05:44 am
I have been playing around with this kind of thing myself. You are a brave man if you will risk your helicopter to nunchuck control. The challenge you will find is that it is very difficult to sense how to physically hold the nunchuck so that the inputs are zeroed. Any slight tilt of the nunchuck causes gravity to change one or more of the outputs (even when I think I am holding the nunchuck in a fixed position) You can't relay on the orientation of the heli to provide feedback because there is always a lag in the helis response (particularly if it has fixed pitch rotors, which it sounds like your is).

In short, it is very very much easier to overcontrol using accelerometer sensor input then it is using a conventional stick.

But, it would be great if you can overcome these obstacles so please post your progress.  But be careful.

When you have your project working, try plugging the arduino output into a simulator that takes trainer port input,  so you can see what its like before risking life and limb and your helicopter.  

Good luck.
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Jan 05, 2008, 12:18 pm
Aballen, thanks! That's exactly the kinda thing I wrote this for :-)

Mem, from my limited experience with helicopters on FMS, I see your point... however, it shouldn't be too hard to include a dead zone and some exponential either in the code on the Arduino or in the radio if it allows for that on student inputs, which should help considerably. Also, the arduino could provide feedback on the control position either via rumbling, tone/pitch or anything else you add to the circuit.

Lastly, he's only planning to have the rudder on the tilt, which seems to me to be the lowest risk choice here, not the cyclic.

In any case, I look forward to hearing about it!
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Jan 05, 2008, 12:25 pm
Which all reminds me... if you have one of those usb thingies to plug your radio into a computer as a joystick for a simulator (like FMS mentioned above), the arduino with the same code, plugged into it, would let you try your control scheme in the safety of the virtual world.

Bound to save you time and money as you iron out the kinks.

This would also be a good quick 'n dirty way to make your arduino speak USB-joystick to your computer, by the way...
Title: Re: Arduino-Controlled RC Transmitter
Post by: eustace on Jan 05, 2008, 08:01 pm
Nice code!  I'm building my way up to telepresence on a crawler bot, so I may end up using it as well - please keep us posted on this COOL project!
Title: Re: Arduino-Controlled RC Transmitter
Post by: eustace on Jan 05, 2008, 08:03 pm
I wanted to add to Aballen - it takes a brave soul to put an RC heli under microcontroller control.  Wear your armor.
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Jan 29, 2008, 07:19 pm
I'm new to the arduino and I think I basically understand how this is working, however I do not understand how he is controlling multiple channels on the transmitter from a single output on the arduino? Are the Pulse widths sent out in series?

If anyone could take a second to explain how that works I would really appreciate it.
Thanks,
Casey
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Jan 29, 2008, 07:41 pm
Yes, that's exactly what I'm doing.  ;)

In essence, the radio transmitter is modulating the carrier signal with a series of servo pulses, channel one first, then two, three, etc... End with a synch pulse that is recognizably different from a servo pulse to keep everyone's understanding of which channel is which, and you're all set.

The receiver demodulates to get the series of pulses, then sends the pulse in channel one to the servo connected to output one, and so on.

All the trainer interface does is substitute the pulses for certain channels from the teacher's radio for the ones from the pupil's. Replace the pupil's radio with an arduino and all it takes is a single signal to pass signals for 12 or more servos to the teacher's radio.
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Jan 29, 2008, 09:28 pm
Wow,
A thousand thanks matt,

I think I've got a better understanding,

http://www.mftech.de/ppm_en.htm

Was also helpful,
Just a few other questions, if you have the time.

Are all transmitters designed to operate with a 20 millisecond frame? (it seems like they are working with a 22.5 millisecond frame in the above link)

If I only need to address 3 of the 4 channels in my transmitter (I'm working with a Futaba T4YF) does the protocol require me to have 4 pulses within each frame or can I only encode the first three and ignore the 4th?

(http://caseyfarina.net/T4YF_scematic.tiff)

This is the schematic for the controller jack on the transmitter I'm using, Can I just connect the arduino output pin to pin 1 on the transmitter and the arduino ground to pin 2 on the transmitter? Or does the output of the arduino need to be altered before it gets to the transmitter?

Thanks again,
Casey
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Jan 29, 2008, 11:28 pm
I think most transmitters and receivers are actually quite flexible on how long the frame is. They seem to care more about finding a synch pulse after some reasonable length of time, but that length of time is not crucial as long as it somewhat close to 20ms. Your mileage may vary depending on hardware, of course.

I'm also pretty sure that once you have given all the pulses (or channels) that you care about, you can omit any others up to whatever the capacity of the transmitter or receiver is. In my case, if I only want to send channels one and two, I just wait for the end of the frame and give the synch pulse. My Royal Evo transmitter and my Futuba receiver don't seem to mind.

Now, the tricky bit is the hardware connection between the radio and the arduino. This is where you could, conceivably, do some permanent damage if you connect wires the wrong way, and you'll notice that in the case of the Multiplex radios like mine, you have to add a transistor between the two. From what I dimly remember reading on other radios, I think this is required only for Multiplex, tho, and it's not for protection, it's just to keep the signal high enough so that the radio can detect it.

I strongly recommend reading up as much as you can find on the web on the particularities of your transmitter and its trainer interface... I don't have any experience with the Futuba radios, for example.  :P If you're nervous about your radio, perhaps you can find a cheap, non-programmable radio that accepts pupil input over a trainer interface from the same brand, and try it first with that hardware?

If you do get it to work with a Futaba radio, the next chap who's trying to do this will appreciate it if you post the details of the connection here, of course. ;-)
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Feb 05, 2008, 06:18 pm
Ok, I have it from an experienced RC source that the Futaba buddy system is 0 volts for Low and 5 volts for High, However anything over 4 volts will be considered a High pulse. I haven't tested this yet but I will later this week and report back. However this should line up well with the arduino output capabilities.
Thanks again Matt for all you help.
Casey
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Feb 09, 2008, 10:17 pm
OK, Just got the arduino to talk to my rc set up,

Which consists of a Futaba T4YF transmitter and an Alpex APR-4FM receiver.
I hooked up the trainer output from the Transmitter to the oscilloscope program (the electroacoustic Toolbox from faber acoustical) and discovered that ppm was essentially the same as what Matt described with slightly different values.

For some reason the PPM was inverted on the Oscilloscope but I just tweaked the Arduino until I had some thing that matched the signal coming out of the transmitter.

So the Futaba T4YF transmitter uses a frame length of 18 milliseconds, a 400 microsecond low pulse before each of the high pulses and for me the high pulses were 1050 microseconds for dead center.

So this code keeps everything in the center
Code: [Select]
int outPin = 12;                 // digital pin 12

void setup()
{
 pinMode(outPin, OUTPUT);      // sets the digital pin as output
}

void loop()
{
 digitalWrite(outPin, LOW);    // sets the pin off
 delayMicroseconds(400);        // pauses for 400 microseconds
  digitalWrite(outPin, HIGH);   // sets the pin on
 delayMicroseconds(1050);        // pauses for 1050 microseconds      
 
 digitalWrite(outPin, LOW);    // sets the pin off
 delayMicroseconds(400);        // pauses for 400 microseconds
  digitalWrite(outPin, HIGH);   // sets the pin on
 delayMicroseconds(1050);        // pauses for 1050 microseconds      
 
 digitalWrite(outPin, LOW);    // sets the pin off
 delayMicroseconds(400);        // pauses for 400 microseconds
  digitalWrite(outPin, HIGH);   // sets the pin on
 delayMicroseconds(1050);        // pauses for 1050 microseconds      
 
 digitalWrite(outPin, LOW);    // sets the pin off
 delayMicroseconds(400);        // pauses for 400 microseconds
  digitalWrite(outPin, HIGH);   // sets the pin on
 delayMicroseconds(1050);        // pauses for 1050 microseconds
 
 digitalWrite(outPin, LOW);    // sets the pin off
 delayMicroseconds(400);        // pauses for 400 microseconds
  digitalWrite(outPin, HIGH);   // sets the pin on
 delayMicroseconds(1050);        // pauses for 1050 microseconds        
 
 digitalWrite(outPin, LOW);    // sets the pin off
   delayMicroseconds(400);        // pauses for 400 microseconds
 digitalWrite(outPin, HIGH);    // sets the pin off
 delayMicroseconds(10350);        // pauses for 10650 microseconds          
}


So my question for everyone now is I'm controlling 6 of these transmitters which should be no problem with the Arduino, However, I want to have global control of the Arduino from Max/MSP. I can't use the Max/MSP message systems because the timing in Max is only millisecond (not microsecond) resolution. How can I send the Arduino global messages from Max while it keeps running its microsecond routines? Is that clear?
Thanks everyone for your help.
Casey
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Feb 10, 2008, 02:28 am
Thanks for putting the details on a different radio setup here! Should make lifer easier for the next person, I'm sure :-)

The signal may be reversed because, at least on US radios, you can have positive or negative shift, while on European ones, it's only negative (I think), so that may indeed happen. The Royal Evo, with US firmware, lets you choose which shift polarity you want.

As for timing, if you're only running 6 channels, you should have a fairly long synch pulse... any chance you can handle the rest of what you need to do during the synch pulse? If not, you'd have to use interrupts for the timing, at a guess, but I haven't tried that yet.
Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Feb 10, 2008, 06:09 am
Quote
So my question for everyone now is I'm controlling 6 of these transmitters which should be no problem with the Arduino, However, I want to have global control of the Arduino from Max/MSP. I can't use the Max/MSP message systems because the timing in Max is only millisecond (not microsecond) resolution. How can I send the Arduino global messages from Max while it keeps running its microsecond routines? Is that clear?
Thanks everyone for your help.
Casey
Casey, you could implement your app by sending serial packets from Max with an array of integers holding the millisecond pulse width for each of the channels for all the transmitters.

The easiest to implement on the arduino side would be to use a single packet for all the data from your six transmitters.

You could us a two dimensional array like the following or define a structure if you are familiar with that construct.

#define NBR_TRANSMITTERS  6
#define NBR_CHANNELS 4
int  channelData[ NBR_TRANSMITTERS ] [NBR_CHANNELS];

In your arduino code you would wait until you had NBR_TRANSMITTERS times NBR_CHANNELS times two data bytes available and read this into the two dimensional array. (times two because there are two bytes oer integer)

You could then loop through each transmitters data to send your pulses.

If its possible that Max could send packets more quickly than the transmitters can handle ( it takes 120 milliseconds to process all the data if you handle each transmitter in sequence) there are a few things you could do. The simplest is to only process the latest data,  but if throwing away older data is not acceptable then you could process all of the transmitter frames in parallel by starting pulses for each sequential channel for all transmitters at the same time and turning them off as per each transmitters received pulse time.

For example, turn on a pulse for channel 1 on all transmitters and as the time for the shortest pulse is reached, turn that one off. Wait for the next shortest pulse time to be reached and turn that one off etc until all transmitters have stopped pulsing channel 1. Then to the next channel until all channels are done.

The delay between channels will look a little different from what you observed on your transmitter but any radio control receiver will be able to cope.

Implimentation gets a little more complicated if you really do neeed millisecond accuracy because digitalWrite takes around five milliseconds to start and stop a pulse so you either need to allow for that or use the faster but more complicated direct port i/o.
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Feb 11, 2008, 03:41 am
Wow, thanks that is quite helpful,

I got the part about having max send the Arduino messages via the serial port. And I determined that I do indeed need to address the receivers in Parallel ( a super long sync pulse that results from serial communication results in an undesirable pulsing of the motors). And I understand conceptually how you described addressing all of the pins concurrently, however I'm have a hard time putting that into code. Would I still be using the delayMicroseconds function? Thanks
Casey
Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Feb 11, 2008, 10:29 am
To output the pulses in parallel lets assume you will start pulsing all Tx output pins at the same time and stop pulsing as per each transmitters pulse width. (we will ignore the alternative of turning on as per the pulse width and turning them all off at the same time, either will work)

Anyway, you need to sort the six pulse width values for the current channel you are pulsing. This lets you easily determine how long to wait until turning off the first pulse (you delay for the pulse width of the shorted pulse). You then delay for the difference between that pulse width and the pulse width of the next shortest pulse. And so on until all pulses have been turned off.

Have a search of quicksort or qsort to see if there is a built in function you could use. If not, there should be plenty of algorithms for C implementations of sort functions on the net.

It may not be too critical timing when to start the next sequence of pulses because receivers and servos are tolerant of small variations in frame rate but you could use one of the arduino timers to tell you when to start pulsing the next frame. I can post code you could use if you want to do this and are not familiar with the timers.

I hope that helps. I don't know your experience level so do please say if you need more detail on turning this into code.
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Feb 11, 2008, 02:03 pm
I think that does help, thanks,
I am pretty new to arduino and coding for it, any example in code would be great if you have the time,
Thanks again
Casey
Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Feb 11, 2008, 05:45 pm
I am not sure if the following fragment will help or not. I threw it together a little to quickly and not only is it incomplete and certainly buggy, i expect the array indirections I have used could confuse more than clarify. But unfortunatly I don't have any more time at the moment to do anyting with it so FWIW here it is. Let me know what you think and I will get back to you later.
Code: [Select]

#define NBR_TRANSMITTERS  6
#define MAX_TRANSMITTERS  8          // we use this only if we want the packet size to be 64 bytes, the last two tx values are ignored in this version
#define NBR_CHANNELS 4
int  channelData[NBR_CHANNELS] [ MAX_TRANSMITTERS ] ;
int SortIndex[NBR_TRANSMITTERS]; // the first element will point the transmitters with the sortest pulse for the given channel,  
int TxPins[NBR_TRANSMITTERS];     // init this with your pin numbers

void setup(){
 Serial.begin(19200);
 for(int i = 0; i <  NBR_TRANSMITTERS; i++)
    pinMode(TxPins[i], OUTPUT);
}

void Sort(int chan){
 // TODO - this function needs to sort the data for the given channel (note that 0 is what futaba calls channel 1)  
 // you can impliment your own algorythm or use a library sort function
 // The pseudocode below assumes you have populated the SortIndex array with indexs to increasing pulse width for the given channel  
}

void PulseChannel(int chan){
 
 for( int tx=0; tx < NBR_TRANSMITTERS; tx++)  // turn on pulse (but only if pulse width is greater than 0)
    if( channelData[chan][SortIndex[0]] > 0 )  // valid pulses must be greater than 0  
       digitalWrite(TxPins[tx], HIGH);     // HIGH or LOW depends if your tx pulses high or low, change as necessary
  delayMicroseconds( channelData[chan][SortIndex[0]]);    // the first element pointed to in the SortIndex is the shortest pulse width so we delay that amount first  
  digitalWrite(TxPins[SortIndex[0]], LOW);        // now turn the pulse for this tx off
  for( int tx=1; tx < NBR_TRANSMITTERS; tx++) {   // here we do all the other elements  
     delayMicroseconds(channelData[chan][SortIndex[tx-1]] - channelData[chan][SortIndex[tx]]); // wait however much longer to reach this channels pulse width    
     digitalWrite(TxPins[tx], LOW);      
  }  
}

void loop(){
  int buffersize = sizeof(channelData) * sizeof(byte) ;
  char * ptr = (char*)channelData;
  if( Serial.available() >= buffersize ) {
      for(int i =0; i < buffersize; i++)
          ptr[i]  = Serial.read();   // fill the buffer with the serial data
  }  
 
  for( int chan=0; chan < NBR_CHANNELS; chan++) {
         Sort(chan);          // get an array sorted so the shortest pulse is first.
         PulseChannel(chan);  // send the correct channel pulse to all transmitters              
  }
  delay(12);  // this is the frame delay , each frame should be around 20 ms and the channel code above will have taken up to 8ms      
              // you can do a more sophisticated calculation later if you want.    
 
}
Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Feb 12, 2008, 11:40 am
The code below has the sort implimented. None of this has been tested !
Code: [Select]
#define NBR_TRANSMITTERS  6
#define MAX_TRANSMITTERS  8          // we use this only if we want the packet size to be 64 bytes, the last two tx values are ignored in this version
#define NBR_CHANNELS 4

int TxPins[NBR_TRANSMITTERS];     // init this with your pin numbers

int channelData[NBR_CHANNELS] [ MAX_TRANSMITTERS ] ;  // this holds the data for all channels for all transmitters
int Index[NBR_TRANSMITTERS] = {0,1,2,3,4,5,}; // after sorting, the first element will point the transmitters with the sortest pulse for a given channel

void setup(){
 Serial.begin(19200);
 for(int i = 0; i <  NBR_TRANSMITTERS; i++)
       pinMode(TxPins[i], OUTPUT);
}

void Sort(int data[]) // sort the channel data in ascending order using Index array
{
 int i, j, index;
 for (i=1; i < NBR_TRANSMITTERS; i++)
 {
   index = Index[i];
   j = i;
   while ((j > 0) && (data[Index[j-1]] > data[index]))
   {
      Index[j] = Index[j-1];
      j = j - 1;
    }
    Index[j] = index;
  }
}

void PulseChannel(int chan){
 
 for( int tx=0; tx < NBR_TRANSMITTERS; tx++)  // turn on pulse (but only if pulse width is greater than 0)
     if( channelData[chan][Index[0]] > 0 )  // valid pulses must be greater than 0  
          digitalWrite(TxPins[tx], HIGH);     // HIGH or LOW depends if your tx pulses high or low, change as necessary
  delayMicroseconds( channelData[chan][Index[0]]);    // the first element pointed to in the SortIndex is the shortest pulse width so we delay that amount first  
  digitalWrite(TxPins[Index[0]], LOW);        // now turn the pulse for this tx off
  for( int tx=1; tx < NBR_TRANSMITTERS; tx++) {   // here we do all the other elements  
     delayMicroseconds(channelData[chan][Index[tx-1]] - channelData[chan][Index[tx]]); // wait however much longer to reach this channels pulse width      
     digitalWrite(TxPins[tx], LOW);      
  }  
}

void loop(){
  int buffersize = sizeof(channelData) * sizeof(byte) ;
  char * ptr = (char*)channelData;
  if( Serial.available() >= buffersize ) {
      for(int i =0; i < buffersize; i++)
      ptr[i]  = Serial.read();   // fill the buffer with the serial data
  }  
 
  for( int chan=0; chan < NBR_CHANNELS; chan++) {
     Sort(channelData[chan]);    // sort this channel so the shortest pulse is first.
     PulseChannel(chan);  // send the correct channel pulse to all transmitters              
  }
  delay(12);  // this is the frame delay , each frame should be around 20 ms and the channel code above will have taken up to 8ms      
   // you can do a more sophisticated calculation later if you want.    
 
}
Title: Re: Arduino-Controlled RC Transmitter
Post by: SOOline on Feb 12, 2008, 02:10 pm
Wow, mem thanks this is a huge help.
I'll wire things up later today and see if I can get it worked out.

Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Feb 12, 2008, 03:26 pm
I simplifed the syntax of the PulseChannel function by passing the channel array rather then the channel number. also fixed a small bug in one of the for loops.  I expect there will be a few more things waiting for you to debug ;)
Code: [Select]
#define NBR_TRANSMITTERS  6
#define MAX_TRANSMITTERS  8          // we use this only if we want the packet size to be 64 bytes, the last two tx values are ignored in this version
#define NBR_CHANNELS 4

int TxPins[NBR_TRANSMITTERS];     // init this with your pin numbers

int channelData[NBR_CHANNELS] [ MAX_TRANSMITTERS ] ;  // this holds the data for all channels for all transmitters
int Index[NBR_TRANSMITTERS] = {0,1,2,3,4,5,}; // after sorting, the first element will point the transmitters with the sortest pulse for a given channel

void setup(){
 Serial.begin(19200);
 for(int i = 0; i <  NBR_TRANSMITTERS; i++)
     pinMode(TxPins[i], OUTPUT);
}

void Sort(int data[]) // sort the channel data in ascending order using Index array
{
 int i, j, index;
 for (i=1; i < NBR_TRANSMITTERS; i++)
 {
   index = Index[i];
   j = i;
   while ((j > 0) && (data[Index[j-1]] > data[index]))
   {
      Index[j] = Index[j-1];
      j = j - 1;
    }
    Index[j] = index;
  }
}

void PulseChannel(int data[]){ // pulse all transmitter using pulse width data in the given channel array
// these are pulsed in the order of shortest to longest pulse width as determined by the sorted Index array  
 for( int tx=0; tx < NBR_TRANSMITTERS; tx++)  // turn on pulse (but only if pulse width is greater than 0)
     if( data[Index[tx]] > 0 )  // valid pulses must be greater than 0  
         digitalWrite(TxPins[tx], HIGH);   // HIGH or LOW depends if your tx pulses high or low, change as necessary
  delayMicroseconds( data[Index[0]]);   // the first element pointed to in the SortIndex is the shortest pulse width so we delay that amount first  
  digitalWrite(TxPins[Index[0]], LOW);   // now turn the pulse for this tx off
  for( int tx=1; tx < NBR_TRANSMITTERS; tx++) {   // here we do all the other elements  
     delayMicroseconds(data[Index[tx-1]] - data[Index[tx]]); // wait however much longer to reach this channels pulse width      
     digitalWrite(TxPins[tx], LOW);      
  }  
}

void loop(){
  int buffersize = sizeof(channelData) * sizeof(byte) ;
  char * ptr = (char*)channelData;
  if( Serial.available() >= buffersize ) {
      for(int i =0; i < buffersize; i++)
           ptr[i]  = Serial.read();   // fill the buffer with the serial data
  }  
 
  for( int chan=0; chan < NBR_CHANNELS; chan++) {
     Sort(channelData[chan]);    // sort this channel so the shortest pulse is first.
     PulseChannel(channelData[chan]);  // send the correct channel pulse to all transmitters              
  }
  delay(12);  // this is the frame delay , each frame should be around 20 ms and the channel code above will have taken up to 8ms      
    // you can do a more sophisticated calculation later if you want.    
 
}
Title: Re: Arduino-Controlled RC Transmitter
Post by: mem on Feb 13, 2008, 11:45 am
Quote
I'll wire things up and see if I can get it worked out.


Remember this code is not even half baked. Even though it looks it may have all the ingredients, the output pulses may not be servo friendly yet, so run it with debugging code first to check the pulse width calculations

A good place for some Serial.print statements is in the PulseChannel function.
In the for loop, you could print the value of data[Index[tx]] (this is the pulse delay for a transmitter).
If you also print the value you are passing to delayMicroseconds and the sum of these delays you can confirm that the actual pulsing matches the data in the array.

If you don't have the communication link to your control program to populate the data, now may be good time to temporarily substitute some hard coded data in your sketch for testing. This enables you to see what happens when out of range values are processed (the posted code does not do much checking).
Title: Re: Arduino-Controlled RC Transmitter
Post by: mnaef on Mar 01, 2008, 05:50 pm
Instead of using the trainer connector, has anybody tried to hook the Arduino between the transmitter and the HF module? That should work also with old and cheap transmitters, and theoretically, one could even extend the number of transmitter channels that way. Just a thought - but I might be onto a dead-end here just as well...
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Mar 01, 2008, 06:26 pm
I haven't tried it, mostly because I wanted to mix manual input with arduino input... including with some mixing done by the radio.

As far as I know, your idea should work because the HF module takes the unmodulated pulse series as input and just modulates it by the carrier wave. IOW, yes, you should be able to hook the arduino straight to the HF module for the win.

I, unfortunately, am too chicken to try it with my HF modules as they are rather pricey, and require some add'l interaction to set the carrier frequency (synth modules, not crystal). If I can get my hands on an inexpensive toy with radio included, I'll give it a shot!
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Dec 08, 2009, 02:05 pm
I have been playing with Mathieu's code and apart from having to change the 'shift' it is working perfectly well.

Mathieu uses 'delayMicroseconds' in his code. I had the impression that using just 'delay' is better because delaymicroseconds turns of interrupts. However, when I changed this in code (from delaymicroseconds to delay), the receiver didn't respond anymore.

Anyone can explain me why?
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Dec 08, 2009, 02:48 pm
I wanted to add to my post above that the reason I ask if it is possible to use delay() instead of delaymicroseconds() is that I would like to have interrupts available for reading the ppm stream coming from my radio at more or less the same time when sending a ppm stream to my radio.
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Dec 08, 2009, 07:20 pm
I used microsecond delays because I needed the finer control over timing I got that way. Delay() only gives you delays in milliseconds, which is not precise enough for this application.

At least, that's what I remember of my reasoning, this was a while ago!
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Dec 08, 2009, 07:23 pm
Ah, I see. Sounds like an interesting application :-)

Again, I don't think you can generate the pulse stream with just delay(), you need smaller time increments, and I agree, that is going to prevent you from using interrupts to read your input.

Does your budget stretch to two arduinos? ;-)
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Dec 08, 2009, 08:10 pm
I overlooked the fact that delayMicroseconds() is about micro seconds and delay is about milli seconds.

I think I need a delayMicroseconds() that doesn't disable interrupts. Maybe it becomes a little less accurate, but I don't think that is a problem.

Two Arduinos wouldn't be a problem, but if it can be done with one than I should do it with one.

Thanks for your comments Mathieu!
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Dec 08, 2009, 08:18 pm
Tomorrow I will try if the following routine can replace delayMicroseconds():

Code: [Select]
void customDelay(unsigned long time) {
   unsigned long end_time = micros() + time;
   while(micros() < end_time);
}
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 25, 2010, 08:21 am
Hi Folks,

I know this is quite an old thread, but I thought you might be interested in this.

I decided to replace the PPM encoder board in my old Micron transmitter that I built from a kit some 15+ years ago with an arduino based solution.

This solution reads the four sticks, along with four switches and encodes them into the appropreate PPM pulse train. I have also included code for v-tail, differential and delta mixing.

The way my code differs from yours is in the way I generate the pulse train: I have used the 16bit timer (timer 1) set to phase and frequency correct PWM to generate the pulse train from an array of values.

The timer settings are:
Code: [Select]

  TCCR1A = B00110001; // Compare register B used in mode '3'
  TCCR1B = B00010010; // WGM13 and CS11 set to 1
  TCCR1C = B00000000; // All set to 0
  TIMSK1 = B00000010; // Interrupt on compare B
  TIFR1  = B00000010; // Interrupt on compare B
  OCR1A = timer_framelength;
  OCR1B = timer_pause;


and the ISR code is:

Code: [Select]

ISR(TIMER1_COMPA_vect)
{
 if (timer_ptr == number_of_outputs) {
   timer_ptr = 0;  //reset the pointer to 0
   OCR1A = timer_framelength - (timer_accumulator * timer_correction_factor); //calculate the padding
   timer_accumulator = 0;  //set the accumulator to 0
 }
 else {
   OCR1A = (pulses[timer_ptr] + timer_pause) * timer_correction_factor; //set the pulse length
   timer_accumulator += pulses[timer_ptr] + timer_pause; //add the pulse length to the accumulator
   timer_ptr++;  //increment the pointer
 }
}


and the required variables and constants are:

Code: [Select]

#define timer_correction_factor 1.09                        //timer correction factor. This is needed if your arduino is too fast or slow, like mine. :(
#define timer_framelength 20000 * timer_correction_factor   //Maximum framelength in counter ticks
#define timer_pause 300 * timer_correction_factor           //Pause between pluses in counter ticks

int timer_accumulator = 0;         //accumulator. Used to calculate the frame padding
int timer_ptr = 0;                 //timer array pointer
int pulses[7];


To generate the pulse train, enter values into the array corrisponding to the channel pulse in micro seconds, so for a 2000 micro seconds pulse enter 2000. The frame padding is calculated automatically.

If anyone would like to take a look at the complete source code, feel free to download it; it's just too big to post here:
http://www.miselph.co.uk/arduino/Version_0_2.zip

I hope this can be of use to someone. When I have finished the project I will post the details on this forum.

If anyone needs any help with timers, I have become quite adept at dealing with them and would be more than happy to help

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Mar 25, 2010, 10:04 am
Wow, I am impressed!

I had a quick look at the code and possibilities. You even included mixing. Are you planning any more possibilities, maybe dual rates?

Can you elaborate on how you connected the sticks and switches.\

You are using the original rf board from your Micron?
Title: Re: Arduino-Controlled RC Transmitter
Post by: Syvwlch on Mar 25, 2010, 02:11 pm
Very, very cool. A huge improvement on my weak efforts! :-)
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 25, 2010, 06:54 pm
Hi guys!
Thanks for the positive comments.

CrashingDuchman:
The code already includes both dual rates and exponential :D The exponential isn't brilliant, I need to find a better equation, but it does work.
The sticks are connected to analog pins 0,1,2 and 3 and the switches are connected to pins 8,11,12 and 13 (I didn't use 9 or 10 because they are the output pins from timer1)
As the code stands, switches 0 and 1 are set up to activate the rates on the ailerons and elevators.

Here is a piccit:
(http://www.miselph.co.uk/arduino/SAM_8501.jpg)

In this picture the yellow wires are the switches (my farnell order only arrived this morning, and I haven't got tound to wiring them up) and connecting any one of them to ground changes the switch state. The green leads trailing off to the right are the connection points for the oscilloscope.

I am using the original RF board from the Micron transmitter, which is a sub-board attached to the base of the antenna. However, this required me to use a FET attached to the pulse output pin (pin 10) to create a transistor NOT gate so as to facillitate switching of a higher voltage as the RF board runs at 9.5v

My long(er) term goals for this project include an on-transmitter (or plug in, as my tx case is quite small) lcd display and buttons for changing settings without having to reload the firmware, and upgrading the RF section to 2.4gHz.

I am planning on building this into my Mircon transmitter case, and when I do I will post more pics and upload the eagle schematics.

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 25, 2010, 08:46 pm
Hi all,

Am jumping in here.......Chris's code is just what I was looking for.

I'm going to fit an Arduino inside a 3-axis joystick in order to generate the PPM for connection to my Futaba radio. So, with a 2*16 LCD embedded also it's going to be fun.

I'd already bought the joystick plus other bits and bobs, so this jump-start with the code is great. Thanks Chris.

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 25, 2010, 08:50 pm
Hi Ian,

If you want to use the 16 x 2 LCD as I have you might like the library I have written to control it via a shift register (so it uses less pins :) ).
All the info, including vero-board layout and library can be found on my blog:

http://cjparish.blogspot.com/

Let me know how you get one with it!

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 27, 2010, 11:40 pm
Well tonight I made a start. I ripped out the original circuit board from a Saitek AV8R-01 and replaced it with an Arduino Nano.

(http://www.ianjohnston.com/content/images/stories/IanJ/FutabaJoystick/joystick1.jpg)

Then I took Chris's code and modified it to use my own I2C LCD library. This will be for de-bugging/testing only as sadly there's no real space to mount an LCD.....unless I change to a tiny 2*16 one. Hmmm!

First problem I have is that all the pots in the joystick are all LOG pots, so the voltages I'm getting aren't linear so I'm gonna change them out.

Chris, I had a quick look through your code when I was changing the LCD library, and I couldn't see where your I/O mapping is done. Also, where to set ranges etc. Any hints/tips before I get stuck right in. I'm more a hardware man than software........but I'll hack my way around no worries.

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 28, 2010, 12:05 am
Hi Ian,

Hardware mapping:

If you open the sketch and look at the sticks_include.h tab and look at line 21 you sould find:

Code: [Select]

int stick_inputs[4] = {0,1,2,3}; //input ports for the sticks


and in switches_include.h on line 6

Code: [Select]

int switch_pins[number_of_switches] = {11,12,13,8};


The stick ranges are set in the sticks_include.h file, right at the top.
Code: [Select]

const int stick_limits[4][3] = { //stick limits, given as top, center and bottom
 {
   604, 501, 396            }
 ,
 {
   620, 501, 396            }
 ,
 {
   617, 511, 398            }
 ,
 {
   649, 480, 368            }
};


I have also changed the PPM generation timings slightly, they should be:

Code: [Select]

#define OUTPUT_TOP 2000 - timer_pause
#define OUTPUT_CENTER 1500 - timer_pause
#define OUTPUT_BOTTOM 1000 - timer_pause

in the output_include.h file

Does that help?
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 28, 2010, 02:48 pm
Chris,

Thanks, that helps.

I'm not getting any PPM output anywhere, have scoped all dig pins. Which output should it be on, and any reason why I'm getting nothing, i.e. does it need activated.

I'm using a Arduino Nano 3.0 (ATmega328) which should be same as Duemilanove (328).

Have reverted back to your original code but still no joy.

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 28, 2010, 05:39 pm
The output should be on pin 10.
Make sure that you have set pinMode(10, OUTPUT); or it won't work.

The chip should be the same, just a different package.

Try running this:

Code: [Select]


void setup()
{
  setup_timer();
}


void setup_timer()
{
  TCCR1A = B00110001; // Compare register B used in mode '3'
  TCCR1B = B00010010; // WGM13 and CS11 set to 1
  TCCR1C = B00000000; // All set to 0
  TIMSK1 = B00000010; // Interrupt on compare B
  TIFR1  = B00000010; // Interrupt on compare B
  OCR1A = 20000;
  OCR1B = 10000;

  pinMode(10, OUTPUT);
}

void loop()
{

}


I haven't tested it, but that should output a nice square waveform at 50hz. If it doesn't work then there is an issue with how I have set the timers. The normal way to set the timers is by using statements like:
Code: [Select]

TCCR1B = _BV(WGM13) | _BV(CS11);

which allow portability across different chips where the registeres might be slightly different, but according to the data sheet our processors are the same.

Let me know how you get on.
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 28, 2010, 06:43 pm
Chris,

Tried your timer test routine and it works fine, a nice clean 50Hz squarewave at pin 10 on the Nano.

However, I notice that timer.pde in your zip has nothing in it at all, i.e. empty file.......is that the problem, no timer setup?

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 30, 2010, 12:12 pm
Hi all,

In the end I ended up writing my own sketch.
A bit of a hack (I'm not a real programmer!) but it does work, at least on the workbench with my Futaba T9.

Still got the switches on  the joystick to do, i.e. better dual rates and trim. For the moment there is 1 switch on the joystick which is read to adjust dual rates.

Ian.

Code: [Select]

// PPM Encoder Joystick to Futaba Trainer Port
// For use with Arduino Nano V3.0
// Ian Johnston 30/03/2010


int AI_Pin0 = 0;    // Ana In Ch.0 pin - Aeleron potentiometer
int AI_Pin1 = 1;    // Ana In Ch.1 pin - Elevator potentiometer
int AI_Pin2 = 2;    // Ana In Ch.2 pin - Throttle potentiometer
int AI_Pin3 = 3;    // Ana In Ch.3 pin - Rudder potentiometer
int AI_Raw0;        // Ana In Ch.0 raw var - 0->1023
int AI_Raw1;        // Ana In Ch.1 raw var - 0->1023
int AI_Raw2;        // Ana In Ch.2 raw var - 0->1023
int AI_Raw3;        // Ana In Ch.3 raw var - 0->1023
int AI_0;           // Ana In Ch.0 raw var - 0->1023 compensated
int AI_1;           // Ana In Ch.1 raw var - 0->1023 compensated
int AI_2;           // Ana In Ch.2 raw var - 0->1023 compensated
int AI_3;           // Ana In Ch.3 raw var - 0->1023 compensated
int Aeleron_uS = 700;     // Ana In Ch.0 uS var - Aeleron
int Elevator_uS = 700;    // Ana In Ch.1 uS var - Elevator
int Throttle_uS = 700;    // Ana In Ch.2 uS var - Throttle
int Rudder_uS = 724;      // Ana In Ch.3 uS var - Rudder
int Spare1_uS = 1225;     // uS var - Spare1 (set to mid)
int Spare2_uS = 1225;     // uS var - Spare2 (set to mid)

int Fixed_uS = 300;       // PPM frame fixed LOW phase
unsigned long SynchroFrameAdj = 0; // Timing adjustment for Synchro blank time in uS
unsigned long SynchroFrameAdjDiff = 0; // Timing adjustment for Synchro blank time in uS
unsigned long TotalFrameLengthAllowed = 20000; // Total Frame Length allowed in uS

int pulseMin = 750;            // pulse minimum width minus start in uS
int pulseMax = 1700;        // pulse maximum width in uS

float DualrateMultAel = 0.9; // Dual rate mult
float DualrateMultEle = 0.9; // Dual rate mult
float DualrateMultThr = 0.9; // Dual rate mult
float DualrateMultRud = 0.9; // Dual rate mult
int DualrateAdjAel = 0;   // Dual rate mid adjustment
int DualrateAdjEle = 0;        // Dual rate mid adjustment
int DualrateAdjThr = 0;        // Dual rate mid adjustment
int DualrateAdjRud = 0;        // Dual rate mid adjustment

int outPin = 10;          // digital pin 10
int inPinD6 = 6;          // digital pin 6


void setup() {

 pinMode(outPin, OUTPUT);      // sets the digital pin as output
 
 pinMode(inPinD6, INPUT);      // sets the digital pin as input
 digitalWrite(inPinD6, HIGH);  // turn on pull-up resistor

}


void loop() { // Main loop

// Frame start save, used to determine required 20mS PPM frame interval
  SynchroFrameAdj = micros();
 
// Read 4 analogue ports and convert to mS
  AI_Raw0 = analogRead(AI_Pin0);
  AI_Raw1 = analogRead(AI_Pin1);
  AI_Raw2 = analogRead(AI_Pin2);
  AI_Raw3 = analogRead(AI_Pin3);

// Compensate for discrepancy in pot inputs, also use this to invert inputs if necessary
  AI_0 = map(AI_Raw0, 0, 1023, 0, 1200) - 50; // y=mx+c, x to y scales to x1 to y1
  AI_1 = map(AI_Raw1, 0, 1023, 0, 1200) - 50; // y=mx+c, x to y scales to x1 to y1
  AI_2 = map(AI_Raw2, 0, 1023, 0, 1023) + 0; // y=mx+c, x to y scales to x1 to y1
  AI_3 = map(AI_Raw3, 0, 1023, 0, 1023) + 0; // y=mx+c, x to y scales to x1 to y1
 
// Map analogue inputs to PPM rates for each of the channels
  Aeleron_uS = (AI_0 * DualrateMultAel) + pulseMin + DualrateAdjAel;
  Elevator_uS = (AI_1 * DualrateMultEle) + pulseMin + DualrateAdjEle;
  Throttle_uS = (AI_2 * DualrateMultThr) + pulseMin + DualrateAdjThr;
  Rudder_uS = (AI_3 * DualrateMultRud) + pulseMin + DualrateAdjRud;

// Check limits
 if (Aeleron_uS <= 750) Aeleron_uS = 750;     // Min
 if (Aeleron_uS >= 1700) Aeleron_uS = 1700;   // Max  
 if (Elevator_uS <= 750) Elevator_uS = 750;   // Min
 if (Elevator_uS >= 1700) Elevator_uS = 1700; // Max
 if (Throttle_uS <= 750) Throttle_uS = 750;   // Min
 if (Throttle_uS >= 1700) Throttle_uS = 1700; // Max
 if (Rudder_uS <= 750) Rudder_uS = 750;       // Min
 if (Rudder_uS >= 1700) Rudder_uS = 1700;     // Max  
 
// Channel 1
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 uS
 digitalWrite(outPin, HIGH);
 delayMicroseconds(Aeleron_uS);  // Hold for Aeleron_uS microseconds      

// Channel 2  
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 uS
 digitalWrite(outPin, HIGH);
 delayMicroseconds(Elevator_uS); // Hold for Elevator_uS microseconds      

// Channel 3  
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 uS
 digitalWrite(outPin, HIGH);
 delayMicroseconds(Throttle_uS); // Hold for Throttle_uS microseconds      

// Channel 4  
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 uS
 digitalWrite(outPin, HIGH);
 delayMicroseconds(Rudder_uS);   // Hold for Rudder_uS microseconds

// Channel 5  
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 uS
 digitalWrite(outPin, HIGH);
 delayMicroseconds(Spare1_uS);   // Hold for xxxx microseconds        

// Channel 6
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 uS
 digitalWrite(outPin, HIGH);
 delayMicroseconds(Spare2_uS);   // Hold for xxxx microseconds  
 
// Synchro pulse
 digitalWrite(outPin, LOW);
 delayMicroseconds(Fixed_uS);    // Hold for 300 microseconds
 digitalWrite(outPin, HIGH);     // Start Synchro pulse

 SwitchesRates();                // Now is the time to jump to subroutine whilst we have some free time

 SynchroFrameAdjDiff = micros() - SynchroFrameAdj;  // Calculate remainder and adjust (fails after 70mins, but more than enough as who flies that long?)
 SynchroFrameAdj = TotalFrameLengthAllowed - SynchroFrameAdjDiff;
 delayMicroseconds(SynchroFrameAdj);   // Hold for remainder (uS), Synchro blank time

}


void SwitchesRates() {

   if (digitalRead(inPinD6) == 0) { // Low rate
          DualrateMultAel = 0.5;
           DualrateMultEle = 0.5;
           DualrateMultThr = 0.9;
           DualrateMultRud = 0.7;
           DualrateAdjAel = 200;
         DualrateAdjEle = 200;
           DualrateAdjThr = 0;
           DualrateAdjRud = 100;
           }
   if (digitalRead(inPinD6) == 1) { // Normal/high rate
       DualrateMultAel = 0.9;
       DualrateMultEle = 0.9;
           DualrateMultThr = 0.9;
           DualrateMultRud = 0.9;
       DualrateAdjAel = 0;
       DualrateAdjEle = 0;
           DualrateAdjThr = 0;
           DualrateAdjRud = 0;
           }      

}


Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 30, 2010, 01:46 pm
Hi Ian,

The missing timer file would certainly explain why is wasn't working!

If your code works then it isn't a hack, it's a solution! :D

I have re-uploaded my code if you want to give it another go. This is the version that is currently working for me.

http://www.miselph.co.uk/arduino/Version_0_2.zip
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 30, 2010, 02:22 pm
Thanks Chris......

File is intact now. I'm putting together another stick so will take a look at your code again.

Ya go build one for yourself and all your mates want one......!

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 30, 2010, 02:30 pm
Isn't that just the way it always goes?

I took delivery of some ferric chloride this morning so I am hoping to make the PPM boad in the next few days. Eagle files coming soon! :)

The new code also includes functions for saving settings to EEPROM and reading them again. It isn't very well documented yet, but it will be soon.

I am currently working on a serial programming interface for it as well, so that you can make changes to the setup without having to re-upload the whole program. As soon as I have done I will upload the new code.

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Mar 30, 2010, 02:39 pm
>ferric chloride

That takes me back........gotta admit I'm too lazy now, I just send my Eagle files to China to get boards made.....far cheaper than UK, even for low quantities.

www.pcbcart.com

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Mar 30, 2010, 02:48 pm
Quote
www.pcbcart.com

Thanks Ian, I will check that out. I don't trust me to get it right first time tho, so I will still make one by hand first, as (so far) it is only single sided.

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: fliggygeek on Apr 06, 2010, 09:50 am
Hi all, i know this is an old thread, but its still relevant.
I saw this today and ive just ripped out the transmitter board out of a HobbyKing HK-T6A and attempted to interface it with an arduino. it has 4 interfae pins, VCC_+5v , GND, SW1 and PPM. interfacing is simple using the code mentioned previously, connect PPM pin to pin 10 on arduino, connect power and gnd up to +5v and gnd respectively and leave SW1 alone, its essentially just used to bind the transmitter when grounded.
So far it looks promising, but i have yet to connect it to a proper serial setup so i can control it using my PC.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Apr 06, 2010, 02:03 pm
Sounds good. Let us know how you get on!

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Apr 22, 2010, 11:36 pm
Chris,

I did write my own code, but it's seems to be glitching a wee bit, not sure why so have decided to give yours a serious go.

So, I'm on it now.....and have got it basically working, i.e. Ael, Ele, Thr & Rud.

Have got some questions, appreciate if you can help.

4 switches are read and as I understand,
0 = Ael dual rate set
1 = Ele dual rate set
.......So, what are switches 2 & 3 for?

I need to use PPM Ch.5 for a switch input.
I also need to use PPM Ch.6 for an analogue input (a pot on my Tx).
This is for special use on a QuadCopter, basically to be able to turn a feature on/off and when it's on have some control over it via the pot.
Not sure what you are using Ch.5 & 6 for at the moment.
.......Any ideas?.....I don't mind hacking it in somewhere, just need a pointer or two.

What about trim?.....is that hardcoded or is the code reading inputs somewhere.

//stick limits, given as top, center and bottom
What is the range of the numbers given? i.e.
604, 501, 396
I was expecting this in mS i.e. in the range 750 to 1800 or whatever your min/max range is, but that doesn't look to be the case obviously.

Ian.

PS. Here is my home made Tx (prior to wiring it), Arduino & 430mHz RF board inside:-

(http://www.ianjohnston.com/content/images/stories/IanJ/JoystickV2/ianjtx1.jpg)

(http://www.ianjohnston.com/content/images/stories/IanJ/JoystickV2/joystickv2b.jpg)
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Apr 23, 2010, 12:42 am
Hi Ian,

At the moment switches 3 and 4 don't do anything. They are there to be used as you like and can be read with get_switch_state(switch number)

At current I am using outputs 0,1,2,3 with 4 used for differential ailerons, but feel free to remap them however you like.
You can use PPM5 and 6 by simply updating the pulse array with the required pulse length in microseconds. Bare in mind that the channels are numbered from 0, not from 1!
[edit]Alternativly you can set the requoired values as a persentage offset from center in the channels array, this might be better as it allows you to use the throw adjustment and reverse functions built into the ouput processor[/edit]

At the moment trims are hard set in the code, as the trims on my current transmitter are mechanical rather than electronic. If you look in the sticks_include.h file you will find the lines:
Code: [Select]

int stick_trims[4] = {
 0,0,0,0}; //stick trims

The values used for the trims should be the trim offset from center, as measured by the ADC (which gives values bewteen 0 and 1023)

The stick limits: The range of values is 0 to 1023 as read by the ADC.

To set the throw limits on the servo you can change the OUTPUT_TOP, OUTPUT_CENTER and OUTPUT_BOTTOM values, which are set in microseconds.

With the help of Santiago Saldana I have developed a better exponential function if you need it:
Code: [Select]

int expo(float pos, float amount)
{
 pos = pos / 100;
 amount = amount / 100;
 if (amount < 0) {
   float temp = pow((float)pos,(float)(1.0/3.0));
   return (((1-amount)*pos)+((amount*temp)))*100;
 } else {
   return (((1-amount)*pos)+((amount*pow(pos,3))))*100;
 }
}


Any other questions, don't hesitate to post.
I am really pleased that my code is proving usefull.

I am currently working on version 2 of the code, and I will post it as and when.

Chris

[edit]
Oh yeah, I forgot: Where the processing is done on a timer induced loop, if you want to add your own functions to be run automatically then add calls to them in the process_loop() function in the main file, just add them before run_outputs(); if you are setting output values using the channels array or after run_outputs() if you are setting the output values directly to the pulses array
[/edit]
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Apr 24, 2010, 02:08 am
Chris,

I had a go at your code for a few hours and whilst I got the sticks working I just couldn't see where to modify the code to get my additional channels working (see below).

I understand what your saying in your post above, it's just that your code is just too advanced for me. You'll see my code is just very basic.

Maybe your V2 will be easier.

Here's the I/O I was trying to implement:-

INPUTS:-
Ana ch.0 = Ele
Ana ch.1 = Ael
Ana ch.2 = Rud
Ana ch.3 = Thr
Ana ch.4 = TI Adjust pot (Quadcopter use)
Ana ch.5 = battery voltage
Dig ch.11 = TI enable sw (Quadcopter use)
Dig ch.2 = dual rates
Dig ch.3 = ?
Dig ch.4 = ?
Dig ch.5 = ?

OUTPUTS:-
Dig ch.12 = low battery buzzer
Dig ch.10 = PPM output

PPM order req'd for quadcopter:-
AEL,ELE,THR,RUD,TIsw,TIpot

Ian.
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Apr 24, 2010, 03:42 am
Hi Ian,

I'm at work at the mo, but when I get home I'll have a shot at re-writing it.

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: IanJohnston on Apr 28, 2010, 08:59 pm
Hi all,

Managed to get a stable version of my own code running.....using timers the PPM stream is FAR more stable. Chris's code showed me the light....:)

The LCD & dual rates implementation is a bit of a hack at the mo, also there is no stick trimming yet....need to work out how to do that, i.e. probably need to have y=mx+c twice....with the centre position the transition between the 2 graphs so can then have a finite point to offset (trim)............or maybe there's another way.

Code to big to post here, so here the link to my page:-
http://www.ianjohnston.com/content/index.php?option=com_content&view=article&id=32:project-rc-joystick-tx&catid=3:hobbies&Itemid=8

Ian.

Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Aug 04, 2010, 08:56 pm
hi chris! i have been using ian's code with good results, but i think yours is a little better suited for my application. i have a question about pin 10... is using pin 10 required? i blew up pin 10 on my arduino mini pro so i would like to use pin 9 since it is still alive. i can't seem to locate where this is controlled other than the line pinMode(10, OUTPUT);. any help will be much appreciated! great job btw! cheers!
-sj
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Aug 04, 2010, 09:32 pm
Hi sonicj!
Unfortunatly pin 10 is required, as it is the output from the hardware timer. The way I have programmed it it uses both compare registeres to produce the waveform, but yeh final output if from compare b which is hardwired to pin 10.
Sorry.

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Aug 05, 2010, 06:57 am
dang!

so is that a hardware limitation or just a product of your specific code that ties it to pin 10? could the timer be inverted to output to the Compare Match A Pin? i skimmed over the timer section of the manual and i got the impression that they performed in the same manner...?

i had no idea that there were this many options and variables available to a single timer! its incredible how much is really going on inside something so small!

i was able to get the transmitter code working with a 16x2 LCD on a 74ls164n shift register using the ShiftRegLCD library in 2-Wire mode with very little effort! i changed the #define, pin_mode and commented out lcd.begin(16,2); and it seems to be working ok. i might be missing some functionality, but at least its not printing chinese anymore!  :) i have a couple 74hc595's in route so i can compare the difference. i prefer my $1.50 LCD and $0.70 shift register over my $25 sparkfun serial lcd anyday!

cheers!
-sj
Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Aug 09, 2010, 10:02 am
built a new "shield" and i've got chris' code running on a duemilanove with working pin 10 now!

any clues to where i should look for variables to invert the ppm stream? i tried inverting / reversing pulse = map but that didn't get it. i tried multiplying some stuff by -1 with no luck. not sure what else to look for... :-/
-sj
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Aug 09, 2010, 01:55 pm
Hello again,

I am not sure exactly which version of the code you are using, but look for this line (it should be on the 'timer' tab)

TCCR1A = B00110001;
and change it to
TCCR1A = B00100001;

That should invert the output for you.

The reason this works it that the output it created using hardware timer1 and we need to change the way that the output compare register effects the output of the signal generator. (see page 136 of the ATMega368 datasheet for more info...)

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Aug 10, 2010, 12:48 am
sweet! that did it, thanx!

i KNEW i had seen inverting somewhere... just couldn't put my finger on it; that manual is LOT to take in!

the spektrum module is recognizing the PPM train as it lights up and binds to a rx. servos are whilin' out though so i suppose i need to make some tweaks to the pulse or frame lengths. there are some slight ripples in voltage (not sure what that matters) but the pulse timings look solid!

*edit* - im using your Version_0_2 code

(http://lh4.ggpht.com/_KapN_vTz8Gk/TGCBPUwS4uI/AAAAAAAACFc/QzLPP0vh7a8/s640/ppm_20ms.jpg)
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Aug 10, 2010, 02:45 am
The voltage ripples are tiny and shouldn't make any difference at all.
What is it your sevos are doing? My thinking is this: if you are missing some channels then try increasing the frame length. If the servos are unstable then you could try increasing the padding time (this is the time the signal spends high) it might help to look at the output from your receiver.
Nice scope by the way. I wish mine did that, but it is 25 years old and I count myself lucky if it takes less than five minutes to warm up!
Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Aug 10, 2010, 06:10 am
Quote
The voltage ripples are tiny and shouldn't make any difference at all.

thats what i thought too... but andykunz of spektrum mentions ac or dc coupling here (http://www.rcgroups.com/forums/showthread.php?t=1273644#post15749872). not sure how that applies yet though...

Quote
What is it your sevos are doing? My thinking is this: if you are missing some channels then try increasing the frame length. If the servos are unstable then you could try increasing the padding time (this is the time the signal spends high) it might help to look at the output from your receiver.

i think it would be best described it as jitter or constant twitching regardless of position. i tried extending the frame length to 25ms as mentioned in this thread (http://www.rcgroups.com/forums/showthread.php?t=1268499) but it didn't seem to help. i'll try adding to the padding next.

when i first loaded ian's code i had some jitter from the servos that seemed to clear up after calibrating the sticks. monitoring the rx outputs made setting up the sticks a lot easier! i'll try that in a minute too!

Quote
Nice scope by the way. I wish mine did that, but it is 25 years old and I count myself lucky if it takes less than five minutes to warm up!

thanx, lol! i purchased this one after much fighting with my dad's Telequipment scope of the same era! i've had it less than a week and im hooked! its surprisingly well built, is easily converted to 100mhz, small, light, cheap, and has a Auto Button!  ;)  heres a link if you're interested. link (http://www.tequipment.net/RigolDS1052E.html)
cheers!
-sj
Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Aug 11, 2010, 03:57 am
its definitely a timing issue! changing values in the timer makes the problem/worse so now it just a matter of locating the proper bits of code and plugging in the right values. this is what i have so far:
Code: [Select]
//Timer data
#define timer_correction_factor 1.00                       //timer correction factor. This is needed if your arduino is too fast or slow
#define timer_framelength 25000 * timer_correction_factor   //Maximum framelength in counter ticks
#define timer_pause 350 * timer_correction_factor           //Pause between pluses in counter ticks

int timer_accumulator = 0;        //accumulator. Used to calculate the frame padding
int timer_ptr = 0;                 //timer array pointer

i changed the correction factor to 1.0 and this gave me a perfect framelength frequency
i changed the framelength to 25ms
and im getting 0.348ms pulses

i think this is right, but does the following produce a centered pulse if no stick connected to a particular channel?
Code: [Select]
void stick_check()
{
 for (int i = 0; i < 5; i++) {
   sticks[i].position = 50;
 }
}


i think all i have left is to widen the LOW so that the pulse ranges are between 1.5 and 2.5ms. looks like currently they are at 1ms at what i think are centered sticks. gotta plug the yoke back in to find out where im at for sure. getting close!  :)
-sj
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Aug 11, 2010, 02:11 pm
Hello,

I have to say, I am very surprised that you are having any problems at all, when I use the code (and I have flown with it on several occasions) i have no problems what so ever; it has been jitter free and rock solid. Admittedly i am on 35mHz rather than 2.4 but I don't see how that would be any different.

The length of the servo pulse is given by the time between the rising edge of one pulse in the ppm chain and the rising edge of the next, not by the length off the low segment in-between.

I know that as i wrote the code I am probably a bit biased, but i assure you it produces a valid ppm stream with accurate pulses for each servo, it must do as i have flown with it. The correction factor is in there because my arduino runs too fast (weird i know, but i have three arduinos and only one of them requires correction!)
I suspect that the problem is coming when the spektrum module you are using is reading the signal. Have you tried scoping the output from a known good transmitter and comparing that to the arduino output. Could it be that the spektrum module is expecting a ppm chain with voltage of 9.6v as most transmitters run on 8 cells? In which case the 5v chain my not be being detected correctly. The reason that the original code produces an inverted ppm chain is because i then ran it through a transistor NOT gate to switch 9.6v as my 35mHz gear needed a higher voltage signal to the rf board.

Let me know how you get on.

Chris  
Title: Re: Arduino-Controlled RC Transmitter
Post by: cjparish on Aug 11, 2010, 02:20 pm
Quote
i think all i have left is to widen the LOW so that the pulse ranges are between 1.5 and 2.5ms. looks like currently they are at 1ms at what i think are centered sticks


Sorry, I ment to say in my last post; the correct timing for standard is 1 to 2ms with 1.5 being centred. I found a PDF file that explains exactly how the ppm stream works that is very very helpful http://www.omegaco.demon.co.uk/mectnpdf/mectn004.pdf
Most modern servoes will work over an extended range of around 0.6 to 2.4ms

Chris
Title: Re: Arduino-Controlled RC Transmitter
Post by: Geo72 on Sep 01, 2010, 02:08 pm
Hi, i am trying to get it running using a Serial connection to my PC. For now its possible to send Channel ID and Position via Serial to the Arduino and the PPM will be adjusted.

The BIG problem is that it my Serial connection is not reliable - i think its because of a timing problem.

Maybe someone of you guys/girls have an idea or solution?

I used Ver 1.6 of Ian´s code and removed all but the most important parts:


? Code should have been here, but i need to post a "normal" message first .... so code in next message (i hope)...


If you start sending - for example-  S010800 ( Set Channel 1 to pos 800) via Serial to the Arduino quite fast you will end up with wrong Serial commands.
I have no real clue why.... :-[
Title: Re: Arduino-Controlled RC Transmitter
Post by: Geo72 on Sep 01, 2010, 02:08 pm
Here is the code i use:


Code: [Select]
//Serial to PPM based on Ian´s:
//// RC Joystick 430mHz
//// For use with Arduino Nano V3.0
//// Ian Johnston 28/04/2010
////
//// If you would like to help support future projects like these then please
//// make a small PayPal donation via my website www.ianjohnston.com
//// Thanks!
////
//// Ver 1.6 - Now using Timer1 to set 22mS refresh for PPM output.
////           Dual rates are implemented but need custom setup.
////           Trimming is not working.
////           Battery monitor sub tweaked
////           Adjusted timing off various subs
////           Various tweaks to LCD & battery monitor
////
// Serial to PPM ??? SEND: S010800 to set Channel 1 to Pos 800

int tick = 0; // Used for various timing of subs
int tick2 = 0; // Used for various timing
int slowflag;

int CH1= 700;
int CH2 = 700;
int CH3 = 700;
int CH4 = 700;
int CH5 = 700;
int CH6 = 700;

int RatesHIMIDLO = 2; // Default is MID rates
int TrimSetting = 0;
int Fixed_uS = 300;       // PPM frame fixed LOW phase
int pulseMin = 700;          // pulse minimum width in uS
int pulseMax = 1700;      // pulse maximum width in uS
int outPinTEST = 8;       // digital pin 8
int outPinPPM = 10;       // digital pin 10


//*** Serial COM&Comand
const int MSG_LENGTH = 7;  // message is char 'S' followed by 6 digits
const char HEADER  = 'S';
//***

ISR(TIMER1_COMPA_vect) {

 ppmoutput(); // Jump to ppmoutput subroutine
 tick = tick + 1;  // update timing tick for subs
 tick2 = tick2 + 1;  // update tick

}

void setup() {

 // setup I/O
 pinMode(outPinPPM, OUTPUT);   // sets the digital pin as output


 // ** SERIAL SETUP
 Serial.begin(57600);         // connect to the serial port
 Serial.println("Serial to PPM");
 //****


 // Setup timer
 TCCR1A = B00110001; // Compare register B used in mode '3'
 TCCR1B = B00010010; // WGM13 and CS11 set to 1
 TCCR1C = B00000000; // All set to 0
 TIMSK1 = B00000010; // Interrupt on compare B
 TIFR1  = B00000010; // Interrupt on compare B
 OCR1A = 22000; // 22mS PPM output refresh
 OCR1B = 1000;
}


void loop() { // Main loop
 processSerial();
 //readanainputsmap(); // Run sub - read ana inputs & map
 checklimits();      // Run sub - check individual channel PPM limits
 //
 //  if (tick >= 11) {     // only run certain subs every 1/4 sec or so (22mS * 11 = 242mS)
 //      tick = 0;
 //      //switchesRates();    // Run sub - read panel switches
 //      //batterymonitor();   // Run sub - check battery
 //  }
 //  
 //  // generate slow changing flag, about 2sec on/off
 //  if (tick2 <= 50) {
 //      slowflag = 0;
 //  }
 //  if (tick2 >= 50 && tick2 <=100) {
 //      slowflag = 1;
 //  }
 //  if (tick2 >= 100) {
 //      slowflag = 0;
 //      tick2 = 0;
 //  }

}


void processSerial() {
 // Process a message available on serial port
 while(Serial.available() >=  MSG_LENGTH )  // process messages when all characters are received: "S" as start indicator, 2 digits as channel number, 4 digits for the value
 {
   if(Serial.read() == HEADER ) //Serial.Read() will "use up" the chars, so we can forget about the "S" now...
   {
     int val = 0;
     int sval =0;
     //First 2 digits are the Channel...
     for(int i =0; i < MSG_LENGTH-5; i++)//7-5=2
     {

       char ch = Serial.read();
       if(ch >= '0' && ch <= '9'){            // is ch a number?
         sval = sval * 10 + ch - '0';           // yes, accumulate the value
       }

     }
     Serial.print("CH: ");
     Serial.println(sval); // For debug


     //Next 4 Digits should be the position/
     for(int i =0; i < MSG_LENGTH-3; i++) // 7-3=4 ... 2+4=6 ... S-12-3456
     {
       char ch = Serial.read();
       if(ch >= '0' && ch <= '9'){            // is ch a number?
         val = val * 10 + ch - '0';           // yes, accumulate the value
       }
     }
     Serial.print("POS: ");
     Serial.println(val); // for debug
     Serial.flush();//clear buffer, there might be some rubbish inside...
     //Serial.println(sval);
     //Serial.println(val);
     // For now its just Channel 1 which will get its new value.
     if (sval==1){
       CH1=val;
       Serial.print("CH1 Set to ");
       Serial.println(CH1);
     }


   }
 }

}


void checklimits() { // check limits sub
 if (CH1 < 700) CH1 = 700;     // Min
 if (CH1 > 1700) CH1 = 1700;   // Max  
 if (CH2 < 700) CH2 = 700;   // Min
 if (CH2 > 1700) CH2 = 1700; // Max
 if (CH3 < 700) CH3 = 700;   // Min
 if (CH3 > 1700) CH3 = 1700; // Max
 if (CH4 < 700) CH4 = 700;       // Min
 if (CH4 > 1700) CH4 = 1700;     // Max  
 if (CH5 < 700) CH5 = 700;               // Min
 if (CH5 > 1700) CH5 = 1700;             // Max
 if (CH6 < 700) CH6 = 700;               // Min
 if (CH6 > 1700) CH6 = 1700;             // Max
}


void ppmoutput() { // PPM output sub
 // test pulse - used to trigger scope
 //digitalWrite(outPinTEST, LOW);
 //delayMicroseconds(100);    // Hold
 // digitalWrite(outPinTEST, HIGH);

 // Channel 1 - Aeleron
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);
 delayMicroseconds(CH1);  // Hold for Aeleron_uS microseconds      

 // Channel 2 - Elevator
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);
 delayMicroseconds(CH2); // Hold for Elevator_uS microseconds      

 // Channel 3 - Throttle
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);
 delayMicroseconds(CH3); // Hold for Throttle_uS microseconds      

 // Channel 4 - Rudder
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);
 delayMicroseconds(CH4);   // Hold for Rudder_uS microseconds

 // Channel 5 - TI Switch
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);
 delayMicroseconds(CH5);     // Hold for TIsw_uS microseconds        

 // Channel 6 - TI pot
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);
 delayMicroseconds(CH6);       // Hold for TI_uS microseconds  

 // Synchro pulse
 digitalWrite(outPinPPM, LOW);
 delayMicroseconds(Fixed_uS);    // Hold
 digitalWrite(outPinPPM, HIGH);  // Start Synchro pulse

}

Title: Re: Arduino-Controlled RC Transmitter
Post by: Geo72 on Sep 02, 2010, 12:28 pm
;D

I used Chris Code today and Lo and behold: Its working like a charm now  ::)

Well, i guess it was all about the Interrupt in the timer ... now there is plenty of time for the UART AND no more kick in while the UART is working...

Only drawback is that i blew my PIN 10 on my Arduino Mega, but work is in progress on an Duemilano now.

You guys Rock!


Question: I like to buy a new Joystick for Mac/PC, the one i have at the moment only puts out values between -127 and +127, so 8Bit resulution. Not that good even i doubt that many RC Servos have a better resolution.
Does anyone know a good (not too expencive) Joystick with atlast a 10Bit Resolution?

Thanks!
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Sep 02, 2010, 01:23 pm
would you consider a Wii Nunchuck?
Title: Re: Arduino-Controlled RC Transmitter
Post by: Geo72 on Sep 02, 2010, 02:59 pm
Wii Nunchuck - mmm... its Bluetooth and i try to avoid 2.4GHz equiptment since it have my 2.4GHz RC Transceiver next to my PC and i don´t like to debug errors which might occure because of that. As soon as everything else works fine, i might try a Nunchuck too  :)

An other Question: As i allready wrote i blew up my Pin 10 on my Adruino Mega.. What would be the best way to protect that Pin since it seems to be quite fragile? A fast Diode?
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Sep 02, 2010, 03:18 pm
No, you are mixing up the Wii remote (wireless) with the Wii Nunchuck (wired). Here is an image:

(http://www1.dealextreme.com/productimages/sku_24529_1.jpg)

You can get them for a few dollars, for example here: http://www.dealextreme.com/details.dx/sku.24529 (http://www.dealextreme.com/details.dx/sku.24529~r.18534066)
Title: Re: Arduino-Controlled RC Transmitter
Post by: sonicj on Sep 02, 2010, 10:51 pm
fmkit has the nunchuck transmitter mastered.

http://www.fmtv.us/wii_nunchuck_rc.html
Title: Re: Arduino-Controlled RC Transmitter
Post by: imprune on Sep 03, 2010, 01:44 pm
This is a pretty good idea I wanted to do this for my project
Title: Re: Arduino-Controlled RC Transmitter
Post by: Geo72 on Sep 06, 2010, 11:29 am
Hi, i bought a Wii Remote and a Nunchuck and use them together with OSCulator (OSCulator is simulating a Joystick HID on my MAC)
Both devices are full 16 Bit resolution (technically) and are working as input for my Arduino via Serial Port.
They gyros are way to sensitive as control for RC Servos. If you flatten out the jitter from the Gyros the reaction time for the servos goes down (maybe the use of vectors could help but i will not dig into that).

The Joystick on the nunchuck gives great results! It has a stable and good resolution and its possible to control Servos very fast and precise. But it has be be kept in mind that RC Servos (altlast all Analog ones that i own) have at best a resolution of 1.5 to 2 Degrees.

Next will be a test of a good "normal" Joystick. The old 8-Bit USB which i own is not really useable because its just wobbly and the values i read are not stable (Value - Postion of Joystick).


Anyone knows which Diode i should use to protect PIN 10 on my Arduinos?


PS: Thanks for the tip with the Wii!  :)
Title: Re: Arduino-Controlled RC Transmitter
Post by: jds on Sep 08, 2010, 12:34 pm
No thanks for the tip on the Wii, glad you like them.

You shouldn't have problems with the sensitivity on the Nunchuck. I know they are being used for controlling r/c aircraft, so you maybe the problem is in your code? Can you show the code you tested with?
Title: Re: Arduino-Controlled RC Transmitter
Post by: Geo72 on Sep 08, 2010, 02:20 pm
Even if the controller is just sitting on my desk i get readings from 316651 to 31995 and as a result an output of 1035-1045 for the PPM on that channel.
I now changed the Serial Data from distinct channels to one array for all channels and with the "smooth" function on OSCulator at 40 the gyros are usable as control for a Servo :)
Title: Re: Arduino-Controlled RC Transmitter
Post by: Mangirdas on Dec 20, 2010, 08:19 pm
Super :) you get A for this :)
Title: Re: Arduino-Controlled RC Transmitter
Post by: Divyanshu on Jan 03, 2011, 02:03 pm
This one helped me! Ty matt!