Go Down

Topic: simple servo... (Read 663 times) previous topic - next topic

gtsown

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.

Thank you in advance..

Code: [Select]
int servo = 14;
int min_pulse = 500;
int max_pulse = 2000;

void setup(){
 int i;
 pinMode(servo, OUTPUT);
 Serial.begin(9600);

}
 
void loop(){
   int i;
// wk_1    
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(2000);
     digitalWrite(servo, LOW);
       delay(100);
       }
delay(100);
// wk_2    
       for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
       }
delay(100);
// wk_3    
   
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(2000);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
// wk_4  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(2000);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);


// wk_5  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(1000);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
 

// wk_6  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
 


// wk_7  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);

 
// wk_8  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(2000);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
// wk_9  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
// wk_10  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
// wk_11  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
// wk_12  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(100);
   }
delay(100);
 
 
 
// wk_13  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(1000);
     digitalWrite(servo, LOW);
       delay(20);
   }
delay(100);
// wk_14  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(100);
     digitalWrite(servo, LOW);
       delay(20);
   }
delay(100);
// wk_15  
   for (i=0; i<100; i++)
   {
     digitalWrite(servo, HIGH);
     delayMicroseconds(2000);
     digitalWrite(servo, LOW);
       delay(20);
   }
delay(100);
 }  

mem

#1
Apr 17, 2008, 10:15 am Last Edit: Apr 17, 2008, 10:17 am by mem Reason: 1
Here is another way to do what you want.

Code: [Select]

/*
* 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

bwevans

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

Code: [Select]
/*  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);
 }
}

mem

#3
Apr 17, 2008, 11:26 am Last Edit: Apr 17, 2008, 12:31 pm by mem Reason: 1
Here is a very simple way of fixing millis overflow:

Code: [Select]
/*
* 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.



gtsown

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?


Code: [Select]
#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.
}


Go Up