Servo library that doesn't reset timer?

I have been struggling with my program reading a 8 channel rc receiver, cleaning up my raw data, and writing to servos. The problem seems that the standard servo library resets or interrupts the timer on an arduino thus causing problems with my pulseIn functions. I tried looking into reading a PPM value to avoid the pulseIn calls but can't figure out how to tap into the PPM signal on my FlySky R8B receiver. That leaves me looking for a new servo library to use that wound conflict with the pulseIn functions?

I came across PWMServo and would like to control more than 3 servos.

At this point, people usually ask you to:

  1. post your code [enclose using the # icon], so they can see what you actually did.

  2. it also helps to say which Arduino board you are using, and

  3. how you are trying to power the servos. You cannot power them directly from an Arudino board, and need to use a separate power supply.

  4. I've never heard of PWMServo, but it sounds like an old obsolete library. Did you try the standard library? http://arduino.cc/en/Reference/Servo found here, http://arduino.cc/en/Reference/Libraries

oric_dan:
At this point, people usually ask you to:

  1. post your code [enclose using the # icon], so they can see what you actually did.

  2. it also helps to say which Arduino board you are using, and

  3. how you are trying to power the servos. You cannot power them directly from an Arudino
    board, and need to use a separate power supply.

  4. I’ve never heard of PWMServo, but it sounds like an old obsolete library. Did you try the
    standard library?
    http://arduino.cc/en/Reference/Servo
    found here,
    http://arduino.cc/en/Reference/Libraries

  1. I have commented out my use of a servo through the standard library after noticing a random “chirp.” My pulseIn values would be 20-30 lower when the chirp would occur.
//This will sketch will read all 8 channels of a RC receiver and input the values via serial monitor.
//Programed for the Arduino MEGA 2560

//Included Libraries
//#include <Servo.h>

// 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;

//Signal Conditioning limits
const int lo=920;
const int hi=1640;
const int deadlo=1270;
const int deadhi=1290;
const int center=1280;

int ch[8];  //Array to store and display the values of each channel
//int ch4;  //Steering Output Variable
//Servo steer;  //Steering Servo

// the setup routine runs once when you press reset:
void setup() 
{
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  //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);
  
//  //Servo Outputs:
//  steer.attach(2);      //Attach Steering Servo to PWM Pin 2
}

//Main Program
void loop()
{
  // read the input channels
  ch[0] = pulseIn (chA,HIGH);  //Read and store channel 1 
  ch[1] = pulseIn (chB,HIGH);
  ch[2] = pulseIn (chC,HIGH);
  ch[3] = pulseIn (chD,HIGH);
  ch[4] = pulseIn (chE,HIGH);
  ch[5] = pulseIn (chF,HIGH);
  ch[6] = pulseIn (chG,HIGH);
  ch[7] = pulseIn (chH,HIGH);
  
  //Input Signal conditioning
  for (int i=0; i<=8; i++)      //Signal Conditioning loop
  {
   if (ch[i] <= lo)             //Trim Noise from bottom end
   {
    ch[i] = lo; 
   }
   
   if (ch[i] <= deadhi && ch[i] >= deadlo)     //Create Dead-Band
   {
    ch[i] = center; 
   }
   
   if (ch[i] >= hi)            //Trim Noise from top end
   {
     ch[i] = hi;
   }
  }
  
  //Steering Control Output on Channel 4
//  ch4 = ch[3];
//  if (ch4 >= lo && ch4 <= deadlo)
//  {
//    ch4 = map(ch4, lo, deadlo, 0, 90);
//  }
//  else if (ch4 == center)
//  {
//    ch4 = 90;
//  }
//  else if (ch4 >= deadhi && ch4 <= hi)
//  {
//    ch4 = map(ch4, deadhi, hi, 90, 180);
//  }
//  steer.write(ch4);
  
 //Serial Outputs
  Serial.print ("Ch1:");  //Display text string on Serial Monitor to distinguish variables
  Serial.print (ch[0]);     //Print in the value of channel 1
  Serial.print ("|");
  Serial.print ("Ch2:");
  Serial.print (ch[1]);
  Serial.print ("|");
  Serial.print ("Ch3:");
  Serial.print (ch[2]);
  Serial.print ("|");
  Serial.print ("Ch4:");
  Serial.print (ch[3]);
  Serial.print ("|");
  Serial.print ("Ch5:");
  Serial.print (ch[4]);
  Serial.print ("|");
  Serial.print ("Ch6:");
  Serial.print (ch[5]);
  Serial.print ("|");
  Serial.print ("Ch7:");
  Serial.print (ch[6]);
  Serial.print ("|");
  Serial.print ("Ch8:");
  Serial.println (ch[7]);
//  Serial.print ("Steering Output:");
//  Serial.println (ch4);
}
  1. I have replicated the chirp on both the Uno and Mega2650.

  2. Yes PWMServo is an obsolete Arduino Library. Using the standard servo library is what causes my chirps when running the pulseIn function.

I have done extensive testing over the last two weeks that lead to the creation of this thread. I first thought I was getting interference from my 2.4GHz WIFI into my 2.4GHz rc signal. I found that going to a local park with no WIFI present I got the same issue using the Arduino and current servo library. I then went home and tried removing the Arduino from the equation with my and everyones WIFI network present by hooking up my other reciever to a few servos and testing response. The servos were steady and responded perfect. The problem laid in the Arduino or my program so I went and commented out my addition of output to a servo being the last major change made to my program. I was getting no chirps in my serial monitor output. After asking the all mighty Google for the answer I found that the standard servo library is a problem for most rc controlled projects but was unable to locate a current link to a replacement library. Sorry, I didn’t think all the information you are asking for was needed but I could have added more background information.

A) Arduino 1.0.1 IDE from the Ubuntu 12.04 backport repositories. Would love the latest version without performing a distro-update or manually installing.
B) Funduino Mega2650 & Arduino Brand Uno.
C) FlySky TH9x TX & R8B RX w/no mods other than removing buzzer in TX.
D) Created a small custom shield to connect RX to Mega2650 with bind and power switches.

