Problem: Servo-motor jumps between ordered angle and 180 degree

Hello again guys!

I have a problem with my servo-motor:

i give it the order to go to an angle of f.e. 90 degrees (and, with the help of an delay, stay there). instead of doing this, the servo keeps jumping between the angle i want (f.e. 90 degrees, tried it with other ones too) and 180 degrees. the code is embedded in an larger code (geocaching-box), the board has other components (LCD, GPS, ect…).

i tried the code-elements i used for the servo in an extra sketch and it worked fine… if i embed it in the whole code it shows the problems.

also i dont think it has something to do with too less power coming from the arduino for all the components or so, because the programm keeps running (tested with batterie/or usb) when the servo do its crazy dance.

also tried different pins… is it possible that the pin switches to HIGH/LOW inbetween and that causes the 180 degrees?

#include <LiquidCrystal.h>
#include <Math.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <EEPROM.h>
#include <Servo.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
SoftwareSerial gpsSerial(2, 3);
TinyGPS gps;
Servo servoschloss;

float lat,lon;
float latdest, londest;
float dist = 0;
int versuch;
int done;
int i=0;

void setup() {

pinMode(8, OUTPUT);
digitalWrite(8,LOW);
lcd.begin(16, 2);
Serial.begin(4800);
gpsSerial.begin(4800);
servoschloss.attach(13);
}

void loop() {

Serial.println(digitalRead(13)); //debugging… :confused:
servoschloss.write(90);
Serial.println(digitalRead(13)); //…
delay(5000);

done=EEPROM.read(9);
versuch=EEPROM.read(8);

if(versuch>=20){ //wenn Versuch größer 20, dann SHUTDOWN
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(“Too much”);
lcd.setCursor(0, 1);
lcd.print(“attempts.”);
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(“System is”);
lcd.setCursor(0, 1);
lcd.print(“shutting down…”);
delay(5000);
digitalWrite(8,HIGH);
} .

code is longer, but the programm goes into the IF-clause and ends there with a shutdown. everything works fine, just the servo doesnt keep the position for the whole time but jumps … :frowning:

anyone have an idea what to do??

thanks a lot!! :slight_smile:

versuch=EEPROM.read(8); Strangely, MY Arduino doesn't have a smiley face address in EEPROM. Clearly you didn't read the posts at the top of the forum. Do so now, and fix your post.

but the programm goes into the IF-clause and ends there with a shutdown

Not with the code you incorrectly posted.

http://snippets-r-us.com is where you need to go.

#include <LiquidCrystal.h>
#include <Math.h>
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <EEPROM.h>
#include <Servo.h>

//EEPROM: 0=Zielkoordinate1, 4=Zielkoordinate2, 8=Anzahl Versuche, 9=Rätsel gelöst j/n

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);   	//LCD-Objekt PINs zuordnen
SoftwareSerial gpsSerial(2, 3); 		//create gps sensor connection
TinyGPS gps;
Servo servoschloss;					

float lat,lon; 					// Latitude und Longitude des aktuellen Standorts -> Var-Typ long v. Libary vorgegeben
float latdest, londest;                                   // Latitude und Longitude des Ziels			
float dist = 0;					// Distanz zur Zielkoordinate
int versuch;
int done;
int i=0;


void setup() {

   pinMode(8, OUTPUT);
   digitalWrite(8,LOW);
lcd.begin(16, 2);
Serial.begin(4800); 				//Serielle Verbindung starten
gpsSerial.begin(4800); 				//GPS seriell verbinden
servoschloss.attach(13);
}

