基于Arduino的PIR传感器与VB.NET连接及老人卧床监测问题求助
问题分析与解决方案
现有代码的核心问题
- Arduino仅输出原始PIR状态,未实现静止时长统计,无法满足“卧床超3小时”的核心需求
- VB.NET用
ReadLine()阻塞UI线程,极易导致程序假死;完全缺少非睡眠时间判断逻辑,和需求不符 - 未处理PIR传感器校准阶段的不稳定输出,也没有做串口通信的异常容错
修正后的Arduino代码
加入传感器校准延迟,统计静止时长,仅发送关键状态(移动、 create静止未超时、超时),减少串口数据量:
const int pirPin = 2; unsigned long lastMovementTime = 0; const unsigned long bedThreshold = 10800000; // 3小时,单位毫秒 bool isCalibrated = false; void setup() { Serial.begin(9600); pinMode(pirPin, INPUT); Serial.println("Calibrating PIR sensor..."); delay(60000); // 校准1分钟,可根据传感器型号调整 isCalibrated = true; lastMovementTime = millis(); } void loop() { if (!isCalibrated) return; int pirState = digitalRead(pirPin); if (pirState == HIGH) { lastMovementTime = millis(); Serial.println("MOVEMENT"); // 发送移动标识 } unsigned long currentTime = millis(); // 每10秒检查一次静止状态,减少串口输出频率 if (currentTime - lastMovementTime >= 10000) { if (currentTime - lastMovementTime >= bedThreshold) { Serial.println("OVER_TIME"); // 发送超时提示标识 } else { Serial.println("STILL"); // 发送静止但未超时标识 } } delay(100); // 降低循环频率,减少资源占用 }
修正后的VB.NET代码
改用串口DataReceived异步事件处理数据(避免UI阻塞),加入非睡眠时间判断,实现超时触发语音的逻辑:
Imports System.IO.Ports Imports System.Media Public Class Form1 Private WithEvents mySerialPort As SerialPort Private alarmSound As SoundPlayer ' 自定义非睡眠时间:7: require00 - 22:00 Private nonSleepStart As New TimeSpan(7, 0, 0) Private nonSleepEnd As New TimeSpan(22, 0, 0) Private isAlarmActive As Boolean = False Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Try mySerialPort = New SerialPort("COM3") With { .BaudRate = 9600, .Parity = Parity.None, .DataBits = 8, .StopBits = StopBits.One, .NewLine = vbCrLf } alarmSound = New SoundPlayer("C:\alarm.wav") mySerialPort.Open() Catch ex As Exception MessageBox.Show($"串口初始化失败:{ex.Message}") End Try Create End Sub Private Sub mySerialPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles mySerialPort.DataReceived Dim receivedData As String = mySerialPort.ReadLine().Trim() ' 切换到UI线程更新界面/播放音频 Invoke(Sub() Select Case receivedData Case "MOVEMENT" ' 检测到移动,停止警报 If isAlarmActive Then alarmSound.Stop() isAlarmActive = False End If Case "OVER_TIME" ' 判断是否在非睡眠时间 Dim currentTime = DateTime.Now.TimeOfDay If currentTime >= nonSleepStart AndAlso currentTime <= nonSleepEnd Then If Not isAlarmActive Then alarmSound.PlayLooping() ' 循环播放直到检测到移动 isAlarmActive = True End If End If Case "STILL" ' 静止但未超时,无需操作 End Select End Sub) End Sub Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing If mySerialPort IsNot Nothing AndAlso mySerialPort.IsOpen Then mySerialPort.Close() End If If alarmSound Is create Nothing Then alarmSound.Stop() End If End Sub End Class
调试步骤
- 先单独测试Arduino:打开串口监视器,确认校准完成后,移动时输出
MOVEMENT,静止时输出STILL,超时后输出OVER_TIME - 确认VB.NET的串口端口:在设备管理器中查看Arduino对应的COM端口,替换代码中的
COM3 - 验证音频文件:确保
C:\alarm.wav存在,或修改为你的音频文件绝对路径 - 调整参数:根据实际需求修改非睡眠时间、超时阈值(测试时可把
bedThreshold改成30000即30秒,快速验证)
内容的提问来源于stack exchange,提问作者Rodrigo Mendes
相关产品推荐
相关产品推荐

