Not sure, but you can use the timer in capture mode:
Based on the posted reference link, the code below sends pulses out Pin 27 with a random period between 1 and 2 seconds (I chose a slow pulse rate so the print outs wouldn’t be crazy, but the timer hardware capture can handle much higher frequencies). The pulses are received on Pin 33 and the time interval between the current pulse and the previous one is printed.
#include "Arduino.h"
#include "driver/mcpwm.h"
#include "soc/rtc.h"
#include "hal/mcpwm_hal.h"
bool captureIsr(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_channel, const cap_event_data_t *edata,
void *user_data);
void processCaptures(void *pvParameters);
void sendPulses(void *pvParameters);
constexpr uint32_t cap0IntEn = 1UL << 27;
constexpr uint8_t pulseOutPin = 27;
QueueHandle_t timerCaptureQueue;
void setup() {
constexpr gpio_num_t capturePin = GPIO_NUM_33;
constexpr size_t timerCaptureQueueSize = 10;
pinMode(pulseOutPin, OUTPUT);
digitalWrite(pulseOutPin, HIGH);
timerCaptureQueue = xQueueCreate(timerCaptureQueueSize, sizeof(uint32_t));
assert((timerCaptureQueue != 0) && "Failed to Create timerCaptureQueue");
BaseType_t returnCode = xTaskCreatePinnedToCore(processCaptures, "Process Captures", 1600, NULL, 4, NULL, CONFIG_ARDUINO_RUNNING_CORE);
assert((returnCode == pdTRUE) && "Failed to Create Process Captures");
Serial.begin(115200);
delay(2000);
Serial.println("Starting");
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM_CAP_0, capturePin);
gpio_pullup_en(capturePin);
mcpwm_config_t pwm_config;
pwm_config.frequency = 1000; // Unused in this example
pwm_config.cmpr_a = 50.0; // Unused in this example
pwm_config.cmpr_b = 50.0; // Unused in this example
pwm_config.counter_mode = MCPWM_UP_COUNTER; // Unused in this example
pwm_config.duty_mode = MCPWM_DUTY_MODE_0; // Unused in this example
esp_err_t result = mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
assert((result != ESP_FAIL) && "MCPWM Initialization Failed");
mcpwm_capture_config_t captureConfig {
MCPWM_NEG_EDGE,
1,
captureIsr,
NULL
};
result = mcpwm_capture_enable_channel(MCPWM_UNIT_0, MCPWM_SELECT_CAP0, &captureConfig);
assert((result != ESP_FAIL) && "MCPWM Capture Enable Failed");
returnCode = xTaskCreatePinnedToCore(sendPulses, "Send Pulses", 1600, NULL, 2, NULL, CONFIG_ARDUINO_RUNNING_CORE);
assert((returnCode == pdTRUE) && "Failed to Create Send Pulses");
}
void loop() {
vTaskDelete(NULL);
}
bool IRAM_ATTR captureIsr(mcpwm_unit_t mcpwm, mcpwm_capture_channel_id_t cap_channel, const cap_event_data_t *edata,
void *user_data) {
if (mcpwm != MCPWM_UNIT_0) {
return false;
}
uint32_t mcpwmItrStatus = MCPWM0.int_st.val;
MCPWM0.int_clr.val = mcpwmItrStatus;
if ((cap_channel != MCPWM_SELECT_CAP0) || (edata->cap_edge != MCPWM_NEG_EDGE)) {
return false;
}
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
uint32_t timerValue = mcpwm_capture_signal_get_value(MCPWM_UNIT_0, MCPWM_SELECT_CAP0);
xQueueSendToBackFromISR(timerCaptureQueue, &timerValue, &pxHigherPriorityTaskWoken);
if (pxHigherPriorityTaskWoken == pdTRUE) {
return true;
}
return false;
}
void sendPulses(void *pvParameters) {
TickType_t xLastWakeTime = xTaskGetTickCount();
TickType_t waitTime = 1000;
while (1) {
vTaskDelayUntil(&xLastWakeTime, waitTime);
digitalWrite(pulseOutPin, LOW);
digitalWrite(pulseOutPin, HIGH);
waitTime = 1000 + random(0, 1000);
}
}
void processCaptures(void *pvParameters) {
uint32_t lastTimerCapture;
uint32_t scale = 10000000000ULL / rtc_clk_apb_freq_get();
xQueueReceive(timerCaptureQueue, &lastTimerCapture, portMAX_DELAY); // wait for first capture
while (1) {
uint32_t currentTimerCapture;
xQueueReceive(timerCaptureQueue, ¤tTimerCapture, portMAX_DELAY);
uint64_t deltaTimer = currentTimerCapture - lastTimerCapture;
lastTimerCapture = currentTimerCapture;
uint32_t microSeconds = scale * deltaTimer / 10000;
Serial.printf("Detected Edge, deltaT = %u us\n", microSeconds);
}
}