Code help please?

Hello everyone. I am trying to figure out why one is only working? Do I want to switch to analog instead of the digital pwm pins? Right now it reads chan1 only but I need it to reed 5 more servo's and they are connected to the receiver. Well all six of them I mean. and the receiver is connected to pin 7.

int rcPin = 7; // PWM signal arduino pin
int ch1 = 0;    // Receiver channel 1 pwm value
int ch2 = 0;    // Receiver channel 2 pwm value
int ch3 = 0;    // Receiver channel 3 pwm value


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

void loop() {
  // Read in the length of the signal in microseconds
  ch1 = pulseIn(rcPin, HIGH, 25000);
  Serial.print("Channel #1: ");
  Serial.println(ch1);
  // Read in the length of the signal in microseconds
  ch2 = pulseIn(rcPin, HIGH, 25000);
  Serial.print("Channel #2: ");
  Serial.println(ch2);
  // Read in the length of the signal in microseconds
  ch2 = pulseIn(rcPin, HIGH, 25000);
  Serial.print("Channel #3: ");
  Serial.println(ch3);
}

Ardcino: Hello everyone. I am trying to figure out why one is only working? Do I want to switch to analog instead of the digital pwm pins? Right now it reads chan1 only but I need it to reed 5 more servo's and they are connected to the receiver. Well all six of them I mean. and the receiver is connected to pin 7.

Do you want to read pulse values from a RC receiver?

If so you only have one input. It can only read one channel. It looks like the code reads the same pin three times. All three outputs are likely the same, right?

You don't want to use an analog input to read pulse lengths from a RC receiver. Each channel has it's own pin on the RC receiver. You need to use one input pin on the Arduino for each receiver channel you want to read.

You question as very hard to understand. Please tell us what you expected the code to do and what the code actual did. What was the output?

DuaneDegn: Do you want to read pulse values from a RC receiver?

If so you only have one input. It can only read one channel. It looks like the code reads the same pin three times. All three outputs are likely the same, right?

You don't want to use an analog input to read pulse lengths from a RC receiver. Each channel has it's own pin on the RC receiver. You need to use one input pin on the Arduino for each receiver channel you want to read.

You question as very hard to understand. Please tell us what you expected the code to do and what the code actual did. What was the output?

Sorry Sir, Yes I do want the receiver to read the pulse values. So I want to hook up the receiver to the ardunio to save on the pwm pins and use those for the standard servo's later when I print a go pro gimble.

Any help would be wonderful. Thank you

Derek.

Ardcino: Sorry Sir, Yes I do want the receiver to read the pulse values. So I want to hook up the receiver to the ardunio to save on the pwm pins and use those for the standard servo's later when I print a go pro gimble.

Any help would be wonderful. Thank you

Derek.

I don't think pulsein is a good way of reading RC channels. The command pulsein blocks the code's execution and the program has to wait for the beginning of a pulse before reading it. It would easily take more than 20ms to read a single channel. By the time six channels were read, it could take 120 ms. It's not likely to take this one but it could (it could even take longer). While you're monitoring one pin for input the other you'll be missing the input from the other channels. Instead of reading the input at 50Hz you'll likely be reading the input at 10Hz (or worse).

Here's a link to a promising way of reading pulse inputs. I like this one much more than using pulsein.

I suggest you try to get one of the examples working before you attempt to modify the code for your own purposes.

Each channel from the RC receiver will need to be connected to a I/O pin on the Arduino. If you run into trouble, I'll try to help. If you have a problem, please tell us what you were expecting and what occurred which was unexpected. If there is serial output please post it.

DuaneDegn: I don't think pulsein is a good way of reading RC channels. The command pulsein blocks the code's execution and the program has to wait for the beginning of a pulse before reading it. It would easily take more than 20ms to read a single channel. By the time six channels were read, it could take 120 ms. It's not likely to take this one but it could (it could even take longer). While you're monitoring one pin for input the other you'll be missing the input from the other channels. Instead of reading the input at 50Hz you'll likely be reading the input at 10Hz (or worse).

Here's a link to a promising way of reading pulse inputs. I like this one much more than using pulsein.

I suggest you try to get one of the examples working before you attempt to modify the code for your own purposes.

