#define BLINKER_WIFI
#define BLINKER_WITHOUT_SSL
#include <Blinker.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
// ==================== 引脚定义 ====================
#define OLED_SDA 21
#define OLED_SCL 22
#define LIGHT_SENSOR 35 // 光敏传感器 (ADC)
#define MQ135_PIN 32 // MQ135空气质量传感器 (ADC)
#define DHT11_PIN 4 // DHT11 数据引脚
#define LIGHT_OUTPUT 16 // 灯光控制引脚 (原为2,为避免与蜂鸣器冲突改为16,可自行修改)
#define BEEPER_PIN 2 // 蜂鸣器引脚 (低电平触发)
// ==================== 阈值定义 ====================
#define TEMP_MAX_THRESHOLD 30.0 // 最高温度阈值 (°C)
#define HUMI_MIN_THRESHOLD 30.0 // 最低湿度阈值 (%)
#define HUMI_MAX_THRESHOLD 70.0 // 最高湿度阈值 (%)
#define AIR_QUALITY_MAX 50 // 空气质量指数阈值 (0-100, 越高越差)
// ==================== OLED配置 ====================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// ==================== DHT11配置 ====================
#define DHTTYPE DHT11
DHT dht(DHT11_PIN, DHTTYPE);
// ==================== Blinker配置 ====================
char auth[] = "a326166646f1"; // 替换为你的Blinker Secret Key
char ssid[] = "wwty"; // 替换为你的WiFi名称
char pswd[] = "aaaaaaaa"; // 替换为你的WiFi密码
// 定义Blinker组件
BlinkerButton ButtonLight("light"); // 灯光控制按钮
BlinkerNumber Temp("temp"); // 温度显示
BlinkerNumber Humi("humi"); // 湿度显示
BlinkerNumber Light("lightness"); // 光照强度显示
BlinkerNumber Air("air"); // 空气质量显示
// ==================== 全局变量 ====================
float temperature = 0.0;
float humidity = 0.0;
int lightLevel = 0;
int airQuality = 0;
bool lightState = false; // 灯光状态
bool alarmActive = false; // 报警状态标志(避免重复触发)
unsigned long lastSensorRead = 0;
const long sensorInterval = 2000; // 传感器读取间隔 (ms)
// ==================== 函数声明 ====================
void readSensors();
void updateDisplay();
void updateBlinker();
void buttonLightCallback(const String &state);
String getFormattedDateTime();
void checkAndAlert(); // 阈值判断与报警
// ==================== 按钮回调 ====================
void buttonLightCallback(const String &state) {
BLINKER_LOG("Light button state: ", state);
if (state == BLINKER_CMD_BUTTON_PRESSED) {
lightState = !lightState;
digitalWrite(LIGHT_OUTPUT, lightState ? HIGH : LOW);
ButtonLight.print(lightState ? "on" : "off");
}
}
// ==================== 数据读取回调(来自App) ====================
void dataRead(const String &data) {
BLINKER_LOG("Blinker readString: ", data);
}
// ==================== 获取网络日期时间 (YYYY-MM-DD HH:MM) ====================
String getFormattedDateTime() {
time_t now = time(nullptr);
struct tm *p_tm = localtime(&now);
if (p_tm->tm_year < 100) { // 时间未同步
return "Time syncing...";
}
char buffer[20];
sprintf(buffer, "%04d-%02d-%02d %02d:%02d",
p_tm->tm_year + 1900,
p_tm->tm_mon + 1,
p_tm->tm_mday,
p_tm->tm_hour,
p_tm->tm_min);
return String(buffer);
}
// ==================== 读取传感器数据 ====================
void readSensors() {
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
BLINKER_LOG("Failed to read from DHT sensor!");
humidity = 0.0;
temperature = 0.0;
}
lightLevel = analogRead(LIGHT_SENSOR);
lightLevel = map(lightLevel, 0, 4095, 0, 100);
int rawAir = analogRead(MQ135_PIN);
airQuality = map(rawAir, 0, 4095, 0, 100);
}
// ==================== 阈值判断与蜂鸣器报警 ====================
void checkAndAlert() {
bool needAlarm = false;
// 判断是否超过阈值
if (temperature > TEMP_MAX_THRESHOLD) {
BLINKER_LOG("Temperature alarm! ", temperature);
needAlarm = true;
}
if (humidity < HUMI_MIN_THRESHOLD || humidity > HUMI_MAX_THRESHOLD) {
BLINKER_LOG("Humidity alarm! ", humidity);
needAlarm = true;
}
if (airQuality > AIR_QUALITY_MAX) {
BLINKER_LOG("Air quality alarm! ", airQuality);
needAlarm = true;
}
// 控制蜂鸣器 (低电平触发)
if (needAlarm) {
if (!alarmActive) {
alarmActive = true;
digitalWrite(BEEPER_PIN, LOW); // 低电平蜂鸣器响
BLINKER_LOG("Beeper ON");
}
} else {
if (alarmActive) {
alarmActive = false;
digitalWrite(BEEPER_PIN, HIGH); // 高电平停止
BLINKER_LOG("Beeper OFF");
}
}
}
// ==================== 更新OLED显示 ====================
void updateDisplay() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
// 第一行:日期和时间
display.println(getFormattedDateTime());
// 第二行:温度、湿度
display.print("Temp: ");
display.print(temperature, 1);
display.print("C Humi: ");
display.print(humidity, 1);
display.println("%");
// 第三行:光照
display.print("Light: ");
display.print(lightLevel);
display.println("%");
// 第四行:空气质量
display.print("Air: ");
display.print(airQuality);
display.println("%");
display.display();
}
// ==================== 更新Blinker数据 ====================
void updateBlinker() {
Temp.print(temperature);
Humi.print(humidity);
Light.print(lightLevel);
Air.print(airQuality);
}
// ==================== 初始化 ====================
void setup() {
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();
// 初始化灯光控制引脚
pinMode(LIGHT_OUTPUT, OUTPUT);
digitalWrite(LIGHT_OUTPUT, LOW);
// 初始化蜂鸣器引脚 (低电平触发,默认高电平关闭)
pinMode(BEEPER_PIN, OUTPUT);
digitalWrite(BEEPER_PIN, HIGH); // 默认不响
// 初始化I2C (OLED)
Wire.begin(OLED_SDA, OLED_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("System init...");
display.display();
dht.begin();
Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);
ButtonLight.attach(buttonLightCallback);
configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov");
readSensors();
updateDisplay();
}
// ==================== 主循环 ====================
void loop() {
Blinker.run();
unsigned long now = millis();
if (now - lastSensorRead >= sensorInterval) {
lastSensorRead = now;
readSensors();
checkAndAlert(); // 阈值判断并触发蜂鸣器
updateDisplay();
updateBlinker();
}
}Loading
ssd1306
ssd1306