这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【2026 Let's do 第2期】简易超声波测距仪实践过程帖

共1条 1/1 1 跳转至

【2026 Let's do 第2期】简易超声波测距仪实践过程帖

助工
2026-09-14 20:46:19     打赏

通过串口向电脑传送数据

硬件准备

  • NXP FRDM-MCXA153 开发板 1 块

  • 上位机电脑 1 台


开发环境说明

        本次活动我尝试使用 Zephyr 进行开发,在 Zephyr 官方恰好有本次活动的开发支持。基于 Zephyr 可以非常简单地实现与上位机的串口通信。只需要新建工程后配置启动 Console 即可。


代码实现

prj.conf 配置串口使能

CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_UART_MCUX_LPUART=y


Zephyr 串口输出日志

LOG_INF("[DBG][seq=%" PRIu32
			"] echo=%" PRIu32 " us raw=%" PRIu32
			" mm median=%" PRIu32 " mm filtered=%" PRIu32
			" mm state=%s err=%" PRId32,
			data.sequence, data.echo_time_us,
			data.raw_distance_mm, data.median_distance_mm,
			data.filtered_distance_mm,
			ranging_state_name(data.state), data.error_code);


效果展示


MCU读取超声波模块数据并传到上位机上

结构与工作原理


工作原理时序

  1. 外部 微控制器 向 TRIG 引脚发送一个至少 10μs 的高电平脉冲,触发模块发射超声波。

  2. 超声波发射头发射超声波信号。

  3. 超声波在空气中传播,遇到障碍物后反射回来,被超声波接收头接收并转换为电信号。

  4. 接收信号经过放大、滤波和整形后,从 ECHO 引脚输出一个高电平信号,其持续时间与超声波的传播时间成正比。

  5. 外部微控制器通过测量 ECHO 引脚高电平的持续时间,并根据超声波的传播速度(在空气中约为 340 m/s),计算出障碍物与模块之间的距离。距离 = 高电平时间*声速(340 M/S)/ 2


声速与温度补偿

硬件准备

  • NXP FRDM-MCXA153 开发板 1 块

  • HC-SR04 超声波距离传感器模块 1 块

  • Arduino 传感器拓展板 1 块

  • 杜邦线 若干

  • 上位机电脑 1 台


        为了方便接线,我将 HC-SR04 超声波距离传感器模块 连接到了 Arduino 接口的 IIC 接口,HC-SR04 的 Trig 引脚接到 Arduino 的 D15,Echo 引脚接到 Arduino 的 D14。如下图所示:


代码实现

// 触发测量
ret = gpio_pin_set_dt(&trig_gpio, 1);
if (ret != 0) {
  measurement_active = false;
  return ret;
}

// 维持触发测量高电平时长
k_busy_wait(APP_TRIG_PULSE_US);

// 触发测量结束,重置 Trig 引脚为低电平
ret = gpio_pin_set_dt(&trig_gpio, 0);
if (ret != 0) {
  measurement_active = false;
  return ret;
}

// 等待测量完成信号量
ret = k_sem_take(&echo_complete,
      K_MSEC(CONFIG_APP_HCSR04_ECHO_TIMEOUT_MS));
if (ret != 0) {
  key = irq_lock();
  measurement_active = false;
  waiting_for_rise = true;
  irq_unlock(key);
  return -ETIMEDOUT;
}

// 计算测量结果下降沿和上升沿时长
pulse_cycles = (uint32_t)(fall_cycle - rise_cycle);
pulse_us = k_cyc_to_us_floor64((uint64_t)pulse_cycles);
if (pulse_us > UINT32_MAX) {
  return -ERANGE;
}

*echo_time_us = (uint32_t)pulse_us;
// 计算距离,单位 mm。
*distance_mm = (uint32_t)((pulse_us * 343U) / 2000U);


效果展示


MCU与显示屏通信并使其显示数字

硬件准备

  • NXP FRDM-MCXA153 开发板 1 块

  • M5Stack StickS3 开发板 1 块

  • Arduino 传感器拓展板 1 块

  • 杜邦线 若干

  • 上位机电脑 1 台


        这里我使用了一个 M5Stack StickS3 开发板作为显示器显示距离数据,我使用 M5Stack StickS3 开发板的 Grove 接口作为串口,读取串口距离数据进行显示。

// 测距仪结果帧:DIST,<序列号>,<距离mm|INVALID>,<状态>
DIST,125,248,NORMAL
DIST,126,INVALID,TIMEOUT


代码实现

auto& d = M5.Display;

const char* unitText = (currentUnit == UNIT_CM) ? "cm" : "mm";
float shownDistance = (currentUnit == UNIT_CM)
                          ? (latestDistanceMm / 10.0f)
                          : latestDistanceMm;

char valueBuf[24];
if (hasValidData) {
    snprintf(valueBuf, sizeof(valueBuf), "%.2f %s",
              shownDistance, unitText);
} else {
    snprintf(valueBuf, sizeof(valueBuf), "--.-- %s", unitText);
}

// 数值使用等宽粗体,宽度超出屏幕时自动缩小
d.setTextFont(&fonts::FreeMonoBold18pt7b);
d.setTextSize(1.0f);
float rawWidth = d.textWidth(valueBuf);
float scale = 1.0f;
float maxWidth = static_cast<float>(d.width()) - 12.0f;
if (rawWidth > maxWidth) {
    scale = maxWidth / rawWidth;
}
d.setTextSize(scale);
d.setTextDatum(middle_center);
d.setTextColor(TFT_WHITE, TFT_BLACK);
// 擦除数值区域,防止位数变短时残留旧字符
d.fillRect(0, d.height() / 2 - 24, d.width(), 48, TFT_BLACK);
d.drawString(valueBuf, d.width() / 2, d.height() / 2);


效果展示




共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]