<think>我们面对的是一个复杂的多传感器控制系统设计问题。用户希望使用Arduino Mega 2560作为主控制器,NodeMCU ESP-32S作为WiFi模块,结合多种传感器和执行器,实现三种模式的切换和远程监控。
首先,我们需要明确系统架构:
1. Arduino Mega 2560作为主控,负责读取所有传感器数据(6条线路,每条线路可接光敏、声音或人体传感器),控制继电器和LED。
2. NodeMCU ESP-32S负责WiFi通信,与Arduino Mega通过串口通信,将传感器数据上传到服务器,并接收来自网页的控制指令(如模式切换)。
系统功能:
- 三种传感器模式:光线模式、声音模式、人体感应模式,通过LED指示当前模式。
- 当某条线路检测到信号(例如光线最强、声音最大或有人体感应)时,导通对应继电器,并根据信号强度变化切换线路(即当另一条线路信号更强时,切换到该线路)。
- 远程监控:通过网页显示光照强度、声音强度、人体感应状态,并可以切换模式。
- 节能模式:根据电池电量(通过太阳能充电系统,包括太阳能板、升压模块、充电保护模块和锂电池)自动进入节能模式(如降低采样频率、关闭部分外设等)。
硬件连接:
- 传感器:6条线路,每条线路可以接一种传感器(光敏电阻5506、声音传感器、人体传感器SR602)。注意:人体传感器SR602是数字输出(高电平触发),光敏电阻和声音传感器是模拟输入。
- 执行器:继电器G6S-2-5VDC(控制外部设备),多个LED(指示模式和状态)。
- 电源系统:太阳能板->升压模块RT9266->充电保护模块TP4056->18650锂电池。锂电池输出给Arduino Mega和NodeMCU供电(注意电压匹配,Arduino Mega需要7-12V输入,而NodeMCU ESP-32S需要3.3V,所以可能需要额外的降压模块给NodeMCU供电,或者直接使用锂电池的电压通过降压模块给整个系统供电?这里需要设计电源管理)。
设计思路:
1. 硬件连接:
- 将6条传感器线路连接到Arduino Mega的模拟输入(A0-A5)或数字输入(对于人体传感器,使用数字输入)。注意:人体传感器SR602是数字传感器,而光敏和声音是模拟传感器。因此,我们需要为每条线路设计一个选择机制:在硬件上,每条线路只能接一种传感器,但在软件上,我们可以根据当前模式来决定读取哪类传感器。但是,用户要求每条线路可以接入不同的传感器,并且有三种模式切换。这意味着在同一个线路上,可能接的是光敏,也可能是声音或人体。因此,我们需要在软件上能够识别每条线路是什么类型的传感器?或者用户会固定每条线路的传感器类型?这里假设用户固定了每条线路的传感器类型,即每条线路只接一种传感器,且不会改变。
因此,我们可以这样安排:
- 定义6个传感器引脚,其中一些是模拟输入(用于光敏和声音),一些是数字输入(用于人体传感器)。但是,由于Arduino Mega有多个模拟输入和数字输入,我们可以灵活分配。例如,分配6个模拟输入引脚(A0-A5)给光敏和声音传感器(因为声音传感器也是模拟输出),而人体传感器使用数字引脚(2-7)。但注意:每条线路的传感器类型是固定的,所以我们可以预先定义好每条线路的传感器类型和对应的引脚。
- 继电器控制:使用6个数字输出引脚控制6个继电器(分别对应6条线路)。同时,使用另外的3个数字输出引脚控制3个LED(用于指示当前模式:光线、声音、人体)。
2. 模式切换:
- 三种模式:光线模式(只关注光敏传感器)、声音模式(只关注声音传感器)、人体模式(只关注人体传感器)。在每种模式下,只读取对应类型的传感器,并比较这些传感器的值(对于人体传感器,只有0或1,可以视为数字量,而光敏和声音是模拟量0-1023)。
- 使用LED指示当前模式:例如,LED1亮表示光线模式,LED2亮表示声音模式,LED3亮表示人体模式。
3. 继电器控制逻辑:
- 在每种模式下,从对应类型的传感器中找出信号最强的线路(对于人体传感器,可以认为有信号(高电平)的线路中,任意一个都可以,或者按优先级?这里用户要求最大信号,但人体传感器只有0和1,所以当多条线路同时有人体感应时,我们可以选择最先检测到的或者按优先级固定顺序)。对于模拟传感器,比较模拟值(注意:光敏电阻是光线越强电阻越小,所以模拟值越大表示光线越强;声音传感器同理,模拟值越大表示声音越大)。
- 当检测到最大信号时,导通该线路对应的继电器,同时断开其他继电器(同一时间只有一个继电器导通)。
- 当信号强度变化(例如,另一条线路的信号更强)时,切换到该线路。
4. 串口通信协议(Arduino Mega与NodeMCU ESP-32S之间):
- 我们需要定义一组简单的通信协议,用于传输传感器数据和模式控制命令。
- 数据上传(Arduino->NodeMCU):可以定期发送(如每1秒)所有传感器的数据(包括6条线路的模拟值或数字状态)和当前模式、电池电量等。
格式建议:使用字符串,如“SENSOR1:500;SENSOR2:0;...;MODE:1;BATT:3.7;”这样,NodeMCU解析后上传到服务器。
- 命令接收(NodeMCU->Arduino):NodeMCU收到网页的控制命令(如切换模式)后,通过串口发送给Arduino,例如“MODE:2”表示切换到声音模式。
5. 远程监控:
- NodeMCU ESP-32S建立WiFi连接(STA模式连接到路由器,或AP模式直接让客户端连接)。建议连接到路由器,然后通过路由器的端口转发或内网穿透实现远程访问。
- 在NodeMCU上运行一个Web服务器,提供网页界面,显示传感器数据,并提供三个按钮用于切换模式。同时,网页上显示电池电量。
6. 节能模式:
- 通过测量电池电压(可以使用Arduino Mega的模拟输入引脚通过电阻分压测量锂电池电压)来判断电量。当电压低于设定阈值(如3.3V)时,进入节能模式。
- 节能模式措施:降低传感器采样频率(如每5秒采样一次)、关闭部分LED(只保留模式指示LED)、降低继电器切换频率等。
7. 电源管理:
- 太阳能板通过升压模块和充电保护模块给18650锂电池充电,锂电池输出通过降压模块给Arduino Mega(注意:Arduino Mega的工作电压是5V,但输入可以是7-12V,而锂电池充满是4.2V,所以需要升压到5V或7V以上?这里可能需要一个升压模块将锂电池电压升到7-12V给Arduino Mega的VIN引脚,同时NodeMCU ESP-32S可以直接用3.3V供电(锂电池电压3.7V左右,需要降压到3.3V)。因此,建议使用两个降压模块:一个将锂电池电压升压到9V给Arduino Mega,另一个降压到3.3V给NodeMCU。
具体实现步骤:
第一步:硬件连接(以6条线路为例,假设前两条是光敏,中间两条是声音,后两条是人体)
- 光敏传感器1:A0
- 光敏传感器2:A1
- 声音传感器3:A2
- 声音传感器4:A3
- 人体传感器5:数字引脚2
- 人体传感器6:数字引脚3
- 继电器控制引脚(6个):分别连接到数字引脚8-13(注意继电器需要5V驱动,Arduino Mega的IO输出5V,可以直接驱动)。
- 模式指示LED:3个,分别连接到数字引脚4、5、6(光线模式、声音模式、人体模式),使用共阴极连接,加限流电阻。
- 电池电压检测:通过电阻分压(例如,用两个电阻将锂电池电压分压到0-5V范围内)连接到A6(模拟输入)。
- 串口连接:Arduino Mega的TX1(18) -> NodeMCU的RX, Arduino Mega的RX1(19) -> NodeMCU的TX(注意电平转换?Arduino Mega是5V TTL,NodeMCU是3.3V TTL,所以需要电平转换,或者使用电阻分压将5V降到3.3V)。
第二步:Arduino Mega程序框架
- 初始化:设置传感器引脚为输入,继电器和LED引脚为输出,串口通信(使用Serial1,因为Serial0用于USB调试)。
- 定义全局变量:
int sensorPins[6] = {A0, A1, A2, A3, 2, 3}; // 传感器引脚
int relayPins[6] = {8,9,10,11,12,13}; // 继电器引脚
int modeLEDs[3] = {4,5,6}; // 模式指示LED引脚
int currentMode = 0; // 0:光线模式,1:声音模式,2:人体模式
int activeRelay = -1; // 当前激活的继电器线路(-1表示没有激活)
float batteryVoltage = 0.0;
bool powerSaving = false; // 是否处于节能模式
- 主循环:
1. 读取电池电压(每10次循环读一次),判断是否进入节能模式。
2. 读取当前模式对应的传感器数据(如果是光线模式,则只读取前两个光敏传感器;声音模式读取中间两个声音传感器;人体模式读取后两个人体传感器)。
3. 找出这些传感器中的最大值(对于人体传感器,只要有一个为高电平,就认为有信号,并记录第一个触发的人体传感器线路)。
4. 如果最大值超过阈值(对于模拟传感器,阈值可设;对于人体传感器,高电平即触发),则激活该线路的继电器,并关闭其他继电器。同时,如果当前激活的线路与最大值线路不同,则切换继电器。
5. 通过串口发送传感器数据、当前模式、电池电压等信息给NodeMCU(注意控制发送频率,在节能模式下降低发送频率)。
6. 检查串口是否有来自NodeMCU的命令,如果有,解析命令(如切换模式)。
7. 根据当前模式点亮对应的LED,熄灭其他LED。
8. 延时(正常模式100ms,节能模式500ms或更长)。
第三步:NodeMCU ESP-32S程序框架
- 初始化:连接WiFi,启动Web服务器,初始化串口(与Arduino Mega通信)。
- Web服务器:提供简单的网页,包含:
- 显示6个传感器的当前值(用进度条或数字显示)
- 显示当前模式(文字显示)
- 三个按钮用于切换模式
- 显示电池电压
- 一个文本框显示状态信息
- 处理客户端请求:当用户点击模式切换按钮时,通过GET或POST请求发送命令,NodeMCU收到后通过串口发送给Arduino Mega。
- 串口通信:定期读取来自Arduino Mega的数据(格式如“SENSOR1:500;SENSOR2:0;...;MODE:1;BATT:3.7;”),解析后更新网页显示的数据。
第四步:网页设计
- 一个简单的HTML页面,使用JavaScript定时刷新数据(通过AJAX请求从NodeMCU获取最新数据)。
注意事项:
- 电平转换:Arduino Mega(5V)与NodeMCU(3.3V)的串口通信需要电平转换,否则可能损坏NodeMCU。
- 电源隔离:继电器线圈在断开时会产生反电动势,需加续流二极管保护。
- 模拟输入范围:Arduino Mega的模拟输入为0-5V,电池电压检测分压电路需设计合理(如锂电池最高4.2V,分压到3.3V以下,但不要超过5V)。
- 节能模式策略:可以进一步细化,比如关闭不需要的传感器电源(如果传感器有独立电源控制)等。
由于篇幅限制,这里无法提供完整的代码,但给出关键部分的伪代码和框架。
Arduino Mega关键代码片段:
```cpp
// 引脚定义
const int sensorPins[6] = {A0, A1, A2, A3, 2, 3}; // 前4个模拟,后2个数字
const int relayPins[6] = {8,9,10,11,12,13};
const int modeLEDs[3] = {4,5,6}; // 分别对应模式0,1,2
// 变量
int currentMode = 0; // 0:light, 1:sound, 2:motion
int activeRelay = -1; // 当前激活的继电器线路索引(0-5),-1表示无激活
float batteryVoltage = 0.0;
bool powerSaving = false;
unsigned long lastUpdateTime = 0;
const long normalInterval = 100; // 正常模式循环间隔100ms
const long powerSavingInterval = 500; // 节能模式500ms
void setup() {
Serial.begin(9600); // 用于调试
Serial1.begin(115200); // 与NodeMCU通信
for (int i=0; i<6; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], LOW);
// 对于数字输入的传感器,设置为输入
if (i>=4) { // 后两个是数字输入
pinMode(sensorPins[i], INPUT);
}
}
for (int i=0; i<3; i++) {
pinMode(modeLEDs[i], OUTPUT);
digitalWrite(modeLEDs[i], LOW);
}
// 初始化模式指示LED
digitalWrite(modeLEDs[currentMode], HIGH);
}
void loop() {
unsigned long currentMillis = millis();
long interval = powerSaving ? powerSavingInterval : normalInterval;
if (currentMillis - lastUpdateTime >= interval) {
lastUpdateTime = currentMillis;
// 1. 读取电池电压(每10次循环读一次)
static int count = 0;
if (count++ >= 10) {
count = 0;
int raw = analogRead(A6); // 假设电池电压检测连接在A6
batteryVoltage = raw * (5.0 / 1023.0) * 2.0; // 假设分压比为2:1,所以乘2
// 判断是否进入节能模式
if (batteryVoltage < 3.3) { // 阈值可调
powerSaving = true;
} else {
powerSaving = false;
}
}
// 2. 读取当前模式下的传感器
int sensorValues[6];
for (int i=0; i<6; i++) {
if (i<4) { // 模拟传感器
sensorValues[i] = analogRead(sensorPins[i]);
} else { // 数字传感器
sensorValues[i] = digitalRead(sensorPins[i]) ? 1023 : 0; // 将数字高电平映射为1023,低电平为0,便于统一处理
}
}
// 3. 根据当前模式,确定需要关注的传感器范围
int startIdx, endIdx;
if (currentMode == 0) { // 光线模式:只关注前两个光敏
startIdx = 0; endIdx = 1;
} else if (currentMode == 1) { // 声音模式:中间两个
startIdx = 2; endIdx = 3;
} else { // 人体模式:后两个
startIdx = 4; endIdx = 5;
}
// 4. 找出关注范围内的最大值及其索引
int maxVal = -1;
int maxIdx = -1;
for (int i=startIdx; i<=endIdx; i++) {
if (sensorValues[i] > maxVal) {
maxVal = sensorValues[i];
maxIdx = i;
}
}
// 5. 判断是否超过阈值(对于人体传感器,阈值可以设为500,因为数字高电平被映射为1023)
int threshold = (currentMode == 2) ? 500 : 200; // 不同模式阈值不同,可调整
if (maxVal > threshold) {
// 如果当前激活的继电器不是最大值对应的线路,则切换
if (activeRelay != maxIdx) {
// 关闭所有继电器
for (int i=0; i<6; i++) {
digitalWrite(relayPins[i], LOW);
}
// 开启最大值对应的继电器
digitalWrite(relayPins[maxIdx], HIGH);
activeRelay = maxIdx;
}
} else {
// 如果没有任何信号超过阈值,则关闭所有继电器
if (activeRelay != -1) {
digitalWrite(relayPins[activeRelay], LOW);
activeRelay = -1;
}
}
// 6. 发送数据给NodeMCU(在非节能模式或即使节能模式也降低发送频率,比如每5次循环发送一次)
static int sendCount = 0;
if (!powerSaving || sendCount >= 5) {
sendCount = 0;
String dataStr = "";
for (int i=0; i<6; i++) {
dataStr += "SENSOR" + String(i+1) + ":" + String(sensorValues[i]) + ";";
}
dataStr += "MODE:" + String(currentMode) + ";";
dataStr += "BATT:" + String(batteryVoltage) + ";";
Serial1.println(dataStr); // 发送给NodeMCU
} else {
sendCount++;
}
// 7. 检查串口命令(来自NodeMCU)
if (Serial1.available()) {
String command = Serial1.readStringUntil('\n');
command.trim();
if (command.startsWith("MODE:")) {
int newMode = command.substring(5).toInt();
if (newMode >=0 && newMode <=2) {
currentMode = newMode;
// 更新LED
for (int i=0; i<3; i++) {
digitalWrite(modeLEDs[i], (i==currentMode) ? HIGH : LOW);
}
}
}
}
}
// 延时(由间隔控制,所以这里不需要额外延时)
}
```
NodeMCU ESP-32S代码框架(使用Arduino框架):
```cpp
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
WebServer server(80);
void handleRoot() {
// 这里返回一个简单的HTML页面,包含显示传感器数据、模式、电池电量的元素,以及三个切换模式的按钮
String html = "<html><body>";
html += "<h1>Sensor Control System</h1>";
html += "<p>Battery Voltage: <span id='batt'>0.0</span> V</p>";
html += "<p>Current Mode: <span id='mode'>Light</span></p>";
for (int i=1; i<=6; i++) {
html += "<p>Sensor " + String(i) + ": <span id='sensor" + String(i) + "'>0</span></p>";
}
html += "<button onclick=\"changeMode(0)\">Light Mode</button>";
html += "<button onclick=\"changeMode(1)\">Sound Mode</button>";
html += "<button onclick=\"changeMode(2)\">Motion Mode</button>";
html += "<script>";
html += "function changeMode(mode) {";
html += " var xhr = new XMLHttpRequest();";
html += " xhr.open('GET', '/setmode?mode='+mode, true);";
html += " xhr.send();";
html += "}";
html += "setInterval(function() {";
html += " fetch('/data').then(response => response.text()).then(data => {";
html += " var items = data.split(';');";
html += " for (var i=0; i<items.length; i++) {";
html += " if (items[i].startsWith('SENSOR')) {";
html += " var parts = items[i].split(':');";
html += " var sensorId = parts[0].substring(5);"; // 提取传感器编号
html += " document.getElementById('sensor'+sensorId).innerHTML = parts[1];";
html += " } else if (items[i].startsWith('MODE')) {";
html += " var mode = parseInt(parts[1]);";
html += " var modeText = ['Light','Sound','Motion'][mode];";
html += " document.getElementById('mode').innerHTML = modeText;";
html += " } else if (items[i].startsWith('BATT')) {";
html += " document.getElementById('batt').innerHTML = parts[1];";
html += " }";
html += " }";
html += " });";
html += "}, 1000);";
html += "</script>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void handleData() {
// 这里返回最新的传感器数据(从串口接收并解析后的数据,存储在全局变量中)
// 假设我们有一个全局字符串sensorData,格式为"SENSOR1:500;SENSOR2:0;...;MODE:1;BATT:3.7;"
server.send(200, "text/plain", sensorData);
}
void handleSetMode() {
if (server.hasArg("mode")) {
int mode = server.arg("mode").toInt();
// 通过串口发送模式切换命令给Arduino Mega
Serial.println("MODE:"+String(mode));
server.send(200, "text/plain", "OK");
} else {
server.send(400, "text/plain", "Bad Request");
}
}
void setup() {
Serial.begin(115200); // 与Arduino Mega通信的串口
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.println(WiFi.localIP());
// 设置Web服务器路由
server.on("/", handleRoot);
server.on("/data", handleData); // 提供传感器数据的接口
server.on("/setmode", handleSetMode); // 设置模式的接口
server.begin();
}
void loop() {
server.handleClient();
// 处理串口数据(从Arduino Mega发来的)
if (Serial.available()) {
String data = Serial.readStringUntil('\n');
data.trim();
// 解析数据并存储到全局变量sensorData中(这里省略解析,直接存储)
// 注意:这里我们假设数据格式正确,实际应用中需要做校验
sensorData = data; // sensorData是全局变量
}
}
```
注意:以上代码仅为框架,实际应用需要根据具体硬件调整引脚和参数,并增加错误处理。
最后,生成相关问题:
1. 如何设计Arduino Mega与NodeMCU ESP-32S之间的串口通信协议?
2. 如何优化多传感器系统的实时响应性能?
3. 如何为太阳能供电系统设计更高效的节能策略?
4. 在网页监控界面中,如何实现更直观的数据可视化?
5. 如何处理多个传感器同时触发时的优先级问题?</think>### 多传感器控制系统设计方案
#### 系统架构设计
采用**分层架构**:Arduino Mega 2560 作为传感器控制层,NodeMCU ESP-32S 作为网络通信层。两者通过串口(UART)通信,实现数据交换和指令传输。
```mermaid
graph TD
A[Arduino Mega 2560] -->|串口通信| B[NodeMCU ESP-32S]
C[光敏传感器] --> A
D[声音传感器] --> A
E[人体传感器] --> A
F[继电器组] --> A
G[LED指示灯] --> A
B -->|WiFi| H[远程监控端]
```
#### 硬件连接方案
1. **传感器接口分配**(6条线路):
- 线路1-2:光敏电阻5506 → Arduino 模拟输入 A0-A1
- 线路3-4:声音传感器 → Arduino 模拟输入 A2-A3
- 线路5-6:人体传感器SR602 → Arduino 数字输入 D2-D3
2. **执行器控制**:
- 继电器控制:数字引脚 D8-D13 → 继电器G6S-2-5VDC
- LED模式指示:数字引脚 D4-D6(红/黄/绿三色)
3. **电源系统**:
```mermaid
graph LR
太阳能板 --> 升压模块RT9266 --> 充电保护TP4056 --> 18650锂电池
18650锂电池 --> Arduino Mega
18650锂电池 --> 降压模块 --> NodeMCU
```
#### 核心功能实现
1. **传感器模式切换**:
```cpp
// Arduino 模式切换代码
enum SensorMode { LIGHT_MODE, SOUND_MODE, MOTION_MODE };
SensorMode currentMode = LIGHT_MODE;
void switchMode(SensorMode newMode) {
currentMode = newMode;
// 更新LED指示
digitalWrite(LED_RED, (newMode == LIGHT_MODE));
digitalWrite(LED_YELLOW, (newMode == SOUND_MODE));
digitalWrite(LED_GREEN, (newMode == MOTION_MODE));
}
```
2. **信号强度检测与继电器控制**:
```cpp
void checkSensors() {
int maxVal = 0;
int activeLine = -1;
for (int i=0; i<6; i++) {
int sensorVal = (i < 2) ? analogRead(A0+i) :
(i < 4) ? analogRead(A2+i-2) :
digitalRead(D2+i-4)*1023;
if (sensorVal > maxVal && sensorVal > thresholds[i]) {
maxVal = sensorVal;
activeLine = i;
}
}
if (activeLine != -1) {
// 关闭所有继电器
for (int j=8; j<=13; j++) digitalWrite(j, LOW);
// 激活对应继电器
digitalWrite(8 + activeLine, HIGH);
}
}
```
3. **串口通信协议**(Arduino ↔ ESP32):
```
// 数据上报格式
[L1:425;L2:380;S1:512;S2:498;M1:0;M2:1;MODE:0;BATT:3.8;]
// 指令接收格式
MODE:1 // 切换至声音模式
```
4. **NodeMCU Web服务器**(基于ESPAsyncWebServer):
```cpp
// ESP32 网络服务代码
server.on("/mode", HTTP_GET, [](AsyncWebServerRequest *request){
if (request->hasParam("type")) {
String mode = request->getParam("type")->value();
Serial.println("MODE:" + mode); // 转发至Arduino
request->send(200, "text/plain", "OK");
}
});
```
#### 节能模式实现
```cpp
void checkBattery() {
float voltage = analogRead(A7) * (5.0 / 1023.0) * 2.0; // 分压电路
if (voltage < 3.3) { // 电压阈值
enablePowerSaving();
}
}
void enablePowerSaving() {
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
// 降低传感器采样频率
ADCSRA &= ~(1<<ADEN);
// 关闭非必要外设
power_adc_disable();
}
```
#### 远程监控界面
设计响应式网页包含:
1. 实时传感器数据仪表盘
2. 模式切换按钮组
3. 电池电量指示器
4. 继电器状态指示
```html
<div class="sensor-data">
<div>光照强度: <span id="light-val">0</span> lx</div>
<div>声音强度: <span id="sound-val">0</span> dB</div>
<div>人体感应: <span id="motion-val">未触发</span></div>
</div>
<button onclick="setMode(0)">光线模式</button>
<button onclick="setMode(1)">声音模式</button>
```
### 关键注意事项
1. **电平转换**:Arduino(5V)与ESP32(3.3V)间需加电平转换电路
2. **继电器保护**:每个继电器线圈并联续流二极管
3. **采样优化**:为模拟输入添加0.1μF滤波电容
4. **电源隔离**:数字电路与模拟电路分开供电
### 测试方案
1. **单元测试**:逐项验证传感器读数准确性
2. **压力测试**:模拟多传感器同时触发
3. **功耗测试**:测量节能模式前后电流消耗
4. **距离测试**:验证WiFi连接稳定性(建议加装PCB天线)
> 完整代码实现需根据具体传感器参数调整阈值和校准值,建议初始阈值设置为:
> - 光敏:`> 300`(暗环境)
> - 声音:`> 450`
> - 人体:`HIGH`(数字信号)