void loop() {
  Serial.println(digitalRead(13));  //!!!!!!!!!
  servoschloss.write(90);
   Serial.println(digitalRead(13));   //!!!!!!!!!
delay(5000);
  done=EEPROM.read(9);
versuch=EEPROM.read(8);
 if(versuch>=90){ //wenn Versuch größer 20, dann SHUTDOWN
      lcd.clear(); 
      lcd.setCursor(0, 0);				
      lcd.print("Too much");
      lcd.setCursor(0, 1);
      lcd.print("attempts.");
      delay(5000);
      lcd.clear(); 
      lcd.setCursor(0, 0);				
      lcd.print("System is");
      lcd.setCursor(0, 1);
      lcd.print("shutting down...");
      delay(5000);
      digitalWrite(8,HIGH);
    } 
      
      
  if(done==0){
                                      //SERVO ZU
    versuch=versuch+1;
    EEPROM.write(8,versuch);
    
    lcd.clear(); 
    lcd.setCursor(0, 0);				
    lcd.print("Attempt ");
    lcd.print(versuch);
    lcd.print(" of 20");
    delay(5000);
    
    
   
      
    getgps();           
    
    // latdest=EEPROMReadlong(0);  FLOAT!!!!
    // londest=EEPROMReadlong(4); 

    dist=acos(sin(latdest*PI/180)*sin(lat*PI/180)+cos(latdest*PI/180)*cos(lat*PI/180)*cos(lon*PI/180-londest*PI/180))*6378.137;
    
    Serial.println();
    Serial.print("latdest: " ); Serial.println(latdest);
    Serial.print("londest: "); Serial.println(londest);
    Serial.print("lat: "); Serial.println(lat,100);
    Serial.print("lon: "); Serial.println(lon,100);
    Serial.print("dist: "); Serial.println(dist);
    Serial.print("versuch: "); Serial.println(versuch);
    Serial.print("done: ");Serial.println(done);
  
    if(dist>0.5){  
      lcd.clear();                                  
      lcd.setCursor(0, 0);
      lcd.print("Entfernung zum");
      lcd.setCursor(0, 1);
      lcd.print("Ziel: " );
      lcd.print(dist);
      lcd.print("km" );
    
      delay(10000);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Access denied.");
      delay(5000);
      Serial.print("ungelöster Pfad, Rätsel nicht gelöst");  
      lcd.clear(); 
      lcd.setCursor(0, 0);								
      lcd.print("System is");
      lcd.setCursor(0, 1);
      lcd.print("shutting down...");
      delay(5000);
      digitalWrite(8,HIGH);
    }
    
    done=1;      
    // EEPROM WRITE done
    lcd.clear();                                  
    lcd.setCursor(0, 0);
    lcd.print("Objective");
    lcd.setCursor(0, 1);
    lcd.print("accomplished! n1" );
    delay(10000);
    //SERVO AUF
    Serial.print("ungelöster Pfad, Rätsel gelöst");
    lcd.clear();                                  
    lcd.setCursor(0,0);
        lcd.print("System is");
      lcd.setCursor(0, 1);
      lcd.print("shutting down...");
      delay(5000);
      digitalWrite(8,HIGH);
    
    
  
  delay(50000);
  }
    //----gelöster Pfad
  //SERVO AUF
  getgps();
  lcd.clear();                                 
    lcd.setCursor(0,0);
    lcd.print("neues Ziel?" );                   
    delay(10000);
  
  //wenn taster gedrückt, dann neues ziel festlegen
  //alle daten zurücksetzen
  lcd.clear();                                  
    lcd.setCursor(0,0);
        lcd.print("System is");
      lcd.setCursor(0, 1);
      lcd.print("shutting down...");
      delay(5000);
      digitalWrite(8,HIGH);
  
   
  

delay(50000);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void EEPROMWritelong(int address, long value)
      {
      //Decomposition from a long to 4 bytes by using bitshift.
      //One = Most significant -> Four = Least significant byte
      byte four = (value & 0xFF);
      byte three = ((value >> 8) & 0xFF);
      byte two = ((value >> 16) & 0xFF);
      byte one = ((value >> 24) & 0xFF);

      //Write the 4 bytes into the eeprom memory.
      EEPROM.write(address, four);
      EEPROM.write(address + 1, three);
      EEPROM.write(address + 2, two);
      EEPROM.write(address + 3, one);
      }

//This function will return a 4 byte (32bit) long from the eeprom
//at the specified address to adress + 3.

long EEPROMReadlong(long address)
      {
      long four = EEPROM.read(address);
      long three = EEPROM.read(address + 1);
      long two = EEPROM.read(address + 2);
      long one = EEPROM.read(address + 3);

      return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
      
      }
      
void getgps(){
  lcd.clear(); 
  lcd.setCursor(0, 0);				// LCD "Searching for signal.."
  lcd.print("Searching");
  lcd.setCursor(0, 1);
  lcd.print("for signal..");

  do{
  while(gpsSerial.available()){ 			// check for gps data
    if(gps.encode(gpsSerial.read())){ 		// encode gps data
    gps.f_get_position(&lat,&lon); 		// get latitude and longitude
    }}
   // lat=554433221;                                  //Behelf: Zuweisung akt. Koordinaten
   // lon=123456789;
    Serial.print(".");
    i=i++;
     Serial.println(digitalRead(10));   //!!!!!!!!
    if(i>=2000){
      lcd.clear();                                  
    lcd.setCursor(0,0);
        lcd.print("Cannot find");
      lcd.setCursor(0, 1);
      lcd.print("signal...");
      delay(5000);
      lcd.clear();                                  
    lcd.setCursor(0,0);
        lcd.print("System is");
      lcd.setCursor(0, 1);
      lcd.print("shutting down...");
      delay(5000);
      digitalWrite(8,HIGH);
    }
      
} while(lat==0); 
}

If the servo is powered from the Arduino 5v pin that may be the cause of the problem. Servos (and all motors) should have their own power supply with the servo GND connected to the Arduino GND.

…R

Will it stay at 90 degrees if you run this? If not see Robin2 post

void loop() {

Serial.println(digitalRead(13)); //debugging... :/ servoschloss.write(90); Serial.println(digitalRead(13)); //...... delay(5000); }

PS What do you expect as output doing this Serial.println(digitalRead(13)); //debugging... :/ ??

Very simple servo test code for use with the serial monitor.

//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
    myservo.write(n);
    readString="";
  } 
}

