I'm trying to capture a digital signal that consists of 8us HIGH pulses with 8us or 16us LOW pauses in between. There are additional LOW pauses of about 6ms (yes, ms) that separate data frames.
I'm looking to measure the time between rising edges, so I need to measure 16us and 24us intervals while not tripping over those 6000us pauses.
My first attempt was using the Arduino API attachInterupt
in RISING
mode, then getting the time with micros()
in the ISR. That worked somewhat, but also produced lots of wrong data, probably due to interrupt latency. The CPU is also drawing a bit on the display over SPI, not sure if that matters.
As this looks like a good use case for Timer Input Capture, I'm now trying to use the Capture facility of MCPWM. The counter is clocked at 80MHz, which should be plenty of resolution. This is what I have so far:
namespace pins { enum
{
pxx = 17,
}; }
volatile int measure[2];
static void IRAM_ATTR pxxIsr(void*)
{
static uint32_t lastTime;
auto now = mcpwm_capture_signal_get_value(MCPWM_UNIT_1, MCPWM_SELECT_CAP1);
auto dt = now - lastTime;
lastTime = now;
measure[0] = dt;
++measure[1];
MCPWM1.int_clr.val = CAP1_INT_EN;
}
void setup()
{
mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM_CAP_1, pins::pxx);
gpio_pulldown_en((gpio_num_t)pins::pxx);
mcpwm_capture_enable(MCPWM_UNIT_1, MCPWM_SELECT_CAP1, MCPWM_POS_EDGE, 80); // prescale by 80 to directly count us
mcpwm_isr_register(MCPWM_UNIT_1, pxxIsr, nullptr, ESP_INTR_FLAG_IRAM, nullptr);
MCPWM1.int_ena.val = CAP1_INT_EN;
}
The ISR is a bit condensed above, but that's all it does at the moment. measure[1]
increases rapidly while the signal is connected to the pin, so I know the interrupt is working. measure[0]
however is zero most of the time, with the occasional 6-digit number.
Best Answer