Servo problems...

Hi:

The servo doesn't really jitter... it just does not hold its position. In other words, it rotates about 10 degrees away from the calculated value, and then swings back to the calculated value. This cycle repeats every few seconds.

Thanks

rdeans

rdeans:
Hi:

The servo doesn't really jitter... it just does not hold its position. In other words, it rotates about 10 degrees away from the calculated value, and then swings back to the calculated value. This cycle repeats every few seconds.

Thanks

rdeans

You've got debug code in there showing the servo commands - does the output correspond to the movement you're seeing?

Do the GPS position fixes alter when the jitter occurs? If so, is the servo jitter being correctly calculated from the GPS jitter?

Yes, the output on the serial monitor corresponds to the movement. This is what I get in the serial monitor throughout about 30 seconds.. in that time, the servo moves about once a second.

LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=206 SENTENCES=1 CSUM ERR=0
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=548 SENTENCES=3 CSUM ERR=0
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=963 SENTENCES=5 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=1235 SENTENCES=7 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=1507 SENTENCES=9 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=1779 SENTENCES=11 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=2172 SENTENCES=12 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=2499 SENTENCES=15 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=2771 SENTENCES=17 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=3043 SENTENCES=19 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=3315 SENTENCES=21 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=3763 SENTENCES=23 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=4035 SENTENCES=25 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=4307 SENTENCES=27 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=4579 SENTENCES=29 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=4851 SENTENCES=31 CSUM ERR=1
LAT=42.241939 LON=-83.009277 SAT=6 PREC=190 distance is greater 60.00 course is case 2 39.00 CHARS=5299 SENTENCES=33 CSUM ERR=1

thanks for your help

  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

Using a while loop where appropriate, instead of twisting a for loop out of shape, would be a good idea.

