Development and testing of ultrasonic distance measurement library for device HC-SR04.

Dependencies:   TextLCD_improved mbed Distance_HC_SR04

main.cpp

Committer:
dzoni
Date:
2015-12-20
Branch:
CLASS_IMPLEMENTATION
Revision:
4:bb5819be6ac3
Parent:
3:cb5931861f4e
Child:
5:1a69f40177b0

File content as of revision 4:bb5819be6ac3:

/*
 * MAIN.CPP
 */
#include "mbed.h"

#include "TextLCD.h"

#define TIMEOUT_DELAY_US    (25000)
#define CALC_COEFF          (340.0f/(2.0f*1000.0f))
#define TICKS_RANGE_MAX     (15000)
#define TICKS_RANGE_MIN     (150)
#define TRIG_PULSE_US       (50)


typedef enum { IDLE, STARTED, COMPLETED, TIMEOUT, OUT_OF_RANGE_MIN, OUT_OF_RANGE_MAX, ERROR_SIG } Distance_HC_SR04_state;


TextLCD lcd(PA_8, PA_7, PA_9, PA_1, PB_5, PA_10, TextLCD::LCD16x2);

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) : _trig(trig), _echo(echo), _tout_us(tout_us), _coeff(coeff), _tmin_us(tmin_us), _tmax_us(tmax_us) {
        _trig = 0;
        _state = IDLE;
    }

    void trigger(void) {
        if (_state == IDLE && _echo == 0) {
            _timeout.detach();
            _echo.rise(NULL);
            _echo.fall(NULL);
            _timer.stop();
            _timer.reset();   

            _trig = 1;
            wait_us(TRIG_PULSE_US);
            _trig = 0;

            if (_echo == 0) {
                _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 (_state == IDLE) {
            _state = ERROR_SIG;
            _ticks_us = 0;
        }
        
        return;
    }

    Distance_HC_SR04_state getState(void) {
        return _state;   
    }
    
    void reset(void) {
        _state = IDLE;
        _echo.rise(NULL);
        _echo.fall(NULL);
        _timeout.detach();
        _timer.stop();
        _timer.reset();   
    }
    
    uint32_t getTicks(void) {
        return _ticks_us;
    }
    
    float getDistance(void) {
        return _ticks_us*_coeff;
    }
    
    float getCoeff(void) {
        return _coeff;
    }
    
    void setCoeff(float coeff) {
        _coeff = coeff;
    }
    
    float measureDistance(void) {
        return measureTicks()*_coeff;   
    }
    
    uint32_t measureTicks(void) {
        reset();
        trigger();

        while (_state == STARTED)
            ;
            
        _echo.rise(NULL);
        _echo.fall(NULL);
        _timeout.detach();

        switch (_state) {
            case COMPLETED:
                break;
            default:
                _ticks_us = 0;
                break;
        }
                 
        return _ticks_us;   
    }



    void _tout(void) {
        if (_state == STARTED) 
            _state = TIMEOUT;
    }

    void _rising(void) {
        if (_state == STARTED) {
            _timer.start();
        }
    }

    void _falling(void) {
        if (_state == STARTED) {
            _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;
            }
        }
    }
 
private:
    DigitalOut  _trig;
    InterruptIn _echo;
    uint32_t    _tout_us;
    uint32_t    _tmin_us;
    uint32_t    _tmax_us;
    float       _coeff;
    
    Timer       _timer;
    Timeout     _timeout;
    
    volatile Distance_HC_SR04_state _state;
    uint32_t                        _ticks_us;
};
 


int main() {

    wait_ms(250);
    lcd.cls();

    lcd.cls();
    lcd.printf("Row 1");
    lcd.locate(0, 1);    
    lcd.printf("Row 2");

    Distance_HC_SR04 distFront(PB_9, PA_6);
    uint32_t ticks_us;
    float distance;        

    while (true) {
        ticks_us = distFront.measureTicks();
        distance = distFront.getDistance();
        
        lcd.cls();

        switch (distFront.getState()) {
            case COMPLETED:
                lcd.printf("Dist.: %u", ticks_us);
                lcd.locate(0, 1);    
                lcd.printf("Dist.: %.3f", distance);
                
                break;
                
            case TIMEOUT:
                lcd.printf("Dist.: ---");
                lcd.locate(0, 1);    
                lcd.printf("TIMEOUT");
                
                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);
    }
}