/*
Servo PWM without library
Most 180 degree servos use a pulse train with 5% to 10% duty cycle at 50Hz (50 pulses per second)
1ms to 2 ms (1000us to 2000us) ON, 19ms to 18ms OFF (18000us to 19000us) over 20ms (20000us)
_ _ x
_|1|_______________19.0| |___________________x 0 degrees
___ ___ x
_|1.5|_____________18.5| |_________________x 90 degrees
____ ____ x
_|2.0 |____________18.0| |________________x 180 degrees
- start timer
- write PWM HIGH = begin EVENT 1
- check timer for 1ms to 2ms (the angle you need, adjusted for your servo)
- write PWM LOW = end EVENT 1
- wait 19ms to 18ms (note this is the 20ms remainder of the 1ms to 2ms pulse)
- any number of EVENTs can be started and ended at any time
*/
unsigned long totalTime = 20000; // PWM time a 20ms/50Hz pulse cycle
unsigned long oldTime, currentMicros, previousMicros = 0; // timers
byte potPin = A0; // potentiometer pin
byte servoPin = 9; // servo pin
void setup() {
Serial.begin(115200); // for debug
pinMode(servoPin, OUTPUT); // servo pin
digitalWrite(servoPin, HIGH); // begin "ON" pulse
}
void loop() {
bool timeONFlag, timeOFFFlag; // indicate xTime has finished
int potentiometerValue; // potentiometer reading
potentiometerValue = analogRead(potPin); // read the potentiometer
// Map 450us to 2550us for simulator. Use 1000us to 2000us (1ms to 2ms) for average servo
unsigned long timeON = map(potentiometerValue, 0, 1023, 440, 2550);
unsigned long timeOFF = totalTime - timeON; // calculate timeOFF LOW signal
// print only changing values
if (oldTime != timeON) {
Serial.print("Pulse width: ");
Serial.println(timeON);
oldTime = timeON;
}
currentMicros = micros(); // start a new pulse train timer
// EVENT 1 - PWM OFF
// - occurs between 1ms and 2ms (1000us and 2000us) after start pulse to end HIGH pulse
if (currentMicros - previousMicros >= timeON) { // bypass this for condition 1000us to 2000us
if (timeONFlag == 0) { // test if timeON has previously been tested
digitalWrite(servoPin, LOW); // set pulse OFF for timeOFF
timeONFlag = 1; // timeON is finished, do not enter this condition until end of timeOFF
// previousMicros = currentMicros; // previousMicros is new "zero" for timeOFF
}
}
// EVENT 2 - PWM ON
// - occurs every 20ms (20000us, 50Hz) to start a new pulse
if (currentMicros - previousMicros >= timeOFF) { // bypass this for condition 18000us to 19000us
timeONFlag = 0; // timeOFF is finished at 20ms. Reset timeONFlag
digitalWrite(servoPin, HIGH); // set pulse ON to begin timeON
previousMicros = currentMicros; // previousMicros is new reference time "zero"
}
}