Each channel from the RC receiver will need to be connected to a I/O pin on the Arduino. If you run into trouble, I'll try to help. If you have a problem, please tell us what you were expecting and what occurred which was unexpected. If there is serial output please post it.

Thank you so much Sir, I will post if I need help and if you have some time.

I will follow your blog and see what I can learn. Again thank you for all the help you've been giving me so far.

Here's another thread about reading pulses from a RC receiver.

I'll try to compare the two different methods tomorrow.

Take your time sir, By the way the other 5 servo's are not respondiong in the receiver.

Just the one is, I will try to take a small video tomorrow and show you what I am trying to tell you. I think that's the best way to explain it.

Ardcino: Just the one is, I will try to take a small video tomorrow and show you what I am trying to tell you. I think that's the best way to explain it.

Yes, that would be very helpful.

Also let us know which radio system you're using (preferably with a link). It's also important to know what you are using as a power supply.

DuaneDegn: Yes, that would be very helpful.

Also let us know which radio system you're using (preferably with a link). It's also important to know what you are using as a power supply.

Will do.

My radio is a flysky 6 channel wireless 2.4 radio. This one here. http://www.amazon.com/gp/product/B00EI9UVOE?psc=1&redirect=true&ref_=oh_aui_detailpage_o00_s00

And I am trying to code the ardunio to give me skid steer with 6 servo's and they are plugged into the receiver so I wouldn't have to use the bread board and get an H bridge.

I hope that makes it easier to understand me...

Ardcino: And I am trying to code the ardunio to give me skid steer with 6 servo's and they are plugged into the receiver so I wouldn't have to use the bread board and get an H bridge.

I hope that makes it easier to understand me...

Yes, that helps me understand what you're trying to do.

You may still need a breadboard. If the servos are going to be controlled by the Arduino instead of the receiver, you need a way to get power and signal to the servos. There are some Arduino compatible boards which include servo connectors but in general you either need to use some sort of shield, breadboard or some other sort of connection between servos and power and servos and signals from the microcontroller.

I posted some of the ways I connect servos to a microcontroller in this thread.

A piece of perfboard can be used for this sort of connection.

|500x326

This way is pretty easy but you do need to do some soldering.

My 22 servo hexapod uses these small PCBs to connect the servos to power and a microcontroller.

|456x500

You can follow the above link to find the Gerber files to have these made at OSHPark or other fab house.

A lot people don't think servos should be powered from breadboards but I don't really agree with them.

Here are 32 servos connected to a breadboard.

Of course they're right about breadboards not being a good way to connect servos especially if the servos are drawing a lot of current but I still think it's fine to use a breadboard while testing.

Have you successfully bound your transmitter and receiver? Can you control four or so servos from the receiver directly? As you wiggle the transmitter sticks do the servos move?

What are you using as a power supply?

6 AA batteries, I may go to lipo's when I get the code figure out.

I still want my rc receiver to control the servo's while hooked up to the ardunio.

I am going for skid steer so I will have 6 Servo's doing the skid steer thing. And if I have to use a breadboard I will go with my prototyping shield and mini breadboard.

Ardcino: 6 AA batteries,

What kind of AA batteries? Alkaline? NiMH? Li-Ion?

There's a big difference depending on the chemistry used.

Ardcino: I may go to lipo's when I get the code figure out.

LiPo packs are great but most servos can't be powered directly from LiPo packs. If you use LiPo cells you will probably need a voltage regulator which can handle the amps pulled by the servos.

Ardcino: I still want my rc receiver to control the servo's while hooked up to the ardunio.

I don't understand what you mean by this. If the Arduino is controlling the servos the servos can't be connected to the receiver.

Ardcino: I am going for skid steer so I will have 6 Servo's doing the skid steer thing.

You should take a look at Dagu's Wild Thumper it uses 6 motors. The center pair of wheels and motors rides lower than the other wheels/motors in order to allow it to turn easier.

Ardcino: And if I have to use a breadboard I will go with my prototyping shield and mini breadboard.

You will not be able to leave the servo connected to the receiver if they're being controlled by the Arduino. You need some way of powering the servos and getting the signals from the RC receiver to the Arduino and the signals from the Arduino to the servos.

I tried using the Read Receiver code today. The library has changed since the code example was written so the example doesn't compile with the most recent version of the library. I modified the code so it will compile but I haven't tested it with a receiver yet.

