Servo Jitter

Hi all,

I am trying to build a controller to operate an outboard motor from an RC stick. Middle position (using different modes) the gear is ion Neutral and power can be applied in the range of idle to fast idle. Stick up or down engages the appropriate gear and allow power application from idle to full (delay protections not implemented yet).

Using the Servo library I got terrible results with unwanted servo movement al over the place. Reading on timer issues I have opted for the no-library approach which worked well, however when I using the PulseIn command I get a small amount of jitter. Is there a way around this?

Thanks

/*

  • ECU
  • No Servo Library
    */

int tlg_pin = 2;
int cmd;
// int last;
int cond_cmd;
int gear_val;
int thr_val;

void setup()

{

pinMode(tlg_pin, INPUT);

}

void loop()
{

// last = cmd;
cmd = pulseIn(tlg_pin, HIGH);
// if (abs(last - cmd) < 2) {
// cmd = last;

// }

if (cmd > 500 and cmd < 735) {
gear_val = 1500;
gear_srv();

//delay
thr_val = map(cmd, 500, 735, 1000, 1200);
thr_srv();
}

if (cmd >= 740 and cmd <= 1120) {
gear_val = 2000;
gear_srv();
//delay
thr_val = (map(cmd, 740, 1120, 1000, 2000));
thr_srv();
}
if (cmd >= 1200 and cmd <= 1570) {
gear_val = 1000;
gear_srv();
//delay
thr_val = (map(cmd, 1200, 1570, 1000, 2000));
thr_srv();
}
}

void thr_srv() {

long startthr = micros();
digitalWrite(9, HIGH);
while (micros() - startthr < thr_val)
;
digitalWrite(9, LOW);
//delay(10);

}

void gear_srv() {

long startgear = micros();
digitalWrite(8, HIGH);
while (micros() - startgear < gear_val)
;
digitalWrite(8, LOW);
delay(10);
}

Care to show us the Servo version that had bad jitter?

/*

  • ECU
    */

#include <Servo.h>

int tlg_pin = 2;
int cmd;
int last;
int cond_cmd;

Servo thr;
Servo gear;

void setup()

{
thr.attach(9);
gear.attach(8);
pinMode(tlg_pin, INPUT);

}

void loop()
{
last = cmd;
cmd = pulseIn(tlg_pin, HIGH);

cond_cmd = map(cmd, 539, 2389, 0, 180);

if (cond_cmd > 0 or cond_cmd < 18) {
gear.write(90);
//delay
thr.write(cond_cmd);
}

if (cond_cmd >= 19 and cond_cmd <= 55) {
gear.write(160);
//delay
thr.write(map(cond_cmd, 20, 55, 20, 160));
}
if (cond_cmd >= 63 and cond_cmd <= 100) {
gear.write(20);
//delay
thr.write(map(cond_cmd, 65, 100, 20, 160));
}

}

Maybe you need to attach to the servo to a pin, instead of a smiley face.

What are you reading input from? Why are you using pulseIn() to read it?

For some reason the 8 became a smiley face, it was pasted directly from the IDE.

The pulsin reads a standard RC signal 500-2500 ms.

I am using PulsIn as I assumed that was the command to read a pulse into the Arduino, is there a better way to read a pulse?

What role, exactly, is the Arduino performing that a standard RC controller couldn't do faster, better, cheaper?

Hi,

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

What size servo are you using and how are you powering it?

Tom...... :slight_smile:

The Arduino is meant to protect the engine from gear change under power, also in a later stage I would like a navigation computer (another Arduino) to control the engine.

Code without the Servo library

/*
 * ECU
 *
 * No Servo Library
 */


int tlg_pin = 2;
int cmd;
int last;
int cond_cmd;
int gear_val;
int thr_val;


void setup()

{

  pinMode(tlg_pin, INPUT);

}

void loop()
{

  last = cmd;
  cmd = pulseIn(tlg_pin, HIGH);
  if (abs(last - cmd) < 2) {
    cmd = last;

  }



  if (cmd > 500 and cmd < 735) {
    gear_val = 1500;
    gear_srv();

    //delay
    thr_val = map(cmd, 500, 735, 1000, 1200);
    thr_srv();
  }

  if (cmd >= 740 and cmd <= 1120) {
    gear_val = 2000;
    gear_srv();
    //delay
    thr_val = (map(cmd, 740, 1120, 1000, 2000));
    thr_srv();
  }
  if (cmd >= 1200 and cmd <= 1570) {
    gear_val = 1000;
    gear_srv();
    //delay
    thr_val = (map(cmd, 1200, 1570, 1000, 2000));
    thr_srv();
  }
}



