美文网首页我爱编程
[Arduino]超声波测距

[Arduino]超声波测距

作者: Cocoonshu | 来源:发表于2017-11-06 17:28 被阅读212次

    一切开始之前,我们需要先来温习一个中学就学习过的物理原理:

    常温常压下空气中的声速: 340m/s

    德罕姆冲你微笑

    声波雷达原理

    超声波也是声波,它在1个标准大气压下,15℃的空气中的传播速度为340m/s。而声波在传播的过程中遇到障碍物时,会反射也会衍射,所以当我们测量出发出声波和听到回声的时间差,就能估算出声音传播的距离。同时因为超声波频率高波长短,所以衍射低,拘束性好,因此能量衰减也更少,传播的距离也更长,更比耳朵能听到的低频率声音更适合做长距离测量。

    超声波测距原理

    如上图所示,测量步骤为:

    • 发出n个mHz的超声波脉冲,超声波脉冲发射结束时开始计时,记作t0
    • 开始监听mHz的超声波脉冲的回声,监听到n个后结束计时,记作t1
    • 计算时间差t = t1 - t0,为超声波来回两程所花费的时间
    • 计算超声波走过的距离s = v * (t1 - t0) / 2(v为声速)

    声波速度与空气温度的关系

    声波传播速度与传播介质的温度成正比,与传输介质的密度成正比。声波在1个标准大气压下的传播速度与空气温度的关系为:

    v = 331.5 + 0.607t

    v为声波的速度,单位m/s
    t为空气的温度,单位℃

    超声波测距模块

    现在市面上的超声波测距模块很多,比较常见的就算HC-SRxxx系列和US-100系列了,它们甚至可以用于汽车的倒车雷达。基本上都长这个样子,一定会有一个或者两个圆筒筒的超声波收发器。

    超声波模块

    目前这个超声波模块都是使用40kHz的声波,人耳可辨识的声音频率范围在20 ~ 20kHz,模块使用的声音频率超过人耳可识频率上限的2倍,完全对人类的正常生活产生影响。

    它们的测距方式都是大同小异的,通常有TTL方式和GPIO方式两种,GPIO是最通用的一种控制方式,我们就用这个方式为例说明超声波测距模块的用法。
    接线方式如下:

    • Trigger,触发输入端,默认低电平,输入一个时常超过10μs的高电平脉冲即可触发模块发射一组超声波脉冲
    • Echo,回声输出端,默认低电平,模块发射超声波脉冲结束后,回声端就会输出高电平,直到监听到所有超声波脉冲的回声(或监听超时)后才会重新输出低电平
    超声波测距时序

    使用步骤如下:

    • 在拉高Trigger端10μs以上后拉低,以触发模块发射8个40kHz的超声波脉冲
    • 开始监听Echo端,Echo输出高电平时开始计时,Echo输出低电平时结束计时
    • 计算出计时的时长,即为声波一来一回花费的时间
    • 计算声波走过的路程

    如果想要测量得更精确,可以测量环境温度,然后如声波速度与空气温度的关系所述,利用环境温度来修正声波的速度后,再计算声波的距离。温度测量的实现方法详见[Ardunio] DS18B20温度传感器

    编码实现

    #define ULTRASONIC_ECHO_PIN              2
    #define ULTRASONIC_TRIGGER_PIN           4
    #define ULTRASONIC_DISCOVERING_STATE_PIN 13
    #define ULTRASONIC_DISCOVERING_INTERVAL  500000
    
    volatile bool mReadyToDiscovering = true;
    unsigned long mEchoStartTime      = 0;
    unsigned long mEchoEndTime        = 0;
    float         mDistance           = 0.0f;
    
    void trigger();
    void calcDistance();
    void onEcho();
    bool isReadyToDiscovering();
      
    void setup() {
        Serial.begin(115200);
        Serial.println();
        Serial.println("Ultrasonic ranging ready");
    
        // UltraSonic pins setup
        pinMode(ULTRASONIC_ECHO_PIN, INPUT);
        pinMode(ULTRASONIC_TRIGGER_PIN, OUTPUT);
        pinMode(ULTRASONIC_DISCOVERING_STATE_PIN, OUTPUT);
        attachInterrupt(digitalPinToInterrupt(ULTRASONIC_ECHO_PIN), onEcho, CHANGE);
    
        // UltraSonic pins initialization
        digitalWrite(ULTRASONIC_TRIGGER_PIN, LOW);
        digitalWrite(ULTRASONIC_DISCOVERING_STATE_PIN, LOW);
    }
    
    void loop() {
        if (isReadyToDiscovering()) {
            calcDistance();
            trigger();
        }
    }
    
    bool isReadyToDiscovering() {
        if (mReadyToDiscovering) {
            unsigned long now = micros();
            if (now - mEchoEndTime > ULTRASONIC_DISCOVERING_INTERVAL) {
                mReadyToDiscovering = false;
                return true;
            }
        }
        return false;
    }
    
    void trigger() {
        digitalWrite(ULTRASONIC_TRIGGER_PIN, HIGH);
        delayMicroseconds(50);
        digitalWrite(ULTRASONIC_TRIGGER_PIN, LOW);
    }
    
    void onEcho() {
        uint8_t echo = digitalRead(ULTRASONIC_ECHO_PIN);
        unsigned long now = micros();
        if (echo == HIGH) {
            mEchoStartTime = now;
            digitalWrite(ULTRASONIC_DISCOVERING_STATE_PIN, HIGH);
        } else {
            mEchoEndTime = now;
            digitalWrite(ULTRASONIC_DISCOVERING_STATE_PIN, LOW);
            mReadyToDiscovering = true;
        }
    }
    
    void calcDistance() {
        long deltaTime = mEchoEndTime - mEchoStartTime;
        mDistance = 340L * deltaTime / 2000000.0; // s = vt = 340 m/s * time / 2
        Serial.print("Distance = ");Serial.print(mDistance * 100.0);Serial.print("cm, Time = ");Serial.print(deltaTime);Serial.println("us");
    }
    

    相关文章

      网友评论

        本文标题:[Arduino]超声波测距

        本文链接:https://www.haomeiwen.com/subject/zunlmxtx.html