Adding servo to rover

I have the rover with Bluetooth. I would like to add a servo and a ping sensor to the front. I tried attaching the servo to pin 9 and uploading the sketch below to get the servo to turn left and then right on the keypress ‘e’ or ‘q’. The servo jumps when the rover is turned on but when I press ‘e’ or ‘q’ the servo does nothing. here is the code:

#include <Servo.h>
int E1 = 6; //M1 Speed Control
int E2 = 5; //M2 Speed Control
int M1 = 8; //M1 Direction Control
int M2 = 7; //M2 Direction Control
Servo servo;


void setup(void)
{
  servo.attach(9); //digital pin 9
 int i;
 for(i=5;i<=8;i++)
 pinMode(i, OUTPUT);
 Serial.begin(9600);
}
void loop(void)
{
 while (Serial.available() < 1) {} // Wait until a character is received
 char val = Serial.read();
 int leftspeed = 255; //255 is maximum speed 
 int rightspeed = 255;
 int slowspeed = 0;
 int nospeed = 0;
 switch(val) // Perform an action depending on the command
 {
 case 's'://Move Forward
 forward (leftspeed,rightspeed);
 break;
 case 'w'://Move Backwards
 reverse (leftspeed,rightspeed);
 break;
 case 'd'://Turn Left
 left (leftspeed,rightspeed);
 break;
 case 'a'://Turn Right
 right (leftspeed,rightspeed);
 break;
 case 'f': //Stop
 halt (slowspeed,nospeed);
 break;
 case 'e':
 servo.write(140);
 break;
 case 'q':
 servo.write(3);
 break;
 default:
 stop();
 break;
 } 
}
void stop(void) //Stop
{
 digitalWrite(E1,LOW);
 digitalWrite(E2,LOW);
}
void forward(char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,LOW);
 analogWrite (E2,b);
 digitalWrite(M2,LOW);}
void reverse (char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,HIGH);
 analogWrite (E2,b);
 digitalWrite(M2,HIGH);
}
void left (char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,HIGH);
 analogWrite (E2,b);
 digitalWrite(M2,LOW);
}
void right (char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,LOW);
 analogWrite (E2,b);
 digitalWrite(M2,HIGH);
}
void halt (char a, char b)
{
  analogWrite (E1,a);
  digitalWrite(M1, LOW);
  analogWrite (E2,b);
  digitalWrite(M2, LOW);
}

That’s odd… Does it happen after a the same amount of presses or when the servo is in a specific position?

I also noticed that these two lines

   if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
   if (pulseWidth < minPulse) { pulseWidth = minPulse; }

appear in the switch structure but after the last break, so they may not be executing properly. Can you try moving it below the closing brace to see if it makes a difference?

Can you try adding the following lines at the end of your for loop, after you generate the pulse?

Serial.print("Servo pulse: ");
Serial.println(pulseWidth, DEC);

I’d like to use this to determine if the movements are happening be the wrong pulses are being sent, or if the servo isn’t responding properly to the right pulses.

I’m also wondering if the way you are generating your own pulses might cause problems since they’re only being sent one per key press and not at a regular interval… Usually the Servo library continuously generates the pulses in background between 40 and 200 times per second…

You code seems good, so I would suspect that there might be a connection problem with the servo. Do you have it’s red wire connected to a 5V pin on the Arduino, it’s black/brown wire to a GND pin, and it’s signal (yellow, orange, white) wire connected to pin 9? If so, you might want to double-check for loose connections.

You can also confirm your code is correct by adding some debug serial output. For instance, after this line

servo.write(140)

you can do

Serial.println("case 'e' received, setting servo to 140");

and do something similar after this line

servo.write(3)

Once you recompile and upload the new code, you can open the Serial Monitor in the Arduino IDE (at a speed of 9600 kbps) and should see those messages print when you press the appropriate keys.

We hope this helps,

I see that you have made your own PWM generator (with the delayMicroseconds). Where you not able to get the servo.write() library to work properly?

I don’t know if that’s your problem, or maybe you are sending more characters than you expect and the default: condition (stop()) is being executed.

Maybe you can add these lines between the default: and stop() lines

Serial.print("Other character: ");
Serial.println(val);

And then you can check the serial console to see if extra characters are being received.

Hope this helps,

Glad to hear you got it working!

I’m wondering now if your microcontroller might be resetting if your servo is consuming too much power. What model servo are you using?

Also, you can try adding add the following line after your Serial.begin() line in the setup() function:

Serial.println("End of setup() function.");

Using the Serial Monitor, you should be able to check if that line appears when you are adjusting the servo and the rover stops moving. Please let us know if that’s the case.