jep, if i use the same hardware (means included LCD etc) and run the sketch u posted, the servo works nice. tried this before - thats why i hope that it has nothing to do with the energy-supply. but i will try to rebuild it tomorrow (extra supply 4 servo and so on) an will see wheater it works.

and i will try the servo-test-code from zoomkat immediately.

so.. with the zoomkat-code the servo works. cant say, whether the possitions are 100% correct, but it goes to the angle and stays there. LCD and GPS and stuff are supplied with energy, so can this really be a problem? and as i said, when i run the arduino with the battery, the servo was going mad, but the programm just continued without problems.

and as i said, when i run the arduino with the battery, the servo was going mad, but the programm just continued without problems.

That is usually associated with a poor ground between the arduino ground and the servo power supply ground.

servo-wire.jpg

i tried two things:
a) the batterie supplied the arduino and i connected the servo to the batterie too, instead of the 5v Pin of the arduino (see picture)

b) i connected the arduino via usb and only the servo with the battery (so just the signal-cable was connected to arduino).

in both cases the servo showed the same problems…

did i do the connection false? if so, picture would be helpful :).

tested the 9V battery directly with an 12V motor and the multimeter showed 8,3V… guess batterie is not the problem?!

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png or pdf? Where does the blue wire go on the arduino?

Thankyou..Tom....... :)

tested the 9V battery directly with an 12V motor and the multimeter showed 8,3V.. guess batterie is not the problem?!

Guess again. A 9V PPV battery is a great thing. For the battery manufacturer that charges more for less for that style battery than ANY other style of battery.

Put that useless piece of crap back in the smoke detector you stole it from and get a real battery.

what kind of battery do i need in your opinion? 9V seems to be enough for the servo, according to all the servo-tutorials. i just want the servo to run correctly, not improve the whole system. could the battery really cause the problem? then i of course try to get another one.

-> and the battery can supply the servo when it runs in a "just-servo-sketch" without problems, why sould there be a problem now, when all the other devices are supplied by the arduino and the servo again with the battery?

and @tom, the blue cable goes to the connector from the arduino. and i also linked the ground from arduino&servo with the battery.

9V seems to be enough for the servo, according to all the servo-tutorials. i just want the servo to run correctly,

It is not the voltage that is the problem, it is the ability of the battery to provide current at that voltage for a reasonable time.

Try 4 AA batteries in series. Only 5 or 6 volts (depending on the battery type), but much more current capacity. Better still 6 AA batteries in series.

