ESP32 PWM duty cycle measurement from input
Posted: Wed Mar 02, 2022 2:23 pm
I am trying to measure the duty cycle interval (from falling to rising edge) in microseconds of an incoming PWM signal of 20 KHz.
I made a test PWM signal on a GPIO pin (50% duty) and connected it to input pin.
Up to 80 microseconds it is all good and stable, but if I raise the PWM frequency, below 80 µs the readings start to get unstable and unusable, the value starts jumping around and doesn't show a "real" value. Why so?
I made a test PWM signal on a GPIO pin (50% duty) and connected it to input pin.
Up to 80 microseconds it is all good and stable, but if I raise the PWM frequency, below 80 µs the readings start to get unstable and unusable, the value starts jumping around and doesn't show a "real" value. Why so?
Code: Select all
static void IRAM_ATTR rising_handler(void* arg) {
uint32_t gpio_num = (uint32_t)arg;
xQueueSendFromISR(rising_evt_queue, &gpio_num, NULL);
}
static void rising_task(void* arg) {
uint32_t io_num;
for (;;) {
if (xQueueReceive(rising_evt_queue, &io_num, portMAX_DELAY)) {
// ESP_LOGI(INTERUPT_TAG, "GPIO_INTR_NEGEDGE!!!");
if (gpio_get_level(io_num)) {
// ESP_LOGI(INTERUPT_TAG, "True!!!");
pwm_value = esp_timer_get_time() - prev_time;
}
if (!gpio_get_level(io_num)) {
// ESP_LOGI(INTERUPT_TAG, "False!!!");
prev_time = esp_timer_get_time();
}
}
}
}
void app_main(void) {
initPeriodicTimer(100000); // func to trigger output pin, so it can be readed by input pin
attachInterupt(4, rising_task, rising_handler, GPIO_INTR_ANYEDGE, true);
while (1) {
// if (flag) {
printf("%lu\n", pwm_value);
// flag = false;
// }
vTaskDelay(50 / portTICK_RATE_MS);
}
}
void attachInterupt(uint8_t gpio, voidFuncPtrArg userTask, voidFuncPtrArg isr_handler, uint8_t, triggerEdge, bool installISR) {
gpio_config_t io_conf;
// interrupt of rising edge
io_conf.intr_type = triggerEdge;
// bit mask of the pins, use GPIO4/5 here
io_conf.pin_bit_mask = (1ULL << gpio);
// set as input mode
io_conf.mode = GPIO_MODE_INPUT;
// enable pull-up mode
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
if (installISR) {
// install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
}
rising_evt_queue = xQueueCreate(10, sizeof(uint32_t));
xTaskCreate(rising_task, "gpio_task_example", 2048, NULL, 10, NULL);
// hook isr handler for specific gpio pin
gpio_isr_handler_add(gpio, isr_handler, (void*)gpio);
}