void thr_srv() {

  long startthr = micros();
  digitalWrite(9, HIGH);
  while (micros() - startthr < thr_val)
    ;
  digitalWrite(9, LOW);
  //delay(10);

}


void gear_srv() {

  long startgear = micros();
  digitalWrite(8, HIGH);
  while (micros() - startgear < gear_val)
    ;
  digitalWrite(8, LOW);
  delay(10);
}

Code with Servo library

/*
 * ECU
 */

#include <Servo.h>

int tlg_pin = 2;
int cmd;
int last;
int cond_cmd;

Servo thr;
Servo gear;

void setup()

{

  thr.attach(9);
  gear.attach(8);
  pinMode(tlg_pin, INPUT);

}

void loop()
{
  last = cmd;
  cmd = pulseIn(tlg_pin, HIGH);



  cond_cmd = map(cmd, 539, 2389, 0, 180);

  if (cond_cmd > 0 or cond_cmd < 18) {
    gear.write(90);
    //delay
    thr.write(cond_cmd);
  }

  if (cond_cmd >= 19 and cond_cmd <= 55) {
    gear.write(160);
    //delay
    thr.write(map(cond_cmd, 20, 55, 20, 160));
  }
  if (cond_cmd >= 63 and cond_cmd <= 100) {
    gear.write(20);
    //delay
    thr.write(map(cond_cmd, 65, 100, 20, 160));
  }


}

I think you have a problem because the servos should all be pulsed every 20ms but you're stopping to read a pulse in which will block the code until a pulse is received. If the previous pulse had just been missed, the pulse in read could could cause a 20ms delay in your code. I think this delay is enough to cause jitter.

I think you need a different method of reading in pulses and or a different way to sending pulses to the servos.

The Servo library is interrupt driven, it going to generate pulses unless you inhibit interrupts.

Thanks but I am no using the Servo library. All was well until I added the Pulsin commnad, is there any other way to read in an RC pulse?

MarkT:
Care to show us the Servo version that had bad jitter?

I second Mark's question. As Mark mentioned a couple of posts ago, the servo library will continue to send pulses as long as the interrupt isn't inhibited. It sure seems like you'd be better off using the normal servo library.

Are you powering the servos with three AA alkaline cells? IMO, this isn't a good power supply for two standard size servos. Alkaline cells don't produce a lot of current. When the servos move, the sudden surge of current can cause the voltage to drop which can cause all sorts of problems.

I think you'd be able to find problems with the code faster if you made sure the servos had a reliable source of power.

Thanks for your replays, with better power supply (i.e. 6 volts from my bench power supply) the jitter is just faster.

Is the problem nit related to the Pulsin command in some way?

josefvs:
Is the problem nit related to the Pulsin command in some way?

Yes. I still think so.

DuaneDegn:
I think you have a problem because the servos should all be pulsed every 20ms but you're stopping to read a pulse in which will block the code until a pulse is received. If the previous pulse had just been missed, the pulse in read could could cause a 20ms delay in your code. I think this delay is enough to cause jitter.

I think you need a different method of reading in pulses and or a different way to sending pulses to the servos.

The normal servo library shouldn't have the same issue since, as Mark mentioned, it's interrupt driven and shouldn't be stopped by your code doing other things.

MarkT:
Care to show us the Servo version that had bad jitter?

DuaneDegn:
I second Mark's question.

It's probably worth revisiting the code which uses the normal servo library.

Is the problem nit related to the Pulsin command in some way?

Below is some very simple servo test code you might try to see if the servo jitters or not using this code. If the servo does not jitter, then your code may be the source of the jitter issue.

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.attach(9);
  Serial.println("servo-test"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured String 
    int n = readString.toInt();  //convert readString into a number
    Serial.println(n); //so you can see the integer
    myservo.write(n);
    readString="";
  } 
}

You may want to abandon pulseIn() and the Servo library entirely - but most certainly at least pulseIn(). Mainly because it is a blocking function, which might be the source of your problems.

Instead, look into the following links; these first two are for a library designed for RC usage - both reading from a receiver, and controlling the servos. In fact, there is enough there that you could implement your own end-to-end system, if you wanted:

This link is more of an "all around projects" regarding the Arduino and RC control; it doesn't focus on any singular portion, but does seem to have a lot of good info about the process, which might help you to understand and debug your issues.

BTW - if you haven't gotten an oscilloscope yet, you might want to look into one for troubleshooting; it might help you pinpoint your issues.