Arduino MKR1000 WiFi 拣选指灯系统(二):UDP 通信与序列号防错
项目演进
这是“拣选指灯”系列的第二个项目。第一版使用有线串口通信,受限于 USB 线缆长度。本版升级为 **MKR1000 内置 WiFi + UDP 协议**,实现无线通信,并引入 **四位序列号** 机制:每条拣选指令携带序号,工人确认拣选时回传该序号,Python 端校验序号连续性,若不匹配即报错停机,有效防止漏拣、错拣。
硬件清单
- Arduino MKR1000 ×1 — 内置 WiFi、LiPo 充电管理
- LED(通用) ×2 — 指示料仓 1/2
- 12mm 轻触开关 ×1 — 工人确认按钮
- NPN 三极管 (如 2N2222) ×1 — 驱动 LED,规避 WiFi 启动时 D8/D9 电压跌落问题
- 330Ω 电阻 ×4 — LED 限流
- 10kΩ 电阻 ×1 — 按钮上拉
- 面包板、跳线、Micro-USB 线 若干
软件环境
- Python 3.6+ + 标准库
socket、csv— PC 端调度脚本 - Arduino IDE +
WiFi101库 — MKR1000 固件 - 序列文件 (sequence1.txt) — CSV 格式:
0001,Bin1,每行一条指令
通信流程
- Python 读取 CSV,逐行发送
序号+料仓号(如0001Bin1)至 MKR1000 UDP 端口 2390 - MKR1000 解析,点亮对应 LED,等待按钮按下
- 按下后熄灭 LED,回传
序号(如0001)至 Python - Python 校验回传序号与发送序号一致,方发送下一条;不一致则报错退出
- 序列文件可随时编辑,重启两端即可从断点续传
关键代码片段
Arduino 端 (核心循环)
void loop() {
int packetSize = Udp.parsePacket();
if (packetSize) {
// 读取包内容,前 4 字节序号,后续为料仓号
String seq = packetBuffer.substring(0,4);
String bin = packetBuffer.substring(4);
// 点亮对应 LED,阻塞等待按钮
if (bin == "Bin1") { digitalWrite(Bin1, HIGH); while(!digitalRead(OKbutton)); digitalWrite(Bin1, LOW); }
else if (bin == "Bin2") { digitalWrite(Bin2, HIGH); while(!digitalRead(OKbutton)); digitalWrite(Bin2, LOW); }
// 回传序号确认
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(seq.c_str(), 4);
Udp.endPacket();
}
}
Python 端 (核心循环)
for row in csvReader:
seq, bin = row[0], row[1]
sock.sendto((seq+bin).encode(), (UDP_IP, UDP_PORT))
data, _ = sock.recvfrom(1024)
if data.decode() != seq:
print(f"序列故障 at {data.decode()}")
sys.exit()
接线要点
- MKR1000 D2 接按钮(另一端接 GND,内部上拉或外接 10kΩ 上拉)
- D8/D9 接三极管基极(串 330Ω),三极管集电极接 LED 阳极,发射极接地,LED 阴极经 330Ω 接 3.3V
- WiFi 启动瞬间 D8/D9 会拉低,直接驱动 LED 会熄灭,三极管隔离可解决
- 务必在
arduino_secrets.h填入 SSID/密码
测试与故障注入
注释 myseq.toCharArray(ReplyBuffer, 5); 并启用固定回传 0001,可模拟序列错位,验证 Python 端检测逻辑。
后续改进方向 (Project 3)
- 扩展至 8/16/32 料仓,配合移位寄存器 (74HC595) 节省 IO
- 引入 OLED 显示当前序号/料仓/状态
- 改用 TCP 或 MQTT,增加可靠性与多设备协同
- PC 端开发 GUI,支持序列文件可视化编辑、进度条、日志导出
- 增加蜂鸣器/语音提示,适应嘈杂车间
项目资源
完整 Arduino 草图、Python 脚本、序列示例文件、Fritzing 原理图均可在项目页面获取。
制造工艺