Tank project

Hi!
I am rebuilding an R/C tank and I’m working on some code for it.
You can find my notes at my website here: www.mikaelmadsen.dk/tank_project

I’m trying make a program that pans a servo from 0 to 180 degrees. On the servo (tower) I have a sensor.
When the sensor gets a HIGH reading I want the servo to DELAY for 2 seconds while it does that I need a DC motor to be activated. and then the SERVO should pan again until next reading.

The program below gives my servo some strange movements. The servo I’m using is an TowerPro MG995

What am I doing wrong in this code?

Thanks in advance.

/* Tank driver
*
*/

int servoPin = 2; // servo connected to digital pin 2
int servoAngle; // angle of the servo roughly 0-180
int pulseWidth; // servoPulse function variable

int targetPin = 3; // target sensor
int val = 0; // variable to store the value coming from the sensor

int gunnerPin = 4; // output to gunner (motor)

//-------------------------------------------------------

void setup()
{
pinMode(servoPin, OUTPUT); // sets pin 2 as output
pinMode(targetPin, INPUT); // sets pin 3 as input
pinMode(gunnerPin, OUTPUT); // sets pin 4 as output
}

//-------------------------------------------------------

// (This section controls the servo)

void servoPulse(int servoPin, int servoAngle)
{
pulseWidth = (servoAngle * 10) + 600; // determines delay
digitalWrite(servoPin, HIGH); // set servo high
delayMicroseconds(pulseWidth); // microsecond pause
digitalWrite(servoPin, LOW); // set servo low
}

void loop()
{
// servo starts at 10 deg and rotates to 170 deg
for (servoAngle=10; servoAngle<=170; servoAngle++)
{
servoPulse(servoPin, servoAngle); // send pin and angle
delay (20); // refresh cycle
}
// servo starts at 170 deg and rotates to 10 deg
for (servoAngle=170; servoAngle>=10; servoAngle–)
{
servoPulse(servoPin, servoAngle); // send pin and angle
delay (20); // refresh cycle
}

//------------------------------------------------------

// Read targetPin and starts gunnerPin if value is high

val = digitalRead(targetPin); // read input value and store it in val
if (val == HIGH) { // check if the sensor is high
digitalWrite(gunnerPin, HIGH); // turns gunner on
delay (5000);
}
}

Hi Drake, the sketch as posted should rotate the turret slowly in one direction for around 3 seconds and back in the other direction for 3 seconds. It then sets the gunnerPin HIGH for 5 seconds. But it does not set it low again so every loop after it has been set the pin will remain high.

So you should digitalWrite the pin low after the delay and you may want to change the delay(5000) to delay (2000) if two seconds is what you want.

You don't say what the strange servo movement are, but the turret will jerk into the 10 degree position when it starts up if the servo was not near the 10 degree position when the Arduino was reset or switched off. I can't think of a simple way to fix that because the servo does not provide position feedback back to the Arduino. You can avoid this by never shutting off when the turret is moving. But if that is not acceptable, then a pot attaced to the turret could provide position feedback so you could slowly move from the actual position at startup to the desired position.

Another issue could be that your pulse widths are a little extreme for your servo, they range from 700us to 2300us. If your servo buzzes at either extreme of movement, increase the minimum and/or maximum angle (or change the pulse width calculation) . 1000us to 2000us may be a safer range to start with and you can increase it if your servo can cope.

anyway, enough guessing. if the suggestions above don't address your problem please do say what it is.