超声波眼睛:双 8×8 LED 矩阵跟随人体移动的互动装置
项目简介
一个俏皮的桌面装置:两个 HC-SR04 超声波测距模块作为“左右眼”,驱动两个级联 MAX7219 8×8 LED 矩阵显示卡通眼球。眼睛会根据左右测距差异向左/右/前注视,随机眨眼,环境光传感器自动调节亮度。无需复杂图像处理,仅用两路测距即可实现生动的“注视跟随”效果,适合放在办公桌、展柜入口吸引目光。
所需材料
- Arduino Nano (或兼容板,需硬件 SPI 引脚 D11/D13)
- HC-SR04 超声波模块 ×2
- MAX7219 8×8 LED 矩阵模块 ×2 (级联接口)
- 光敏电阻 (LDR) + 330Ω 电阻 (分压采样)
- 半尺寸面包板、公母杜邦线若干
- 可选:3D 打印外壳 (作者提供 STL),巧板固化
接线指南
电源与地
- Nano 3.3V/5V → 面包板正/负轨 (矩阵模块部分要求 5V,实测 3.3V 也可,不稳则改 5V)
- 两路超声波 VCC/GND 并联到电源轨
- 两块矩阵级联:第一块 VCC/GND 接电源轨,第二块从第一块输出端取电
信号线
| 模块 | 信号 | Arduino 引脚 |
|---|---|---|
| 超声波左 | Trig | D2 |
| Echo | D3 | |
| 超声波右 | Trig | D4 |
| Echo | D5 | |
| 矩阵 1 (主) | DIN (MOSI) | D11 (硬件 MOSI) |
| CLK (SCK) | D13 (硬件 SCK) | |
| CS | D10 | |
| 矩阵 2 (从) | DIN/CLK/CS | 级联自矩阵 1 对应输出引脚 |
| LDR 分压 | 中点 | A5 |
注意:代码使用硬件 SPI (D11 MOSI, D13 SCK),换板子需对应修接线。
软件库
MD_MAX72XX(库管理器安装,驱动矩阵)NewPing(库管理器安装,超声波中位值滤波)
眼球图案定义 (8×8 位图)
uint8_t eye_forward[8] = {
0b00111100, 0b01000010, 0b01011010, 0b10101101,
0b10111101, 0b10011001, 0b01000010, 0b00111100
};
uint8_t eye_right[8] = { ... }; // 瞳孔偏右
uint8_t eye_left[8] = { ... }; // 瞳孔偏左
uint8_t eye_blink[8] = { ... }; // 闭合动画帧
主循环逻辑
- 读取 LDR 光照值 (0-1023) → 映射到矩阵亮度 0-15
- 左眼
ping_median(5)获取中位距离distance1 - 延时 500ms 避免串扰,右眼同理得
distance2 - 随机触发眨眼:单眨/双眨,眨完恢复原注视方向
- 判向逻辑:
- |d1-d2| < 25cm 或均为 0 (无物体) → 看前方
- d2 < d1 且 d1>0 → 右侧更近 → 看右
- d1 < d2 且 d2>0 → 左侧更近 → 看左
- 延时 250ms 进入下一轮
完整代码
#include <MD_MAX72xx.h>
#include <NewPing.h>
#define CS_PIN 10
#define MAX_DEVICES 2
#define LIGHT A5
MD_MAX72XX mx = MD_MAX72XX(CS_PIN, MAX_DEVICES);
#define t1 2; #define e1 3;
#define t2 4; #define e2 5;
#define maxDist 400
NewPing eyeL(t1, e1, maxDist);
NewPing eyeR(t2, e2, maxDist);
int currentState = -1; // 0 前, 1 右, 2 左
float nextBlink = millis() + 1000;
float lightAmount = 0;
// 眼球位图数组 ... (同上)
void setup() {
mx.begin();
pinMode(t1, OUTPUT); pinMode(e1, INPUT);
pinMode(t2, OUTPUT); pinMode(e2, INPUT);
digitalWrite(t1, LOW); digitalWrite(t2, LOW);
pinMode(LIGHT, INPUT);
ShowEye_Forward(); currentState = 0;
}
void loop() {
lightAmount = analogRead(LIGHT);
lightAmount = (lightAmount / 255.0) * MAX_INTENSITY;
mx.control(MD_MAX72XX::INTENSITY, lightAmount);
distance1 = eyeL.ping_median(5);
delay(500);
distance2 = eyeR.ping_median(5);
if (nextBlink < millis()) {
nextBlink = millis() + random(2000, 10000);
if (random(1,13) <= 6) ShowEye_Blink_Dbl(); else ShowEye_Blink();
delay(250); return;
}
float diff = distance2 - distance1;
if (abs(diff) < 250 || (distance1==0 && distance2==0)) {
ShowEye_Forward(); currentState = 0;
} else if (distance2 < distance1 && distance1 > 0) {
ShowEye_Right(); currentState = 1;
} else if (distance1 < distance2 && distance2 > 0) {
ShowEye_Left(); currentState = 2;
}
delay(250);
}
// ShowEye_Forward/Right/Left/Blink/Blink_Dbl 函数实现 ...
// 均通过 mx.setColumn(row, pattern[row]) 双屏同步写入
进阶玩法
- 加电容触摸/按钮切换表情包 (心形、星星、动漫眼)
- 增加第三个超声波模块实现上下视觉
- 接入 MPU6050 做头部摇摆 (舵机驱动整个装置)
- 做成墙挂式“守护者”,配合 PIR 传感器有人靠近才激活
- 移植到 ESP32 增加 WiFi 控制、MQTT 上报互动数据
制作建议
- 面包板验证无误后再焊巧板,节省调试时间
- 超声波模块发射角约 15°,安装时略微向外张角 (约 30°) 扩大覆盖
- 矩阵模块级联排线要短,防止信号衰减
- LDR 分压电阻 330Ω 适合室内,强光环境可改 1kΩ
- 3D 打印外壳建议 PETG 耐热,内部留出散热槽
制造工艺
- Arduino UNO + MAX7219 自制《UFO攻击》复古射击游戏机
- 智能窗帘:基于Arduino与太阳能的自动光控系统
- 3D RGB Arduclock — 蓝牙控制全彩LED时钟带RTC与闹钟
- MyRiver:基于 Arduino MKR FOX 1200 的河流水质远程监测系统
- DIY 钢铁侠人偶:Arduino 控制超声波触发音效与灯光
- 自制简易红外避障传感器:IR LED + 光电二极管 + Arduino
- Arduino + 模拟摇杆互动游戏:五向 LED 反馈
- Find Me:基于 Arduino 与蓝牙的智能寻物器制作指南
- DIY Arduino 加湿器控制器:继电器安全控制高压电路
- Arduino 驱动的迷你漫游车:自制避障机器人
- DIY Arduino 手柄方向盘 - 游戏竞速模拟器自制指南
- Arduino 101 计步器:集成 DHT11 温湿度 + LCD 显示步数/距离/卡路里