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;
}
}
}