madhephaestus / ESP32Servo

Arduino-compatible servo library for the ESP32
139 stars 55 forks source link

PWM generated by library does not match real measured PWM in certain cases #22

Closed t3chn1ca closed 3 years ago

t3chn1ca commented 3 years ago

I am seeing an issue where the PWM generated does not tally with the PWM measured.

This issue occurs when there is a small delay between 2 calls to writeMicroseconds(), The second call is ignored in this case.

  myservo.writeMicroseconds(1900); //<============ This is the PWM which is seen at the end
  delay(30);
  myservo.writeMicroseconds(1500); //<=============== Ignored, does not have any impact

Sample code to reproduce issue on ESP32 Devkit V1:

#include <ESP32Servo.h>

Servo myservo; 

int servoPin = 13;

int PWM_PIN = 14;
int pwm_value; //Connected to servoPin by wire

#define DELAY_BETWEEN_PWM_CHANGE 30

void setup() {
    // Allow allocation of all timers
    ESP32PWM::allocateTimer(0);
    ESP32PWM::allocateTimer(1);
    ESP32PWM::allocateTimer(2);
    ESP32PWM::allocateTimer(3);
        Serial.begin(115200);
    myservo.setPeriodHertz(50);     
    myservo.attach(servoPin);  
        pinMode(PWM_PIN, INPUT); //Connected to servoPin by wire
}

void loop() {

  delay(1500);
  myservo.writeMicroseconds(1500);
  delay(1000);
  Serial.println("Writing 1900");
  myservo.writeMicroseconds(1900);
  delay(DELAY_BETWEEN_PWM_CHANGE);
  myservo.writeMicroseconds(1500);
  Serial.println("Writing 1500");
  Serial.println("readMicroseconds():"+String(myservo.readMicroseconds()));
  delay(1000);
  pwm_value = pulseIn(PWM_PIN, HIGH);
  Serial.println("PWM measured from pin: "+String(pwm_value));
  Serial.println("==================================================");

  delay(1500);
  myservo.writeMicroseconds(1500);
  delay(1000);
  Serial.println("Writing 1100");
  myservo.writeMicroseconds(1100);
  delay(DELAY_BETWEEN_PWM_CHANGE);
  myservo.writeMicroseconds(1500);
  Serial.println("Writing 1500");
  Serial.println("readMicroseconds():"+String(myservo.readMicroseconds()));
  delay(1000);
  pwm_value = pulseIn(PWM_PIN, HIGH);
  Serial.println("PWM measured from pin: "+String(pwm_value));
  Serial.println("==================================================");
}

Results from above example:

    Writing 1100
    Writing 1500
    readMicroseconds():1499
    PWM measured from pin: 1099
    ==================================================
    Writing 1900
    Writing 1500
    readMicroseconds():1499
    PWM measured from pin: 1899
    ==================================================
    Writing 1100
    Writing 1500
    readMicroseconds():1499
    PWM measured from pin: 1099
    ==================================================
    Writing 1900
    Writing 1500
    readMicroseconds():1499
    PWM measured from pin: 1899
    ==================================================
madhephaestus commented 3 years ago

PulseIn is not a precise measurement. Please use an o-scope to check timing, not the internal pulse measurement from Arduino.