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)

Dependents:   TEST_Dist_lib

Committer:
dzoni
Date:
Fri Apr 13 13:42:47 2018 +0000
Revision:
12:5bf5a7e62c5d
Parent:
11:12f9cb7d88f3
Documentation improvement (including code examples).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dzoni 0:4fbf332e6759 1 #include "Distance_HC_SR04.h"
dzoni 0:4fbf332e6759 2
Jan Tetour 7:a254dc462f4c 3 /**
dzoni 10:89df9c40abc3 4 * Applied rules: 0, 1,
Jan Tetour 7:a254dc462f4c 5 */
Jan Tetour 7:a254dc462f4c 6
dzoni 6:5beda7c318d5 7 /** Create Distance_HC_SR04 instance. Set FSM to IDLE state.
dzoni 6:5beda7c318d5 8 *
dzoni 6:5beda7c318d5 9 */
dzoni 6:5beda7c318d5 10 Distance_HC_SR04::Distance_HC_SR04(PinName trig, PinName echo, uint32_t tout_us, float coeff,
dzoni 6:5beda7c318d5 11 uint32_t tmin_us, uint32_t tmax_us) :
Jan Tetour 7:a254dc462f4c 12 _trig(trig), _echo(echo), _tout_us(tout_us), _coeff(coeff), _tmin_us(tmin_us), _tmax_us(tmax_us)
Jan Tetour 7:a254dc462f4c 13 {
dzoni 11:12f9cb7d88f3 14 _trig = 0;
dzoni 11:12f9cb7d88f3 15 _state = IDLE;
dzoni 6:5beda7c318d5 16 }
dzoni 0:4fbf332e6759 17
dzoni 6:5beda7c318d5 18 /** Measure and return "echo" pulse duration in synchronous blocking mode.
dzoni 6:5beda7c318d5 19 *
dzoni 6:5beda7c318d5 20 * New measurement is started and the code waits for measurement completion or timeout.
dzoni 6:5beda7c318d5 21 *
dzoni 6:5beda7c318d5 22 * @param void -
dzoni 6:5beda7c318d5 23 * @returns
dzoni 6:5beda7c318d5 24 * uint32_t value of distance > 0 in case of a success, 0 in case of an error
dzoni 6:5beda7c318d5 25 */
Jan Tetour 7:a254dc462f4c 26 uint32_t Distance_HC_SR04::measureTicks(void)
Jan Tetour 7:a254dc462f4c 27 {
dzoni 11:12f9cb7d88f3 28 reset();
dzoni 11:12f9cb7d88f3 29 trigger();
dzoni 0:4fbf332e6759 30
dzoni 11:12f9cb7d88f3 31 while (STARTED == _state)
Jan Tetour 7:a254dc462f4c 32 {
dzoni 6:5beda7c318d5 33 ;
Jan Tetour 7:a254dc462f4c 34 }
dzoni 0:4fbf332e6759 35
dzoni 11:12f9cb7d88f3 36 _echo.rise(NULL);
dzoni 11:12f9cb7d88f3 37 _echo.fall(NULL);
dzoni 11:12f9cb7d88f3 38 _timeout.detach();
dzoni 0:4fbf332e6759 39
dzoni 11:12f9cb7d88f3 40 switch (_state)
Jan Tetour 7:a254dc462f4c 41 {
dzoni 6:5beda7c318d5 42 case COMPLETED:
dzoni 6:5beda7c318d5 43 break;
Jan Tetour 7:a254dc462f4c 44
dzoni 6:5beda7c318d5 45 default:
dzoni 11:12f9cb7d88f3 46 _ticks_us = 0;
dzoni 6:5beda7c318d5 47 break;
dzoni 0:4fbf332e6759 48 }
dzoni 0:4fbf332e6759 49
dzoni 11:12f9cb7d88f3 50 return _ticks_us;
dzoni 6:5beda7c318d5 51 }
dzoni 0:4fbf332e6759 52
dzoni 6:5beda7c318d5 53 /** Measure and return the distance in synchronous blocking mode.
dzoni 6:5beda7c318d5 54 *
dzoni 6:5beda7c318d5 55 * New measurement is started and the code waits for measurement completion or timeout.
dzoni 6:5beda7c318d5 56 *
dzoni 6:5beda7c318d5 57 * @param void -
dzoni 6:5beda7c318d5 58 * @returns
dzoni 6:5beda7c318d5 59 * float value of distance > 0.0f in case of a success, 0.0f in case of an error
dzoni 6:5beda7c318d5 60 */
Jan Tetour 7:a254dc462f4c 61 float Distance_HC_SR04::measureDistance(void)
Jan Tetour 7:a254dc462f4c 62 {
dzoni 11:12f9cb7d88f3 63 return measureTicks()*_coeff;
dzoni 6:5beda7c318d5 64 }
dzoni 0:4fbf332e6759 65
dzoni 6:5beda7c318d5 66 /** Reset whole device and prepare for triggering of the next measurement in asynchronous non-blocking mode.
dzoni 6:5beda7c318d5 67 *
dzoni 6:5beda7c318d5 68 * FSM set to IDLE state.
dzoni 6:5beda7c318d5 69 *
dzoni 6:5beda7c318d5 70 */
Jan Tetour 7:a254dc462f4c 71 void Distance_HC_SR04::reset(void)
Jan Tetour 7:a254dc462f4c 72 {
dzoni 11:12f9cb7d88f3 73 _state = IDLE;
dzoni 11:12f9cb7d88f3 74 _echo.rise(NULL);
dzoni 11:12f9cb7d88f3 75 _echo.fall(NULL);
dzoni 11:12f9cb7d88f3 76 _timeout.detach();
dzoni 11:12f9cb7d88f3 77 _timer.stop();
dzoni 11:12f9cb7d88f3 78 _timer.reset();
dzoni 6:5beda7c318d5 79 }
dzoni 0:4fbf332e6759 80
dzoni 6:5beda7c318d5 81 /** Start the measurement in asynchronous non-blocking mode.
dzoni 6:5beda7c318d5 82 *
dzoni 6:5beda7c318d5 83 * Generates pulse on "trig" output and checks proper value of "echo" signal. Sets FSM STATE and exits.
dzoni 6:5beda7c318d5 84 *
dzoni 6:5beda7c318d5 85 * If "echo" is low right after "trig" pulse is generated, sets FSM state to "STARTED".
dzoni 6:5beda7c318d5 86 * In other case FSM sate is set to "ERROR_SIG".
dzoni 6:5beda7c318d5 87 *
dzoni 6:5beda7c318d5 88 */
Jan Tetour 7:a254dc462f4c 89 void Distance_HC_SR04::trigger(void)
Jan Tetour 7:a254dc462f4c 90 {
dzoni 11:12f9cb7d88f3 91 if (IDLE == _state && 0 == _echo)
Jan Tetour 7:a254dc462f4c 92 {
dzoni 11:12f9cb7d88f3 93 _trig = 1;
dzoni 6:5beda7c318d5 94 wait_us(TRIG_PULSE_US);
dzoni 11:12f9cb7d88f3 95 _trig = 0;
dzoni 11:12f9cb7d88f3 96 if (0 == _echo) {
dzoni 11:12f9cb7d88f3 97 _state = STARTED;
dzoni 11:12f9cb7d88f3 98 _timeout.attach_us(this, &Distance_HC_SR04::_tout, TIMEOUT_DELAY_US);
dzoni 11:12f9cb7d88f3 99 _echo.rise(this, &Distance_HC_SR04::_rising);
dzoni 11:12f9cb7d88f3 100 _echo.fall(this, &Distance_HC_SR04::_falling);
dzoni 0:4fbf332e6759 101
dzoni 6:5beda7c318d5 102 return;
dzoni 0:4fbf332e6759 103 }
dzoni 0:4fbf332e6759 104 }
dzoni 0:4fbf332e6759 105
dzoni 11:12f9cb7d88f3 106 if (IDLE == _state) {
dzoni 11:12f9cb7d88f3 107 _state = ERROR_SIG;
dzoni 11:12f9cb7d88f3 108 _ticks_us = 0;
dzoni 6:5beda7c318d5 109 }
dzoni 6:5beda7c318d5 110
dzoni 6:5beda7c318d5 111 return;
dzoni 6:5beda7c318d5 112 }
dzoni 6:5beda7c318d5 113
dzoni 6:5beda7c318d5 114 /** Returns a state of measurement FSM in asynchronous non-blocking mode.
dzoni 6:5beda7c318d5 115 *
dzoni 6:5beda7c318d5 116 * This function is used in asynchronous non-blocking mode.
dzoni 6:5beda7c318d5 117 *
dzoni 6:5beda7c318d5 118 * @returns
dzoni 6:5beda7c318d5 119 * Distance_HC_SR04_state FSM state value.
dzoni 6:5beda7c318d5 120 */
Jan Tetour 7:a254dc462f4c 121 Distance_HC_SR04_state Distance_HC_SR04::getState(void)
Jan Tetour 7:a254dc462f4c 122 {
dzoni 11:12f9cb7d88f3 123 return _state;
dzoni 6:5beda7c318d5 124 }
dzoni 6:5beda7c318d5 125
dzoni 6:5beda7c318d5 126 /** Return measured duration of "echo" pulse in "COMPLETED" state. Use in asynchronous non-blocking mode.
dzoni 6:5beda7c318d5 127 *
dzoni 6:5beda7c318d5 128 * New measurement is not started. Uses result from last measurement.
dzoni 6:5beda7c318d5 129 *
dzoni 6:5beda7c318d5 130 * @returns
dzoni 6:5beda7c318d5 131 * uint32_t Measured duration of "echo" pulse in microseconds.
dzoni 6:5beda7c318d5 132 */
Jan Tetour 7:a254dc462f4c 133 uint32_t Distance_HC_SR04::getTicks(void)
Jan Tetour 7:a254dc462f4c 134 {
dzoni 11:12f9cb7d88f3 135 return _ticks_us;
dzoni 6:5beda7c318d5 136 }
dzoni 6:5beda7c318d5 137
dzoni 6:5beda7c318d5 138 /** Return distance of the obstacle. Use in asynchronous non-blocking mode.
dzoni 6:5beda7c318d5 139 *
dzoni 6:5beda7c318d5 140 * New measurement is not started. Uses result from last measurement.
dzoni 6:5beda7c318d5 141 *
dzoni 6:5beda7c318d5 142 * @returns
dzoni 6:5beda7c318d5 143 * float Distance in milimiters calculated from measured duration of "echo" pulse.
dzoni 6:5beda7c318d5 144 */
Jan Tetour 7:a254dc462f4c 145 float Distance_HC_SR04::getDistance(void)
Jan Tetour 7:a254dc462f4c 146 {
dzoni 11:12f9cb7d88f3 147 return _ticks_us * _coeff;
dzoni 6:5beda7c318d5 148 }
dzoni 6:5beda7c318d5 149
dzoni 6:5beda7c318d5 150 /** Return actual value of coefficient used to calculate distance from "echo" pulse duration.
dzoni 6:5beda7c318d5 151 *
dzoni 6:5beda7c318d5 152 * @returns
dzoni 6:5beda7c318d5 153 * float Value of the coefficient used to multiply time in microseconds to get distance in mm.
dzoni 6:5beda7c318d5 154 */
Jan Tetour 7:a254dc462f4c 155 float Distance_HC_SR04::getCoeff(void)
Jan Tetour 7:a254dc462f4c 156 {
dzoni 11:12f9cb7d88f3 157 return _coeff;
dzoni 6:5beda7c318d5 158 }
dzoni 0:4fbf332e6759 159
dzoni 6:5beda7c318d5 160 /** Set the actual value of coefficient used to calculate distance from "echo" pulse duration.
dzoni 6:5beda7c318d5 161 *
dzoni 6:5beda7c318d5 162 * @param coeff Coeficient for multiplication with pulse duration in microseconds
dzoni 6:5beda7c318d5 163 * @returns
dzoni 6:5beda7c318d5 164 * void -
dzoni 6:5beda7c318d5 165 */
Jan Tetour 7:a254dc462f4c 166 void Distance_HC_SR04::setCoeff(float coeff)
Jan Tetour 7:a254dc462f4c 167 {
dzoni 11:12f9cb7d88f3 168 _coeff = coeff;
dzoni 6:5beda7c318d5 169 }
dzoni 6:5beda7c318d5 170
dzoni 6:5beda7c318d5 171 /** Timeout callback function (private).
dzoni 6:5beda7c318d5 172 *
dzoni 6:5beda7c318d5 173 * @param void -
dzoni 6:5beda7c318d5 174 * @returns
dzoni 6:5beda7c318d5 175 * void -
dzoni 6:5beda7c318d5 176 */
dzoni 6:5beda7c318d5 177 void Distance_HC_SR04::_tout(void) {
dzoni 11:12f9cb7d88f3 178 if (STARTED == _state)
dzoni 11:12f9cb7d88f3 179 _state = TIMEOUT;
dzoni 6:5beda7c318d5 180 }
dzoni 6:5beda7c318d5 181
dzoni 6:5beda7c318d5 182 /** Rising edge callback function (private).
dzoni 6:5beda7c318d5 183 *
dzoni 6:5beda7c318d5 184 * @param void -
dzoni 6:5beda7c318d5 185 * @returns
dzoni 6:5beda7c318d5 186 * void -
dzoni 6:5beda7c318d5 187 */
dzoni 6:5beda7c318d5 188 void Distance_HC_SR04::_rising(void) {
dzoni 11:12f9cb7d88f3 189 if (STARTED == _state) {
dzoni 11:12f9cb7d88f3 190 _timer.start();
dzoni 6:5beda7c318d5 191 }
dzoni 6:5beda7c318d5 192 }
dzoni 6:5beda7c318d5 193
dzoni 6:5beda7c318d5 194 /** Falling edge callback function (private).
dzoni 6:5beda7c318d5 195 *
dzoni 6:5beda7c318d5 196 * @param void -
dzoni 6:5beda7c318d5 197 * @returns
dzoni 6:5beda7c318d5 198 * void -
dzoni 6:5beda7c318d5 199 */
dzoni 6:5beda7c318d5 200 void Distance_HC_SR04::_falling(void) {
dzoni 11:12f9cb7d88f3 201 if (STARTED == _state) {
dzoni 11:12f9cb7d88f3 202 _timer.stop();
dzoni 11:12f9cb7d88f3 203 _ticks_us = _timer.read_us();
dzoni 6:5beda7c318d5 204
dzoni 11:12f9cb7d88f3 205 if (_ticks_us < _tmin_us)
Jan Tetour 7:a254dc462f4c 206 {
dzoni 11:12f9cb7d88f3 207 _ticks_us = 0;
dzoni 11:12f9cb7d88f3 208 _state = OUT_OF_RANGE_MIN;
dzoni 11:12f9cb7d88f3 209 } else if (_ticks_us > _tmax_us)
Jan Tetour 7:a254dc462f4c 210 {
dzoni 11:12f9cb7d88f3 211 _ticks_us = 0;
dzoni 11:12f9cb7d88f3 212 _state = OUT_OF_RANGE_MAX;
Jan Tetour 7:a254dc462f4c 213 } else
Jan Tetour 7:a254dc462f4c 214 {
dzoni 11:12f9cb7d88f3 215 _state = COMPLETED;
dzoni 0:4fbf332e6759 216 }
dzoni 0:4fbf332e6759 217 }
dzoni 6:5beda7c318d5 218 }