I did control a servo with an Arduino for the first time today. I haven't yet had the Arduino read the pulses from the receiver.

Thanks again for the reply mate, For now I am using 6 Double a batteries I will go with what you suggest.

Here is a picture of what I’ve done so far with the shield uno r3 and my servos and radio.

I think the Read Receiver code has problems. I added a counter for each channel and I found the program was missing over a third of the pulses from the receiver.

I think the problem is the code only watches for the interrupt from one pin at a time. The other pins are ignored while the one pin is monitored. This approach is still much better than using pulsein but I wanted to find a program with reads all the pulses from the receiver.

I believe the program shown in this blog does the job nicely.

I added similar counters to this other program to monitor the number of input pulses were captured as frequently as expected.

Here's the output from some debug statements I added.

time since last = 6817 ms, expected new count = 340, [0] total = 8987, new = 310, pulse = 1616, [1] total = 8987, new = 310, pulse = 1476, [2] total = 8987, new = 310, pulse = 1480
time since last = 6819 ms, expected new count = 340, [0] total = 9297, new = 310, pulse = 1616, [1] total = 9297, new = 310, pulse = 1476, [2] total = 9297, new = 310, pulse = 1476
time since last = 6818 ms, expected new count = 340, [0] total = 9607, new = 310, pulse = 1616, [1] total = 9607, new = 310, pulse = 1476, [2] total = 9607, new = 310, pulse = 1476
time since last = 6819 ms, expected new count = 340, [0] total = 9917, new = 310, pulse = 1616, [1] total = 9917, new = 310, pulse = 1476, [2] total = 9917, new = 310, pulse = 1476
time since last = 6819 ms, expected new count = 340, [0] total = 10227, new = 310, pulse = 1616, [1] total = 10227, new = 310, pulse = 1476, [2] total = 10227, new = 310, pulse = 1476
time since last = 6817 ms, expected new count = 340, [0] total = 10537, new = 310, pulse = 1620, [1] total = 10537, new = 310, pulse = 1464, [2] total = 10537, new = 310, pulse = 1476
time since last = 6819 ms, expected new count = 340, [0] total = 10847, new = 310, pulse = 1616, [1] total = 10847, new = 310, pulse = 1480, [2] total = 10847, new = 310, pulse = 1476

Each line of output displays the time since the last debug statement. The number of pulses expected per channel if the pulses came at 50Hz. The channel id followed by the total pulses received from the channel, the new pulses received since the last debug statement and the pulse reading in microseconds. The same information is displayed for the other two channels.

I think this code is very promising.

Here's a copy of the code with the debug statements added. Nope, the post exceeded the 9000 character limit. I'll try adding it to its own post.

The code uses the input pulses to set servos. It would certainly be possible to mix the incoming pulses to customize control of the servos.

I'm not sure what the next step is. I think I'll try to modify the code to read additional input channels. I'll probably try adding three additional channels.

Here’s the code I tried to add to the earlier post.

