I have a 9G Servo which I'm using to control a set of points on my model railroad. It works when first turned on, and will respond and act as expected for a while. However, after about 20 minutes or so of sitting at idle, it starts to make a faint, regular 'ticking' sound and does not respond. I have to reset the Arduino to get it to work properly.
What's going on, and how do I fix it? I'm thinking in the code, of using the attach() function just before writing to it, then the detach() function afterwards.
It is powered from the same supply as the Arduino.
Is the servo in the correct position when making the ticking sound or has it moved to the end of its movement range and is pressing against its internal end stop?
I am familiar with servos making an irritating buzzing noise at times (which can be solved by detach) but I have not experienced loss of control.
If you need more help please post your program.
What Arduino are you using?
How are the servos powered? - the should NOT be drawing power from the Arduino 5v pin.
...R
Hi,
To answer your questions:
- It's in a position where it's just against the internal end stop. It doesn't make a buzzing in either position, which I take to mean it's 'tuned' correctly. It works correctly for a while, then stops.
- I'm using a Crowduino, which is essentially an Arduino Duemilanove with a built-in XBee socket.
- I'll have to check how the servos are powered. This was an update to one of my very first Arduino projects, so it's possible it may be drawing power from the Arduino rather than from the 5v supply for it. I've got a voltage regulator board which I can install to power the Arduino and the rest of the system.
I should probably mention that the rest of the Arduino functionality works as expected when the servo is ticking - it's just the servo itself that doesn't respond.
I've tried to include my complete sketch, but most of it doesn't relate to the servo, and if I post the whole thing I get an error saying that my message is too long. As such, here are the functions that call it:
#include <ServoTimer2.h>
ServoTimer2 pointServo; //Servo for controlling point motor.
void setup() {
//Next 3 lines initialise LCD:
lcdScreen.begin(20, 4); //Set up 20x4 LCD screen
lcdScreen.setBacklightPin(3, POSITIVE);
lcdScreen.setBacklight(HIGH);
//Set up OneButton object:
contButton.attachClick(startElevator);//attach the Single Click function to this event
//Set up transmission back to base station
initSendData();
sendET.begin(details(sendPacket), &Serial);
//Set up pins - input and output
//Outputs
pinMode(elevPwr, OUTPUT);
pinMode(prmPwr, OUTPUT);
pinMode(botEntryPin, INPUT);
pinMode(pointSet, INPUT);
pinMode(prmProxTrig, OUTPUT);
pinMode(prmProxEcho, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(motPin1, OUTPUT);
pinMode(motPin2, OUTPUT);
pinMode(buzzPin, OUTPUT);
//Inputs - LDRs:
pinMode(topEntryPin, INPUT);
pinMode(elevSens, INPUT);
//Inputs - Switch:
pinMode(riseSwitch, INPUT_PULLUP);
//Analog pins don't need to be initialised. Reading analog from them.
//Set all output pins to starting state
digitalWrite(elevPwr, HIGH); //For this relay module, HIGH=off, LOW=on
digitalWrite(prmPwr, HIGH); //Same as for elevPwr
digitalWrite(prmProxTrig, LOW);
digitalWrite(motPin1, LOW);
digitalWrite(motPin2, LOW);
digitalWrite(ledPin, LOW);
digitalWrite(buzzPin, LOW); //May need to remove if buzzer doesn't work.
//Set up point motor servo & initialise
pointServo.attach(servoPin);
pointServo.write(elevPos); //Set to go to train elevator - default position
//Initialise controller data
initBaseData();
//Start serial communication
Serial.begin(38400);
//Initialise EasyTransfer object
baseET.begin(details(baseData), &Serial);
//Determine current status of system
prmDistance = getDistance();
lcdScreen.setCursor(3, 0); //Move LCD screen cursor to 2 characters in on the first line
lcdScreen.print("Staging Online");
delay(2000); //Pause for 2 seconds
updateLCD();
if (!digitalRead(riseSwitch)){
//Elevator is raised - switch is triggered. Need to move to bottom position on startup.
startElevator();
}
}
void setTrack(int track) {
/*Sets points to whichever track is specified in the argument and
turns track power on.*/
if (track == elevTrack) {
//Set points for train elevator
if (track != getPoints()) {
//if points aren't already set
pointServo.write(elevPos); //Set servo to train elevator
}
//Turn elevator track power on
digitalWrite(elevPwr, LOW);
digitalWrite(prmPwr, HIGH); //Make sure other track is turned off
}
if (track == prmTrack) {
//Set points for PRM track
if (track != getPoints()) {
//if points aren't already set
pointServo.write(prmPos); //Set servo to PRM track
}
//Turn PRM track power on
digitalWrite(prmPwr, LOW);
digitalWrite(elevPwr, HIGH); //Make sure other track is turned off
}
}
Tbdanny:
It's in a position where it's just against the internal end stop.
My cheap analog SG90 servos have an irritating feature that they move a small amount in one direction (maybe clockwise, but I'm not sure) every time they are powered up. After several successive power-ups if they are not instructed to move to a position they eventually get to their end-stop. This is not a problem with the digital versions.
I suspect the ticking is because the servo is pressing against the end stop which is not good for it - maybe a gear tooth is slipping.
You should always arrange your linkages so that in normal use the servo never gets to its end-stop.
Rather than post a program with parts excluded please make a complete short program that illustrates the problem. It is always much easier to find faults and to give advice with short programs.
...R
I think I've worked it out. I had a microswitch under the points, which was used to detect which position they were in. In one position, the spring on the switch arm was pushing against the servo, which would have been stressing it. Unfortunately, this is the position the servo is in for 90% of the time. That could be what's causing the gear tooth to start slipping - the tug-of-war that's going on. Furthermore, it wasn't really needed and was only 'grandfathered' in from the previous version of the mechanism.
So I removed the microswitch, and adjusted the code so that it just sets the servo position without checking. If the servo's already in that position, it won't move anyway.
The servo does do the 'slight shift' on startup, all the servos I've used do that. So I usually write the 'default' starting position to them as part of the setup() routine.
I've also updated the power supply. Instead of the servo, buttons and other parts of the system being powered by the Aruduino's 5V rail, they and the Arduino are now being powered by a 5v voltage regulator module.
Tbdanny:
I think I've worked it out. I had a microswitch under the points, which was used to detect which position they were in. In one position, the spring on the switch arm was pushing against the servo, which would have been stressing it.
It would need to be a strong spring to be able to overcome the internal friction in the servo gear train.
So I removed the microswitch, and adjusted the code so that it just sets the servo position without checking. If the servo's already in that position, it won't move anyway.
That makes me curious to know what the previous code had been doing - perhaps that code was the root cause of the problem?
...R