http://sourceforge.net/projects/arduinorclib/

I have found ArduinoRCLib and has wondered if anyone has experince using it? I'm looking through it's wiki and may have answered my own thread. I'll post pack once I figure out how to output to a servo.

Sorry, I didn't think all the information you are asking for was needed but I could have added more background information.

Trust me, there are numerous ways people go wrong, between h.w. and s.w., and in your case you also are dealing with RF, and most of the time trying to help involves about 80% guesswork, due to what's not being said.

After asking the all mighty Google for the answer I found that the standard servo library is a problem for most rc controlled projects but was unable to locate a current link to a replacement library.

Can you post links you looked at concerning this.

The servo lib uses Timer 1 for the UNO chip, and I looked at the source code for pulseIn(), and that appears to use the std Timer 0 timing functions, so it's uncertain why there should be an interaction. All in all, my first guess would be either poor power source for the servos or flakey RF transmissions. See, it's mostly guesswork.

I understand your point and couldn’t find the links I read from Google.

I don’t think that the RF Transmission is the cause as I get proper operation when I directly plug a servo into the receiver. Also, If I run the code above with the Servo related code commented out I didn’t have any “chirps” in the data reported via serial monitor last night. I’m using my Funduino Mega2650’s 5V supply to power the receiver or the Uno’s regulator. However, I will use a 6V lantern battery as a supply for servos and testing with only receiver and servos. I do make sure to hook up the common ground between the arduino and the lantern battery when used.

First, I have commented out my signal conditioning section to give a sense of my raw input data. I have left all auxiliary switches/pots turned down or off and moved my throttle to 100%. See attached RawData.txt.
I have some small attenuation but don’t know what should be expected?

Second, I will uncomment my signal conditioning and give the output from serial monitor. See attached ConditionedData.txt.
Same Attenuation as before.