/*  ReadThreeRc
 *  modified by Duane Degn
 *  Original notes below.
 * /
// MultiChannels
//
// rcarduino.blogspot.com
//
// A simple approach for reading three RC Channels using pin change interrupts
//
// See related posts - 
// http://rcarduino.blogspot.co.uk/2012/01/how-to-read-rc-receiver-with.html
// http://rcarduino.blogspot.co.uk/2012/03/need-more-interrupts-to-read-more.html
// http://rcarduino.blogspot.co.uk/2012/01/can-i-control-more-than-x-servos-with.html
//
// rcarduino.blogspot.com
//

// include the pinchangeint library - see the links in the related topics section above for details
#include <PinChangeInt.h>

#include <Servo.h>

// Assign your channel in pins
#define THROTTLE_IN_PIN 8
#define STEERING_IN_PIN 9
#define AUX_IN_PIN 10

// Assign your channel out pins
#define THROTTLE_OUT_PIN 5
#define STEERING_OUT_PIN 6
#define AUX_OUT_PIN 7

// Servo objects generate the signals expected by Electronic Speed Controllers and Servos
// We will use the objects to output the signals we read in
// this example code provides a straight pass through of the signal with no custom processing
Servo servoThrottle;
Servo servoSteering;
Servo servoAux;

// These bit flags are set in bUpdateFlagsShared to indicate which
// channels have new signals
#define THROTTLE_FLAG 1
#define STEERING_FLAG 2
#define AUX_FLAG 4

// holds the update flags defined above
volatile uint8_t bUpdateFlagsShared;

// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the 
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint16_t unThrottleInShared;
volatile uint16_t unSteeringInShared;
volatile uint16_t unAuxInShared;

// These are used to record the rising edge of a pulse in the calcInput functions
// They do not need to be volatile as they are only used in the ISR. If we wanted
// to refer to these in loop and the ISR then they would need to be declared volatile
uint32_t ulThrottleStart;
uint32_t ulSteeringStart;
uint32_t ulAuxStart;
unsigned long loopCount = 0;
unsigned long channelCount[3];
unsigned long previousCount[] = {0, 0, 0};
unsigned long nowTime;
unsigned long lastTime;
const unsigned long TWENTY_MS = 20;
uint16_t pulseLength[3];

void setup()
{
  Serial.begin(115200);
  
  Serial.println("multiChannels");

  // attach servo objects, these will generate the correct 
  // pulses for driving Electronic speed controllers, servos or other devices
  // designed to interface directly with RC Receivers  
  servoThrottle.attach(THROTTLE_OUT_PIN);
  servoSteering.attach(STEERING_OUT_PIN);
  servoAux.attach(AUX_OUT_PIN);

  // using the PinChangeInt library, attach the interrupts
  // used to read the channels
  PCintPort::attachInterrupt(THROTTLE_IN_PIN, calcThrottle,CHANGE); 
  PCintPort::attachInterrupt(STEERING_IN_PIN, calcSteering,CHANGE); 
  PCintPort::attachInterrupt(AUX_IN_PIN, calcAux,CHANGE); 

  lastTime = millis();
}

void loop()
{
  // create local variables to hold a local copies of the channel inputs
  // these are declared static so that thier values will be retained 
  // between calls to loop.
  static uint16_t unThrottleIn;
  static uint16_t unSteeringIn;
  static uint16_t unAuxIn;
  // local copy of update flags
  static uint8_t bUpdateFlags;

  loopCount++;
  if (loopCount == 1000000)
  {
    
    loopCount = 0;
    nowTime = millis();
    pulseLength[0] = unThrottleInShared;
    pulseLength[1] = unSteeringInShared;
    pulseLength[2] = unAuxInShared;
    //Serial.println("----------------------------------------------");
    Serial.print("time since last = ");
    Serial.print(nowTime - lastTime,DEC);
    Serial.print(" ms, expected new count = ");
    Serial.print((nowTime - lastTime) / TWENTY_MS, DEC);
    lastTime = nowTime;

    for (byte i=0; i < 3; i++)
    {
      Serial.print(", [");
      Serial.print(i,DEC);
      Serial.print("] total = ");
      Serial.print(channelCount[i],DEC);
      Serial.print(", new = ");
      Serial.print(channelCount[i] - previousCount[i],DEC);
      Serial.print(", pulse = ");
      Serial.print(pulseLength[i],DEC);
      
      previousCount[i] = channelCount[i];
      
      
    }
    Serial.println();
  }
  // check shared update flags to see if any channels have a new signal
  if(bUpdateFlagsShared)
  {
    noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables

    // take a local copy of which channels were updated in case we need to use this in the rest of loop
    bUpdateFlags = bUpdateFlagsShared;
    
    // in the current code, the shared values are always populated
    // so we could copy them without testing the flags
    // however in the future this could change, so lets
    // only copy when the flags tell us we can.
    
    if(bUpdateFlags & THROTTLE_FLAG)
    {
      unThrottleIn = unThrottleInShared;
    }
    
    if(bUpdateFlags & STEERING_FLAG)
    {
      unSteeringIn = unSteeringInShared;
    }
    
    if(bUpdateFlags & AUX_FLAG)
    {
      unAuxIn = unAuxInShared;
    }
     
    // clear shared copy of updated flags as we have already taken the updates
    // we still have a local copy if we need to use it in bUpdateFlags
    bUpdateFlagsShared = 0;
    
    interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on
    // as soon as interrupts are back on, we can no longer use the shared copies, the interrupt
    // service routines own these and could update them at any time. During the update, the 
    // shared copies may contain junk. Luckily we have our local copies to work with :-)
  }
  
  // do any processing from here onwards
  // only use the local values unAuxIn, unThrottleIn and unSteeringIn, the shared
  // variables unAuxInShared, unThrottleInShared, unSteeringInShared are always owned by 
  // the interrupt routines and should not be used in loop
  
  // the following code provides simple pass through 
  // this is a good initial test, the Arduino will pass through
  // receiver input as if the Arduino is not there.
  // This should be used to confirm the circuit and power
  // before attempting any custom processing in a project.
  
  // we are checking to see if the channel value has changed, this is indicated  
  // by the flags. For the simple pass through we don't really need this check,
  // but for a more complex project where a new signal requires significant processing
  // this allows us to only calculate new values when we have new inputs, rather than
  // on every cycle.
  if(bUpdateFlags & THROTTLE_FLAG)
  { 
    channelCount[0]++;
    if(servoThrottle.readMicroseconds() != unThrottleIn)
    {
      servoThrottle.writeMicroseconds(unThrottleIn);
    }
  }
  
  if(bUpdateFlags & STEERING_FLAG)
  {
    channelCount[1]++;
    if(servoSteering.readMicroseconds() != unSteeringIn)
    {
      servoSteering.writeMicroseconds(unSteeringIn);
    }
  }
  
  if(bUpdateFlags & AUX_FLAG)
  {
    channelCount[2]++;
    if(servoAux.readMicroseconds() != unAuxIn)
    {
      servoAux.writeMicroseconds(unAuxIn);
    }
  }
  
  bUpdateFlags = 0;
}


// simple interrupt service routine
void calcThrottle()
{
  // if the pin is high, its a rising edge of the signal pulse, so lets record its value
  if(digitalRead(THROTTLE_IN_PIN) == HIGH)
  { 
    ulThrottleStart = micros();
  }
  else
  {
    // else it must be a falling edge, so lets get the time and subtract the time of the rising edge
    // this gives use the time between the rising and falling edges i.e. the pulse duration.
    unThrottleInShared = (uint16_t)(micros() - ulThrottleStart);
    // use set the throttle flag to indicate that a new throttle signal has been received
    bUpdateFlagsShared |= THROTTLE_FLAG;
  }
}

void calcSteering()
{
  if(digitalRead(STEERING_IN_PIN) == HIGH)
  { 
    ulSteeringStart = micros();
  }
  else
  {
    unSteeringInShared = (uint16_t)(micros() - ulSteeringStart);
    bUpdateFlagsShared |= STEERING_FLAG;
  }
}

void calcAux()
{
  if(digitalRead(AUX_IN_PIN) == HIGH)
  { 
    ulAuxStart = micros();
  }
  else
  {
    unAuxInShared = (uint16_t)(micros() - ulAuxStart);
    bUpdateFlagsShared |= AUX_FLAG;
  }
}

Nice, I've also found another code, I will modify I will post it for you when I get back from the gym later today.

As promised here is a </>
// Define Variables:
const int chA=22; //Constant variables relating to pin locations
const int chB=24;
const int chC=26;
const int chD=28;
const int chE=30;
const int chF=32;
const int chG=34;
const int chH=36;

int ch1; //Varibles to store and display the values of each channel
int ch2;
int ch3;
int ch4;
int ch5;
int ch6;
int ch7;
int ch8;

// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(115200);
// Set input pins
pinMode(chA, INPUT);
pinMode(chB,INPUT);
pinMode(chC,INPUT);
pinMode(chD,INPUT);
pinMode(chE,INPUT);
pinMode(chF,INPUT);
pinMode(chG,INPUT);
pinMode(chH,INPUT);
}

//Main Program
void loop() {
// read the input channels
ch1 = pulseIn (chA,HIGH); //Read and store channel 1
Serial.print (“Ch1:”); //Display text string on Serial Monitor to distinguish variables
Serial.print (ch1); //Print in the value of channel 1
Serial.print ("|");

ch2 = pulseIn (chB,HIGH);
Serial.print (“Ch2:”);
Serial.print (ch2);
Serial.print ("|");

ch3 = pulseIn (chC,HIGH);
Serial.print (“Ch3:”);
Serial.print (ch3);
Serial.print ("|");

ch4 = pulseIn (chD,HIGH);
Serial.print (“Ch4:”);
Serial.print (ch4);
Serial.print ("|");

ch5 = pulseIn (chE,HIGH);
Serial.print (“Ch5:”);
Serial.print (ch5);
Serial.print ("|");

ch6 = pulseIn (chF,HIGH);
Serial.print (“Ch6:”);
Serial.print (ch6);
Serial.print ("|");

ch7 = pulseIn (chG,HIGH);
Serial.print (“Ch7:”);
Serial.print (ch7);
Serial.print ("|");

ch8 = pulseIn (chH,HIGH);
Serial.print (“Ch8:”);
Serial.println (ch8);
}
</>

The code you posted is likely the simplest way of reading in pulses from a RC receiver but (IMO) it’s horribly slow. As I pointed out earlier:

DuaneDegn:
I don’t think pulsein is a good way of reading RC channels. The command pulsein blocks the code’s execution and the program has to wait for the beginning of a pulse before reading it. It would easily take more than 20ms to read a single channel. By the time six channels were read, it could take 120 ms. It’s not likely to take this one but it could (it could even take longer). While you’re monitoring one pin for input the other you’ll be missing the input from the other channels. Instead of reading the input at 50Hz you’ll likely be reading the input at 10Hz (or worse).

Pulsein ties up the Arduino while waiting for the input. If you want the Arduino to do other tasks besides reading in the pulses, I don’t think it would be a good idea to use pulsein.

The code I posted doesn’t display the pulse values very often (about once every 6.8 seconds). Serial writes can dramatically slow a program down. It’s fine to have lots of serial output while debugging the program but the debug statements will have a negative impact on the program’s performance (but the pulsein commands will likely slow the program down more than the serial output).

Your first post used code tags correctly, as you can see, your latest post didn’t use the correct tags. “</>” is the icon for code tags not the tag itself. If you quote a post with code blocks, you can see how code tags can be manually entered.

DuaneDegn:
Your first post used code tags correctly, as you can see, your latest post didn’t use the correct tags. “</>” is the icon for code tags not the tag itself. If you quote a post with code blocks, you can see how code tags can be manually entered.

Sorry DuaneDegn, I will keep learning to use Ardunio and this forum. I do appropriate the help you can and has given me so far.

I want to be able to use 6 Rc chans 3 of them to control 3 servos on the left side of the robot and a second chan to control the other 3 on the right side of the robot for skid steer. And yes I do want the ardunio to use other functions.

I am still very much a noob but you are teaching me slowly sir.

Ardcino: Sorry DuaneDegn, I will keep learning to use Ardunio and this forum.

Not a problem.

There is a lot of stuff to learn but IMO, it's a lot of fun to learn it.

Ardcino: I want to be able to use 6 Rc chans 3 of them to control 3 servos on the left side of the robot and a second chan to control the other 3 on the right side of the robot for skid steer.

I imagine you want all three servos on each to perform the same action in unison. Right?

You don't need a separate channel for each servo. You would use the same output for all three servos on a side.

You could use the breadboard to route the single signal to the three servos.

You will likely need two receiver channels to control all six servos. One channel will be used to indicate how fast forward or reverse the robot should move and the second channel would tell the robot how much to move. There's a relatively simple equation to convert the speed and turning inputs to speed values of the two sets of motors.

Here are the equations.

  joystickY = unSpeedInShared - STOPPED_US;
  joystickX = unSteeringInShared - STOPPED_US;
  pulseAux = unAuxInShared;
  if (joystickX != previousJoystickX || joystickY != previousJoystickY) // if joystick has changed compute new speeds
  {
    speedPort = joystickY - joystickX + STOPPED_US;
    speedStarboard = STOPPED_US - (joystickY + joystickX);
    previousJoystickX = joystickX;
    previousJoystickY = joystickY;
    changeFlag = 1;
  }

"STOPPED_US" is the center servo position (when using position control rather than speed). This is set to 1500us.

The joystickX would normally be the aileron channel and joystickY would be taken from the elevator channel.

The above equations will likely need to be adjusted based on which direction you move the sticks to increase the pulse length.

The code I'll post in the next reply, compiles but I haven't tested it. Hopefully I'll do so tomorrow.

There are still only three channels being read, but it only takes two channels to control the speed and direction of a robot.

I don't think it would be a problem to add additional channels. These additional channels could be used to control pan and tilt turrets or other devices on the robot.