Synchronous and asynchronous library for ultrasonic distance measurement for the device HC-SR04 with error handling functionality (out of range detection, HW error detection). Main features: "echo" puls duration measurement, distance measurement from "echo" pulse duration, detection of "echo" signal malfunction, timeout detection, detection of measured values outside reliable limits (min, max)
Distance_HC_SR04.cpp
- Committer:
- dzoni
- Date:
- 2018-04-13
- Revision:
- 12:5bf5a7e62c5d
- Parent:
- 11:12f9cb7d88f3
File content as of revision 12:5bf5a7e62c5d:
#include "Distance_HC_SR04.h" /** * Applied rules: 0, 1, */ /** Create Distance_HC_SR04 instance. Set FSM to IDLE state. * */ Distance_HC_SR04::Distance_HC_SR04(PinName trig, PinName echo, uint32_t tout_us, float coeff, uint32_t tmin_us, uint32_t tmax_us) : _trig(trig), _echo(echo), _tout_us(tout_us), _coeff(coeff), _tmin_us(tmin_us), _tmax_us(tmax_us) { _trig = 0; _state = IDLE; } /** Measure and return "echo" pulse duration in synchronous blocking mode. * * New measurement is started and the code waits for measurement completion or timeout. * * @param void - * @returns * uint32_t value of distance > 0 in case of a success, 0 in case of an error */ uint32_t Distance_HC_SR04::measureTicks(void) { reset(); trigger(); while (STARTED == _state) { ; } _echo.rise(NULL); _echo.fall(NULL); _timeout.detach(); switch (_state) { case COMPLETED: break; default: _ticks_us = 0; break; } return _ticks_us; } /** Measure and return the distance in synchronous blocking mode. * * New measurement is started and the code waits for measurement completion or timeout. * * @param void - * @returns * float value of distance > 0.0f in case of a success, 0.0f in case of an error */ float Distance_HC_SR04::measureDistance(void) { return measureTicks()*_coeff; } /** Reset whole device and prepare for triggering of the next measurement in asynchronous non-blocking mode. * * FSM set to IDLE state. * */ void Distance_HC_SR04::reset(void) { _state = IDLE; _echo.rise(NULL); _echo.fall(NULL); _timeout.detach(); _timer.stop(); _timer.reset(); } /** Start the measurement in asynchronous non-blocking mode. * * Generates pulse on "trig" output and checks proper value of "echo" signal. Sets FSM STATE and exits. * * If "echo" is low right after "trig" pulse is generated, sets FSM state to "STARTED". * In other case FSM sate is set to "ERROR_SIG". * */ void Distance_HC_SR04::trigger(void) { if (IDLE == _state && 0 == _echo) { _trig = 1; wait_us(TRIG_PULSE_US); _trig = 0; if (0 == _echo) { _state = STARTED; _timeout.attach_us(this, &Distance_HC_SR04::_tout, TIMEOUT_DELAY_US); _echo.rise(this, &Distance_HC_SR04::_rising); _echo.fall(this, &Distance_HC_SR04::_falling); return; } } if (IDLE == _state) { _state = ERROR_SIG; _ticks_us = 0; } return; } /** Returns a state of measurement FSM in asynchronous non-blocking mode. * * This function is used in asynchronous non-blocking mode. * * @returns * Distance_HC_SR04_state FSM state value. */ Distance_HC_SR04_state Distance_HC_SR04::getState(void) { return _state; } /** Return measured duration of "echo" pulse in "COMPLETED" state. Use in asynchronous non-blocking mode. * * New measurement is not started. Uses result from last measurement. * * @returns * uint32_t Measured duration of "echo" pulse in microseconds. */ uint32_t Distance_HC_SR04::getTicks(void) { return _ticks_us; } /** Return distance of the obstacle. Use in asynchronous non-blocking mode. * * New measurement is not started. Uses result from last measurement. * * @returns * float Distance in milimiters calculated from measured duration of "echo" pulse. */ float Distance_HC_SR04::getDistance(void) { return _ticks_us * _coeff; } /** Return actual value of coefficient used to calculate distance from "echo" pulse duration. * * @returns * float Value of the coefficient used to multiply time in microseconds to get distance in mm. */ float Distance_HC_SR04::getCoeff(void) { return _coeff; } /** Set the actual value of coefficient used to calculate distance from "echo" pulse duration. * * @param coeff Coeficient for multiplication with pulse duration in microseconds * @returns * void - */ void Distance_HC_SR04::setCoeff(float coeff) { _coeff = coeff; } /** Timeout callback function (private). * * @param void - * @returns * void - */ void Distance_HC_SR04::_tout(void) { if (STARTED == _state) _state = TIMEOUT; } /** Rising edge callback function (private). * * @param void - * @returns * void - */ void Distance_HC_SR04::_rising(void) { if (STARTED == _state) { _timer.start(); } } /** Falling edge callback function (private). * * @param void - * @returns * void - */ void Distance_HC_SR04::_falling(void) { if (STARTED == _state) { _timer.stop(); _ticks_us = _timer.read_us(); if (_ticks_us < _tmin_us) { _ticks_us = 0; _state = OUT_OF_RANGE_MIN; } else if (_ticks_us > _tmax_us) { _ticks_us = 0; _state = OUT_OF_RANGE_MAX; } else { _state = COMPLETED; } } }