/*
Auto correct servo between 15RPM and 30RPM for Walter
https://wokwi.com/projects/396018983767404545
https://forum.arduino.cc/t/control-velocidad-de-servo-5-5kg-giro-360-entre-15-y-30-rpm/1251242
Make the servo arm hit a limit switch (button).
Use a "button debounce" sketch to read the switch.
Count the "button" presses.
Record button press 1.
Record button press 2.
The difference is the TIME per REVOLUTION.
Continuous servo have different and imperfect values.
These values are approximate:
myservo.write(0); // full-speed counter-clockwise
myservo.write(45); // half-speed counter-clockwise
myservo.write(90); // stop
myservo.write(135); // half-speed clockwise
myservo.write(180); // full-speed clockwise
SERVO RPM to MS/REV
15RPM = 0.00025 = 4000ms/rev (msPerRev)
30RPM = 0.00050 = 2000ms/rev (msPerRev)
ADJUSTING SERVO SPEED
if (msPerRev > 4000) ( < 15RPM) increase servo speed
if (msPerRev < 2000) ( > 30RPM) decrease servo speed
*/
#include "Servo.h" // add servo library
Servo myservo; // Create a servo object
byte servoPin = 3; // servo signal pin
byte buttonPin = 2; // limit switch
bool lastButtonReading, // old button reading LOW/pressed or HIGH/not pressed
newButtonReading, // new button reading
currentButtonState, // new button state
count; // where to store next time reading
int speed = 90; // start at "stop" speed
unsigned long timer, // when the button was pressed
timeout = 50, // debounce time for a ringing button
time0, // first rotation
time1, // second and subsequent rotations
msPerRev; // difference between first and second rotation is ms-per-revolution
void setup() {
Serial.begin(115200); // start Serial Monitor debugging
myservo.attach(servoPin); // attach servo to servo object
myservo.write(90); // stop the motor
pinMode(buttonPin, INPUT_PULLUP); // microswitch
}
void loop() {
buttonRead(); // read the limit switch
}
void buttonRead() {
newButtonReading = digitalRead(buttonPin); // read button pin
if (newButtonReading != lastButtonReading) { // if button pin reading changes...
timer = millis(); // ...start a timer
lastButtonReading = newButtonReading; // ... and store current state
}
if ((millis() - timer) > timeout) { // if button state change was longer than timeout
if (currentButtonState == HIGH && // ... while STATE is NOT pressed
newButtonReading == LOW) { // ... and button IS pressed
if (!time0 && !count) { // if time0 is empty...
time0 = millis(); // ...store the time
Serial.print(" time0:");
Serial.print(time0);
Serial.println(" 'time1' will be the new 'time0'");
}
if (!time1 && count) { // if time1 is empty...
time1 = millis(); // ...store the time
Serial.print(" time1:");
Serial.print(time1);
}
if (time0 && time1) { // two time stamps have readings
msPerRev = time1 - time0; // difference in times is the RPM
Serial.print(" msPerRev:");
Serial.print(msPerRev);
servoWrite(); // change servo speed
// After the first two rotations, make every rotation calibrate the RPM
time0 = time1; // move second timer to first timer
time1 = 0; // clear second timer
}
count = 1; // force storing millis() into time1 only
}
currentButtonState = newButtonReading; // change the button state
}
}
void servoWrite() {
if (msPerRev > 4000) { // < 15RPM
speed++; // increase RP<
if (speed > 180) // maximum clockwise speed is 90 + 90 = 180
speed = 180;
}
if (msPerRev < 2000) { // > 30RPM
speed--; // decrease RP<
if (speed < 91) // minimum clockwise speed 90 + 1 = 91
speed = 91;
}
myservo.write(speed); // change clockwise servo rpm
Serial.print(" speed:");
Serial.println(speed);
}