Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
7 years, 3 months ago.
High accuracy measurement on NUCLEO L432KC
Hi there, I've created following code to measure the time between two pulses:
my code
#include "mbed.h" Timer t; // timer to measure time between two sensor signals Serial device(USBTX, USBRX); // for debug output on terminal InterruptIn sensor(PA_9); // for sensor signal int32_t delta_us = 0; void signalOccurred() { delta_us = t.read_us(); // global delta_us holds time difference between the last two signals now t.reset(); // reset the timer } void sendMessage() { device.printf("Delta = %d\r\n", delta_us); //Debug out //send value via CAN here... } int main() { Timer sendViaCAN; device.baud(115200); device.printf("========== Device started up ==========\r\n"); t.start(); //global sendViaCAN.start(); sensor.rise(&signalOccurred); // attach the address of the signalOccurred function to the rising edge // spin in a main loop and if signal occurs interrupt it! while(1) { if (sendViaCAN.read_ms() >= 20) { sendViaCAN.reset(); sendMessage(); } } }
I've tested it with an Arduino board which has an hardware PWM. The problem with this code is, that it is giving me different results: the values changes several µs. This is not enough accuracy for me and I think the problem lies on the software side. - Is it possible to get a better accuracy with the NUCLEO L432KC?
1 Answer
7 years, 3 months ago.
Hello Peter,
I have tested the code below on NUCLEO-F103RB (using an LPC1768 mbed board as PWM signal generator) and it worked with 1us accuracy (in range from 10us to 4s).
#include "mbed.h" // enum State { IDLE, READY, MEASURING, FINISHED, TIMEOUT }; // const float MEASUREMENT_TIMEOUT = 5.0f; // measurement timeout in seconds // Serial pc(USBTX, USBRX); InterruptIn input(PA_9); Timeout timeout; volatile State state; volatile uint32_t now; volatile uint32_t begin; volatile uint32_t period; /** * @brief ISR handling 'measurement timeout' * @note Called when input line is idle longer than expected. * Signals 'end of measurement' by setting state to TIMEOUT. * @param None * @retval None */ void measurementTimeout(void) { input.disable_irq(); timeout.detach(); state = TIMEOUT; } /** * @brief Measures pulse period (time elapsed between two rising edges) * @note Waits until a rising edge is detected at input or timeout occured. * @param None * @retval None */ void measurePeriod(void) { bool finished; state = READY; timeout.attach(callback(measurementTimeout), MEASUREMENT_TIMEOUT); input.enable_irq(); do { finished = ((state == FINISHED) || (state == TIMEOUT)); } while (!finished); } /** * @brief ISR handling signal rise at input * @note Called on signal rise at input * @param * @retval */ void onInputRise(void) { now = us_ticker_read(); switch (state) { case READY: state = MEASURING; begin = now; break; case MEASURING: input.disable_irq(); timeout.detach(); state = FINISHED; period = now - begin; break; default: break; } } /** * @brief * @note * @param * @retval */ int main(void) { state = IDLE; input.mode(PullDown); input.disable_irq(); input.rise(callback(onInputRise)); while (1) { switch (state) { case IDLE: measurePeriod(); break; case FINISHED: state = IDLE; pc.printf("Pulse period = %dus\r\n", period); wait(1); // prevents PC's serial terminal from overloading when period is very short break; case TIMEOUT: state = IDLE; pc.printf("Measurement timeout. No signal detected at input.\r\n"); break; default: break; } } }
Zoltan