/*
  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