Servo Sweep Using millis(); ?

Status
Not open for further replies.

siredward

Member
Can anybody tell me why my servo sweep function does not work? Its meant to be a simple mod of the generic servo sweep using millis();

Not shown--

In both the setup and loop:

currentMillis = millis();

and at the beginning of the sketch:

#include <PWMServo.h>
PWMServo myservo;
int previousMillisServo = 0;
int pos = 0;
long servoInterval = 15;
unsigned long currentMillis = 0;

So, the issue is with how I am writing the function.
Please weigh in.
Thank you!!

HTML:
void servoSweep() {
if (currentMillis - previousMillisServo > servoInterval) {
  previousMillisServo = currentMillis;
  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 15ms 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 15ms for the servo to reach the position
  }
}
}
 
Please weigh in.

We generally expect you to show a complete program, not code fragments and assurances like "In both the setup and loop: currentMillis = millis();" without the actual code.

We do help here (probably more than most forms), but you need to do your part. Compose a small but complete program which reproduces the problem. If this is part of a huge project, trim it to a small program and verify that program really demonstrates the problem, then post the complete code.
 
Here is the complete code -

I am trying to substitute a millis() based function for delay()

If the delay commands were to be uncommented, and the first two lines in the function servoSweep() were to be commented out, then the servo sweeps.

However if the delays are commented out as seen below, the millis code here does not do what I intend for it to.

Any thoughts on using millis() in place of delay for servo pauses?

Thank you

Code:
//SweepwithMillis

#include <PWMServo.h>
PWMServo myservo;
int previousMillisServo = 0;
int pos = 0;  
long servoInterval = 15;
unsigned long currentMillis = 0;

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

void loop() {
  currentMillis = millis();
  servoSweep();                   
  }


void servoSweep() {
if (currentMillis - previousMillisServo > servoInterval) {
  previousMillisServo = currentMillis;
  for (pos = 0; pos <= 175; pos += 1) { 
    myservo.write(pos);              
    //delay(15);                       
  }
  for (pos = 175; pos >= 0; pos -= 1) { 
    myservo.write(pos);              
    //delay(15);                     
  }
}
 
Last edited:
Nothing updates :: unsigned long currentMillis = 0;

It might work with this change to a PJRC elapsedMillis that auto updates with reference to millis() :: elapsedMillis currentMillis = 0;
 
next problem is this :: int previousMillisServo = 0;

Should be :: uint32_t previousMillisServo = 0;

That is the clearest way to get known Unsigned 32 bit integer.
 
Here is the complete code -

I am trying to substitute a millis() based function for delay()

If the delay commands were to be uncommented, and the first two lines in the function servoSweep() were to be commented out, then the servo sweeps.

However if the delays are commented out as seen below, the millis code here does not do what I intend for it to.

Any thoughts on using millis() in place of delay for servo pauses?

Thank you

Code:
//SweepwithMillis

#include <PWMServo.h>
PWMServo myservo;
int previousMillisServo = 0;
int pos = 0;  
long servoInterval = 15;
unsigned long currentMillis = 0;

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

void loop() {
  servoSweep();                   
  }


void servoSweep() {
if (currentMillis - previousMillisServo > servoInterval) {
  previousMillisServo = currentMillis;
  for (pos = 0; pos <= 175; pos += 1) { 
    myservo.write(pos);              
    //delay(15);                       
  }
  for (pos = 175; pos >= 0; pos -= 1) { 
    myservo.write(pos);              
    //delay(15);                     
  }
}

@siredward:

The very first time your program calls the servoSweep() function, using the values of currentMillis (which == 0), previousMillisServo (which == 0), & servoInterval (which == 15), your "if" comparison looks like this:

Code:
if (0 - 0 > 15)

With these values, this comparison will never be true, so nothing after this in the servoSweep() function will be executed. Maybe you intended to add the following as the first line in the servoSweep() function:

Code:
currentMillis = millis();

As an alternative, you could just do away with the currentMillis variable & use the millis() call in its place as follows:

Code:
void servoSweep() {
if (millis() - previousMillisServo > servoInterval) {
  previousMillisServo = millis();
  for (pos = 0; pos <= 175; pos += 1) { 
    myservo.write(pos);              
    //delay(15);                       
  }
  for (pos = 175; pos >= 0; pos -= 1) { 
    myservo.write(pos);              
    //delay(15);                     
  }
}

However, this still suffers from another problem: the original code using the delay(15) call will delay 15ms between servo steps, but your modified code will not delay at all between servo steps. Not sure if this is what you intended. Normally, if you want to use the millis() function call to allow you to delay for a fixed amount, you would use the following generic approach (using the previous 15ms delays as an example):

Code:
void servoSweep() {
  for (pos = 0; pos <= 175; pos += 1) { 
    myservo.write(pos);              

    previousMillisServo = millis();

    // delay for the servoInterval
    while ((millis() - previousMillisServo) < servoInterval) ;
  }

  for (pos = 175; pos >= 0; pos -= 1) { 
    myservo.write(pos);              

    previousMillisServo = millis();

    // delay for the servoInterval
    while ((millis() - previousMillisServo) < servoInterval) ;
  }
}

See if that's what you had in mind. Let me know if I misinterpreted you intentions and/or if you have any other questions.


Good luck & have fun !!

Mark J Culross
KD5RXT
 
Mark!! IT WORKS!! (The last function in your post)
Thank you so much for your time and contribution. I am going to study what you did here and learn from it.
Now onwards to see if I can run it simultaneously with the other libraries which were getting interrupted.
Great job!!
 
Mark!! IT WORKS!! (The last function in your post)
Thank you so much for your time and contribution. I am going to study what you did here and learn from it.
Now onwards to see if I can run it simultaneously with the other libraries which were getting interrupted.
Great job!!

Glad that I was able to help. Feel free to ask any other questions & the forum members will do our best to help if/as we can . . .

Mark J Culross
KD5RXT
 
Status
Not open for further replies.
Back
Top