Your original solution uses blocking code (the for loops with delay()
calls in them). Surely that works, but it can easily get you in trouble, when extending the project with more functionalities (since nothing else can be done during the sensor movement). So I would suggest a way to ditch all blocking for loops and delays, so that other code can run during the servo movement. For this we can use millis()
and the coding principle from the BlinkWithoutDelay
example, that comes with the Arduino IDE.
#include <Servo.h>
Servo servo1;
int set_angle = 0;
int current_angle = 90; // setting starting angle to 90 degrees
unsigned long servo_timestamp = 0;
#define SERVO_INTERVAL 10 // changing the servo position every 10ms, defines the speed of the servo
void setup()
{
servo1.attach(11); // connect Servo to pin 11
pinMode(A0, INPUT); // Connect potentiometer or Joystick x or y pin to A0 input
}
void loop(){
if(millis()-servo_timestamp > SERVO_INTERVAL){
servo_timestamp += SERVO_INTERVAL; // increment our timestamp by the servo interval
// Measure the new set_angle only, if we really want to move the sensor
int val1 = analogRead(A0); // Read the potentiometer position
set_angle = map(val1, 0, 1023, 0, 180); // Map the value to be used with servo
// Increment or decrement the current angle according to the set_angle
// and don't change it, when we already are at the set_angle
if(set_angle > current_angle){
current_angle++;
} else if(set_angle < current_angle){
current_angle--;
}
// Write the new angle to the servo
servo1.write(current_angle);
}
}
For learning more about the non-blocking coding style using millis()
, you can google for it and look at the BlinkWithoutDelay
example. There are many resources for this on the web. The combination of timestamp and millis()
if statement executes the code inside the if statement at the regular interval SERVO_INTERVAL
. There we read the potentiometer and calculate the new setpoint for the servo angle. Then we increment or decrement the current angle by 1 depending on the set angle. And then we write that new angle to the servo.
You can change the speed by either changing SERVO_INTERVAL
or by in-/decrementing current_angle
by more than only 1.
The code outside the if statement still runs at full speed. So in the (a bit less than) 10ms, that the servo code isn't running, you can execute other code. Also this code will react immediately, where a blocking code would first let the servo run to the set position and only then change again.
Note: The above code isn't tested. It's purpose is to show the principle. There might be small errors, that I haven't seen.