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.h@12:5bf5a7e62c5d, 2018-04-13 (annotated)
- Committer:
- dzoni
- Date:
- Fri Apr 13 13:42:47 2018 +0000
- Revision:
- 12:5bf5a7e62c5d
- Parent:
- 6:5beda7c318d5
Documentation improvement (including code examples).
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dzoni | 12:5bf5a7e62c5d | 1 | /** |
dzoni | 12:5bf5a7e62c5d | 2 | * @file Distance_HC_SR04.h |
dzoni | 12:5bf5a7e62c5d | 3 | * @author Jan Tetour |
dzoni | 12:5bf5a7e62c5d | 4 | * @date 21. Dec 2015 |
dzoni | 12:5bf5a7e62c5d | 5 | * @brief Library for distance measurement with device HC-SR04 and similar. |
dzoni | 12:5bf5a7e62c5d | 6 | * |
dzoni | 12:5bf5a7e62c5d | 7 | * 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) |
dzoni | 12:5bf5a7e62c5d | 8 | * |
dzoni | 12:5bf5a7e62c5d | 9 | * @see https://os.mbed.com/users/dzoni/code/Distance_HC_SR04/ |
dzoni | 12:5bf5a7e62c5d | 10 | */ |
dzoni | 0:4fbf332e6759 | 11 | #ifndef MBED_DISTANCE_HC_SR04_H |
dzoni | 0:4fbf332e6759 | 12 | #define MBED_DISTANCE_HC_SR04_H |
dzoni | 0:4fbf332e6759 | 13 | |
dzoni | 0:4fbf332e6759 | 14 | #include "mbed.h" |
dzoni | 0:4fbf332e6759 | 15 | |
dzoni | 5:2f6992aad3a0 | 16 | #define TIMEOUT_DELAY_US (25000) // Timeout in microseconds |
dzoni | 5:2f6992aad3a0 | 17 | #define CALC_COEFF (340.0f/(2.0f*1000.0f)) // Coefficient for distance calculation (distance = coeff * microseconds) |
dzoni | 5:2f6992aad3a0 | 18 | #define TICKS_RANGE_MAX (15000) // Maximum reliable measurement - echo pulse width in microseconds |
dzoni | 5:2f6992aad3a0 | 19 | #define TICKS_RANGE_MIN (150) // Minimum reliable measurement - echo pulse width in microseconds |
dzoni | 5:2f6992aad3a0 | 20 | #define TRIG_PULSE_US (50) // Width of trigger pulse in microseconds |
dzoni | 0:4fbf332e6759 | 21 | |
dzoni | 12:5bf5a7e62c5d | 22 | /** |
dzoni | 12:5bf5a7e62c5d | 23 | * @brief Definition of measurement FSM states. |
dzoni | 12:5bf5a7e62c5d | 24 | * |
dzoni | 12:5bf5a7e62c5d | 25 | * Measurement FSM (Finite State Machine) states definition. |
dzoni | 6:5beda7c318d5 | 26 | * |
dzoni | 6:5beda7c318d5 | 27 | */ |
dzoni | 12:5bf5a7e62c5d | 28 | typedef enum { |
dzoni | 12:5bf5a7e62c5d | 29 | IDLE, /**< No activity. Ready to start measurement with trigger(). This is state after reset(). */ |
dzoni | 12:5bf5a7e62c5d | 30 | STARTED, /**< Measurement started and in progress. This is state after trigger(). */ |
dzoni | 12:5bf5a7e62c5d | 31 | COMPLETED, /**< Measurement succesfuly completed by falling edge of echo signal. Measured values in range. */ |
dzoni | 12:5bf5a7e62c5d | 32 | TIMEOUT, /**< It was not possible to complete echo pulse width measurement in given time. Measurement cancelled. */ |
dzoni | 12:5bf5a7e62c5d | 33 | OUT_OF_RANGE_MIN, /**< Measurement completed. Measured distance under reliable range. */ |
dzoni | 12:5bf5a7e62c5d | 34 | OUT_OF_RANGE_MAX, /**< Measurement completed. Measured distance over reliable range. */ |
dzoni | 12:5bf5a7e62c5d | 35 | ERROR_SIG /**< Faulty value of echo signal just after trigger pulse (echo != 0). Possible HW fault. */ |
dzoni | 12:5bf5a7e62c5d | 36 | } Distance_HC_SR04_state; |
dzoni | 0:4fbf332e6759 | 37 | |
dzoni | 0:4fbf332e6759 | 38 | /** Distance_HC_SR04 class. |
dzoni | 0:4fbf332e6759 | 39 | * |
dzoni | 0:4fbf332e6759 | 40 | * Library for interfacing ultrasonic distance measurement device HC-SR04. |
dzoni | 4:71f01fbc9246 | 41 | * Works in 2 basic modes: |
dzoni | 6:5beda7c318d5 | 42 | * - blocking (via measureTicks() or measureDistance()) |
dzoni | 6:5beda7c318d5 | 43 | * - non-blocking asynchronous (via reset() + trigger() + getState() + getTicks() or getDistance()) |
dzoni | 4:71f01fbc9246 | 44 | * |
dzoni | 0:4fbf332e6759 | 45 | * Functionality includes detection of error in echo signal, detection of timeout and limits of reliable measurement. |
dzoni | 0:4fbf332e6759 | 46 | * |
dzoni | 0:4fbf332e6759 | 47 | */ |
dzoni | 0:4fbf332e6759 | 48 | class Distance_HC_SR04 { |
dzoni | 0:4fbf332e6759 | 49 | |
dzoni | 0:4fbf332e6759 | 50 | public: |
dzoni | 0:4fbf332e6759 | 51 | Distance_HC_SR04(PinName trig, PinName echo, uint32_t tout_us = TIMEOUT_DELAY_US, float coeff = CALC_COEFF, |
dzoni | 0:4fbf332e6759 | 52 | uint32_t tmin_us = TICKS_RANGE_MIN, uint32_t tmax_us = TICKS_RANGE_MAX); |
dzoni | 0:4fbf332e6759 | 53 | void trigger(void); |
dzoni | 0:4fbf332e6759 | 54 | Distance_HC_SR04_state getState(void); |
dzoni | 0:4fbf332e6759 | 55 | void reset(void); |
dzoni | 0:4fbf332e6759 | 56 | uint32_t getTicks(void); |
dzoni | 0:4fbf332e6759 | 57 | float getDistance(void); |
dzoni | 0:4fbf332e6759 | 58 | float getCoeff(void); |
dzoni | 0:4fbf332e6759 | 59 | void setCoeff(float coeff); |
dzoni | 12:5bf5a7e62c5d | 60 | |
dzoni | 12:5bf5a7e62c5d | 61 | /** |
dzoni | 12:5bf5a7e62c5d | 62 | * @brief Measure (synchronous) distance of the object by reflected ultrasonic signal. |
dzoni | 12:5bf5a7e62c5d | 63 | * |
dzoni | 12:5bf5a7e62c5d | 64 | * Measure the distance from the object by reflected ultrasonic signal in synchronous |
dzoni | 12:5bf5a7e62c5d | 65 | * (blocking) mode. In case of any error, returns 0. Error information can be retrieved via getState() method. |
dzoni | 12:5bf5a7e62c5d | 66 | * |
dzoni | 12:5bf5a7e62c5d | 67 | * Example of usage: |
dzoni | 12:5bf5a7e62c5d | 68 | * @code |
dzoni | 12:5bf5a7e62c5d | 69 | * Distance_HC_SR04 dist(PIN_TRIG, PIN_ECHO); |
dzoni | 12:5bf5a7e62c5d | 70 | * float distance; |
dzoni | 12:5bf5a7e62c5d | 71 | * |
dzoni | 12:5bf5a7e62c5d | 72 | * while (true) { |
dzoni | 12:5bf5a7e62c5d | 73 | * distance = dist.getDistance(); |
dzoni | 12:5bf5a7e62c5d | 74 | * lcd.cls(); |
dzoni | 12:5bf5a7e62c5d | 75 | * |
dzoni | 12:5bf5a7e62c5d | 76 | * switch (dist.getState()) { |
dzoni | 12:5bf5a7e62c5d | 77 | * case COMPLETED: |
dzoni | 12:5bf5a7e62c5d | 78 | * lcd.printf("Dist.: %.3f", dist); |
dzoni | 12:5bf5a7e62c5d | 79 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 80 | * lcd.printf("COMPLETED"); |
dzoni | 12:5bf5a7e62c5d | 81 | * |
dzoni | 12:5bf5a7e62c5d | 82 | * break; |
dzoni | 12:5bf5a7e62c5d | 83 | |
dzoni | 12:5bf5a7e62c5d | 84 | * case TIMEOUT: |
dzoni | 12:5bf5a7e62c5d | 85 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 86 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 87 | * lcd.printf("TIMEOUR"); |
dzoni | 12:5bf5a7e62c5d | 88 | |
dzoni | 12:5bf5a7e62c5d | 89 | * break; |
dzoni | 12:5bf5a7e62c5d | 90 | * case ERROR_SIG: |
dzoni | 12:5bf5a7e62c5d | 91 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 92 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 93 | * lcd.printf("ERROR_SIG"); |
dzoni | 12:5bf5a7e62c5d | 94 | |
dzoni | 12:5bf5a7e62c5d | 95 | * break; |
dzoni | 12:5bf5a7e62c5d | 96 | |
dzoni | 12:5bf5a7e62c5d | 97 | * case OUT_OF_RANGE_MIN: |
dzoni | 12:5bf5a7e62c5d | 98 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 99 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 100 | * lcd.printf("OUT_OF_RANGE_MIN"); |
dzoni | 12:5bf5a7e62c5d | 101 | |
dzoni | 12:5bf5a7e62c5d | 102 | * break; |
dzoni | 12:5bf5a7e62c5d | 103 | |
dzoni | 12:5bf5a7e62c5d | 104 | * case OUT_OF_RANGE_MAX: |
dzoni | 12:5bf5a7e62c5d | 105 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 106 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 107 | * lcd.printf("OUT_OF_RANGE_MAX"); |
dzoni | 12:5bf5a7e62c5d | 108 | |
dzoni | 12:5bf5a7e62c5d | 109 | * break; |
dzoni | 12:5bf5a7e62c5d | 110 | |
dzoni | 12:5bf5a7e62c5d | 111 | * default: |
dzoni | 12:5bf5a7e62c5d | 112 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 113 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 114 | * lcd.printf("OTHER"); |
dzoni | 12:5bf5a7e62c5d | 115 | |
dzoni | 12:5bf5a7e62c5d | 116 | * break; |
dzoni | 12:5bf5a7e62c5d | 117 | * } |
dzoni | 12:5bf5a7e62c5d | 118 | * wait_ms(100); |
dzoni | 12:5bf5a7e62c5d | 119 | * } |
dzoni | 12:5bf5a7e62c5d | 120 | * @endcode |
dzoni | 12:5bf5a7e62c5d | 121 | * @param - |
dzoni | 12:5bf5a7e62c5d | 122 | * @return Object distance in milimeters. 0 in case of error. |
dzoni | 12:5bf5a7e62c5d | 123 | * @see - |
dzoni | 12:5bf5a7e62c5d | 124 | * @note - Calculation can be influenced by changing _coeff via setCoeff() or Distance_HC_SR04(). |
dzoni | 12:5bf5a7e62c5d | 125 | * @warning - |
dzoni | 12:5bf5a7e62c5d | 126 | */ |
dzoni | 0:4fbf332e6759 | 127 | float measureDistance(void); |
dzoni | 12:5bf5a7e62c5d | 128 | |
dzoni | 12:5bf5a7e62c5d | 129 | /** |
dzoni | 12:5bf5a7e62c5d | 130 | * @brief Measure (synchronous) ultrasonic signal travel time. |
dzoni | 12:5bf5a7e62c5d | 131 | * |
dzoni | 12:5bf5a7e62c5d | 132 | * Measure the ultrasonic signal travel time in microseconds in synchronous |
dzoni | 12:5bf5a7e62c5d | 133 | * (blocking) mode. In case of any error, returns 0. Error information can be retrieved via getState() method. |
dzoni | 12:5bf5a7e62c5d | 134 | * |
dzoni | 12:5bf5a7e62c5d | 135 | * Example of usage: |
dzoni | 12:5bf5a7e62c5d | 136 | * @code |
dzoni | 12:5bf5a7e62c5d | 137 | * Distance_HC_SR04 dist(PIN_TRIG, PIN_ECHO); |
dzoni | 12:5bf5a7e62c5d | 138 | * uint32_t ticks_us; |
dzoni | 12:5bf5a7e62c5d | 139 | * |
dzoni | 12:5bf5a7e62c5d | 140 | * while (true) { |
dzoni | 12:5bf5a7e62c5d | 141 | * ticks_us = dist.measureTicks(); |
dzoni | 12:5bf5a7e62c5d | 142 | * lcd.cls(); |
dzoni | 12:5bf5a7e62c5d | 143 | * |
dzoni | 12:5bf5a7e62c5d | 144 | * switch (dist.getState()) { |
dzoni | 12:5bf5a7e62c5d | 145 | * case COMPLETED: |
dzoni | 12:5bf5a7e62c5d | 146 | * lcd.printf("Dist.: %u", ticks_us); |
dzoni | 12:5bf5a7e62c5d | 147 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 148 | * lcd.printf("COMPLETED"); |
dzoni | 12:5bf5a7e62c5d | 149 | * |
dzoni | 12:5bf5a7e62c5d | 150 | * break; |
dzoni | 12:5bf5a7e62c5d | 151 | |
dzoni | 12:5bf5a7e62c5d | 152 | * case TIMEOUT: |
dzoni | 12:5bf5a7e62c5d | 153 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 154 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 155 | * lcd.printf("TIMEOUR"); |
dzoni | 12:5bf5a7e62c5d | 156 | |
dzoni | 12:5bf5a7e62c5d | 157 | * break; |
dzoni | 12:5bf5a7e62c5d | 158 | * case ERROR_SIG: |
dzoni | 12:5bf5a7e62c5d | 159 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 160 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 161 | * lcd.printf("ERROR_SIG"); |
dzoni | 12:5bf5a7e62c5d | 162 | |
dzoni | 12:5bf5a7e62c5d | 163 | * break; |
dzoni | 12:5bf5a7e62c5d | 164 | |
dzoni | 12:5bf5a7e62c5d | 165 | * case OUT_OF_RANGE_MIN: |
dzoni | 12:5bf5a7e62c5d | 166 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 167 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 168 | * lcd.printf("OUT_OF_RANGE_MIN"); |
dzoni | 12:5bf5a7e62c5d | 169 | |
dzoni | 12:5bf5a7e62c5d | 170 | * break; |
dzoni | 12:5bf5a7e62c5d | 171 | |
dzoni | 12:5bf5a7e62c5d | 172 | * case OUT_OF_RANGE_MAX: |
dzoni | 12:5bf5a7e62c5d | 173 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 174 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 175 | * lcd.printf("OUT_OF_RANGE_MAX"); |
dzoni | 12:5bf5a7e62c5d | 176 | |
dzoni | 12:5bf5a7e62c5d | 177 | * break; |
dzoni | 12:5bf5a7e62c5d | 178 | |
dzoni | 12:5bf5a7e62c5d | 179 | * default: |
dzoni | 12:5bf5a7e62c5d | 180 | * lcd.printf("Dist.: ---"); |
dzoni | 12:5bf5a7e62c5d | 181 | * lcd.locate(0, 1); |
dzoni | 12:5bf5a7e62c5d | 182 | * lcd.printf("OTHER"); |
dzoni | 12:5bf5a7e62c5d | 183 | |
dzoni | 12:5bf5a7e62c5d | 184 | * break; |
dzoni | 12:5bf5a7e62c5d | 185 | * } |
dzoni | 12:5bf5a7e62c5d | 186 | * wait_ms(100); |
dzoni | 12:5bf5a7e62c5d | 187 | * } |
dzoni | 12:5bf5a7e62c5d | 188 | * @endcode |
dzoni | 12:5bf5a7e62c5d | 189 | * @param - |
dzoni | 12:5bf5a7e62c5d | 190 | * @return Ultrasonic signal total travel time (including reflected signal) in microseconds. 0 in case of error. |
dzoni | 12:5bf5a7e62c5d | 191 | * @see - |
dzoni | 12:5bf5a7e62c5d | 192 | * @note - |
dzoni | 12:5bf5a7e62c5d | 193 | * @warning - |
dzoni | 12:5bf5a7e62c5d | 194 | */ |
dzoni | 12:5bf5a7e62c5d | 195 | uint32_t measureTicks(void); |
dzoni | 0:4fbf332e6759 | 196 | |
dzoni | 6:5beda7c318d5 | 197 | private: |
dzoni | 0:4fbf332e6759 | 198 | void _tout(void); |
dzoni | 0:4fbf332e6759 | 199 | void _rising(void); |
dzoni | 0:4fbf332e6759 | 200 | void _falling(void); |
dzoni | 0:4fbf332e6759 | 201 | |
dzoni | 0:4fbf332e6759 | 202 | DigitalOut _trig; |
dzoni | 0:4fbf332e6759 | 203 | InterruptIn _echo; |
dzoni | 0:4fbf332e6759 | 204 | uint32_t _tout_us; |
dzoni | 0:4fbf332e6759 | 205 | float _coeff; |
dzoni | 0:4fbf332e6759 | 206 | uint32_t _tmin_us; |
dzoni | 0:4fbf332e6759 | 207 | uint32_t _tmax_us; |
dzoni | 0:4fbf332e6759 | 208 | |
dzoni | 0:4fbf332e6759 | 209 | Timer _timer; |
dzoni | 0:4fbf332e6759 | 210 | Timeout _timeout; |
dzoni | 0:4fbf332e6759 | 211 | |
dzoni | 0:4fbf332e6759 | 212 | volatile Distance_HC_SR04_state _state; |
dzoni | 0:4fbf332e6759 | 213 | uint32_t _ticks_us; |
dzoni | 0:4fbf332e6759 | 214 | }; |
dzoni | 0:4fbf332e6759 | 215 | |
dzoni | 0:4fbf332e6759 | 216 | #endif |