servo possition not latching

Hi Everyone, my name is shane and i am new to Arduino so sorry in advance if i ask a few trivial questions.
i am having a problem with one of my projects, i am trying to control servos with an Arduino Uno R3, i would like these servos to pull on cables in my car which control the air flow, temperature ect of my aircon (converting the bulky knobs into push buttons) so i have written a sketch which i though would work but for some reason every time i press a push button the servo moves to the set position but shortly after it moves back to its origin position. i have pasted a copy of my sketch below could someone please explain why it is doing this and how i can get it to "latch" in the last position it was instructed to move to?

#include <Servo.h>
Servo Airspeed;
int button1 = 1;
int button2 = 2;
int button3 = 3;
int button4 = 4;

void setup() {
Airspeed.attach (11);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
}

void loop() {
// put your main code here, to run repeatedly:
if (digitalRead(button1) == HIGH)
{
Airspeed.writeMicroseconds (650);
delay (1000);
}
if (digitalRead(button2) == HIGH)
{
Airspeed.writeMicroseconds (1100);
delay (1000);
}
if (digitalRead(button3) == HIGH)
{
Airspeed.writeMicroseconds (1800);
delay (1000);
}
if (digitalRead(button4) == HIGH)
{
Airspeed.writeMicroseconds (2200);
delay (1000);
}
}

How are your switches wired?

Hi AWOL

i have wired 5v from the board to each button then from the other end of each button to the digital inputs, i have 10k pull down resistors between the return wire (from button back to Arduino) and ground.

Is there any chance your board is resetting?

(BTW, please remember to use code tags when posting code)

How is the servo powered ?

It should NOT be drawing power from the Arduino board - that is likely to cause the Arduino to reset which would match your symptoms.

Give the servo a separate power supply with a common GND between it and the Arduino.

...R

the servo is being powered by a SMPS from the 5v line. i dont see the lights on the board flash as if it were resetting. sorry about the code tags i will remember for the next time, should i fix it quick? the SMPS and arduino have there GND joined.

A good way to be sure it is not resetting is to put a short Serial.println() message in setup(). It will appear everytime there is a reset.

Another option is to change your code to something like this

static int servoPos = 0;
if (digitalRead(button1) == HIGH)
{
   servoPos = 650;
}
if (digitalRead(button2) == HIGH)
{
   servoPos = 1100;
}
// etc
Serial.println(servoPos);
Airspeed.writeMicroseconds (servoPos);
delay (1000);

Writing the value to a variable gives the opportunity to see the value of the variable in case it is not what you expect.

...R

Pin 1 is one of the Serial pins. Try a different pin for your button. You might be getting false HIGH signals from the USB-to-Serial chip.

Note: 650 microseconds and 2200 microseconds are outside the normal servo control range of 1000 to 2000 microseconds. This might cause the servo to fight against its mechanical stops and overheat or strip gears.

johnwasser:
Pin 1 is one of the Serial pins.

HOW is it so easy to miss the obvious :slight_smile:

...R

I tried your new code (and extended it to 4 buttons) but only button 2 responds (and returns to the first position after 1 second). I also tried changing button one to pin 5 and i am still getting the same result, it seems like it always returns the the value that appears in the code first. I made sure that it is not resetting by changing my delay time and button one value and the servo responds accordingly. thanks for everyone's help so far. I read that normally the servo range is 1000 to 2000 but i tested this servo before i started this project and found that the minimum and maximum value before it stopped turning was around 650 and 2200.

I tried your new code (and extended it to 4 buttons) but

So, it isn't EXACTLY the same code, or exactly the same wiring. But, you choose not to share either one. Fine. Good luck.

Is the pin 1 stuff just a red herring? I don't see serial used.

Shaneloots:
I tried your new code ...

It is essential for you to keep us up-to-date with changes in your code. Please post the latest version.

...R

Sorry Robin2 this is the latest code i am using (based off your suggested code)

#include <Wire.h>
#include <Servo.h>
Servo Airspeed;
int button1 = 1;
int button2 = 2;
int button3 = 3;
int button4 = 4;

