Servo & Potentiometer
This assignment was a really great refresher for me on servos, circuits, and Arduino programming. Essentially, how the program works is that by default, Servo library does not have a speed control. Which means to get a speed, we need to have the rotation of the servo divided by certain amount of time to reach it. In other words, we need a clock counter (something akin to blink without delay), gain the potentiometer values, map it, and then apply that to the Sweeper class.
In Action



What was tricky?
When I was programming the Arduino, I stopped after a while and just thought of a few things:
- We need to have an internal clock that is the
millis()andlastUpdate()that acts as a “counter” and “store” the servo’s state. This is important because, - When the button is not pressed, then the servo stops, but when its pressed, it has to continue moving with the same speed and state from where it left off previously
- This also means we have to change
someparts of the original SparkFun code
#include <Servo.h>21 collapsed lines
const byte potMeterPin = A3; // Potentiometer Portconst byte buttonPin = 2; // Button pin for easier changingconst long interval = 0; // Interval for speedint potMeterValue=0; // Potentiometer initial valuebyte rotation=0; // Rotation for servo
unsigned long previousMillis = 0; // will store last time LED was updated
// Code taken from Sparkfun// Written & Modified by Ahmad Dahlan Hafizh// 28 Jan 2026
///// HOW THE PROGRAM WORKS //////
/// By default, Servo library does not have a speed control. Which means to get a speed, we need to have the rotation of the servo divided by certain amount of time to reach it/// In other words, we need a clock counter (blink without delay), and then apply that to the Sweeper class/// We also need to map out the potentiometer values to the speed
///// CLASS SERVO /////
class Sweeper{ Servo servo; // the servo int pos; // current servo position int increment; // increment to move for each interval int updateInterval; // interval between updates int rotation; unsigned long lastUpdate; // last update of position
18 collapsed lines
public: // We can delete the need for passing int values in Sweeper() because we are going to use update Sweeper() { lastUpdate = 0; }
void Attach(int pin) { servo.attach(pin); }
void Detach() { servo.detach(); }
// If we have update, then we also need to save the update information in the event that the button is not pressed, so that the counter doesn't reset. Let's add that. void Update(int speed) { if((millis() - lastUpdate) > speed) // time to update { lastUpdate = millis(); pos += increment;
servo.write(pos); Serial.println(pos);
if ((pos >= 180)) // end of sweep { pos = 180; increment = -1; }
else if (pos <= 0) { pos = 0; increment = 1; } } }
void Rotation(int rotation) { servo.write(rotation); }};
Sweeper sweeper1;9 collapsed lines
void setup(){ Serial.begin(9600); pinMode(buttonPin, INPUT_PULLUP); pinMode(potMeterPin,INPUT); //potentiometer is an input=>it sends information to the computer sweeper1.Attach(10);}
void loop(){
// Read Potentiometer and map to a speed interval (e.g 5ms to 100ms) int potValue = analogRead(potMeterPin); int speed = map(potValue, 0, 1023, 5, 100);
// Check button state if (digitalRead(buttonPin) == LOW) { sweeper1.Update(speed); }
// Debugging static unsigned long lastPrint = 0; if (millis() - lastPrint > 500) { Serial.print("Speed Interval: "); Serial.println(speed); lastPrint = millis(); }}In the beginning, because I was using SparkFun’s original code for turning from 0-180-0, it only worked one way for some reason? But then, I just changed the pos code to increment and decrement only when reaching 180 and 0 which worked. Overall, this was pretty fun practice!
Resources
Servo Motor Basics Controlling Servo with Potentiometer Adjusting Servo Speed