Third, I uncommented my use of a servo and give serial output as well as physical operation. See attached ConditionedDataWithServo.txt.
As you can see I’m getting up to a 5 degree change in my servo output.

Lastly, I will hook up my other receiver to some servos and test without an Arduino. I had normal response from all three servos. Granted, I used a different receiver but I tested the receiver I’m using with the Arduino today before I created a little shield with it. I have been waiting for my male/female jumper wires in the mail otherwise I wouldn’t have created a small shield and soldered wires to the receiver.

From my tests it sees that A) receiver is bad, B) receiver shield is introducing noise, C) Arduino is introducing noise, or D) Arduino isn’t accurately reading receiver output?

If the image didn’t get inserted you can follow the link below:

RawData.txt (14.7 KB)

ConditionedData.txt (5.78 KB)

ConditionedDataWithServo.txt (5.33 KB)

TankProgram.ino (2.77 KB)

It'll take a bit of time to sort through all of this. Would still be nice if you could find where people said the servo lib doesn't work well with rc projects. I would want to see what they talked about.

I would also try powering the receiver from a different power source than the Arduino. It might not like seeing the digital hash from a microcontroller Vcc buss. Also, do you have any idea how much current the receiver draws? Also, I don't even see how these systems can be reliable at 2.4 Ghz, given you can pick up a dozen or more routers everywheres. The band is an overloaded mess.

I wonder, when you have the entire system hooked up, using both pulseIn() and the Servo functions, and with the servos powered up, do you see glitches in the values that pulseIn() reads, or only glitches in the servo positions?

I looked at your files, and am not really sure what your problem is, but I don’t much
care for this code

  //Input Signal conditioning
  for (int i=0; i<=8; i++)      //Signal Conditioning loop
  {
   if (ch[i] <= lo)             //Trim Noise from bottom end
   {
    ch[i] = lo; 
   }
   
   if (ch[i] <= deadhi && ch[i] >= deadlo)     //Create Dead-Band
   {
    ch[i] = center; 
   }
   
   if (ch[i] >= hi)            //Trim Noise from top end
   {
     ch[i] = hi;
   }
  }

It seems to me the “deadband” [actually a window] is too narrow, and you have 2 big holes
between the window and the hi/lo thresholds, and the output will be jumping around a lot.
What I might do is perform a running average on the readings, and see if that helps with
the noise problem.

oric_dan: I wonder, when you have the entire system hooked up, using both pulseIn() and the Servo functions, and with the servos powered up, do you see glitches in the values that pulseIn() reads, or only glitches in the servo positions?

I see glitches in the values that then lead to position glitches.

oric_dan: What I might do is perform a running average on the readings, and see if that helps with the noise problem.

How big of an average would you recommend? If the PPM signal is assumed to be 50Hz thus supplying 50 different values per second for each channel. I was going to start with averaging three points. http://rcarduino.blogspot.com/2012/11/how-to-read-rc-receiver-ppm-stream.html

oric_dan: I looked at your files, and am not really sure what your problem is, but I don't much care for this code

I'm doing this because even after TX calibration, if you move a stick to its limit it doesn't give a constant value and the sticks don'e return to exact center. The dead-band is personal preference and trimming the max/min values ensures that the servo will go to a max/min using the map function. The only thing I lose is some of my input signal resolution but will have clear boundaries. This isn't ideal but maybe after performing a running average my signal massaging could be lessened or removed entirely.

Once I get a chance this evening I will prepare some new code snipets and also use an external power source to power the receiver.

I would just try some some different averages and see how it goes. Using only 3 values is probably as good as not doing it at all. Also, to me, your deadband window is very narrow. Very difficult to troubleshoot this sort of thing from 1000s of miles away, too many variables. As mentioned earlier, I don't see how this can be a timer issue, since the 2 functions use different timers. Good luck.

I greatly appreciate the help! I went back to my default dead-band before creating the thread, sorry if I misunderstood. I will most pack on my results. Lastly, I may dismantle my shield to move the wires farther apart on the Mega just to hopefully remove any interference in the shield.

