/*
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
// SIMULATOR: map 450us to 2550us. REAL SERVO: map 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 1ns (1000us) and 2ms (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
}
}
// 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"
}
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
pot1:GND
pot1:SIG
pot1:VCC
servo1:GND
servo1:V+
servo1:PWM
Loading
ssd1306
ssd1306