finally, i crafted 6 AA (each 1,5V) batteries together and used it for the servo. the arduino run via usb. same result, the servo switches the angles :(.

Aznagro: finally, i crafted 6 AA (each 1,5V) batteries together and used it for the servo. the arduino run via usb. same result, the servo switches the angles :(.

Draw the wiring diagram as you have been requested and post a photo of it here.

...R

something happend: while reducing the code step by step i realized, that the problem is the following code-fragment:

gpsSerial.begin(4800);

if i erase just these line, the servo works fine!!! so finally there is something in the library of the TinyGPS that disturbs the servo?! also tried TinyGPS++, but have the same problem, guess the library is nearly equal.

any chance for me to get this running with the tinygps and some changings? cant find annother programm as compact/easy as the tinygps… :confused:

ps: drawing already nessesary? there are so much cables… Oo

attached the library-code

#ifndef TinyGPS_h

#define TinyGPS_h


#if defined(ARDUINO) && ARDUINO >= 100

#include "Arduino.h"

#else
#include "WProgram.h"

#endif


#include <stdlib.h>


#define _GPS_VERSION 13 // software version of this library

#define _GPS_MPH_PER_KNOT 1.15077945

#define _GPS_MPS_PER_KNOT 0.51444444

#define _GPS_KMPH_PER_KNOT 1.852

#define _GPS_MILES_PER_METER 0.00062137112

#define _GPS_KM_PER_METER 0.001
// 
#define _GPS_NO_STATS

class TinyGPS
{
public:
  enum {
    GPS_INVALID_AGE = 0xFFFFFFFF,      GPS_INVALID_ANGLE = 999999999, 
    GPS_INVALID_ALTITUDE = 999999999,  GPS_INVALID_DATE = 0,
    GPS_INVALID_TIME = 0xFFFFFFFF,		 GPS_INVALID_SPEED = 999999999, 
    GPS_INVALID_FIX_TIME = 0xFFFFFFFF, GPS_INVALID_SATELLITES = 0xFF,
    GPS_INVALID_HDOP = 0xFFFFFFFF
  };


  static const float GPS_INVALID_F_ANGLE, GPS_INVALID_F_ALTITUDE, GPS_INVALID_F_SPEED;

  

TinyGPS();
  
bool encode(char c); // process one character received from GPS
  
TinyGPS &operator << (char c) {encode(c); return *this;}

  // lat/long in MILLIONTHs of a degree and age of fix in milliseconds
  // (note: versions 12 and earlier gave lat/long in 100,000ths of a degree.
  

void get_position(long *latitude, long *longitude, unsigned long *fix_age = 0);

  // date as ddmmyy, time as hhmmsscc, and age in milliseconds
  
void get_datetime(unsigned long *date, unsigned long *time, unsigned long *age = 0);

  // signed altitude in centimeters (from GPGGA sentence)
  

inline long altitude() { return _altitude; }

  // course in last full GPRMC sentence in 100th of a degree
  
inline unsigned long course() { return _course; }

  // speed in last full GPRMC sentence in 100ths of a knot
  
inline unsigned long speed() { return _speed; }

  // satellites used in last full GPGGA sentence
  
inline unsigned short satellites() { return _numsats; }

  // horizontal dilution of precision in 100ths
  
inline unsigned long hdop() { return _hdop; }

  

void f_get_position(float *latitude, float *longitude, unsigned long *fix_age = 0);
  
void crack_datetime(int *year, byte *month, byte *day, 
    byte *hour, byte *minute, byte *second, byte *hundredths = 0, unsigned long *fix_age = 0);


float f_altitude();
  
float f_course();
  
float f_speed_knots();
  
float f_speed_mph();
 
float f_speed_mps();
  
float f_speed_kmph();

  

static int library_version() { return _GPS_VERSION; }

  
static float distance_between (float lat1, float long1, float lat2, float long2);
  
static float course_to (float lat1, float long1, float lat2, float long2);
  
static const char *cardinal(float course);



#ifndef _GPS_NO_STATS
  
void stats(unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs);

#endif

private:
  enum {_GPS_SENTENCE_GPGGA, _GPS_SENTENCE_GPRMC, _GPS_SENTENCE_OTHER};

  // properties
  

unsigned long _time, _new_time;
  
unsigned long _date, _new_date;
  
long _latitude, _new_latitude;
  
long _longitude, _new_longitude;
  
long _altitude, _new_altitude;
  
unsigned long  _speed, _new_speed;
  
unsigned long  _course, _new_course;
  
unsigned long  _hdop, _new_hdop;
  
unsigned short _numsats, _new_numsats;

  
unsigned long _last_time_fix, _new_time_fix;
  
unsigned long _last_position_fix, _new_position_fix;

  // parsing state variables
  
byte _parity;
  
bool _is_checksum_term;
  
char _term[15];
  
byte _sentence_type;
  
byte _term_number;
  
byte _term_offset;
  
bool _gps_data_good;



#ifndef _GPS_NO_STATS
  // statistics
  
unsigned long _encoded_characters;
  
unsigned short _good_sentences;
  
unsigned short _failed_checksum;
  
unsigned short _passed_checksum;

#endif

  // internal utilities
  

int from_hex(char a);
  
unsigned long parse_decimal();
  
unsigned long parse_degrees();
  
bool term_complete();
  
bool gpsisdigit(char c) { return c >= '0' && c <= '9'; }
  long gpsatol(const char *str);
  
int gpsstrcmp(const char *str1, const char *str2);
};


#if !defined(ARDUINO) 
// Arduino 0012 workaround

#undef 
int
#undef 
char
#undef 
long
#undef 
byte
#undef 
float
#undef 
abs
#undef round 

#endif


#endif

Try using an alternative Servo library such as this one download ServoTimer2 library

good idea, but same problem. the servo-code works, but putting gpsSerial.begin(4800); inside disturbs the servo.

but the library it depends on isnt the tinygps, right? seems to be the SoftwareSerial.h. maybe i find an alternative for these..

UPDATE: its the softwareserial.h -> changed to AltSoftSerial.h and now the servo works, even when gpsSerial.begin(4800); is in.

now my GPS doesnt send signals (because of AltSoftSerial), but thats another question. Thanks so far.