SR04 induces servo chatter when it gets false readings

I am running the newping library and find that when I hook up an SR04 the servo I am also running starts to chatter. I find that when I point the SR04 at something close, the chatter is much less, at times non existent, but when the SR04 is maxed out for distance, the servo chatters a lot.

I have tried running the servo off its own power supply, and the problem still exists. I have tried running both the SR04 and servo off their own supplies, and the problem still exists.

If I unplug only the servo data lead, the chatter stops. If I plug the servo data lead into any other analog line, it chatters.

If I unplug the SR04 trigger and output, the chatter stops.

So, it seems the SR04 when it is not within close range IE less than 150 cm, induces some sort of instability to the servo. I am running the servo.h library, and setting the servo with servo.write

The rate of chatter seems to coincide with the number of false readings I get back from the SR04. If the output is steady and consistent, ie at close range, no chatter. The further out I move, the more erroneous readings, and the more servo chatter.

Any idea what I can do to improve the situation?
I am thinking this is a hardware problem, and not software related, but then again?

Northof49:
If I unplug only the servo data lead, the chatter stops. If I plug the servo data lead into any other analog line, it chatters.

What do you mean by an "analog line" and why is the servo plugged into one of them?

Steve

Sorry, your are correct. It is using the pwm side of the board.

Servo works fine in any initialized pin until the SR04 sensor is hooked up, then it gets jittery when the SR04 is making readings beyond say 25cm, at which time the readings become, around 1/10 erroneous. At 175 cm, the readings are even less stable, and the servo becomes even more jittery.

I may hook an oscilloscope up to the line and see if the frequency to the servo is becoming unstable when the ultrasonic sensor is hooked up. I don't think its the power supply, since I put the servo on its own power supply. I can also try a different SR04, just in case this one is defective.

I am thinking this is a hardware problem, and not software related, but then again?

Are we supposed to guess too?

Why haven't you posted the code, using code tags?

[code]

// Example 5 - Receive with start- and end-markers combined with parsing
// This consists of
// #1 - parsing serial to two integers from format <7,180>
// #2 - writing the parsed integers to servos in the format of <pin number,degrees>
// #3 - incorporating NewPing library with 15 sensors, and writing the results to serial


const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
int firstIntegerFromPC = 0;
int secondIntegerFromPC = 0;
// int floatFromPC = 0.0;

boolean newData = false;

// my servo addition

#include <Servo.h>
Servo mys[20]; //Now we have 20 servos but only use 2-19 (ie 18 servos)
//

//Start Ping code addition
#include <NewPing.h>

#define SONAR_NUM     1 // Number or sensors.
#define MAX_DISTANCE 200 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).

unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM];         // Where the ping distances are stored.
uint8_t currentSensor = 0;          // Keeps track of which sensor is active.

NewPing sonar[SONAR_NUM] = {     // Sensor object array.
  NewPing(41, 42, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
  //NewPing(43, 44, MAX_DISTANCE),
  //NewPing(45, 46, MAX_DISTANCE),
  //NewPing(21, 22, MAX_DISTANCE),
  //NewPing(23, 24, MAX_DISTANCE),
  //NewPing(25, 26, MAX_DISTANCE),
  //NewPing(27, 28, MAX_DISTANCE),
  //NewPing(29, 30, MAX_DISTANCE),
  //NewPing(31, 32, MAX_DISTANCE),
  //NewPing(34, 33, MAX_DISTANCE),
  //NewPing(35, 36, MAX_DISTANCE),
  //NewPing(37, 38, MAX_DISTANCE),
  //NewPing(39, 40, MAX_DISTANCE),
  //NewPing(50, 51, MAX_DISTANCE),
  //NewPing(52, 53, MAX_DISTANCE)
};
// end newping addition============

void setup() {
  Serial.begin(115200);
  Serial.println("This demo expects 2 pieces of data - two integers");
  Serial.println("Enter data in this style <1, 180>  ");
  Serial.println();
  // my addition
  for (int i = 2; i < 20; i++)
  {
    mys[i].attach(i); // was i+2
  }
  // end my addition

  // Start Ping code void setup addition

  // already done   Serial.begin(115200);
  pingTimer[0] = millis() + 75;           // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
    pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
  // end ping code addition============
}
void loop() {
  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    showParsedData();
    servoMove();
    newData = false;
  }
  // Ping code addition to void loop

  {
    for (uint8_t i = 0; i < SONAR_NUM; i++) { // Loop through all the sensors.
      if (millis() >= pingTimer[i]) {         // Is it this sensor's time to ping?
        pingTimer[i] += PING_INTERVAL * SONAR_NUM;  // Set next time this sensor will be pinged.
        if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Sensor ping cycle complete, do something with the results.
        sonar[currentSensor].timer_stop();          // Make sure previous timer is canceled before starting a new ping (insurance).
        currentSensor = i;                          // Sensor being accessed.
        cm[currentSensor] = 0;                      // Make distance zero in case there's no ping echo for this sensor.
        sonar[currentSensor].ping_timer(echoCheck); // Do the ping (processing continues, interrupt will call echoCheck to look for echo).
      }
    }
    // The rest of your code would go here.
  }



  // end Ping code addition to void loop

}

//============

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

//============

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  // tim comments out strcpy(firstIntegerFromPC, strtokIndx); // copy it to firstIntegerFromPC
  firstIntegerFromPC = atoi(strtokIndx); // my addition convert first part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  secondIntegerFromPC = atoi(strtokIndx);     // convert this part to an integer

  // Tim comments out strtokIndx = strtok(NULL, ",");
  //  Tim comments out floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
  Serial.print("Servo Number ");
  Serial.println(firstIntegerFromPC);
  Serial.print("Degrees movement ");
  Serial.println(secondIntegerFromPC);
  // Serial.print("Float ");
  // Serial.println(floatFromPC);

}
void servoMove() {
  // start my addition
  mys[firstIntegerFromPC].write(secondIntegerFromPC); //write servo position
  // end my addition
}
void oneSensorCycle() { // Sensor ping cycle complete, do something with the results.
  for (uint8_t i = 0; i < SONAR_NUM; i++) {
    Serial.print(i);
    Serial.print("=");
    Serial.print(cm[i]);
    Serial.print("cm ");

    //  Serial.print(cm[0]);
    //  Serial.print(cm[1]);
    //  Serial.print(cm[2]);
  }
  Serial.println();
}


void echoCheck() { // If ping received, set the sensor distance to array.
  if (sonar[currentSensor].check_timer())
    cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}

[/code]

What do you suppose this code does, when SONAR_NUM == 1? I did not check any further.

  for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.

Changed it to three sensors and it still does it.

If I unplug either the trigger or echo pin, the chatter stops.

If I point the sensor at a solid object 10 cm away, the chatter stops. If I point it off in the distance, the chatter resumes. It's not really bad chatter, just a degree of movement, but it shouldn't be there for a servo not under load.

There is no serial read event occurring unless I move a servo, so I knows its not that.

Ok,
I am pleased to report that changing to a different brand and model of servos has eliminated the chatter. Some servo models (Hextronik htx900) must be more sensitive to slight deviations in the signal than others (Tower pro MG996R).

I'm puzzled why the distance reading by the SR04 sensor would have such a profound effect on servo chatter, but for the first type of servo I tried, it does.