基于TinkerCad中Arduino Uno的报警系统代码问题求助
基于Arduino Uno的夜间报警系统代码修复
项目需求
- 报警系统仅在夜间工作
- 门/窗对应按钮被触发后,声光报警持续激活30秒
- 需添加传感器触发阈值的可配置项
当前存在的问题
- LCD显示屏消息重叠、频繁卡顿闪烁
- 夜间按下按钮后,蜂鸣器与LED无法正常触发报警
变量翻译(葡萄牙语→中文)
botaoAtivarJanelaPin= 窗户触发按钮引脚botaoAtivarPortaPin= 门触发按钮引脚fotoresistorPin= 光敏电阻引脚alarmeAtivado= 报警激活状态sensorLuz= 光线传感器读数Sistema desligado= 系统关闭Sistema ligado= 系统开启Janela Aberta= 窗户打开Porta Aberta= 门打开
原代码
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); const int alarmePiezoPin = 3; const int ledPin = 4; const int botaoAtivarJanelaPin = 5; const int botaoAtivarPortaPin = 6; const int fotoresistorPin = A0; const int sensorPirPin = A2; int sensorState = LOW; int ledState = LOW; int alarmeAtivado = 0; int sensorLuz = 0; // void setup() { pinMode(alarmePiezoPin, OUTPUT); pinMode(ledPin, OUTPUT); pinMode(sensorPirPin, INPUT); pinMode(botaoAtivarJanelaPin, INPUT_PULLUP); pinMode(botaoAtivarPortaPin, INPUT_PULLUP); lcd.init(); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("Sistema desligado"); } void loop() { sensorState = digitalRead(sensorPirPin); sensorLuz = analogRead(fotoresistorPin); if(sensorLuz < 500){ alarmeAtivado = 0; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Sistema desligado"); } else { lcd.setCursor(0, 0); lcd.print("Sistema Ligado "); } if ((digitalRead(botaoAtivarPortaPin) == LOW)) { alarmeAtivado = 1; lcd.setCursor(0, 1); lcd.print("PORTA ABERTA! "); } if ((digitalRead(botaoAtivarJanelaPin) == LOW)) { alarmeAtivado = 1; lcd.setCursor(0, 1); lcd.print("JANELA ABERTA!"); } if(sensorLuz < 500){ if ((sensorState == HIGH) || (alarmeAtivado == 1)) { ativarAlarme(); } } delay(100); } void ativarAlarme(){ tone(alarmePiezoPin, 2000); digitalWrite(ledPin, HIGH); delay(500); noTone(alarmePiezoPin); digitalWrite(ledPin, LOW); }
修复后的代码
#include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // 可配置常量 const int alarmePiezoPin = 3; const int ledPin = 4; const int botaoAtivarJanelaPin = 5; const int botaoAtivarPortaPin = 6; const int fotoresistorPin = A0; const int sensorPirPin = A2; const int LUZ_NOTURNA_LIMITE = 500; // 夜间光线阈值(可调整) const int ALARME_DURACAO = 30000; // 报警持续时间(30秒) const int PIR_TRIGGER_ESTADO = HIGH; // PIR传感器触发状态(可结合硬件调整) // 状态变量 int sensorState = LOW; int alarmeAtivado = 0; int sensorLuz = 0; unsigned long alarmeInicioTempo = 0; int ultimoEstadoSistema = -1; // 记录上一次系统状态,避免重复更新LCD int ultimoEstadoAlarme = -1; // 记录上一次报警触发状态 void setup() { pinMode(alarmePiezoPin, OUTPUT); pinMode(ledPin, OUTPUT); pinMode(sensorPirPin, INPUT); pinMode(botaoAtivarJanelaPin, INPUT_PULLUP); pinMode(botaoAtivarPortaPin, INPUT_PULLUP); lcd.init(); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("Sistema desligado"); } void loop() { sensorState = digitalRead(sensorPirPin); sensorLuz = analogRead(fotoresistorPin); // 判断是否为夜间(系统激活条件) int estadoSistema = (sensorLuz < LUZ_NOTURNA_LIMITE) ? 1 : 0; // 仅当系统状态变化时更新LCD,避免频繁闪烁 if (estadoSistema != ultimoEstadoSistema) { lcd.setCursor(0, 0); if (estadoSistema == 1) { lcd.print("Sistema Ligado "); // 补空格覆盖旧内容 } else { lcd.print("Sistema desligado"); alarmeAtivado = 0; // 白天强制关闭报警 } ultimoEstadoSistema = estadoSistema; } // 检测门/窗按钮触发 if (digitalRead(botaoAtivarPortaPin) == LOW && estadoSistema == 1) { alarmeAtivado = 1; atualizarLCDLinha1("PORTA ABERTA! "); } else if (digitalRead(botaoAtivarJanelaPin) == LOW && estadoSistema == 1) { alarmeAtivado = 1; atualizarLCDLinha1("JANELA ABERTA! "); } else if (alarmeAtivado == 0 && estadoSistema == 1) { // 无报警时清空第二行 atualizarLCDLinha1(" "); } // 夜间触发报警逻辑 if (estadoSistema == 1) { if ((sensorState == PIR_TRIGGER_ESTADO) || (alarmeAtivado == 1)) { if (ultimoEstadoAlarme != 1) { alarmeInicioTempo = millis(); ultimoEstadoAlarme = 1; } // 持续触发报警直到30秒结束 if (millis() - alarmeInicioTempo < ALARME_DURACAO) { tone(alarmePiezoPin, 2000); digitalWrite(ledPin, HIGH); } else { // 报警结束后重置状态 noTone(alarmePiezoPin); digitalWrite(ledPin, LOW); alarmeAtivado = 0; ultimoEstadoAlarme = 0; atualizarLCDLinha1(" "); } } else { // 无触发时关闭报警 noTone(alarmePiezoPin); digitalWrite(ledPin, LOW); ultimoEstadoAlarme = 0; } } else { // 白天强制关闭报警 noTone(alarmePiezoPin); digitalWrite(ledPin, LOW); ultimoEstadoAlarme = 0; } delay(50); // 缩短延迟,提升响应速度 } // 封装LCD第二行更新函数,避免重复代码 void atualizarLCDLinha1(String texto) { lcd.setCursor(0, 1); lcd.print(texto); }
修复说明
LCD显示问题解决
- 新增状态变量记录上一次系统和报警状态,仅当状态变化时更新LCD,避免频繁刷新导致的闪烁
- 打印文本时补充空格,覆盖旧内容,解决消息重叠问题
- 封装LCD第二行更新函数,简化代码逻辑
报警触发逻辑修复
- 修正夜间判断逻辑:原代码将
sensorLuz <500判定为系统关闭,与需求完全相反,现在改为夜间(光线低于阈值)系统激活 - 使用
millis()替代delay()实现30秒报警持续,避免阻塞主循环,保证LCD和按钮响应正常 - 完善报警状态重置逻辑,报警结束后自动恢复系统正常状态
- 修正夜间判断逻辑:原代码将
添加可配置阈值
- 新增
LUZ_NOTURNA_LIMITE常量,可直接调整夜间光线判定阈值 - 新增
ALARME_DURACAO常量,方便修改报警持续时间 - 新增
PIR_TRIGGER_ESTADO常量,可结合硬件调整PIR传感器的触发逻辑
- 新增
内容的提问来源于stack exchange,提问作者Matheus Mendonca
相关产品推荐
相关产品推荐

