便携测距仪 DIY 套件:Arduino Nano + HC-SR04 + 18650 电池 + 3D 打印外壳
组件与物料
| Arduino Nano R3 | ×1 |
| HC-SR04 超声波测距模块 | ×1 |
| 18650 锂电池 | ×1 |
| TP4056 锂电池充电板 | ×1 |
| DC-DC 5V 升压模块 | ×1 |
| 蜂鸣器 | ×1 |
| 旋转电位器 | ×1 |
| 滑动开关 | ×1 |
| LED (红×2、绿×1、蓝×1) | ×4 |
| 330 Ω 电阻 | ×2 |
| M3×10 螺丝 | ×4 |
| 18 AWG 导线 | ×1 |
| 3D 打印外壳 (3 件) | ×1 |
| 三脚架螺纹转接头 | ×1 |
必需工具
- 3D 打印机(我用 Anet A8)
- 电烙铁
- 热熔胶枪
- Dremel 旋转工具(或同类工具)
应用与在线服务
- Arduino IDE (需安装
NewPing库) - Simplify3D 或任意切片软件
项目简介
缘起
Lehman 学院运动科学系研究力量训练,发现受试者动作幅度不一致影响数据。受邀开发一款装置,识别器械/大重量训练的完整运动幅度。需满足:距离可调、非永久固定、兼容三脚架、无线缆。
物料概览


选型基于手头现有材料,非最优解。若用定制 PCB、SMT 元件或 LiPo 电池可大幅缩小体积。
代码逻辑
需安装 NewPing 库。蜂鸣频率、上下限阈值为全局变量可调。上下限指传感器触发距离范围,映射自电位器模拟值 [0,5]V。
int frequency = 700; // 蜂鸣频率 Hz
int lower_bound = 60; // 最小触发距离 mm
int upper_bound = 200; // 最大触发距离 mm
上电蜂鸣 3 声提示启动成功 (setup())。loop() 持续读取超声波距离,与电位器设定阈值比较:距离小于阈值则蜂鸣器响并点亮指示灯。
3D 打印


模型考虑 3D 打印工艺:用 45° 倒角减少悬空与支撑,间隙宽裕适配不同打印机校准。我的打印耗时:顶盖 2h40min、底座 2h20min、旋钮 20min。文件已上传 Thingiverse 或见文末合并文件。
组装


先不接线试装确认尺寸。废弃 IDE 线提供导线,成组剥离保持整齐。电子元件多安装在同一打印件上,需规划走线。


TP4056 板载 SMD 指示灯拆除,飞线接 3mm 直插 LED(板载限流电阻保留)。Arduino Nano 仅 2 个 GND 焊盘,用洞洞板扩展 GND 与 5V 总线(见下图红 X 处切断铜箔防止短路)。



元件在外壳外焊接完成,反复试装测量线长、检查干涉。电位器轴剪短 6mm 减少突出。18650 直接焊接(不规范,易过热损坏,量产应点焊镍带)。热熔胶固定电子件(仅限原型,量产应用机械结构)。



总结与改进方向
回顾更倾向用红外测距(视野窄、最大距离 ~1m),但实验前无法知晓。二版计划:改用 LiPo 电池省去笨重转接螺母(标准三脚架 1/4" 螺母即可);定制 PCB 体积减半。两周从概念到交付,原型尚可。
未来规划
超声波局限:视野角 ±15° 导致侧向物体误触发;被测平面不垂直声波则无反射波。工程师伙伴提议倒装:传感器固定在移动杠铃上朝下对准地面,地面成固定反射面,消除视野角误差。随货附赠的 1/4"→3/8"→1/4" 转接头正好派上用场。待拿到 Dremel 后重新建模安装座,减重优化。敬请期待!
代码
RangeDetectionDevice.ino (Arduino)
/** Viktor Silivanov 3/22/2018 Portable distance detection device using the HC-SR04 Ultrasonic sensor with distance adjustment for triggering the buzzer. **/
//******************** Libraries ****************************************************************************************************************************************************************************************************************
#include <NewPing.h>
//******************** Pins *********************************************************************************************************************************************************************************************************************
#define wiper A5
#define echo 2
#define trig 3
#define ON_LED 7
#define buzzer 8
#define buzzer_LED 9
//******************** Global Variables **********************************************************************************************************************************************************************************************************
int frequency = 700;
int lower_bound = 60;
int upper_bound = 200;
int buzz_time = 250;
int buzz_delay = 280;
int max_distance = 400;
int i = 0;
int distance;
int threshold;
NewPing sonar(trig, echo, max_distance);
//******************** Setup ********************************************************************************************************************************************************************************************************************
void setup() {
Serial.begin(9600);
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
pinMode(buzzer, OUTPUT);
pinMode(buzzer_LED, OUTPUT);
pinMode(ON_LED, OUTPUT);
digitalWrite(ON_LED, HIGH);
while(i < 3){
digitalWrite(buzzer_LED, HIGH);
tone(buzzer, frequency, buzz_time);
delay(buzz_delay);
i++;
}
digitalWrite(buzzer_LED, LOW);
}
//******************** Runs Endlessly ***********************************************************************************************************************************************************************************************************
void loop() {
distance = sonar.ping_cm();
threshold = analogRead(wiper);
threshold = map(threshold, 0, 1023, lower_bound, upper_bound);
if(distance != 0 && distance < threshold){
tone(buzzer, frequency);
digitalWrite(buzzer_LED, HIGH);
} else{
noTone(buzzer);
digitalWrite(buzzer_LED, LOW);
}
// serial_test(); // Uncomment for debug
}
//******************** Test Function ************************************************************************************************************************************************************************************************************
void serial_test(){
Serial.print("Ping: "); Serial.print(distance); Serial.println("cm");
Serial.print("Range: ["); Serial.print(lower_bound); Serial.print(", "); Serial.print(upper_bound); Serial.println("] cm");
Serial.print("Threshold: "); Serial.print(threshold); Serial.println("cm");
delay(100);
}
自定义零件与外壳
三个零件合并为单一文件
原理图

制造工艺
- 基于 Edge Impulse 的 TinyML 语言检测器:Arduino Nano 33 BLE Sense 实战
- Arduino Nano 与 MPU-6050 构建实时陀螺仪游戏
- Arduino 数字骰子:LCD 显示随机点数的电子骰子
- 用 Arduino Nano 自制 37 灯珠轮盘赌游戏机
- ATtiny85 迷你街机:贪吃蛇 — 打造掌上 OLED 游戏机
- 声控氛围灯:Arduino Nano + 麦克风模块 + WS2812B 灯珠
- Arduino Nano + OpenCV 人脸追踪自主机器人小车
- 铜电镀智能系统:基于 Arduino UNO 的可控电解装置
- Arduino Nano 驱动 NeoPixel 矩阵:自制霓虹乒乓游戏
- 便携温度监测站:TMP36 + LCD1602 双温标显示
- 使用 Arduino 移位寄存器创建绚丽灯光序列
- 智能插座:基于 Arduino 与 RTC 的 120V 定时开关插座