Stuck on making servo work with software timers

I’ve been trying to make a servo that moves back and forth using a software timer. I don’t want to use delays because I have to use the Serial monitor as well. The code is the following right now:

int minVal = 0;
int maxVal = 180;

#include <Servo.h>
Servo servo;

const int SERVOPIN = 9;
const int POTPIN = 0; // you can ignore this for the time being.

void setup() {
  servo.attach(SERVOPIN);
}

void loop() {
  backAndForth();
}

void backAndForth() {
  int val;
  val = analogRead(POTPIN);
  val = map(val, 0, 1023, minVal, maxVal);
  int pos;

  for (pos = minVal; pos <= maxVal; pos += 1) {
    servo.write(pos);
    delay(20);
  }
  for (pos = maxVal; pos >= minVal; pos -= 1) {
    servo.write(pos);
    delay(20);
  }
}

If I implement a software timer in this piece of code (using the Blinkwithoutdelay example sketch), the servo motor spazzes out and, the delay does not work at all. I hope someone could help me. Let me know if I have made any errors while making this post. I’ve just signed up!

PS: I’ve also tried using a library that takes care of software timers but to no avail.

show us what you tried with the millis() approach, no reason it should not work (as long as you take small steps on your way from the current position to the one defined by the pot)

I have to use the Serial monitor as well

then don't forget the Serial.begin()... and don't use pin 0 and 1.

(for readability instead of const int POTPIN = 0;you should doconst byte POTPIN = A0; // A0 easier to understand and pins don't need an int, a byte is enough

Alright, I’ve added your suggestions and moved the potentiometer to analog 5,added the Serial function, and used softwaretimers. The code is the following right now:

int minVal = 0;
int maxVal = 180;

#include <Servo.h>
Servo servo;

const byte SERVOPIN = 9;
const byte POTPIN = A5; // you can ignore this for the time being.

const long eventTimer_1 = 20;
const long eventTimer_2 = 20;

unsigned long prevTime_1;
unsigned long prevTime_2;


void setup() {
  servo.attach(SERVOPIN);
  Serial.begin(9600); // not implemented yet, ignore this.
}

void loop() {
  backAndForth();
}

void backAndForth() {
  int val;
  val = analogRead(POTPIN);
  val = map(val, 0, 1023, minVal, maxVal);
  int pos;
  unsigned long currentTime = millis();

  if ((currentTime - prevTime_1) >= eventTimer_1) {
    for (pos = minVal; pos <= maxVal; pos += 1) {
      servo.write(pos);
    }
    prevTime_1 = currentTime;
  }

  if ((currentTime - prevTime_2) >= eventTimer_2) {
    for (pos = maxVal; pos >= minVal; pos -= 1) {
      servo.write(pos);
    }
    prevTime_2 = currentTime;
}
}

It still does not work, do you have any other suggestions? The servo works fine if I use a delay.

  if ((currentTime - prevTime_2) >= eventTimer_2)
  {
    for (pos = maxVal; pos >= minVal; pos -= 1)
    {
      servo.write(pos);
    }

Are you trying to introduce a waiting period between each servo move ?

Yes, that's what I'm trying to make. I wasn't clear enough :)

As it stands there is no form of timing controlling the servo movement

Put the 2 servo control sections of the code in separate functions, let's call then clockwise and anticlockwise (you can do it in one, but start simple)

Initialise the timing and servo position variables

Now, when you call the clockwise function check whether the required period has elapsed. If not then return from the function at once

If the period has elapsed then move the servo one position by updating the pos variable and writing to the servo.

Save the time of the move ready for next time

Each time you update pos check that it is still in range. If not then don't move the servo. Maybe it is time to change direction, so you need to start calling the anticlockwise function from loop() instead. Use a boolean variable to control which of the two servo movement functions is called and invert its value when pos has reached the end of range

assume your start angle is S and your potentiometer says you need to move to destination angle D assume for sake of simplicity that D is larger than S

so you have to turn (D-S) degrees

(eg: you are at 20° you want to go to 45° --> you need to turn 25°)

now the question is how long do you want this to last ?

if you want fixed speed, say 1° per second, then as you need to cross (D-S) degrees, you'll need (D-S) seconds and so y*ou take a 1° step every ∆t = 1 second*

if you want fixed duration for whatever move say you want 5 second to reach the destination regardless of the difference in angles, then you have to issue (D-S) steps of 1° in those 5 seconds, so you take a 1° step every ∆t = 5 / (D-S) seconds

--> the millis() timing test will be used for checking that ∆t has elapsed and then you take a 1° step ( until you have taken (D-S) steps)