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