void setup() {
Airspeed.attach (11);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
static int servoPos = 0;
if (digitalRead(button1) == HIGH)
{
   servoPos = 650;
}
if (digitalRead(button2) == HIGH)
{
   servoPos = 1100;
}
if (digitalRead(button3) == HIGH)
{
   servoPos = 1800;
}
if (digitalRead(button4) == HIGH)
{
   servoPos = 2200;
}
// etc
Serial.println(servoPos);
Airspeed.writeMicroseconds (servoPos);
delay (1000);

}

this latest code behaves exactly the same as my code in the first post. i also dont get any feedback in the serial monitor.
As for the wiring it is exactly the same as the first post, i changed button one back to pin one because the servo behaved the same when using pin 5 in pin 1's place so i dont see the problem as using pin one. if you think it could still be pin one i will be happy to change it to pin 5 again.

i also dont get any feedback in the serial monitor.

Because you're using one of its pins, perhaps?

thanks AWOL i will change that quick and report back.

Thanks AWOL i just changed button one to pin 5 but still nothing on serial monitor.

my latest code is

#include <Wire.h>
#include <Servo.h>
Servo Airspeed;
int button1 = 5;
int button2 = 2;
int button3 = 3;
int button4 = 4;

void setup() {
Airspeed.attach (11);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
static int servoPos = 0;
if (digitalRead(button1) == HIGH)
{
   servoPos = 650;
}
if (digitalRead(button2) == HIGH)
{
   servoPos = 1100;
}
if (digitalRead(button3) == HIGH)
{
   servoPos = 1800;
}
if (digitalRead(button4) == HIGH)
{
   servoPos = 2200;
}
// etc
Serial.println(servoPos);
Airspeed.writeMicroseconds (servoPos);
delay (1000);

}

my wiring is as follows

button one to pin 5
button two to pin 2
button three to pin 3
button four to pin 4

all buttons have pull down resistors.

You need to tell it how fast you want the serial line to run

Thanks AWOL i sorted the serial out. these are the results i get while pushing button 1 to 4 only once each.

650
1100
1800
650
2200
650
650

my wiring is the same as the previous post and my code looks like this now.

#include <Wire.h>
#include <Servo.h>
Servo Airspeed;
int button1 = 5;
int button2 = 2;
int button3 = 3;
int button4 = 4;

void setup() {
Airspeed.attach (11);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
static int servoPos = 0;
if (digitalRead(button1) == HIGH)
{
   servoPos = 650;
}
if (digitalRead(button2) == HIGH)
{
   servoPos = 1100;
}
if (digitalRead(button3) == HIGH)
{
   servoPos = 1800;
}
if (digitalRead(button4) == HIGH)
{
   servoPos = 2200;
}
// etc
Serial.println(servoPos);
Airspeed.writeMicroseconds (servoPos);
delay (1000);

}

Thanks for your help everyone, i changed the 10k pull down resistors for 1k and now the servo behaves as intended.
my final code is as follows, feel free to use it in any way you want.

#include <Wire.h>
#include <Servo.h>
Servo Airspeed;
int button1 = 5;
int button2 = 2;
int button3 = 3;
int button4 = 4;

void setup() {
Airspeed.attach (11);
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
static int servoPos = 0;
if (digitalRead(button1) == HIGH)
{
   servoPos = 650;
}
if (digitalRead(button2) == HIGH)
{
   servoPos = 1100;
}
if (digitalRead(button3) == HIGH)
{
   servoPos = 1800;
}
if (digitalRead(button4) == HIGH)
{
   servoPos = 2150;
}
// etc
Serial.println(servoPos);
Airspeed.writeMicroseconds (servoPos);
delay (1000);

}

my wiring is as follows:
5v to the base of all buttons
Button 1 to pin 5 with a pull down resistor.
button 2 to pin 2 with a pull down resistor.
button 3 to pin 3 with a pull down resistor.
button 4 to pin 4 with a pull down resistor.
all pull down resistors are 1k ohm.

Thanks Robin2 for the more efficient code you suggested. :slight_smile: