Operate servo without using delay

Hello

I am trying to build a robot that follows a line and at the same time operates a servo motor that controls an arm to pick up wooden pegs. The problem is that I can’t use delays or the processor won’t do anything else while its delaying.
So I did a little research and found that the way to get around that is using the internal clock? on the Arduino utilizing the millis() function. I’m definitely a beginner so the logic is a little hard to grasp for me.

Basically I just want to make a basic program first that opens the servo 60 degrees, pauses for 1 second, and then closes 60 degrees. I want it to sweep fairly quickly as well. Then I can work from there.

The following is the code I have so far and I know it’s probably all jacked up. When I upload it the servo doesn’t do anything right now. i guess I should probably start simpler.

#include <Servo.h>

Servo myservo;

unsigned long Starttimer;
unsigned long current_time;
unsigned long elapsed_time;
long servoMillis = 0;
long servointerval = 15;
long interval = 1000;

int pos = 0;

void setup() {
  myservo.attach(9);
}
 
void loop() { 
    for(pos == 0; pos < 60; pos+=5) {      //opens the arm 60 degrees
      if(millis() - servoMillis > servointerval)  //created to delay 15 milliseconds before next pulse
        {
        servoMillis = millis();  //starts timer
        myservo.write(pos);      //moves 5 degrees every 15 milliseconds
        }}
        
      Starttimer=millis();      //starts one second delay timer?
         do {
            current_time = millis();
            elapsed_time = current_time - Starttimer;
            }
            while(elapsed_time < interval);      //leaves loop when 1 second has passed
      
      for(pos == 60; pos >=5; pos-=5) {    //closes the arm back to 0 degrees
        if(millis() - servoMillis > servointerval)
        {
        servoMillis = millis();
        myservo.write(pos);
        }}
        }

do {
current_time = millis();
elapsed_time = current_time - Starttimer;
}
while(elapsed_time < interval); //leaves loop when 1 second has passed

Oh, yeah, reinvent the delay function, why don’t you?

    for(pos == 0; pos < 60; pos+=5) {      //opens the arm 60 degrees

The first clause in the for statement is an assignment, not a test. That should be a single = there,

Why is pos a global variable? It is not used in any function other than loop, so it should be a local variable.

Does your servo work with any of the Servo examples? How is the servo powered? What connections exist between the servo and the Arduino?

By the way, all variables involved with millis() should be unsigned long, not long.

Hey thanks for the reply!

So I defined “pos” in the loop and changed the == sign to a single.

The servo works fine with examples and actually I made a program using delays that does exactly what I want it to do. In this case 90 degrees though.

I have the servo hooked up to a voltage regulator supplying a regulated 5 volts. This is the sweep program modified from the example library that works the way I want it to.

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
  // set servo to mid-point
} 

void loop() {
  
for(pos = 0; pos < 90; pos += 5)
  {
  myservo.write(pos);
  delay(15);
  }
  delay(1000);
  for(pos = 90; pos >=5; pos-=5)
  {
  myservo.write(pos);
  delay(15);
  }

}

Sorry it was sent prematurely. I did define "int pos = 0;" locally. It's omitted in the above accidentally.

I have the servo hooked up to a voltage regulator supplying a regulated 5 volts.

If you are using a regulator chip like the L7805 you can add a diode on the regulator ground to boost the ouput to 5.7v for better servo performance.

What connections exist between the servo and the Arduino?

I have the servo hooked up to a voltage regulator supplying a regulated 5 volts.

My servos have three wires. Guess how they are connected.

I’m not sure what you mean by that PaulS, but I have my servo wired correctly. I’m just not powering the servo from the Arduino, I’m sending pulses from it, i.e. ground to ground and white wire to pin 9 on Arduino then 5v and ground to voltage regulator.

Anyways, I got the servo to work the way I want using millis(). I just thought I’d post it to help out future users.

#include <Servo.h>

Servo myservo;



long elapsed_time = 0;
long previousMillis = 0;
long previousMillis2 = 0;
long servointerval = 15;
long interval = 1000;
int pos = 0;


void setup() {
  myservo.attach(9);
}
 
void loop() { 
  
  for(pos = 0; pos < 60; pos+=60) {      //opens the arm 60 degrees
       unsigned long servoMillis = millis();
      if(servoMillis - previousMillis > servointerval)  //created to delay 15 milliseconds before next pulse
        {
         previousMillis = servoMillis;
         myservo.write(pos);      //moves 5 degrees every 15 milliseconds
        }
     
     }
       
      unsigned long Starttimer=millis();      //starts one second delay timer?
         do {
            unsigned long current_time = millis();
            elapsed_time = current_time - Starttimer;
            }
            while(elapsed_time < interval);      //leaves loop when 1 second has passed
      
      
      for(pos = 60; pos >=60; pos-=60) {    //closes the arm back to 0 degrees
        unsigned long servoMillis2 = millis();
        if(servoMillis2 - previousMillis2 > servointerval)
        {
        previousMillis2 = servoMillis2;
        myservo.write(pos);
        }
       
    }
       
      }

I have written a sketch that allows you to do smooth motion with a servo (possibly multiple servos)…

#include <Servo.h>

Servo myservo; // create servo object to control a servo, max = 8 servos
int myservo_pin = 9; // pin that controls the servo
int myservo_speed = 5; // how fast the servo moves, 1 = very fast, 10 = very slow
long myservo_movetime = 0; // next time in millis servo next moves
int myservo_gPos = 0; // target position to move towards
int myservo_cPos = 0; // current postion of servo

int pos = 0; // variable to store the servo position
int cPos; // current position
int gPos; // goal position
int tDelay = 5; // delay between moves, gives appearance of smooth motion

void setup() {
Serial.begin(9600);
myservo.attach(9); // attaches the servo on pin 9 to the servo object

Serial.println(“setup complete : smooth servo movment without delay v1”);
}

void loop() {
cPos = myservo.read();
if (cPos == 0) gPos = 180;
if (cPos == 180) gPos = 0;
if (cPos != gPos && millis() >= myservo_movetime) {
moveServo();
}
if (Serial.available() > 0) { GetCommand(); }
}

void moveServo() {
if (cPos < gPos) myservo.write(cPos+1);
if (cPos > gPos) myservo.write(cPos-1);
//if (cPos == gPos) // nothing
myservo_movetime = millis() + tDelay;
}

void GetCommand() {
int command = Serial.read() - ‘0’;
int mVal = command;
if (mVal == ‘x’) {
tDelay = tDelay * 10;
} else {
tDelay = mVal;
}
Serial.print(“Pauses changed to : “); Serial.print(tDelay); Serial.println(” mSeconds”);
Serial.flush();
}