No Delay Servo Code

Hi guys,

This is a pretty simple task but I just can’t seem to come right.

I have 3 potentiometers, 1 servo and 1 led. The servo sweeps back and forth as seen in the sweep example code in the IDE and the LED blinks on and off.

Pot 1 Controls the speed of the servo sweep.
Pot 2 Controls the angle the servo that sweeps back and forth
Pot 3 Controls the speed of the blinking LED.

My Servo control is working fine using the VarServoSpeed Library as found here.

But it seems as though there are delays in the library that causes the LED to blink only after the servo has rotated where it needs to be so the speed control wont work properly. Can anyone suggest a method to do this or point me in the right direction? I’ve seen it been done with millis(); but it looked like it didn’t work so well. Please can someone help me out here, Pulling my hair out!. Here is my code below.

#include <VarSpeedServo.h> 
 
VarSpeedServo myservo;  // create servo object to control a servo 
                        // a maximum of eight servo objects can be created 
 
const int servoPin = 9; // the digital pin used for the servo
const int speedpot = 0;
const int anglepot = A1;
const int LEDpot = A2;
const int LEDpin = 6;


int LED;
int Speed;
int Angle;

void setup() { 
  pinMode(0,INPUT);
  myservo.attach(servoPin);  // attaches the servo on pin 9 to the servo object
  myservo.write(0,255,true); // set the intial position of the servo, as fast as possible, wait until done
  Serial.begin(9600);
} 

void loop() {
  
  
  Angle = analogRead(anglepot);
  Angle = map(Angle,0,1023,25,180);
  Serial.print("Angle: ");
  Serial.println(Angle);
  
  Speed = analogRead(speedpot);
  Speed = map(Speed,0,1023,25,255);
  Serial.print("Speed: ");
  Serial.println(Speed);
  
  myservo.write(Angle,Speed,true);        // move the servo to 180, max speed, wait until done
                                      // write(degrees 0-180, speed 1-255, wait to complete true-false)
  myservo.write(0,Speed,true);          // move the servo to 180, slow speed, wait until done
}

I haven't included the LED Control in that version posted above. I would just use Blink Without Delay and Map the Pot to the interval. That's not the issue. I'm just struggling with the servo control without delay

Looks like you will have to ditch that servo library and write your own code a sort of sweep without delay.

I've seen it been done with millis();

Yes that is what you have to do.

but it looked like it didn't work so well

Why, there is no reason why it should not work.

Yeah you're right, I think it just wasn't good code, it had bugs in it. To be honest I haven't written my own sweep code yet because I don't entirely know how to do it with millis(). I'm busy trying to see how I can implement the Blink Without Delay concept into a servo sweep that lets me adjust speed.

I'm busy trying to see how I can implement the Blink Without Delay concept into a servo sweep that lets me adjust speed.

You seen this:- http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html

I had not read that before, thanks for the link! its super helpful. I managed to get the grasp of the scheduler and state machine code when it comes to simple things like digital on and offs such as LEDs etc. But I get lost when I have to run loops etc. (I apologize I am still very new to programming). I have this done so far which is just a cut together from example code but it works. My servo goes from one set degree to the next. Now I just have no clue how I could change the speed of it. Do you have any suggestions?

#include <Servo.h>

int State = LOW;             
long previousMillis = 0;        

long interval = 1000;
 
Servo myservo;  
                        
 
const int servoPin = 9; // the digital pin used for the servo
 
void setup() { 
  myservo.attach(servoPin);  // attaches the servo on pin 9 to the servo object
} 

void loop()

{
   unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (State == LOW)
      State = HIGH;
    else
      State = LOW;
      
  }
 
  if (State == HIGH){
    myservo.write(180);
  }
  
  if(State == LOW){
      myservo.write(0);}
  }

Now I just have no clue how I could change the speed of it.

Well every time interval, instead of turning the LED on and off you increment a counter and send that value of the counter to the servo. When the counter reaches the final position you stop, either by setting a flag or by putting the next time to a long time in the future ( several days ). The speed is increased by increment the counter by more than one or decreased the time that you change the counter.

Hope that helps.

The servo sweep code in the demo several things at a time does not use delay()

...R

Robin2:
The servo sweep code in the demo several things at a time does not use delay()

…R

Wow that’s an awesome demo you’ve made for learning. Its very easy to see each function and where it comes into play. Thanks man! :slight_smile:

I see the variables at the top is where you can set your values for different outcomes like the blink and the servo variables. So if I change the servoDegrees, it will change the amounts of steps and thus changes the speed so i can map that to an analog input and use a pot. That sounds great, but whats the most effective way to change the sweep angle? I’ve been playing with your variables and it seems I can only get like ± 30Degree sweep angle no matter what I change.

Otherwise it’s a really great example to use thanks again!

Thank you for your kind words.

The servo position is controlled by the constants servoMinDegrees and servoMaxdegrees and the variable servoDegrees

...R

Robin2:
Thank you for your kind words.

The servo position is controlled by the constants servoMinDegrees and servoMaxdegrees and the variable servoDegrees

…R

Worked perfect! Thanks again. Just one little thing I’m having trouble with there.
I’m trying to map the servoDegrees to a pot which works but as soon as I make my variable that is reading the pot = the servoDegrees. It just doesn’t change. As soon as i try make them talk to each other it remains at 0 degrees and simply doesn’t move. Any reason for this?

Below is what I’ve done if you want a reference.

// SeveralThingsAtTheSameTimeRev1.ino

// An expansion of the BlinkWithoutDelay concept to illustrate how a script
//  can appear to do several things at the same time

// this sketch does the following
//    it blinks the onboard LED (as in the blinkWithoutDelay sketch)
//    it blinks two external LEDs (LedA and LedB) that are connected to pins 12 and 11.
//    it turns another Led (buttonLed connected to pin 10) on or off whenever a button
//       connected to pin 7 is pressed
//    it sweeps a servo (connected to pin 5) back and forth at different speeds

//  One leg of each LED should be connected to the relevant pin and the other leg should be connected to a
//   resistor of 470 ohms or more and the other end of the resistor to the Arduino GND. 
//   If the LED doesn't light its probably connected the wrong way round.

//  On my Uno and Mega the "button" is just a piece of wire inserted into pin 7. 
//   Touching the end of the wire with a moist finger is sufficient to cause the switching action
//   Of course a proper press-on-release-off button switch could also be used!

//  The Arduino is not capable of supplying enough 5v power to operate a servo
//    The servo should have it's own power supply and the power supply Ground should
//      be connected to the Arduino Ground.

// The sketch is written to illustrate a few different programming features.
//    The use of many functions with short pieces of code. 
//       Short pieces of code are much easier to follow and debug
//    The use of variables to record the state of something (e.g. onBoardLedState) as a means to
//       enable the different functions to determine what to do.
//    The use of millis() to manage the timing of activities
//    The definition of all numbers used by the program at the top of the sketch where 
//       they can easily be found if they need to be changed

//=======

// -----LIBRARIES

#include <Servo.h>

// ----CONSTANTS (won't change)

const int onBoardLedPin =  13;      // the pin numbers for the LEDs
const int led_A_Pin = 12;
const int led_B_Pin = 11;
const int buttonLed_Pin = 10;

const int buttonPin = 7; // the pin number for the button

const int servoPin = 5; // the pin number for the servo signal

const int onBoardLedInterval = 500; // number of millisecs between blinks
const int led_A_Interval = 2500;
const int led_B_Interval = 4500;

const int blinkDuration = 500; // number of millisecs that Led's are on - all three leds use this

const int buttonInterval = 300; // number of millisecs between button readings

const int servoMinDegrees = 0; // the limits to servo movement
const int servoMaxDegrees = 180;
const int speedpin = A0;
const int anglepin = A1;

//------- VARIABLES (will change)

byte onBoardLedState = LOW;             // used to record whether the LEDs are on or off
byte led_A_State = LOW;           //   LOW = off
byte led_B_State = LOW;
byte buttonLed_State = LOW;

Servo myservo;  // create servo object to control a servo 


int Setspeed;
int Setangle;

int servoPosition = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval = 40; // millisecs between servo moves
int servoFastInterval = 40;
int servoInterval = servoSlowInterval; // initial millisecs between servo moves
int servoDegrees = Setspeed;       // amount servo moves at each step 
                           //    will be changed to negative value for movement in the other direction

unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousOnBoardLedMillis = 0;   // will store last time the LED was updated
unsigned long previousLed_A_Millis = 0;
unsigned long previousLed_B_Millis = 0;

unsigned long previousButtonMillis = 0; // time when button press last checked

unsigned long previousServoMillis = 0; // the time when the servo was last moved

//========

void setup() {

 Serial.begin(9600);
 Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 

     // set the Led pins as output:
 pinMode(onBoardLedPin, OUTPUT);
 pinMode(led_A_Pin, OUTPUT);
 pinMode(led_B_Pin, OUTPUT);
 pinMode(buttonLed_Pin, OUTPUT);
 
     // set the button pin as input with a pullup resistor to ensure it defaults to HIGH
 pinMode(buttonPin, INPUT_PULLUP);
 
 myservo.write(servoPosition); // sets the initial position
 myservo.attach(servoPin);

}

//=======

void loop() {
  
 Setspeed = analogRead(speedpin);
 Setspeed = map(setspeed, 0, 1023, 0, 5);
 
 Setangle = analogRead(anglepin);
 Setangle = map(setangle,0,1023,0,180);
 
  Serial.print("Speed: ");
 Serial.println(setspeed);

     // Notice that none of the action happens in loop() apart from reading millis()
     //   it just calls the functions that have the action code

 currentMillis = millis();   // capture the latest value of millis()
                             //   this is equivalent to noting the time from a clock
                             //   use the same time for all LED flashes to keep them synchronized
 
 
 servoSweep();

}

//========

void servoSweep() {

     // this is similar to the servo sweep example except that it uses millis() rather than delay()

     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 
 if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative

   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
         // if the servo is at either extreme change the sign of the degrees to make it move the other way
     servoDegrees = - servoDegrees; // reverse direction
         // and update the position to ensure it is within range
     servoPosition = servoPosition + servoDegrees; 
   }
       // make the servo move to the next position
   myservo.write(servoPosition);
       // and record the time when the move happened
 }
}

//=====END

You may think well then your pot is not giving a any values out but it is. If I print the pot value (which is setspeed) to the serial, I can see it clearly changing from 1 to 5 but as I said it just wont let me make it = servoDegrees.

Can you post the code when you try and set the angle to servo degrees and get it not working.

The code you posted updates the variable Setangle but then that variable is not used anywhere so I don't understand what is the problem.

...R

Hey Mike,

Okay well Im trying to set two things. I’m trying to change the Angle of the sweep (from 0 to 180) which is defined in the code as ServoMinDegrees and ServoMaxDegrees I’m mapping a pot to ServoMaxDegrees and keeping the ServoMinDegrees at 0. So just directly changing the angle. Not a difficult task.

For the Angle part. It seems to just say variable not declared in the scope but it clearly is. So I’m not sure.

Regarding the speed. I’m mapping an analogRead from another pot to the Variable servoDegrees (which changes how many degrees the servo moves at each step which will directly affect the speed)

The code I’m using is blow, Please can you try find out where I’m going wrong :frowning: = \

// SeveralThingsAtTheSameTimeRev1.ino

// An expansion of the BlinkWithoutDelay concept to illustrate how a script
//  can appear to do several things at the same time

// this sketch does the following
//    it blinks the onboard LED (as in the blinkWithoutDelay sketch)
//    it blinks two external LEDs (LedA and LedB) that are connected to pins 12 and 11.
//    it turns another Led (buttonLed connected to pin 10) on or off whenever a button
//       connected to pin 7 is pressed
//    it sweeps a servo (connected to pin 5) back and forth at different speeds

//  One leg of each LED should be connected to the relevant pin and the other leg should be connected to a
//   resistor of 470 ohms or more and the other end of the resistor to the Arduino GND. 
//   If the LED doesn't light its probably connected the wrong way round.

//  On my Uno and Mega the "button" is just a piece of wire inserted into pin 7. 
//   Touching the end of the wire with a moist finger is sufficient to cause the switching action
//   Of course a proper press-on-release-off button switch could also be used!

//  The Arduino is not capable of supplying enough 5v power to operate a servo
//    The servo should have it's own power supply and the power supply Ground should
//      be connected to the Arduino Ground.

// The sketch is written to illustrate a few different programming features.
//    The use of many functions with short pieces of code. 
//       Short pieces of code are much easier to follow and debug
//    The use of variables to record the state of something (e.g. onBoardLedState) as a means to
//       enable the different functions to determine what to do.
//    The use of millis() to manage the timing of activities
//    The definition of all numbers used by the program at the top of the sketch where 
//       they can easily be found if they need to be changed

//=======

// -----LIBRARIES

#include <Servo.h>

// ----CONSTANTS (won't change)

const int onBoardLedPin =  13;      // the pin numbers for the LEDs
const int led_A_Pin = 12;
const int led_B_Pin = 11;
const int buttonLed_Pin = 10;

const int buttonPin = 7; // the pin number for the button

const int servoPin = 5; // the pin number for the servo signal

const int onBoardLedInterval = 500; // number of millisecs between blinks
const int led_A_Interval = 2500;
const int led_B_Interval = 4500;

const int blinkDuration = 500; // number of millisecs that Led's are on - all three leds use this

const int buttonInterval = 300; // number of millisecs between button readings

const int servoMinDegrees = 0; // the limits to servo movement
const int servoMaxDegrees = Setangle;

const int speedpin = A0;
const int anglepin = A1;

//------- VARIABLES (will change)

byte onBoardLedState = LOW;             // used to record whether the LEDs are on or off
byte led_A_State = LOW;           //   LOW = off
byte led_B_State = LOW;
byte buttonLed_State = LOW;

Servo myservo;  // create servo object to control a servo 


int Setspeed;
int Setangle;

int servoPosition = 90;     // the current angle of the servo - starting at 90.
int servoSlowInterval = 40; // millisecs between servo moves
int servoFastInterval = 40;
int servoInterval = servoSlowInterval; // initial millisecs between servo moves
int servoDegrees = Setspeed;       // amount servo moves at each step 
                           //    will be changed to negative value for movement in the other direction

unsigned long currentMillis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previousOnBoardLedMillis = 0;   // will store last time the LED was updated
unsigned long previousLed_A_Millis = 0;
unsigned long previousLed_B_Millis = 0;

unsigned long previousButtonMillis = 0; // time when button press last checked

unsigned long previousServoMillis = 0; // the time when the servo was last moved

//========

void setup() {

 Serial.begin(9600);
 Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 

     // set the Led pins as output:
 pinMode(onBoardLedPin, OUTPUT);
 pinMode(led_A_Pin, OUTPUT);
 pinMode(led_B_Pin, OUTPUT);
 pinMode(buttonLed_Pin, OUTPUT);
 
     // set the button pin as input with a pullup resistor to ensure it defaults to HIGH
 pinMode(buttonPin, INPUT_PULLUP);
 
 myservo.write(servoPosition); // sets the initial position
 myservo.attach(servoPin);

}

//=======

void loop() {
  
 Setspeed = analogRead(speedpin);
 Setspeed = map(Setspeed, 0, 1023, 0, 5);
 
 Setangle = analogRead(anglepin);
 Setangle = map(Setangle,0,1023,0,180);
 
  Serial.print("Speed: ");
 Serial.println(Setspeed);

     // Notice that none of the action happens in loop() apart from reading millis()
     //   it just calls the functions that have the action code

 currentMillis = millis();   // capture the latest value of millis()
                             //   this is equivalent to noting the time from a clock
                             //   use the same time for all LED flashes to keep them synchronized
 
 
 servoSweep();

}

//========

void servoSweep() {
  
     // this is similar to the servo sweep example except that it uses millis() rather than delay()

     // nothing happens unless the interval has expired
     // the value of currentMillis was set in loop()
 
 if (currentMillis - previousServoMillis >= servoInterval) {
       // its time for another move
   previousServoMillis += servoInterval;
   
   servoPosition = servoPosition + servoDegrees; // servoDegrees might be negative

   if (servoPosition <= servoMinDegrees) {
         // when the servo gets to its minimum position change the interval to change the speed
      if (servoInterval == servoSlowInterval) {
        servoInterval = servoFastInterval;
      }
      else {
       servoInterval = servoSlowInterval;
      }
   }
   if ((servoPosition >= servoMaxDegrees) || (servoPosition <= servoMinDegrees))  {
         // if the servo is at either extreme change the sign of the degrees to make it move the other way
     servoDegrees = - servoDegrees; // reverse direction
         // and update the position to ensure it is within range
     servoPosition = servoPosition + servoDegrees; 
   }
       // make the servo move to the next position
   myservo.write(servoPosition);
       // and record the time when the move happened
 }
}

//=====END

Robin2:
The code you posted updates the variable Setangle but then that variable is not used anywhere so I don’t understand what is the problem.

…R

Sorry yeah that was a bad post. See the post above. Its set to map a an analogRead from a pot in the main loop()

For the Angle part. It seems to just say variable not declared in the scope but it clearly is.

Now then a bit of modesty is called for here. If the compiler says so it is true.

What happens is that you use the variable Setangle in the line:- const int servoMaxDegrees = Setangle ; BEFORE you declare int Setangle ; About 10 lines after. Also you do not give Setangle a value so how can the compiler set the value of servoMaxDegrees to a value it does not know.

If you change things to:-

int Setangle = 180;
const int servoMaxDegrees = Setangle;

Then there is no compiler error.

Oohh, So it needs to be declared before the const int. That makes sense and fixes that compiler error. Thanks so much Mike!

Unfortunately, my original problem still persists. When I try give the servoMaxDegrees or the servoDegrees values that are coming from my Pot. They just won't take. They remain at 0 when I print to the Serial and the Servo just locks up. I know the Pot is working because I can print that directly to the Serial and the readings come out as they should.

I don't know, I think its pretty hard for anyone else to try help me without having like a little setup of their own with them = \

Anything I could try though?

I don’t know what you mean by “don’t take”.

What I can tell you is that you are not using either of those variables that you set by reading the analogue input to do anything to alter the angle of the servo you are commanding nor the speed it is doing any movement.

Unless you use Setspeed and Setangle then they will have no effect.

Razzik: Sorry yeah that was a bad post. See the post above. Its set to map a an analogRead from a pot in the main loop()

I looked at the code in Reply #13 and I see Setangle is set in lines 124 and 125. But it is not used anywhere else.

The reference to it on line 61 is only used by the compiler at compile time. It is not affected by the running program. Only code in loop() or called from loop() has any effect at runtime after setup() is finished.

...R