I am at my wits end with this today. I have written a bit of code that is supposed to read two receiver channels and then move two servos according to the input values from the receiver, and print those values to the Serial monitor. It reads the values from the receiver just fine and prints those values to the screen just fine. It will not command the servos though. I know it must be a very simple snag, but I just cannot get this to run.
Can someone look at this code and tell me if you see what may be wrong?
Thanks in advance.
// This sketch is to test reception of RCVR PWM and
// move the appropriate servo.
// 12-29-2008 by JWH
#include <SoftwareServo.h>
SoftwareServo servo1;
SoftwareServo servo2;
unsigned long counter = 0;
unsigned long Channel1Value;
unsigned long Channel2Value;
unsigned long servo1Value;
unsigned long servo2Value;
void setup()
{
servo1.attach(14); // connect servo1 to analog pin 0
servo1.setMaximumPulse(2000);
servo1.setMinimumPulse(700);
I have not used the SoftwareServo-library myself, but the documentation say that you must call the refresh-method atleast once every 50 milliseconds. You are reading two servo-pulses and writing four lines to the serial-port before calling refresh - this might be too much. Try re-arranging your code to something like this:
Hmm... What values are you getting from pulseIn()? I'm not very familiar with this servo-library - does it expect pulse width or angles as argument to servo.write? Could it be that you're trying to pass pulse width (in the range of approx 600 to 2400) when .write is expecting degrees?
I think Skumlerud has found the problem, the software servo library uses degrees, not millisconds. The Arduino Map function can do the conversion for you.
"Hmm... What values are you getting from pulseIn()? I'm not very familiar with this servo-library - does it expect pulse width or angles as argument to servo.write? Could it be that you're trying to pass pulse width (in the range of approx 600 to 2400) when .write is expecting degrees?"
The values I get back range from 1013 to 2000 with 1496 being mid-stick. I will look up the Map to see if I can decipher the syntax. and report back.
If you modify the code above to hard code the value:
Channel1Value = 90;
and that servo no longer chatters, that indicates that the input signal is not constant and you can look to see why its changing. If the servo still chatters, try a different servo.
When the servos are at center stick, they pulse back and forth a just perceptable bit either way of center.
Does the measured pulse width fluctuate too? If it does, you might need to add code to smooth the pulses or get a better receiver.
If it doesn't, you could try a different library. ServoTimer1 generates the pulses in hardware, so it's very accurate and there is no need to update the pulses in software. The downside is that it only works on two pins (9 and 10 I think).
Yup, the pulses vary a tiny bit. I am using a Futaba FP-R148DF so I may need to smooth the pulses a bit. Since you have been such help, what would you recommend for smoothing? One of the built in functions? ServoTimer1 is not an option since I will be moving and commanding 4 or 5 servos or a couple of ESC motor controllers.
How much does the read angles vary? If it varies just a small amount you can get away by using a simple treshold to remove the small variations. A simple way of doing this would be something like...
The drawback of this is that it will only move the servo i steps of THRESHOLD+1 degrees. If this is not acceptable, you would probably have to sample the pulses over time (five pulses perhaps, that depends on how the pulses fluctuates) and calculate an average before moving the servo. This would smooth out the pulses and still keep a resolution of one degree, but at the cost of a small delay (20ms for each sampled pulse).
Your project sounds interesting. I'm into R/C myself, mostly cars, and have been playing with the idea of adding traction control and ESP to a buggy using an Arduino. Please keep us posted on your progress