float distanceangle;
  if (distance <= 100){
  distanceangle =int(-0.6*distance + 120);

Declare a variable of type float. Compute a float value. Cast it to an int and store in the float. I wonder why more people don't do that.

The indenting of
your code makes
it really
hard to
follow. Use the Tools + Auto Format
menu item to do something
about it.

Simplifying your output would be useful. Print millis(), distanceangle, and courseangle only. If you are not changing the value written to the servo on any given pass through loop, but the servo still moves, it is underpowered or undersized.

How are you powering the servos?

Looks to me as if the GPS input is being received on average twice a second, there was only one error, the GPS position was consistent throughout and the commanded servo angle was 39 degrees throughout.

If the servo moved during that time then either there's a problem with the servo itself (or wiring/power supply etc), or memory corruption causing the servo's internal state to be corrupted, or a timing issue preventing the Servo class from outputting the PWM pulses accurately. It seems unlikely that a timing issue would occur consistently so the third option seems unlikely. I suggest you check the free memory immediately before doing the gps.encode and see whether you're anywhere near running out. I haven't looked at the gps implementation but presumably it's got a buffer big enough to hold at least a complete sentence, so it'll be a bit of a memory hog. It's also possible that gps.encode itself uses significant stack or heap space , so unless your freeMemory check shows you have hundreds of bytes to spare I would suggest you also look under the covers of the GPS library and see whether the memory consumption is likely to be static, or changing significantly over time. (If it's changing, then your free memory checks won't tell you what the peak consumption is unless you put them INSIDE the library.)

hi:

I'm running the servos off of the 5V power supply on the Arduino. I've made the changes to code:

#include <SoftwareSerial.h>
#include "TinyGPS.h"
#include <Servo.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
 It requires the use of SoftwareSerial, and assumes that you have a
 4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
 */

Servo panservo;
Servo tiltservo;

TinyGPS gps;
SoftwareSerial ss(3, 4);

float dest_latitude =42.24707;
float dest_longitude =-83.00085;
float distance;
float distanceangle;

void setup()
{
  Serial.begin(115200);
  ss.begin(9600);

  panservo.attach(9);
  tiltservo.attach(10);
  Serial.print("Simple TinyGPS library v. "); 
  Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // For one second we parse GPS data and report some key values
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
 Serial.print("Millis() is ");
 Serial.print(millis());  
  }
    
  }

  
  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
 


    float distance = (TinyGPS::distance_between(flat, flon, dest_latitude, dest_longitude ));
    float distanceangle;
    if (distance <= 100){
      distanceangle =int(-0.6*distance + 120);
      Serial.print(" distance is less");
      Serial.print( distanceangle);
      tiltservo.write(distanceangle);
    }

    else {
      distanceangle = 60;
      Serial.print(" distance is greater ");
      Serial.print( distanceangle);
      tiltservo.write(distanceangle);
    }

    float course =  (TinyGPS::course_to(flat, flon, dest_latitude, dest_longitude ));
    float courseangle;
    if (270 <= course && course <= 360){
      courseangle = int(-course + 450);
      Serial.print (" course is case 1 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);

    }
    else if (0 <= course && course <= 90){
      courseangle = int(-course + 90);
      Serial.print (" course is case 2 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);

    }
    else if (90 < course && course < 180){
      courseangle = 0;
      Serial.print (" course is case 3 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);


    }

    else if (180 <= course && course < 270){
      courseangle = 180;
      Serial.print (" course is case 4 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);

    }

  }


}

This is what I'm getting in the Serial monitor:
Millis() is 150
Millis() is 159
Millis() is 166
Millis() is 174
Millis() is 182
Millis() is 190
Millis() is 198
Millis() is 206
etc...

The distanceangle and courseangle values have not changed.

Thanks

rdeans

rdeans:
I'm running the servos off of the 5V power supply on the Arduino.

I suspect that's your problem then.

thanks..

what power supply should I run the servos off of?

rdeans:
thanks..
what power supply should I run the servos off of?

External at ~6v.

This is what I'm getting in the Serial monitor:

That's a little hard to believe. That means that you are getting, parsing and using a complete sentence from the GPS approximately every 8 milliseconds, at 9600 baud, or 125 per sentences per second. I don't believe that that is the case.

PaulS:
That means that you are getting, parsing and using a complete sentence from the GPS approximately every 8 milliseconds, at 9600 baud, or 125 per sentences per second.

No, it doesn't mean that. It means that a single character is being received in that time - which is credible.

No, it doesn't mean that.

The Serial.print() statements are inside the if(gps.decode(c)) block, which, according to the comment, returns true only when the end of sentence marker arrives. So, that looks to me like they should happen only when the $ at the end of the NMEA sentence arrives.

Never mind. I went back and looked at the code. I assumed some curly braces that were not really there.

OP: I wanted you to print the time only when you got a complete sentence, so we could see how long that was taking.

It's a good idea to always use curly braces, so that you can add code to a block (or not), and it is clear that the code is (or is not) part of a block.

Yes, missing curly braces is right up there with poor indentation on my list of dislikes.

Hi all:

Thanks for your help. What kind of external 6V power source should I use - a battery? If so, how would I connect it to the servos (including grounds).

Thanks again

rdeans

rdeans:
Hi all:

Thanks for your help. What kind of external 6V power source should I use - a battery? If so, how would I connect it to the servos (including grounds).

Thanks again

rdeans

Four 1.5v batterys in series can be used.

Hi:

I'm in Grade 10 and I don't have much experience with engineering or arduino. How would I specifically hook up the servos and arduino? For example, how would I connect the 4 x 1.5 V batteries to the servo, and how would I establish a common ground for the arduino and servos.

Thanks for your help

Have a look at the pic I've attached....

Three things need to happen:

Arduino still gets its power which ever way suits you, eg from its USB or barrel
Servo gets its power from those batteries, straight into its red and black
The common ground joins servo black to Arduino ground: without that the signal on the yellow from Arduino pin to servo has no "0" and so its level has no meaning.

I just showed this with breadboard, but of course you can hang this together any way that works for you.

thanks so much... everything's clear :smiley:

Hi:
I've bought this battery holder and have connected it to the servo as in zoomkat's picture.
http://www.thesource.ca/estore/product.aspx?language=en-CA&catalog=Online&category=BatteryAccessories&product=2700409

However: the servos are still not staying at the right location. Even the tilt servo is moving from the correct degree to about 180 degrees and back again. I think the problem must be in the code because the batteries seem to make no difference. I wrote a similar program to just move the servo to a position - the program worked perfectly, there were no jitters - the servos held their correct position.
Here is the "similar code"

#include <Servo.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/

Servo panservo;
Servo tiltservo;


float dest_latitude =42.24707;
float dest_longitude =-83.00085;
float distance =50;
float distanceangle;
float course = 50;
float courseangle;

void setup()
{
  Serial.begin(115200);
 
  
  panservo.attach(9);
  tiltservo.attach(10);
 
}

void loop()
{
 
  if (distance <= 100){
  distanceangle =int(-0.6*distance + 120);
Serial.print(" distance is less");
 Serial.print( distanceangle);
 tiltservo.write(distanceangle);
}

else {
  distanceangle = 60;
 Serial.print(" distance is greater ");
  Serial.print( distanceangle);
  tiltservo.write(distanceangle);
}


if (270 <= course && course <= 360){
  courseangle = int(-course + 450);
  Serial.print (" course is case 1 ");
  Serial.print ( courseangle);
  panservo.write(courseangle);
  
}
else if (0 <= course && course <= 90){
courseangle = int(-course + 90);
  Serial.print (" course is case 2 ");
  Serial.print ( courseangle);
   panservo.write(courseangle);
  
}
else if (90 < course && course < 180){
courseangle = 0;
  Serial.print (" course is case 3 ");
  Serial.print ( courseangle);
   panservo.write(courseangle);
     

}

else if (180 <= course && course < 270){
courseangle = 180;
  Serial.print (" course is case 4 ");
  Serial.print ( courseangle);
   panservo.write(courseangle);
   
}
}

It seems as if when one servo is working, the other one will jitter.

Here is the code:

#include <SoftwareSerial.h>
#include "TinyGPS.h"
#include <Servo.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
 It requires the use of SoftwareSerial, and assumes that you have a
 4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
 */

Servo panservo;
Servo tiltservo;

TinyGPS gps;
SoftwareSerial ss(3, 4);

float dest_latitude =42.24129;
float dest_longitude =-83.00351;
float distance;
float distanceangle;

void setup()
{
  Serial.begin(115200);
  ss.begin(9600);

  panservo.attach(9);
  tiltservo.attach(10);
  Serial.print("Simple TinyGPS library v. "); 
  Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // For one second we parse GPS data and report some key values
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(" SAT=");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" PREC=");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
    Serial.print("Millis is");
    Serial.print(millis());
    
    
    float distance = (TinyGPS::distance_between(flat, flon, dest_latitude, dest_longitude ));
    float distanceangle;
    float course =  (TinyGPS::course_to(flat, flon, dest_latitude, dest_longitude ));
    float courseangle;
    
    if (distance <= 100){
      distanceangle =int(-0.6*distance + 120);
      Serial.print(" distance is less");
      Serial.print( distanceangle);
      tiltservo.write(distanceangle);
    }

    else {
      distanceangle = 60;
      Serial.print(" distance is greater ");
      Serial.print( distanceangle);
      tiltservo.write(distanceangle);
    }

   
    if (270 <= course && course <= 360){
      courseangle = int(-course + 450);
      Serial.print (" course is case 1 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);

    }
    else if (0 <= course && course <= 90){
      courseangle = int(-course + 90);
      Serial.print (" course is case 2 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);

    }
    else if (90 < course && course < 180){
      courseangle = 0;
      Serial.print (" course is case 3 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);


    }

    else if (180 <= course && course < 270){
      courseangle = 180;
      Serial.print (" course is case 4 ");
      Serial.print ( courseangle);
      panservo.write(courseangle);

    }

  }
  gps.stats(&chars, &sentences, &failed);
  Serial.print(" CHARS=");
  Serial.print(chars);
  Serial.print(" SENTENCES=");
  Serial.print(sentences);
  Serial.print(" CSUM ERR=");
  Serial.println(failed);


}

Thanks for your help

rdeans

And this is what i get in the serial monitor

And here is what I get in the Serial monitor

LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is1041 distance is greater 60.00 course is case 3 0.00 CHARS=128 SENTENCES=1 CSUM ERR=0
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is2148 distance is greater 60.00 course is case 3 0.00 CHARS=470 SENTENCES=2 CSUM ERR=1
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is3219 distance is greater 60.00 course is case 3 0.00 CHARS=976 SENTENCES=5 CSUM ERR=2
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is4229 distance is greater 60.00 course is case 3 0.00 CHARS=1254 SENTENCES=7 CSUM ERR=2
LAT=42.241939 LON=-83.009376 SAT=8 PREC=110Millis is5239 distance is greater 60.00 course is case 3 0.00 CHARS=1530 SENTENCES=9 CSUM ERR=2
LAT=42.241939 LON=-83.009376 SAT=8 PREC=110Millis is6249 distance is greater 60.00 course is case 3 0.00 CHARS=1806 SENTENCES=11 CSUM ERR=2
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is7296 distance is greater 60.00 course is case 3 0.00 CHARS=2152 SENTENCES=12 CSUM ERR=2
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is8368 distance is greater 60.00 course is case 3 0.00 CHARS=2534 SENTENCES=14 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is9378 distance is greater 60.00 course is case 3 0.00 CHARS=2812 SENTENCES=16 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is10388 distance is greater 60.00 course is case 3 0.00 CHARS=3090 SENTENCES=18 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is11398 distance is greater 60.00 course is case 3 0.00 CHARS=3368 SENTENCES=20 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is12421 distance is greater 60.00 course is case 3 0.00 CHARS=3839 SENTENCES=22 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is13431 distance is greater 60.00 course is case 3 0.00 CHARS=4130 SENTENCES=24 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is14441 distance is greater 60.00 course is case 3 0.00 CHARS=4408 SENTENCES=26 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is15451 distance is greater 60.00 course is case 3 0.00 CHARS=4686 SENTENCES=28 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is16461 distance is greater 60.00 course is case 3 0.00 CHARS=4964 SENTENCES=30 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is17471 distance is greater 60.00 course is case 3 0.00 CHARS=5448 SENTENCES=32 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is18481 distance is greater 60.00 course is case 3 0.00 CHARS=5726 SENTENCES=34 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is19491 distance is greater 60.00 course is case 3 0.00 CHARS=6004 SENTENCES=36 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is20501 distance is greater 60.00 course is case 3 0.00 CHARS=6282 SENTENCES=38 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is21511 distance is greater 60.00 course is case 3 0.00 CHARS=6560 SENTENCES=40 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is22521 distance is greater 60.00 course is case 3 0.00 CHARS=7046 SENTENCES=42 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=8 PREC=140Millis is23532 distance is greater 60.00 course is case 3 0.00 CHARS=7322 SENTENCES=44 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is24542 distance is greater 60.00 course is case 3 0.00 CHARS=7600 SENTENCES=46 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is25552 distance is greater 60.00 course is case 3 0.00 CHARS=7878 SENTENCES=48 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is26563 distance is greater 60.00 course is case 3 0.00 CHARS=8156 SENTENCES=50 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is27573 distance is greater 60.00 course is case 3 0.00 CHARS=8642 SENTENCES=52 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is28583 distance is greater 60.00 course is case 3 0.00 CHARS=8920 SENTENCES=54 CSUM ERR=3
LAT=42.241939 LON=-83.009376 SAT=9 PREC=110Millis is29594 distance is greater 60.00 course is case 3 0.00 CHARS=9198 SENTENCES=56 CSUM ERR=3