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

Distance_HC_SR04.h

Committer:
dzoni
Date:
2018-04-13
Revision:
12:5bf5a7e62c5d
Parent:
6:5beda7c318d5

File content as of revision 12:5bf5a7e62c5d:

/**
 * @file Distance_HC_SR04.h
 * @author Jan Tetour
 * @date 21. Dec 2015
 * @brief Library for distance measurement with device HC-SR04 and similar.
 *
 * 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)
 *
 * @see https://os.mbed.com/users/dzoni/code/Distance_HC_SR04/
 */
#ifndef MBED_DISTANCE_HC_SR04_H
#define MBED_DISTANCE_HC_SR04_H
 
#include "mbed.h"
 
#define TIMEOUT_DELAY_US    (25000)                     // Timeout in microseconds
#define CALC_COEFF          (340.0f/(2.0f*1000.0f))     // Coefficient for distance calculation (distance = coeff * microseconds)
#define TICKS_RANGE_MAX     (15000)                     // Maximum reliable measurement - echo pulse width in microseconds
#define TICKS_RANGE_MIN     (150)                       // Minimum reliable measurement - echo pulse width in microseconds
#define TRIG_PULSE_US       (50)                        // Width of trigger pulse in microseconds

/**
 * @brief Definition of measurement FSM states.
 *
 * Measurement FSM (Finite State Machine) states definition.
 *
 */
typedef enum {
    IDLE,               /**< No activity. Ready to start measurement with trigger(). This is state after reset(). */
    STARTED,            /**< Measurement started and in progress. This is state after trigger(). */
    COMPLETED,          /**< Measurement succesfuly completed by falling edge of echo signal. Measured values in range. */
    TIMEOUT,            /**< It was not possible to complete echo pulse width measurement in given time. Measurement cancelled. */
    OUT_OF_RANGE_MIN,   /**< Measurement completed. Measured distance under reliable range. */
    OUT_OF_RANGE_MAX,   /**< Measurement completed. Measured distance over reliable range. */
    ERROR_SIG           /**< Faulty value of echo signal just after trigger pulse (echo != 0). Possible HW fault. */
} Distance_HC_SR04_state;

/** Distance_HC_SR04 class.
 *
 *  Library for interfacing ultrasonic distance measurement device HC-SR04.
 *  Works in 2 basic modes:
 *    - blocking (via measureTicks() or measureDistance())
 *    - non-blocking asynchronous (via reset() + trigger() + getState() + getTicks() or getDistance())
 *
 *  Functionality includes detection of error in echo signal, detection of timeout and limits of reliable measurement.
 *
 */
class Distance_HC_SR04 {

public:
    Distance_HC_SR04(PinName trig, PinName echo, uint32_t tout_us = TIMEOUT_DELAY_US, float coeff = CALC_COEFF,
            uint32_t tmin_us = TICKS_RANGE_MIN, uint32_t tmax_us = TICKS_RANGE_MAX);
    void trigger(void);
    Distance_HC_SR04_state getState(void);
    void reset(void);
    uint32_t getTicks(void);
    float getDistance(void);
    float getCoeff(void);
    void setCoeff(float coeff);

    /**
     * @brief Measure (synchronous) distance of the object by reflected ultrasonic signal.
     *
     * Measure the distance from the object by reflected ultrasonic signal in synchronous
     * (blocking) mode. In case of any error, returns 0. Error information can be retrieved via getState() method.
     *
     * Example of usage:
     * @code
     * Distance_HC_SR04 dist(PIN_TRIG, PIN_ECHO);
     * float distance;
     *
     * while (true) {
     *     distance = dist.getDistance();
     *     lcd.cls();
     *
     *     switch (dist.getState()) {
     *         case COMPLETED:
     *             lcd.printf("Dist.: %.3f", dist);
     *             lcd.locate(0, 1);
     *             lcd.printf("COMPLETED");
     *
     *             break;

     *         case TIMEOUT:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("TIMEOUR");

     *             break;
     *         case ERROR_SIG:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("ERROR_SIG");

     *             break;

     *         case OUT_OF_RANGE_MIN:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("OUT_OF_RANGE_MIN");

     *             break;

     *         case OUT_OF_RANGE_MAX:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("OUT_OF_RANGE_MAX");

     *             break;

     *         default:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("OTHER");

     *             break;
     *     }
     *     wait_ms(100);
     * }
     * @endcode
     * @param -
     * @return Object distance in milimeters. 0 in case of error. 
     * @see -
     * @note - Calculation can be influenced by changing _coeff via setCoeff() or Distance_HC_SR04().
     * @warning -
     */
    float measureDistance(void);

    /**
     * @brief Measure (synchronous) ultrasonic signal travel time.
     *
     * Measure the ultrasonic signal travel time in microseconds in synchronous
     * (blocking) mode. In case of any error, returns 0. Error information can be retrieved via getState() method.
     *
     * Example of usage:
     * @code
     * Distance_HC_SR04 dist(PIN_TRIG, PIN_ECHO);
     * uint32_t ticks_us;
     *
     * while (true) {
     *     ticks_us = dist.measureTicks();
     *     lcd.cls();
     *
     *     switch (dist.getState()) {
     *         case COMPLETED:
     *             lcd.printf("Dist.: %u", ticks_us);
     *             lcd.locate(0, 1);
     *             lcd.printf("COMPLETED");
     *
     *             break;

     *         case TIMEOUT:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("TIMEOUR");

     *             break;
     *         case ERROR_SIG:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("ERROR_SIG");

     *             break;

     *         case OUT_OF_RANGE_MIN:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("OUT_OF_RANGE_MIN");

     *             break;

     *         case OUT_OF_RANGE_MAX:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("OUT_OF_RANGE_MAX");

     *             break;

     *         default:
     *             lcd.printf("Dist.: ---");
     *             lcd.locate(0, 1);
     *             lcd.printf("OTHER");

     *             break;
     *     }
     *     wait_ms(100);
     * }
     * @endcode
     * @param -
     * @return Ultrasonic signal total travel time (including reflected signal) in microseconds. 0 in case of error. 
     * @see -
     * @note -
     * @warning -
     */
     uint32_t measureTicks(void);

private:
    void _tout(void);
    void _rising(void);
    void _falling(void);

    DigitalOut  _trig;
    InterruptIn _echo;
    uint32_t    _tout_us;
    float       _coeff;
    uint32_t    _tmin_us;
    uint32_t    _tmax_us;

    Timer       _timer;
    Timeout     _timeout;

    volatile Distance_HC_SR04_state _state;
    uint32_t                        _ticks_us;
};
 
#endif