I finished implementing the averaging, debug modes for serial monitor input, and other minor touches. It seems to be working great but it is incredibly slow. What would the main cause of this? Averaging, my extensive use of various variables, run out of RAM?

//This will sketch will read all 8 channels of a RC receiver and input the values via serial monitor.
//Programmed for the Arduino MEGA 2560

//Included Libraries
#include <Servo.h>

//Enable debug mode to input data via serial
//0=OFF, 1=Engineering Data On, 2=Raw Data On, 3=Both Eng & Raw Data Output
const int debug=1;

//Arrays for pin location and averaging
const int chPin[]={22,24,26,28,30,32,34,36};
int chx[8];  //Store Raw Data
int chy[8];  //Store values from previous read
int chz[8];  //Store values from read before last
int chEng[8];//Store averaged and massaged data

//RX signal massaging values
const int RXLo=920;
const int RXHi=1640;
const int RXDeadLo=1270;
const int RXDeadHi=1290;
const int RXMid=1280;

//Servo Ranges
const int serHi=180;
const int serLo=0;
const int serMid=90;

//Servo Output
const int steerPin=2;
int ch4;  //Steering Output Variable
Servo steer;  //Steering Servo

// the setup routine runs once when you press reset:
void setup() 
{
  if(debug > 0)
  {
    Serial.begin(115200);
  }

  //Input Pins:
  for (int i=0; i<=8; i++)
  {
    pinMode(chPin[i],INPUT); 
  }
  //Servo Outputs:
  steer.attach(steerPin);      //Attach Steering Servo to PWM Pin 2
}

//Main Program
void loop()
{
  //Move values from chy to chz, chx to chy, and read new values
  for (int i=0; i<=8; i++)
  {
    chz[i]=chy[i];
    chy[i]=chx[i];
    chx[i]=pulseIn(chPin[i],HIGH);
    chEng[i]=(chx[i]+chy[i]+chz[i])/3;
  }

  //Input Signal conditioning
  for (int i=0; i<=8; i++)      //Signal Conditioning loop
  {
    if (chEng[i] <= RXLo)             //Trim Noise from bottom end
    {
      chEng[i] = RXLo; 
    }

    if (chEng[i] <= RXDeadHi && chEng[i] >= RXDeadLo)     //Create Dead-Band
    {
      chEng[i] = RXMid; 
    }

    if (chEng[i] >= RXHi)            //Trim Noise from top end
    {
      chEng[i] = RXHi;
    }
  }

  //Steering Control Output on Channel 4
  ch4 = chEng[3];
  if (ch4 >= RXLo && ch4 <= RXDeadLo)
  {
    ch4 = map(ch4, RXLo, RXDeadLo, serLo, serMid);
  }
  else if (ch4 == RXMid)
  {
    ch4 = serMid;
  }
  else if (ch4 >= RXDeadHi && ch4 <= RXHi)
  {
    ch4 = map(ch4, RXDeadHi, RXHi, serMid, serHi);
  }
  steer.write(ch4);

  //Debug Output
  if(debug > 0 && debug != 2)  //Engineering Data
  {
    Serial.print ("EngData|Ch1:");
    Serial.print (chEng[0]);
    Serial.print ("|Ch2:");
    Serial.print (chEng[1]);
    Serial.print ("|Ch3:");
    Serial.print (chEng[2]);
    Serial.print ("|Ch4:");
    Serial.print (chEng[3]);
    Serial.print ("|Ch5:");
    Serial.print (chEng[4]);
    Serial.print ("|Ch6:");
    Serial.print (chEng[5]);
    Serial.print ("|Ch7:");
    Serial.print (chEng[6]);
    Serial.print ("|Ch8:");
    Serial.print (chEng[7]);
    Serial.println ("|");
    Serial.print ("Steering Output:");
    Serial.println (ch4);
  }
  if(debug>=2)
  {
   Serial.print ("RawData|Ch1:");
   Serial.print (chEng[0]);
   Serial.print ("|Ch2:");
   Serial.print (chEng[1]);
   Serial.print ("|Ch3:");
   Serial.print (chEng[2]);
   Serial.print ("|Ch4:");
   Serial.print (chEng[3]);
   Serial.print ("|Ch5:");
   Serial.print (chEng[4]);
   Serial.print ("|Ch6:");
   Serial.print (chEng[5]);
   Serial.print ("|Ch7:");
   Serial.print (chEng[6]);
   Serial.print ("|Ch8:");
   Serial.print (chEng[7]);
   Serial.println ("|"); 
  }
}

