如何解决HC-SR04P 读取错误
在我的项目中,我需要测量长达 3-4m 的距离,因此我使用了连接到 ESP32 开发板的 HC-SR04P 传感器。
代码是在没有任何第三方库的情况下编写的(虽然受到了一个非常简单的 HC-SR04 arduino 库的启发),在从 ESP32 eclipse IDF 插件创建的项目中使用纯 C 语言编写;没有额外的库或 arduino 代码;只是实时操作系统。
当设备启动并且测量非常准确时一切正常,但过了一段时间(不能确切地说是什么触发了这个),传感器/开发板电路(不能说是哪个)开始出现奇怪的行为:在 TRIG 之后脉冲,ECHO 引脚在合理的 1 秒超时内不会变为高电平,并且不执行任何测量。
一旦发生这种情况,除非重新启动/上电,否则不会再次执行新的测量;看起来好像发生了一些事情,并且不知何故传感器或通信代码中存在错误状态。
一些观察:
- 传感器是采用 3.3V 供电的正确版本。
- HC-SR04P 将 GPIO2 和 GPIO4 用于 TRIG 和 ECHO。
- 测量不需要频繁,因此测量任务的计时器为 30 秒。
- 开机后,一切正常。
- 通过开发板微动开关复位后,一切正常。
- 当超时发生时,重新初始化传感器(设置 GPIO 等),但没有任何反应;仍然超时。
作为参考,时序函数如下(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 ms 的脉冲;这是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
(可能是因为复制/粘贴或坏习惯错误),而 esp_timer_get_time()
返回微秒作为 uint64_t
.
因此它在启动后大约 1h 11m 34s(大约 232 微秒)“溢出”,并且超时计算关闭,因为 (esp_timer_get_time() - pDevice->startMicros)
显然将是 {{1} }.
因为 uint64_t
在 1h 11m 34s 之后总是假的,所以循环在得到 ECHO 输入之前中断。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。