#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const uint32_t TEMP_PIN = A0;
const uint32_t LIGHT_PIN = A1;
const uint32_t THRESHOLD_PIN = A2;
const uint32_t KEY1_PIN = PB8;
const uint32_t KEY2_PIN = PB9;
const uint32_t GREEN_LED_PIN = PB12;
const uint32_t RED_LED_PIN = PB13;
const uint32_t BUZZER_PIN = PB14;
const uint32_t FAN_PIN = PB15;
const float ADC_REF_VOLTAGE = 3.3f;
const float ADC_MAX_VALUE = 4095.0f;
const unsigned long UI_UPDATE_MS = 200;
const unsigned long SERIAL_UPDATE_MS = 1000;
const unsigned long DEBOUNCE_MS = 30;
const unsigned long BUZZER_REARM_MS = 250;
LiquidCrystal_I2C lcd(0x27, 16, 2);
enum LightLevel {
LIGHT_DARK,
LIGHT_NORMAL,
LIGHT_BRIGHT
};
struct ButtonState {
bool stableLevel;
bool lastRawLevel;
unsigned long lastChangeMs;
};
struct SensorData {
int tempAdc;
int lightAdc;
int thresholdAdc;
float tempVoltage;
float lightVoltage;
float thresholdVoltage;
float temperatureC;
float thresholdC;
LightLevel lightLevel;
};
ButtonState key1State = {HIGH, HIGH, 0};
ButtonState key2State = {HIGH, HIGH, 0};
SensorData data;
uint8_t lcdPage = 0;
bool alarmActive = false;
bool tempAlarm = false;
bool darkAlarm = false;
bool fanOn = false;
bool buzzerLatched = false;
unsigned long lastUiUpdateMs = 0;
unsigned long lastSerialUpdateMs = 0;
unsigned long buzzerRearmAtMs = 0;
float adcToVoltage(int adc) {
return adc * ADC_REF_VOLTAGE / ADC_MAX_VALUE;
}
LightLevel classifyLight(int adc) {
if (adc < 1365) {
return LIGHT_DARK;
}
if (adc < 3000) {
return LIGHT_NORMAL;
}
return LIGHT_BRIGHT;
}
const char *lightLevelText(LightLevel level) {
switch (level) {
case LIGHT_DARK:
return "DARK";
case LIGHT_BRIGHT:
return "BRIGHT";
case LIGHT_NORMAL:
default:
return "NORMAL";
}
}
const char *onOffText(bool value) {
return value ? "ON" : "OFF";
}
bool pressedEdge(uint32_t pin, ButtonState &state) {
bool raw = digitalRead(pin);
unsigned long now = millis();
if (raw != state.lastRawLevel) {
state.lastRawLevel = raw;
state.lastChangeMs = now;
}
if ((now - state.lastChangeMs) >= DEBOUNCE_MS && raw != state.stableLevel) {
state.stableLevel = raw;
if (state.stableLevel == LOW) {
return true;
}
}
return false;
}
SensorData readSensors() {
SensorData result;
result.tempAdc = analogRead(TEMP_PIN);
result.lightAdc = analogRead(LIGHT_PIN);
result.thresholdAdc = analogRead(THRESHOLD_PIN);
result.tempVoltage = adcToVoltage(result.tempAdc);
result.lightVoltage = adcToVoltage(result.lightAdc);
result.thresholdVoltage = adcToVoltage(result.thresholdAdc);
result.temperatureC = result.tempVoltage * 100.0f;
result.thresholdC = 20.0f + result.thresholdVoltage / ADC_REF_VOLTAGE * 60.0f;
result.lightLevel = classifyLight(result.lightAdc);
return result;
}
void updateAlarmAndOutputs(const SensorData ¤t) {
unsigned long now = millis();
tempAlarm = current.temperatureC >= current.thresholdC;
darkAlarm = current.lightLevel == LIGHT_DARK;
alarmActive = tempAlarm || darkAlarm;
fanOn = tempAlarm;
if (alarmActive && now >= buzzerRearmAtMs) {
buzzerLatched = true;
}
if (!alarmActive) {
buzzerRearmAtMs = 0;
}
digitalWrite(GREEN_LED_PIN, alarmActive ? LOW : HIGH);
digitalWrite(RED_LED_PIN, alarmActive ? HIGH : LOW);
digitalWrite(FAN_PIN, fanOn ? HIGH : LOW);
digitalWrite(BUZZER_PIN, buzzerLatched ? HIGH : LOW);
}
void printLcdLine(uint8_t row, String text) {
if (text.length() > 16) {
text = text.substring(0, 16);
}
while (text.length() < 16) {
text += ' ';
}
lcd.setCursor(0, row);
lcd.print(text);
}
void updateLcd() {
if (lcdPage == 0) {
String line1 = "T:";
line1 += String(data.temperatureC, 1);
line1 += "C TH:";
line1 += String(data.thresholdC, 0);
String line2 = "STAT:";
line2 += alarmActive ? "ALARM" : "NORMAL";
printLcdLine(0, line1);
printLcdLine(1, line2);
} else {
String line1 = "L:";
line1 += data.lightAdc;
line1 += " ";
line1 += lightLevelText(data.lightLevel);
String line2 = "F:";
line2 += onOffText(fanOn);
line2 += " B:";
line2 += onOffText(buzzerLatched);
printLcdLine(0, line1);
printLcdLine(1, line2);
}
}
void printSerialHeader() {
Serial1.println("Smart Sensing System Started");
Serial1.println("Time(ms),Temp(C),Threshold(C),LightADC,LightLevel,Alarm,Fan,Buzzer,Page");
}
void printSerialData() {
Serial1.print(millis());
Serial1.print(",T=");
Serial1.print(data.temperatureC, 1);
Serial1.print("C,TH=");
Serial1.print(data.thresholdC, 1);
Serial1.print("C,LIGHT=");
Serial1.print(data.lightAdc);
Serial1.print(",");
Serial1.print(lightLevelText(data.lightLevel));
Serial1.print(",ALARM=");
Serial1.print(onOffText(alarmActive));
Serial1.print(",FAN=");
Serial1.print(onOffText(fanOn));
Serial1.print(",BUZ=");
Serial1.print(onOffText(buzzerLatched));
Serial1.print(",PAGE=");
Serial1.println(lcdPage + 1);
}
void handleButtons() {
if (pressedEdge(KEY1_PIN, key1State)) {
lcdPage = (lcdPage + 1) % 2;
updateLcd();
}
if (pressedEdge(KEY2_PIN, key2State)) {
buzzerLatched = false;
buzzerRearmAtMs = millis() + BUZZER_REARM_MS;
digitalWrite(BUZZER_PIN, LOW);
}
}
void setup() {
Serial1.begin(115200);
delay(200);
printSerialHeader();
analogReadResolution(12);
pinMode(KEY1_PIN, INPUT_PULLUP);
pinMode(KEY2_PIN, INPUT_PULLUP);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(FAN_PIN, OUTPUT);
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(FAN_PIN, LOW);
Wire.setSDA(PB7);
Wire.setSCL(PB6);
Wire.begin();
lcd.init();
lcd.backlight();
printLcdLine(0, "STM32 Sensing");
printLcdLine(1, "System Ready");
delay(500);
data = readSensors();
updateAlarmAndOutputs(data);
updateLcd();
printSerialData();
}
void loop() {
unsigned long now = millis();
handleButtons();
if ((now - lastUiUpdateMs) >= UI_UPDATE_MS) {
lastUiUpdateMs = now;
data = readSensors();
updateAlarmAndOutputs(data);
updateLcd();
}
if ((now - lastSerialUpdateMs) >= SERIAL_UPDATE_MS) {
lastSerialUpdateMs = now;
printSerialData();
}
}
Loading
stm32-bluepill
stm32-bluepill
TEMP SENSOR
模拟 LM35 温度传感器
A0 / ADC1_IN0
电压越高,温度越高
LIGHT SENSOR
模拟 LDR 光照分压
A1 / ADC1_IN1
用于判断 DARK / NORMAL / BRIGHT
THRESHOLD SET
温度报警阈值设定
A2 / ADC1_IN2
0~3.3V 映射为 20~80℃
LCD1602 I2C DISPLAY
页面1:温度 / 阈值 / 系统状态
页面2:光照 / 风扇 / 蜂鸣器状态
KEY1 PAGE
切换 LCD 显示页面
KEY2 RESET
复位蜂鸣器报警锁存
NORMAL
正常状态指示灯
正常亮,报警灭
ALARM
报警状态指示灯
温度超限或光照偏暗时亮
BUZZER
报警提示
异常发生后锁存,KEY2 可复位
FAN
温度超过阈值时启动
用 LED 或电机等效模拟风扇
STM32 BLUE PILL
多传感器 ADC 采集与报警控制核心
A0 温度,A1 光照,A2 阈值
GPIO 控制 LED / BUZZER / FAN / KEY
USART1: A9=TX, A10=RX -> Serial Monitor
系统流程:传感器输入 → ADC采样 → 数据换算 → 阈值判断 → LCD/串口显示 → 声光报警/风扇控制