HC-SR04P读数错误

HC-SR04P reading errors

在我的项目中,我需要测量长达 3-4 米的距离,因此我使用连接到 ESP32 开发板的 HC-SR04P 传感器。

代码是在没有任何第三方库的情况下编写的(尽管受到非常简单的 HC-SR04 arduino 库的启发),在纯 C 中,在从 ESP32 eclipse IDF 插件创建的项目中;没有额外的库或 arduino 代码;只是 RTOS。

当设备启动并且测量非常准确时,一切正常,但过了一段时间(不能确切地说出是什么触发了这个),sensor/devboard 电路(不能说是哪个)开始表现异常: 在 TRIG 脉冲之后,ECHO 引脚在合理的 1 秒超时内没有变为高电平,并且不执行任何测量。

一旦发生这种情况,除非reboot/power开启,否则不会再次执行新的测量;看起来有些事情发生了,不知何故,传感器或通信代码出现故障。

几点观察:

作为参考,计时功能如下(HCSR04_Info 结构仅包含引脚和测量数据);每 30 秒从定时任务中调用它。

uint32_t hcsr04_timing(HCSR04_Info* pDevice)
{
    // TRIG pulse for 10ms
    gpio_set_level(pDevice->trig, 1);
    ets_delay_us(10);
    gpio_set_level(pDevice->trig, 0);

    pDevice->startMicros = esp_timer_get_time();

    // wait for the echo pin HIGH or timeout
    while ((!gpio_get_level(pDevice->echo)) && (esp_timer_get_time() - pDevice->startMicros) <= pDevice->timeout);

    if (!gpio_get_level(pDevice->echo)) {
        pDevice->status = STATUS_OFFLINE;
        ESP_LOGE(TAG, "hcsr04_timing timeout (1)");
        return 0;
    }

    pDevice->startMicros = esp_timer_get_time();

    // wait for the echo pin LOW or timeout
    while ((gpio_get_level(pDevice->echo)) && (esp_timer_get_time() - pDevice->startMicros) <= pDevice->timeout);

    if (gpio_get_level(pDevice->echo)) {
        pDevice->status = STATUS_OFFLINE;
        ESP_LOGE(TAG, "hcsr04_timing timeout (2)");
        return 0;
    }

    pDevice->status = STATUS_ONLINE;
    pDevice->endMicros = esp_timer_get_time();

    return pDevice->endMicros - pDevice->startMicros;
}

感谢任何帮助。谢谢。

这不会产生 10 毫秒的脉冲;这是10我们。最终可能会使您的设备进入未确定状态。

    // TRIG pulse for 10ms
    gpio_set_level(pDevice->trig, 1);
    ets_delay_us(10);
    gpio_set_level(pDevice->trig, 0);

定义ets_delay_us()的头文件中的注释说:In FreeRTOS task, please call FreeRTOS apis.

无论如何,如果在 Arduino-land 中,请使用 delay(10);或 vTaskDelay(pdMS_TO_TICKS(10)) 如果在 FreeRTOS 领域。

根据 campescassiano 关于溢出的建议,解决方案终于出现了。在问题的确切意义上并不是真正的溢出,但密切相关。

终于是代码中的一个愚蠢的错误,所以如果合适请关闭或删除问题。

问题是 pDevice->startMicros 被定义为 uint32_t(可能是因为 copy/paste 或坏习惯错误),而 esp_timer_get_time() returns微秒作为 uint64_t.

所以它 'overflows' 在启动后大约 1h 11m 34s(大约 232 微秒),并且超时计算停止,因为 (esp_timer_get_time() - pDevice->startMicros) 将显然是 uint64_t.

因为 (esp_timer_get_time() - pDevice->startMicros) <= pDevice->timeout 在 1h 11m 34s 之后总是 false,所以在获得 ECHO 输入之前循环中断。