Hi Everyone,
i have this cycle for a servo...I what it to move every 1 min to one of three position. High(180Left), Medium(90middle), Low(180Right). I have a piece of code which works, however, the servo whenever i delay the time longer, pulses(vibrates). Is there an alternate way of doing this. Here is what i have so far. Anyhelp on this would greatly be appreciated.
/*
* this sketch moves a servo every 1 min to one of three positions, Left, middle and right
*/
int servo = 14;
int left_pulse = 750; // left (you may need to reverse left and right for your servo)
int mid_pulse = 1500; // tweek this for your actual mid position
int right_pulse = 2000;
void setup(){
pinMode(servo, OUTPUT);
Serial.begin(9600);
}
void updateServo( int pulse){
digitalWrite(servo, HIGH);
delayMicroseconds(pulse);
digitalWrite(servo, LOW);
delay(20); // 20 millisecond delay between pulses is required for the servo
}
void loop(){
unsigned long startTime;
startTime = millis(); // set our timer
while(millis() - startTime < 1000) { // loop for one second
updateServo(left_pulse);
}
startTime = millis(); //restart timer
while(millis() - startTime < 1000) { // loop for one second
updateServo(mid_pulse);
}
startTime = millis(); //restart timer
while(millis() - startTime < 1000) { // loop for one second
updateServo(right_pulse);
}
}
If you will run this code for many hours you will need look into handing millis() overflow
The millis thing has always been a problem for me. Until I can work out a better solution this was an example I worked up for my students. Basically the problem youre having is that the servo needs to be updated every 20mS or else it will freak out. So this example uses for loops to continue to update the servo position by calling the servoPulse function 50 times to create a delay of 1 second. (50 loops x 20ms = 1000ms = 1 second) So to delay for 1 minute at each position you would need to change the 50 in each of the lines: for(int i=0; i<50; i++) to 300. Also notice I have this example set to 10, 90, and 170 degrees... some servos have varying tolerances at the 0 and 180 sides of things so you have to work into the full range to see how well your servo does. In other words you may not quite get 180 out of it and then again you might get more, it all depends. The last thing you need to change in this example is the servo pin your sero is attached to.
Cheers,
Brian
/* 10º, 90º, 170º
Moves servo to 3 different angles
with a pause of 1 second each.
*/
int servoPin = 2; // servo connected to digital pin 2
int myAngle; // angle of the servo roughly 0-180
int pulseWidth; // servoPulse function variable
void setup()
{
pinMode(servoPin, OUTPUT); // sets pin 2 as output
}
void servoPulse(int servoPin, int myAngle)
{
pulseWidth = (myAngle * 10) + 600; // determines delay
digitalWrite(servoPin, HIGH); // set servo high
delayMicroseconds(pulseWidth); // micro pause
digitalWrite(servoPin, LOW); // set servo low
delay(20); // refresh cycle
}
void loop()
{
myAngle = 10; // starts at 10º
for(int i=0; i<50; i++) // loops 50 times
{
servoPulse(servoPin, myAngle);
}
myAngle = 90; // moves to 90º
for(int i=0; i<50; i++) // loops 50 times
{
servoPulse(servoPin, myAngle);
}
myAngle = 170; // then moves to 170º
for(int i=0; i<50; i++) // loops 50 times
{
servoPulse(servoPin, myAngle);
}
}
Here is a very simple way of fixing millis overflow:
/*
* this sketch moves a servo every 1 min to one of three positions, Left, middle and right
*/
int servo = 14;
int left_pulse = 750; // left (you may need to reverse left and right for your servo)
int mid_pulse = 1000; // tweek this for your actual mid position
int right_pulse = 2000;
extern unsigned long timer0_overflow_count; // add this line to tell the compiler about the time counter
void setup(){
pinMode(servo, OUTPUT);
Serial.begin(9600);
}
void updateServo( int pulse){
digitalWrite(servo, HIGH);
delayMicroseconds(pulse);
digitalWrite(servo, LOW);
delay(20); // 20 millisecond delay between pulses is required for the servo
}
void loop(){
unsigned long startTime;
startTime = millis(); // start our timer
while(millis() - startTime < 1000) { // wait for one second
updateServo(left_pulse);
}
startTime = millis(); //restart timer
while(millis() - startTime < 1000) { // wait for one second
updateServo(mid_pulse);
}
startTime = millis(); //restart timer
while(millis() - startTime < 1000) { // wait for one second
updateServo(right_pulse);
}
cli(); disable interrupts;
timer0_overflow_count = 0; // reset the time back to 0 at the end of the loop so it never overflows
sei(); enable interrupts
}
I have modified the previous sketch so it resets the millis counter to 0 after every loop.
thanks for the help guys...i am now trying to incorporate turning on an led blink at each cycle...works great...I have an lcd screen connected as well to arduino, which retrieves messages sent from python..I would like to keep the serial open and have the messages coming as often as possible. The problem i am having is that while the servo is moving and the led's are turning on, as soon as i open the serial connection to python and send a message, the servo is stall and they stop moving. The code is not structured problem, however, i'm not not sure how to fix this?
#include "Wire.h"
// LCD
char stringIn[] = {' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ',
' ', ' ', ' ', ' ', ' ', ' '};
/* 10º, 90º, 170º
Moves servo to 3 different angles
with a pause of 1 second each.
*/
int ledPin = 13;
int ledPin1 = 12;
int ledPin2 = 11;
int servoPin = 14; // servo connected to digital pin 2
int myAngle; // angle of the servo roughly 0-180
int pulseWidth; // servoPulse function variable
void setup()
{
pinMode(servoPin, OUTPUT); // sets pin 2 as output
pinMode(ledPin, OUTPUT);
backlightOn();
clearLCD();
Serial.begin(9600);
}
void servoPulse(int servoPin, int myAngle)
{
pulseWidth = (myAngle * 10) + 600; // determines delay
digitalWrite(servoPin, HIGH); // set servo high
delayMicroseconds(pulseWidth); // micro pause
digitalWrite(servoPin, LOW); // set servo low
delay(20); // refresh cycle
}
void loop()
{
//wk_1
digitalWrite(ledPin, HIGH); // sets the LED on
myAngle = 10; // starts at 10º
for(int i=0; i<3000; i++) // loops 300 times
{
servoPulse(servoPin, myAngle);
}
digitalWrite(ledPin, LOW); // sets the LED off
if (nextByte() == 126) { // header byte ('~' character)
char charIn = 0;
byte i = 0;
while (charIn != 126) { // wait for header byte again
charIn = nextByte();
stringIn[i] = charIn;
i += 1;
} // stringIn is finished
for (int j=i-1; j<16; j++) {
stringIn[j] = ' '; // null out string
}
clearLCD();
delay(2);
selectLineOne();
delay(2);
Serial.println(stringIn);
delay(10);
}
}
byte nextByte() {
while(1) {
if(Serial.available() > 0) {
byte b = Serial.read();
return b;
}
}
}
void selectLineOne(){ //puts the cursor at line 0 char 0.
Serial.print(0xFE, BYTE); //command flag
Serial.print(128, BYTE); //position
}
void clearLCD(){
Serial.print(0xFE, BYTE); //command flag
Serial.print(0x01, BYTE); //clear command.
}
void backlightOn(){ //turns on the backlight
Serial.print(0x7C, BYTE); //command flag for backlight stuff
Serial.print(157, BYTE); //light level.
}