If so, then we know it’s a power problem. You can either change your servo for a more efficient one, or add a second battery for the servo specifically.

I did end up adding another battery but the servo is getting confused on the key press. If I push ‘e’ sometimes the servo will go the opposite direction.

The servo is still getting confused… it basically moves on any keypress and will move whatever direction it feels like

ok, I changed my code a little to get what I truly want out of the servo and I’m running into another issue. When communicating through Bluetooth I have the rover moving forward and then try turning the servo. This causes the rover to stop moving forward to allow the servo to turn. any ideas? here is the sketch:

#include <Servo.h>
int E1 = 6; //M1 Speed Control
int E2 = 5; //M2 Speed Control
int M1 = 8; //M1 Direction Control
int M2 = 7; //M2 Direction Control
Servo servo;
int servoPin = 9;
int minPulse = 900;
int maxPulse = 2100;
int turnRate = 100;
int refreshTime = 20;
int centerServo = 90 ;
int pulseWidth;
int moveServo;
long lastPulse = 0;


void setup(void)
{
 pinMode(servoPin, OUTPUT);
  centerServo = maxPulse - ((maxPulse - minPulse)/2);
  pulseWidth = centerServo; 
 int i;
 for(i=5;i<=8;i++)
 pinMode(i, OUTPUT);
 Serial.begin(9600);
}
void loop(void)
{
 while (Serial.available() < 1) {} // Wait until a character is received
 char val = Serial.read();
 int leftspeed = 255; //255 is maximum speed 
 int rightspeed = 255;
 int slowspeed = 0;
 int nospeed = 0;
 switch(val) // Perform an action depending on the command
 {
 case 'w'://Move Forward
 forward (leftspeed,rightspeed);
 break;
 case 's'://Move Backwards
 reverse (leftspeed,rightspeed);
 break;
 case 'a'://Turn Left
 left (leftspeed,rightspeed);
 break;
 case 'd'://Turn Right
 right (leftspeed,rightspeed);
 break;
 case 'f': //Stop
 halt (slowspeed,nospeed);
 break;
 case 'e':
 pulseWidth = pulseWidth - 100;
 break;
 case 'q':
 pulseWidth = pulseWidth + 100;
 break;
 case 'r':
 pulseWidth = centerServo;
 break;
 default:
 stop();
 break;
 if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
   if (pulseWidth < minPulse) { pulseWidth = minPulse; }
 } 
 if (millis() - lastPulse >= refreshTime) {
    digitalWrite(servoPin, HIGH);   // start the pulse
    delayMicroseconds(pulseWidth);  // pulse width
    digitalWrite(servoPin, LOW);    // stop the pulse
    lastPulse = millis();           // save the time of the last pulse
  }
}
void stop(void) //Stop
{
 digitalWrite(E1,LOW);
 digitalWrite(E2,LOW);
}
void forward(char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,LOW);
 analogWrite (E2,b);
 digitalWrite(M2,LOW);}
void reverse (char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,HIGH);
 analogWrite (E2,b);
 digitalWrite(M2,HIGH);
}
void left (char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,HIGH);
 analogWrite (E2,b);
 digitalWrite(M2,LOW);
}
void right (char a,char b)
{
 analogWrite (E1,a);
 digitalWrite(M1,LOW);
 analogWrite (E2,b);
 digitalWrite(M2,HIGH);
}
void halt (char a, char b)
{
  analogWrite (E1,a);
  digitalWrite(M1, LOW);
  analogWrite (E2,b);
  digitalWrite(M2, LOW);
}

I tried what you are saying jarcand, it receives it but still nothing. I have even tried uploading the sweep sketch found at arduino.cc/en/Tutorial/Sweep to try and troubleshoot. The servo still responds the same. It will jump when it receives power but nothing further. I also received this error when I uploaded the sweep code, any ideas?
Binary sketch size: 2,666 bytes (of a 32,256 byte maximum)
avrdude: stk500_getsync(): not in sync: resp=0x00

ok, here is what I did after the last reply. I turned the switch to the opposite xbee slot. then uploaded the code and the servo will work. I then unplugged the usb cable and connected via Bluetooth and it works but I think it is drawing too much power because the Bluetooth will disconnect and the servo will reset to center after every move. So now I will try and hook up an external power source for the servo.

sure enough, after adding a external power source of 9v with a transistor the servo works perfectly. Even over Bluetooth the servo will respond and move accordingly! hope this can at least help someone else as well

I included that into my sketch but nothing was printed. I changed my sketch for the simple fact that I wanted the servo to move right incrementally so I can mount a camera on it without it being this fast movement.

ok I will try this and then post the results. I am at work right now so it will have to be later today.