
/*
* ============================================
* ESP32-S3 智能晾衣架控制器 V3.0
* 功能:
* 1. 单击伸出晒衣,长按3秒收回
* 2. 【新增】雨滴检测,自动收回保护
* 3. 冷却期防误触机制
* ============================================
*
* 【硬件连接】
* GPIO4 → MK-51 INA (马达A端)
* GPIO5 → MK-51 INB (马达B端)
* GPIO20 → 带灯按键 (墙面控制)
* GPIO21 → 雨滴传感器 DO (数字输出)
* GND → 共地连接
*
* 【雨滴传感器】
* VCC → 3.3V
* GND → GND
* DO → GPIO21 (数字信号:有雨=LOW,无雨=HIGH)
* AO → 不接 (本例用数字输出即可)
*/
// -------- 硬件引脚定义 --------
const int INA = 4; // 马达驱动A端
const int INB = 5; // 马达驱动B端
const int BTN = 20; // 手动控制按键
const int RAIN_SENSOR = 21; // 【新增】雨滴传感器DO引脚
// -------- 时间参数定义 --------
const unsigned long CLICK_MAX = 1000; // 单击阈值
const unsigned long LONG_PRESS_MIN = 3000; // 长按阈值
const unsigned long RUN_TIME = 2000; // 马达运行时间
const unsigned long COOLDOWN_TIME = 5000; // 冷却期
const unsigned long RAIN_CHECK_INTERVAL = 500; // 【新增】雨滴检测间隔500ms
// -------- 状态变量 --------
bool motorRunning = false;
bool inCooldown = false;
bool isExtended = false; // 【新增】晾衣架当前状态:false=收回,true=伸出
unsigned long motorStartTime = 0;
unsigned long btnPressTime = 0;
unsigned long cooldownStartTime = 0;
unsigned long lastRainCheck = 0; // 【新增】上次检测雨滴时刻
bool btnPressed = false;
// -------- 初始化 --------
void setup() {
Serial.begin(115200);
delay(500);
// 马达初始停止
pinMode(INA, OUTPUT);
pinMode(INB, OUTPUT);
stopMotor();
// 按键配置
pinMode(BTN, INPUT_PULLDOWN);
// 【新增】雨滴传感器配置
pinMode(RAIN_SENSOR, INPUT_PULLUP); // 通常雨滴模块低电平有效
delay(100);
Serial.println("=== 智能晾衣架 V3.0 ===");
Serial.println("手动:单击伸出 | 长按3秒收回");
Serial.println("自动:检测雨滴 → 自动收回");
}
// -------- 主循环 --------
void loop() {
unsigned long now = millis();
// ========================================
// 【新增】持续检测雨滴(优先级最高)
// ========================================
if (now - lastRainCheck >= RAIN_CHECK_INTERVAL) {
lastRainCheck = now;
checkRainAndAutoRetract(now); // 检查并自动收回
}
// ========================================
// 阶段1:马达运行中
// ========================================
if (motorRunning) {
if (now - motorStartTime >= RUN_TIME) {
stopMotor();
// 【更新状态】根据最后动作判断位置
// 注意:自动收回也更新为收回状态
startCooldown(now);
Serial.println("○ 到位停止");
}
return;
}
// ========================================
// 阶段2:冷却期中
// ========================================
if (inCooldown) {
if (now - cooldownStartTime >= COOLDOWN_TIME) {
inCooldown = false;
Serial.println("=== 冷却结束 ===");
}
else {
// 冷却期按键提示
if (digitalRead(BTN) == HIGH && !btnPressed) {
btnPressed = true;
unsigned long remain = COOLDOWN_TIME - (now - cooldownStartTime);
Serial.print("! 冷却中,等待");
Serial.print(remain / 1000);
Serial.println("秒");
}
if (digitalRead(BTN) == LOW && btnPressed) {
btnPressed = false;
}
}
return;
}
// ========================================
// 阶段3:待机状态,检测手动按键
// ========================================
bool btnState = (digitalRead(BTN) == HIGH);
// 按键按下
if (btnState && !btnPressed) {
btnPressed = true;
btnPressTime = now;
Serial.println("→ 按键按下...");
}
// 按键释放
else if (!btnState && btnPressed) {
btnPressed = false;
unsigned long duration = now - btnPressTime;
Serial.print("→ 释放,持续");
Serial.print(duration);
Serial.println("ms");
if (duration < CLICK_MAX) {
// 短按:伸出
if (!isExtended) { // 只在收回状态下执行伸出
Serial.println(">>> 【手动伸出】");
startMotor(1);
isExtended = true; // 标记为伸出状态
} else {
Serial.println("○ 已在伸出位置,忽略");
}
}
else if (duration >= LONG_PRESS_MIN) {
// 长按:收回
if (isExtended) { // 只在伸出状态下执行收回
Serial.println("<<< 【手动收回】");
startMotor(-1);
isExtended = false; // 标记为收回状态
} else {
Serial.println("○ 已在收回位置,忽略");
}
}
else {
Serial.println("○ 无效操作");
}
}
delay(10);
}
// -------- 功能函数 --------
/**
* 【新增】检查雨滴并自动收回
* 优先级最高,一旦检测到有雨立即执行
*/
void checkRainAndAutoRetract(unsigned long now) {
int rainState = digitalRead(RAIN_SENSOR);
// 【注意】根据传感器类型调整判断条件
// 常见雨滴模块:有雨=LOW,无雨=HIGH
if (rainState == LOW) {
Serial.println("☔ 检测到雨滴!");
// 只有在伸出状态且未运行时才收回
if (isExtended && !motorRunning && !inCooldown) {
Serial.println("!!! 【紧急收回】自动保护启动");
startMotor(-1); // 执行收回(同长按3秒效果)
isExtended = false; // 更新状态
// 自动收回后进入短冷却期,避免频繁触发
inCooldown = true;
cooldownStartTime = now;
Serial.println("! 雨天保护模式,冷却3秒");
}
else if (motorRunning) {
Serial.println("! 马达运行中,稍后检测");
}
else if (!isExtended) {
Serial.println("○ 已收回,无需动作");
}
}
}
void startMotor(int dir) {
motorRunning = true;
motorStartTime = millis();
if (dir == 1) {
digitalWrite(INA, HIGH); // 正转 = 伸出
digitalWrite(INB, LOW);
} else {
digitalWrite(INA, LOW); // 反转 = 收回
digitalWrite(INB, HIGH);
}
}
void stopMotor() {
digitalWrite(INA, LOW);
digitalWrite(INB, LOW);
motorRunning = false;
}
void startCooldown(unsigned long now) {
inCooldown = true;
cooldownStartTime = now;
}
维度 | 内容 |
What(新增) | 雨滴传感器,数字输出检测有雨/无雨 |
What(功能) | 雨天自动收回,保护衣物不被淋湿 |
Why(优先级) | 自动保护 > 手动控制,安全第一 |
How(实现) | 定时检测(500ms)+ 状态判断 + 中断式执行 |
本文标签:#少儿编程 #编程思维 #跨学科学习 #逻辑训练 #信奥
![]() | ![]() |
关注我们,方便学习和答疑