hello,小伙伴们。这里是少卿。
最近手上刚好有个Arduino板和超声波模块,想着搭建一个小demo,希望能分享给大家。
硬件模块部分
硬件具体由以下部分组成,均可以再wokwi的Arduino Uno的模块库中找到





引脚连接
硬件引脚连接部分如图


仿真连接

代码如下
主要有几个
cpp
#include <LiquidCrystal_I2C.h>
#define TRIG 6
#define ECHO 5
#define GREEN 4
#define YELLOW 3
#define RED 2
#define BUZZ 13
#define BUTTON A0
LiquidCrystal_I2C lcd(0x27, 16, 2);
const char* NAME[4] = { "SAFE", "CAUTION", "WARNING", "STOP" }; // 屏幕文字
int cm = -1; // 距离(cm);-1 = 没测到
int state = 0; // 0=SAFE 1=CAUTION 2=WARNING 3=STOP
int mode = 0; // 0=ALARM 1=MUTE
int bad = 0; // 连续没测到的次数
unsigned long t100 = 0, tRed = 0, tBeep = 0, tPress = 0; // 计时
bool redOn = false, beepOn = false, pressed = false;
/* 测距:Wokwi 官方 HC-SR04 示例写法(脉宽 / 58 = 厘米) */
int distance() {
digitalWrite(TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
unsigned long us = pulseIn(ECHO, HIGH, 40000); // 40ms 超时
if (us == 0) return -1; // 没回波
int d = us / 58;
if (d > 500) return -1; // 离谱值
return (d > 400) ? 400 : d; // 量程封顶
}
/* LCD屏幕:补空格到 16 位,刷新无残留 */
void line(int row, String s) {
while (s.length() < 16) s += ' ';
lcd.setCursor(0, row);
lcd.print(s);
}
void setup() {
pinMode(TRIG, OUTPUT); pinMode(ECHO, INPUT);
pinMode(GREEN, OUTPUT); pinMode(YELLOW, OUTPUT); pinMode(RED, OUTPUT);
pinMode(BUZZ, OUTPUT); pinMode(BUTTON, INPUT_PULLUP);
lcd.init();
lcd.backlight();
}
void loop() {
unsigned long now = millis();
/* 每 100ms 测一次 + 刷屏
偶发丢回波沿用上次值,连续 3 次才显示 */
if (now - t100 >= 100) {
t100 = now;
int d = distance();
if (d >= 0) { cm = d; bad = 0; }
else if (++bad >= 3) cm = -1;
/* 临界判断:等号位置就是采分点 */
if (cm < 0 || cm > 100) state = 0; // SAFE
else if (cm >= 50) state = 1; // CAUTION
else if (cm >= 20) state = 2; // WARNING
else state = 3; // STOP
/* 距离 / 状态 + 模式(各字段间留空格) */
line(0, cm < 0 ? String("D: --- cm") : "D: " + String(cm) + " cm");
line(1, String(NAME[state]) + (mode ? " MUTE" : " ALARM"));
}
/* 三色灯:绿/黄常亮,WARNING 250/250,STOP 越近闪得越快 */
digitalWrite(GREEN, state == 0);
digitalWrite(YELLOW, state == 1);
unsigned long half = (state == 3) ? 40 + cm * 10 : 250;
if (state > 1) {
if (now - tRed >= half) { tRed = now; redOn = !redOn; }
} else {
redOn = false;
}
digitalWrite(RED, redOn);
/* 蜂鸣器:WARNING 500/500,STOP 125/125; MUTE 立即静音 */
unsigned long halfBeep = (state == 2) ? 500 : (state == 3) ? 125 : 0;
if (mode == 0 && halfBeep > 0) {
if (now - tBeep >= halfBeep) {
tBeep = now;
beepOn = !beepOn;
if (beepOn) tone(BUZZ, 2000); else noTone(BUZZ);
}
} else if (beepOn) {
beepOn = false;
noTone(BUZZ);
}
/* 只有 WARNING/STOP 下按键才切模式
按下沿 + 50ms 消抖 + 长按不连发 */
int b = digitalRead(BUTTON);
if (b == LOW && !pressed) {
pressed = true;
if (now - tPress > 50) {
tPress = now;
if (state > 1) mode = 1 - mode;
}
}
if (b == HIGH) pressed = false;
}