i have wired up a Hitec HS-785HB Winch Servo Motor to an arduino.
I am attempting to get it so the servo is triggered by a motion sensor. The arduino will activate the servo to move to a number of positions and then return to its position, delay and then get triggered again when motion is sensed.
I have wired this up and have it running on several normal servos, but when i turn on the circuit the servo continuously rotates rather than heading to its starting position of 1500.
Here is the schematic (the only difference between the schematic and the actual circuit is that i have the PIR wired up to pin 8, not pin 12 as stated):
#include <Servo.h>
#define S_IDLE 1
#define S_MAXA 2
#define S_MID 3
#define S_MAXB 4
#define S_WAITING 5
#define S_FINISH 6
Servo myservo;
int PIR_SensorPin = 8;
unsigned long duration;
unsigned long lastMillis;
int calibrationTime = 30;
int state = S_IDLE;
void setup()
{
Serial.begin(9600);
pinMode (PIR_SensorPin, INPUT); // Set pinMode
digitalWrite(PIR_SensorPin, LOW);
myservo.attach(9, 700, 2300); // servo.attach(pin, min, max)
myservo.writeMicroseconds(1500); // set servo to mid-point
Serial.print("calibrating sensor ");
for (int i = 0; i < calibrationTime; i++) {
Serial.print(".");
delay(1000);
}
}
void loop() {
if (millis() - lastMillis > duration) { // Step in sequence finished - time to take action!
lastMillis = millis();
switch (state) {
case S_MAXA:
myservo.writeMicroseconds(2100); // turn servo to new position
duration = 200; // Duration of this position
state = S_MID; // Next step of the sequence - runs when duration has passed.
break;
case S_MID:
myservo.writeMicroseconds(800); // turn servo to new position
duration = 200; // Duration of this position
state = S_MAXB; // Move to the next state
break;
case S_MAXB:
myservo.writeMicroseconds(2100); // turn servo to new position
duration = 200; // Duration of this position;
state = S_WAITING; // Move to the next state
break;
case S_WAITING:
myservo.writeMicroseconds(1500); // return servo to netural position
duration = 5000; // Wait for moving on.
state = S_FINISH; // Move to the next state
break;
case S_FINISH:
state = S_IDLE; // Done - time to look at the PIR sensor again.
break;
}
// General state: only look at the sensor when IDLE.
if (state == S_IDLE) {
if (digitalRead(PIR_SensorPin) == HIGH) {
state = S_MAXA;
duration = 0;
lastMillis = millis();
}
}
}
}
Can anyone see why it might be continuously rotating when the circuit is powered up?
The ground wire from the Arduino needs to run alongside the pin 9 signal to the servo directly, so its
not a big loop antenna for noise. You can run the Vin wire alongside them too, but what you mustn't do
is have a signal wire going off on its own like the drawing.
Try doing the writeMicroseconds(1500) immediately BEFORE the attach(). That does at least make sure the servo has a fixed position on start up
Have you tested that servo with something like the Knob example program to see what range of pulse lengths it is actually willing to respond to correctly?
I have wired this up and have it running on several normal servos, but when i turn on the circuit the servo continuously rotates rather than heading to its starting position of 1500.
What do you expect the continuous servo to do when you send 1500, return to centre position?
You cannot control the position of a continuous servo like a 0 to 180 servo.
A continuous servo response with speed and direction, not position to servo commands.
Unless it is a winch servo for RC yachts.
Typically 90deg is stop, 0 is full speed in one direction, 180 is full speed in the other.
But the OP did say it was an HS785HB which isn't a continuous servo. It is a winch servo and should be fully controllable over about 8 turns. It shouldn't be possible for it to turn continuously...unless it's broken or a fake (it is a bit suspicious that it doesn't have it's normal winch drum fitted).
/*
Controlling a servo position using a potentiometer (variable resistor)
by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
modified on 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Knob
*/
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = 0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop() {
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits for the servo to get there
}
when i power up the servo spins, and it does not change direction or come to a stop when i turn the pot, turning the pot has no effect on the servo.
As a note, i have two identical servos and it happens to them both, also, i didn't put the standard winch drum on it.
You say turning the pot has no effect? The servo rotates continuously in on direction and at the same speed? Do they rotate even if the signal wire is disconnected? It certainly sounds like the servos are bad.
Can you test them with anything else like maybe an RC receiver or basic servo tester? Or just get them replaced.
I have set up the original circuit that i made and altered the code:
#include <Servo.h>
#define S_IDLE 1
#define S_MAXA 2
#define S_MID 3
#define S_MAXB 4
#define S_WAITING 5
#define S_FINISH 6
Servo myservo;
int PIR_SensorPin = 8;
unsigned long duration;
unsigned long lastMillis;
int calibrationTime = 30;
int state = S_IDLE;
void setup()
{
Serial.begin(9600);
pinMode (PIR_SensorPin, INPUT); // Set pinMode
digitalWrite(PIR_SensorPin, LOW);
myservo.writeMicroseconds(1000); // set servo to mid-point
myservo.attach(9, 1000, 1000); // servo.attach(pin, min, max)
Serial.print("calibrating sensor ");
for (int i = 0; i < calibrationTime; i++) {
Serial.print(".");
delay(1000);
}
}
void loop() {
if (millis() - lastMillis > duration) { // Step in sequence finished - time to take action!
lastMillis = millis();
switch (state) {
case S_MAXA:
myservo.writeMicroseconds(1000); // turn servo to new position
duration = 200; // Duration of this position
state = S_MID; // Next step of the sequence - runs when duration has passed.
break;
case S_MID:
myservo.writeMicroseconds(1000); // turn servo to new position
duration = 200; // Duration of this position
state = S_MAXB; // Move to the next state
break;
case S_MAXB:
myservo.writeMicroseconds(1000); // turn servo to new position
duration = 200; // Duration of this position;
state = S_WAITING; // Move to the next state
break;
case S_WAITING:
myservo.writeMicroseconds(1000); // return servo to netural position
duration = 5000; // Wait for moving on.
state = S_FINISH; // Move to the next state
break;
case S_FINISH:
state = S_IDLE; // Done - time to look at the PIR sensor again.
break;
}
// General state: only look at the sensor when IDLE.
if (state == S_IDLE) {
if (digitalRead(PIR_SensorPin) == HIGH) {
state = S_MAXA;
duration = 0;
lastMillis = millis();
}
}
}
}
When the code is as seen above, on power up the servo turns about 90 degrees clockwise then continuously rotates anti clockwise. Do you think the centre point is not 1500?
Looks as though i have mixed some of my power supplies up. I am normally using a 36W 9V 4A Switch Mode AC/DC Power Supply Do you think this might be the cause of the problems?
Hi,
Can you try this code with this circuit please, open the monitor in the Arduino IDE and set it to 9600 baud.
As you turn the pot you should see the "Pot Values" change and the "Servo Values" change, tell us what the servo does as you slowly turn the pot from end to end.
Then leave the pot in about mid position and see what the servo does.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
int potpin = A0; // analog pin used to connect the potentiometer
int val; // variable to read the value from the analog pin
int sval;
void setup()
{
Serial.begin(9600);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}
void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
Serial.print("Pot Value :");
Serial.print(val);
sval = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180)
myservo.write(sval); // sets the servo position according to the scaled value
Serial.print(" Servo Value :");
Serial.println(sval);
delay(15); // waits for the servo to get there
}
As i turned the pot, the Pot and Servo Values both changed in relation to each other in the Serial Monitor. The servo started rotating as soon as i powered up. Turning the pot from 0 to 180 (Servo Value reading) made the servo turn faster, in the direction it was already turning at. It never stopped rotating or came to a stop.