Button operated non-blocking full servo sweep

Hi guys!

I am a very beginner at coding but I would appreciate if someone could help me out.

I found this code that allows non-blocking servo movement and I managed to get two servos working
"simultaneously" with it. The problem is that I have to keep the button(s) pressed for it to do the sweep.
Is there a way to make it do a full sweep with one click and keep it non-blocking (with no delay)?

Original post by "Lasrin" (at the bottom): Operate servo without using delay - Programming Questions - Arduino Forum

Any help would be highly appreciated
Thank you :slight_smile:

block_free_one_servo.ino (1.81 KB)

Is there a way to make it do a full sweep with one click and keep it non-blocking (with no delay)?

You need to detect when the button becomes pressed rather than when it is pressed. The StateChangeDetection example in the IDE shows you how.

It would have been better if you had posted your code here as it is so small.

//működik a gomb de csak akkor hajtja végre a sort ha folyamatosan nyomom
#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 inPin = 2;   // choose the input pin (for a pushbutton)
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
int val = 0;     // variable for reading the pin status

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");
  pinMode(inPin, INPUT);    // declare pushbutton as input
}

 void loop() { 
  val = digitalRead(inPin);  // read input value
  if (val == HIGH)          // check if the input is HIGH (button released)
  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();
}

Note the use of code tags

Thank you UKHeliBob for your advice!

I will have a look at that now.

  cPos = myservo.read();

The read() function tells you where you last told the servo to go to, NOT where the servo is now. Surely you can remember where you last told the servo to go to.