TankProgram.ino (3.24 KB)

Hi,

I am using an ipad, so cant see all of your code, but i can say the following -

The servo library resets timer1 around every 20ms.

In all the RC projects I have built I have never had to average across multiple samples on the basis that if the code is working, it is receiving the signals as the project would without the arduino in place.

this can mean a variation of around 20us which the equipment averages out through the slower response of the mechanical compnents ( motors, servos) we are only aware of this variation when we measure it, its not visible in the project itself.

If your vatiation is bigger than 20us, its most likley your code that is the problem. I have a library that reads PPM or individual channels and also outputs upto 20 servo/esc signals, check the recent post on rcarduino.blogspot.com, the library is named rcarduinofastlib, there are two posts explaining it and some sample sketches.

Duane B

I have seen that library and currently can't figure out how to tap into my PPM signal on my receiver. I also attached my sketch to my last post if that makes reading my code easier. I could read the values fast before but after implementing averaging to take care of a chirp in my readings it has slowed way down and only updates servo position every half a second. I only get these chirps when using an arduino.

charles88,

You do not need to access the PPM Stream, here is an example of an efficient way of reading and outputting RC Chaanels using the rcarduinofastlib -

http://rcarduino.blogspot.com/2012/11/how-to-read-rc-channels-rcarduinofastlib.html

You will see that the code is specifically written to reduce signal variation resulting from clashing interrupts, it also plays nicely with timer1.

Duane B

rcarduino.blogspot.com

I am using an ipad, so cant see all of your code

Frustrating, isn't it? Try using two fingers in the code box - it's been a while but IIRC, you can scroll it that way.

DuaneB: charles88,

You do not need to access the PPM Stream, here is an example of an efficient way of reading and outputting RC Chaanels using the rcarduinofastlib -

http://rcarduino.blogspot.com/2012/11/how-to-read-rc-channels-rcarduinofastlib.html

You will see that the code is specifically written to reduce signal variation resulting from clashing interrupts, it also plays nicely with timer1.

Duane B

rcarduino.blogspot.com

I found that link last night and will give it a go this evening. Is RCArduinoFastLib the same as RCArduinoLib? I would hate to assume something as I'm often wrong.

Hi,

Its the same library but without using the PPM reading functionality.

You will need to set the number of servos/ESCs at compile time, I have started a FAQ to help here -

http://rcarduino.blogspot.ae/2013/02/rcarduino-libraries-faq.html

Duane B

Duane, I have a few questions on the examples in the RC Arduino Library.

Channel Example: 1) When defining channels with "rc::Channel", if I wanted to add another channel the line would I treat "g_channel" as an array or one variable for one channel?

rc::Channel g_channel[2];
OR
rc:Channel g_channel1 g_channel2
OR
rc:Channel g_channel1
rc:Channel g_channel2

1) In the setup the "g_channel.setSubtrim(20);", does 20 represent degrees? 2) In the program loop, if I was reading an actual receiver I would replace the analogRead function with pulseIn, correct?

Blog Example: http://rcarduino.blogspot.com/2012/11/how-to-read-rc-channels-rcarduinofastlib.html 3) In the blog example for reading individual channels, I see towards the end is the header file for the RC Arduino Fast Library. Is this the only library file needed besides PinChangeInt?

Misc: 4) Would either library prove to be a better fit for reading and outputting 8+ channels on a Mega? I'm looking at reading 8 channels and outputting 8+ channels.