Pages: [1]   Go Down
Author Topic: simple servo...  (Read 602 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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);
  }  
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is another way to do what you want.

Code:
/*
 * 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
« Last Edit: April 17, 2008, 03:17:45 am by mem » Logged

Denver, CO
Offline Offline
Jr. Member
**
Karma: 0
Posts: 85
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
/*  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);
  }
}
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is a very simple way of fixing millis overflow:

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


« Last Edit: April 17, 2008, 05:31:42 am by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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.
}
Logged

Pages: [1]   Go Up
Jump to: