Servo code non blocking

How to wire this same code but make it non blocking run in the back ground

#include <Servo.h>

Servo myservo;  // create Servo object to control a servo
// twelve Servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the Servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
}

Place the movement of the servo in a function that does one step at a time.

Use a millis() based approach to call that function every 15 milliseconds.

You need to expand it a bit for the forward and backward move.

1 Like

look at

you might also benefit from studying state machines. Here is a small introduction to the topic: Yet another Finite State Machine introduction

Ok so pwm is non blocking it's the delay I guess causing the problem see i have added a reed switch that it sweeps back and forth over but it miss reads

#include <Servo.h>

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

const unsigned long MsecPeriod = 15;
      unsigned long msec0;

int pos = 0;    // variable to store the servo position
int dir = 1;

// -----------------------------------------------------------------------------
void loop( )
{
    unsigned long msec = millis ();
    if (msec - msec0 >= MsecPeriod)  {
        msec += MsecPeriod;

        pos += dir;
        if (0 == pos || 180 == pos)
            dir = -dir;

        myservo.write(pos);
    }
}

void setup() {
    myservo.attach(9);  // attaches the servo on pin 9 to the Servo object
}

it's the delay inside the for loop. when you do

  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    ...
    delay(15);                       // waits 15 ms for the servo to reach the position
  }

you are stuck for 180 x 15ms (= 2.7s) in this loop and the code does not do anything else. Same in the other direction.

you need to get rid of the delay AND the for loop (and let the loop be your iterator)

basically the loop should do

if 15ms elapsed since the last step then
   take a step (and note the time)

Well I'm not getting anywhere fast just the servo it sweeps way to fast
here what i tried

#include <Servo.h>

Servo myservo;  // create Servo object to control a servo
// twelve Servo objects can be created on most boards

int pos = 0;      // variable to store the servo position
unsigned long previousMillis = 0;
const long interval = 1000;  // interval in milliseconds

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the Servo object
}

void loop() {
  unsigned long currentMillis = millis();

  

    for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
      // in steps of 1 degree
      myservo.write(pos);          // tell servo to go to position in variable 'pos'
      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        
      }
    }
    for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
      
        myservo.write(pos);          // tell servo to go to position in variable 'pos'
        if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
      }
    }
  }

you still have the for loop... and currentMillis does not even update so...

try to write code going only one direction as a start and don't use a for() loop, just a if

it should look like this

void loop() {
  // if it's time to take a step
  if (millis() - lastStepTime >= 15) {
    // then go to the new position
    myservo.write(pos);
    // prepare the future position
    pos++;
    // ensure the future position is OK
    if (pos > 180) {
      ...
   }
    // make a note of the time you took the step
   lastStepTime = millis();
  }
}

when you reach 180 you should update a flag that should be taken into account to not execute this again

void loop() {
  //unsigned long  lastStepTime = millis();
  // if it's time to take a step
  if (millis() - lastStepTime >= 15) {
    // then go to the new position
    myservo.write(pos);
    // prepare the future position
    pos++;
    // ensure the future position is OK
    if (pos > 180) {
     
   }
    // make a note of the time you took the step
   lastStepTime = millis();
  }
  if (millis() - lastStepTime >= 15) {
    // then go to the new position
    myservo.write(pos);
    // prepare the future position
    pos--;
    // ensure the future position is OK
    if (pos < 180) {
     
   }
    // make a note of the time you took the step
   lastStepTime = millis();
  }

jumps around and stops

may be you want to read this short summary how to slow down the servo movement non blocking:

https://werner.rothschopf.net/microcontroller/202207_millis_slow_servo.htm

it can very easily expanded to be used with several servos.

what's that code?

focus on just going one way for the time being from 0 to 180 and stop.

Can you disclose the desired sweep speed?

please look at the code in post #5, it shows how to use millis() to determine when do do something and how to handle both directions

i did thats all good i need it sweep

show the code. you can build from that

@be80be -

This is a near-exact copy of post #5 with some descriptions.

#include <Servo.h>
byte servoPin = 9; // define pin to control servo
Servo myservo; // create Servo object to control

unsigned long timer; // keep track of time between steps
unsigned long nextStep = 100; // 100 ms between steps ADJUST THIS FOR FASTER/SLOWER STEPS
int dir = 1; // direction of sweep
int pos = 0; // initial position of horn

void setup() {
  myservo.attach(servoPin); // arm object with servo control pin
}

void loop() {
  if (millis() - timer > nextStep) { // is it time to step again?
    timer = millis(); // yes, and set new timer for next step
    pos += dir; // change the postion of the horn
    if (pos >= 180 || pos <= 0) // is the horn at the end of the sweep?
      dir = -dir; // yes, change sweep direction
    myservo.write(pos); // MOVE THAT HORN
    delay(15); // time to allow horn to move from one position to the next
  }
}

Are you using the +5V regulator of the Arduino to power the servo?

Look at this servo-moving function from within the excellent several things at the same time tutorial:

2 Likes

you can refer to this:

This provide the instruction how to control the speed of servo motor in non-blocking manner