/**比特树创造力【BIT.SH1003多功能智能风扇板卡全功能验证】 1、能够根据接收到的红外遥控器数字按键值0-3改变风速,同时在数码管上显示0-3数字风速档位; 2、能够根据接收到的红外遥控器按键值(齿轮键0xFFA857)或实体按键1(D4)在不同的工作模式切换; 3、工作模式1蜂鸣器响1声为红外遥控模式; 4、工作模式2蜂鸣器响2声为超声波测距模式,距离越远,风速越快,(<5cm=0档、<30cm=1档、<60cm=2档、>60cm=3档)数码管显示相应档位; 5、工作模式3蜂鸣器响3声为温湿度自动调速模式,当温湿度越高风速越大; 5、工作模式4蜂鸣器响4声为手动调速模式,结合A3引脚电位器映射风扇转速; 6、实体按键SW1和SW2按下有不同声音; 7、所有操作能够通过A1引脚的蜂鸣器不同声音次数反馈; bit-tree.com by liking [2025-07-25] **/ #include <IRremote.h> // 红外遥控库 #include <Wire.h> // IIC通信库,用于AHT20温湿度传感器 // ====================================== // 硬件引脚与参数定义区 // ====================================== /** 引脚定义 **/ #define BEEPER A1 // 有源蜂鸣器控制引脚 #define IR_RECEIVE_PIN 7 // 红外接收模块引脚 #define TRIG_PIN 2 // 超声波传感器触发引脚 #define ECHO_PIN 3 // 超声波传感器回声引脚 #define FAN_NEG 6 // 风扇电机负极控制引脚 #define FAN_POS 5 // 风扇电机正极PWM控制引脚 #define SW1 4 // 实体按键1(模式切换) #define SW2 A2 // 实体按键2(保留音效) #define POT A3 // 手动调速模式电位器引脚 /** 数码管引脚定义 **/ #define SEG_A A0 // 数码管A段 #define SEG_B 8 // 数码管B段 #define SEG_C 9 // 数码管C段 #define SEG_D 10 // 数码管D段 #define SEG_E 11 // 数码管E段 #define SEG_F 12 // 数码管F段 #define SEG_G 13 // 数码管G段 /** 红外遥控器按键码定义 **/ #define FAN_0 0xFF6897 // 0档风速对应红外码 #define FAN_1 0xFF30CF // 1档风速对应红外码 #define FAN_2 0xFF18E7 // 2档风速对应红外码 #define FAN_3 0xFF7A85 // 3档风速对应红外码 #define MODE_SWITCH 0xFFA857 // 模式切换按键(齿轮键)对应红外码 /** 工作模式定义 **/ #define MODE_IR 1 // 模式1:红外遥控模式(蜂鸣器响1声) #define MODE_ULTRASONIC 2 // 模式2:超声波测距模式(蜂鸣器响2声) #define MODE_TEMP_HUM 3 // 模式3:温湿度自动模式(蜂鸣器响3声) #define MODE_MANUAL 4 // 模式4:手动调速模式(蜂鸣器响4声) /** AHT20温湿度传感器参数 **/ #define AHT20_ADDR 0x38 // AHT20的IIC通信地址 #define AHT20_INIT_CMD 0xBE // AHT20初始化命令 #define AHT20_MEASURE_CMD 0xAC // AHT20测量命令 /** 蜂鸣器音效参数 **/ #define BEEP_DURATION 100 // 单声持续时间(毫秒) #define BEEP_GAP 100 // 声音之间的间隔(毫秒) // ====================================== // 全局变量定义区 // ====================================== int currentMode = MODE_IR; // 当前工作模式(初始化为红外遥控模式) int modeSpeeds[5] = {0}; // 各模式独立保存的风速档位 unsigned long modeTimers[5] = {0}; // 各模式定时计数器 unsigned long debounceDelay = 200; // 按键去抖延迟(毫秒) float humidity = 0.0; // 湿度值(百分比) float temperature = 0.0; // 温度值(摄氏度) bool isPlaying = false; // 蜂鸣器播放状态标志 // 红外接收对象 IRrecv irrecv(IR_RECEIVE_PIN); decode_results results; // 数码管段码表(共阴极,0-3) const byte digitPatterns[4][7] = { {1, 1, 1, 1, 1, 1, 0}, // 0 {0, 1, 1, 0, 0, 0, 0}, // 1 {1, 1, 0, 1, 1, 0, 1}, // 2 {1, 1, 1, 1, 0, 0, 1} // 3 }; // ====================================== // 蜂鸣器控制函数区 // ====================================== /** 控制有源蜂鸣器开关 @param on true=发声,false=停止 */ void setBuzzer(bool on) { digitalWrite(BEEPER, on ? HIGH : LOW); } /** 播放指定次数的提示音 @param count 发声次数 */ void playBeepSequence(int count) { if (isPlaying || count < 1) return; isPlaying = true; for (int i = 0; i < count; i++) { setBuzzer(true); delay(BEEP_DURATION); setBuzzer(false); if (i < count - 1) delay(BEEP_GAP); } isPlaying = false; } /** 播放模式切换提示音 @param mode 模式编号(1-4),响对应次数 */ void playModeTone(int mode) { playBeepSequence(mode); } /** 按键2(SW2)的音效 播放1声短音 */ void playButton2Sound() { if (isPlaying) return; isPlaying = true; setBuzzer(true); delay(BEEP_DURATION); setBuzzer(false); isPlaying = false; } /** 红外操作反馈音 播放短提示音 */ void playIRFeedback() { if (isPlaying) return; isPlaying = true; setBuzzer(true); delay(BEEP_DURATION / 2); setBuzzer(false); isPlaying = false; } // ====================================== // 传感器控制函数区 // ====================================== /** 初始化AHT20温湿度传感器 @return 成功返回true,失败返回false */ bool initAHT20() { Wire.beginTransmission(AHT20_ADDR); Wire.write(AHT20_INIT_CMD); Wire.write(0x08); Wire.write(0x00); if (Wire.endTransmission() != 0) return false; delay(100); return true; } /** 读取AHT20温湿度数据 */ void readAHT20() { Wire.beginTransmission(AHT20_ADDR); Wire.write(AHT20_MEASURE_CMD); Wire.write(0x33); Wire.write(0x00); Wire.endTransmission(); delay(80); if (Wire.requestFrom(AHT20_ADDR, 6) != 6) return; byte status = Wire.read(); if ((status & 0x80) == 0) { byte hum1 = Wire.read(); byte hum2 = Wire.read(); byte hum3 = Wire.read(); byte temp1 = Wire.read(); byte temp2 = Wire.read(); byte temp3 = Wire.read(); unsigned long humValue = ((unsigned long)hum1 << 12) | ((unsigned long)hum2 << 4) | (hum3 >> 4); humidity = humValue * 100.0 / 0x100000; unsigned long tempValue = ((unsigned long)(hum3 & 0x0F) << 16) | ((unsigned long)temp1 << 8) | temp2; temperature = tempValue * 200.0 / 0x100000 - 50; } } /** 超声波测距 @return 距离(厘米) */ long getDistance() { digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); long duration = pulseIn(ECHO_PIN, HIGH); return constrain(duration * 0.0343 / 2, 0, 150); } // ====================================== // 模式控制函数区 // ====================================== /** 红外遥控模式逻辑 */ void runIRMode() {} /** 超声波模式逻辑(每500ms更新) */ void runUltrasonicMode() { if (millis() - modeTimers[MODE_ULTRASONIC] < 500) return; long distance = getDistance(); int newSpeed = distance < 5 ? 0 : (distance < 30 ? 1 : (distance < 60 ? 2 : 3)); if (newSpeed != modeSpeeds[MODE_ULTRASONIC]) { modeSpeeds[MODE_ULTRASONIC] = newSpeed; setFanSpeed(newSpeed); } modeTimers[MODE_ULTRASONIC] = millis(); } /** 温湿度模式逻辑(每2000ms更新) */ void runTempHumMode() { if (millis() - modeTimers[MODE_TEMP_HUM] < 2000) return; readAHT20(); float tempIndex = constrain((temperature - 20) / 20, 0, 1); float humIndex = constrain(humidity / 100, 0, 1); float index = (tempIndex * 0.6 + humIndex * 0.4) * 100; int newSpeed = index < 25 ? 0 : (index < 50 ? 1 : (index < 75 ? 2 : 3)); if (newSpeed != modeSpeeds[MODE_TEMP_HUM]) { modeSpeeds[MODE_TEMP_HUM] = newSpeed; setFanSpeed(newSpeed); } modeTimers[MODE_TEMP_HUM] = millis(); } /** 手动模式逻辑(每200ms更新) */ void runManualMode() { if (millis() - modeTimers[MODE_MANUAL] < 200) return; int newSpeed = map(analogRead(POT), 0, 1023, 0, 3); if (newSpeed != modeSpeeds[MODE_MANUAL]) { modeSpeeds[MODE_MANUAL] = newSpeed; setFanSpeed(newSpeed); } modeTimers[MODE_MANUAL] = millis(); } // ====================================== // 设备控制函数区 // ====================================== /** 设置风扇风速 @param speed 风速档位(0-3) */ void setFanSpeed(int speed) { if (speed < 0 || speed > 3) return; int pwmValue = speed * 85; // 0→0, 1→85, 2→170, 3→255 digitalWrite(FAN_NEG, LOW); analogWrite(FAN_POS, pwmValue); } /** 数码管显示数字 @param digit 数字(0-3) */ void displayDigit(int digit) { if (digit < 0 || digit > 3) return; digitalWrite(SEG_A, digitPatterns[digit][0]); digitalWrite(SEG_B, digitPatterns[digit][1]); digitalWrite(SEG_C, digitPatterns[digit][2]); digitalWrite(SEG_D, digitPatterns[digit][3]); digitalWrite(SEG_E, digitPatterns[digit][4]); digitalWrite(SEG_F, digitPatterns[digit][5]); digitalWrite(SEG_G, digitPatterns[digit][6]); } // ====================================== // 事件处理函数区 // ====================================== /** 处理红外命令 @param cmd 红外码值 */ void processIRCommand(unsigned long cmd) { switch (cmd) { case FAN_0: modeSpeeds[currentMode] = 0; setFanSpeed(0); playIRFeedback(); break; case FAN_1: modeSpeeds[currentMode] = 1; setFanSpeed(1); playIRFeedback(); break; case FAN_2: modeSpeeds[currentMode] = 2; setFanSpeed(2); playIRFeedback(); break; case FAN_3: modeSpeeds[currentMode] = 3; setFanSpeed(3); playIRFeedback(); break; case MODE_SWITCH: switchMode(); // 红外模式切换 break; } } /** 模式切换函数(循环切换) */ void switchMode() { currentMode = (currentMode % 4) + 1; // 1→2→3→4→1 setFanSpeed(modeSpeeds[currentMode]); playModeTone(currentMode); // 播放模式提示音 } /** 检查按键状态 SW1改为模式切换,SW2保留音效 */ void checkButtons() { static unsigned long lastDebounce = 0; unsigned long now = millis(); // SW1按键:模式切换(带防抖) if (digitalRead(SW1) == LOW && now - lastDebounce > debounceDelay) { switchMode(); // 执行模式切换 lastDebounce = now; } // SW2按键:保留原有音效 if (digitalRead(SW2) == LOW && now - lastDebounce > debounceDelay) { playButton2Sound(); lastDebounce = now; } } // ====================================== // 初始化与主循环区 // ====================================== void setup() { // 初始化引脚 pinMode(BEEPER, OUTPUT); pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); pinMode(FAN_POS, OUTPUT); pinMode(FAN_NEG, OUTPUT); pinMode(SW1, INPUT_PULLUP); // 模式切换按键 pinMode(SW2, INPUT_PULLUP); // 音效按键 pinMode(POT, INPUT); // 初始化数码管 pinMode(SEG_A, OUTPUT); pinMode(SEG_B, OUTPUT); pinMode(SEG_C, OUTPUT); pinMode(SEG_D, OUTPUT); pinMode(SEG_E, OUTPUT); pinMode(SEG_F, OUTPUT); pinMode(SEG_G, OUTPUT); // 初始化通信 Serial.begin(9600); Wire.begin(); irrecv.enableIRIn(); // 初始化AHT20 if (!initAHT20()) { Serial.println("AHT20初始化失败!"); while (1); } // 初始化定时器 for (int i = 1; i <= 4; i++) modeTimers[i] = millis(); // 初始状态 setBuzzer(false); setFanSpeed(0); displayDigit(0); playModeTone(MODE_IR); // 启动提示 } void loop() { // 处理红外信号 if (irrecv.decode(&results) && !isPlaying) { processIRCommand(results.value); irrecv.resume(); } // 检查按键(SW1模式切换,SW2音效) checkButtons(); // 执行当前模式逻辑 if (!isPlaying) { switch (currentMode) { case MODE_IR: runIRMode(); break; case MODE_ULTRASONIC: runUltrasonicMode(); break; case MODE_TEMP_HUM: runTempHumMode(); break; case MODE_MANUAL: runManualMode(); break; } displayDigit(modeSpeeds[currentMode]); } delay(50); }