#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ===== Pins (đổi nếu bạn nối khác) =====
#define DHT_PIN 4
#define DHT_TYPE 22
#define RELAY_PIN 5
#define OLED_SDA 21
#define OLED_SCL 22
#define LUX_ADC 34
#define BUZZ_PIN 14
#define BTN_PIN 12
#define LED_PIN 2
#define RELAY_ACTIVE_LEVEL HIGH // nhiều relay active-LOW -> đổi LOW nếu thấy đảo
// ===== Logic =====
#define TEMP_THRESHOLD_C 30.0f
#define TEMP_HYSTERESIS 1.5f
#define LUX_THRESHOLD 30 // % ánh sáng, < ngưỡng => bật đèn
#define READ_MS 1500UL
#define BUZZ_MS 200UL
DHT dht(DHT_PIN, DHT_TYPE);
Adafruit_SSD1306 display(128, 64, &Wire, -1);
bool fanOn = false;
bool lampOn = false;
float lastT = NAN, lastH = NAN;
uint8_t lastLux = 0;
unsigned long tRead = 0, tBuzzOff = 0;
void setRelay(bool on) {
fanOn = on;
digitalWrite(RELAY_PIN,
(RELAY_ACTIVE_LEVEL == HIGH) ? (on ? HIGH : LOW)
: (on ? LOW : HIGH));
}
void setLamp(bool on) {
lampOn = on;
digitalWrite(LED_PIN, on ? HIGH : LOW);
}
void beep(uint16_t ms = BUZZ_MS) {
ledcAttachPin(BUZZ_PIN, 0);
ledcWriteTone(0, 2200); // 2.2 kHz beep
tBuzzOff = millis() + ms;
}
uint8_t readLuxPct() {
int adc = analogRead(LUX_ADC); // 0..4095
int pct = map(adc, 0, 4095, 0, 100);
return (uint8_t)constrain(pct, 0, 100);
}
void drawOLED(float t, float h, uint8_t lux) {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 0); display.println("Multi-sensor Smart Home");
display.setCursor(0, 16); display.print("T: "); display.print(t, 1); display.println(" C");
display.print("H: "); display.print(h, 1); display.println(" %");
display.print("Lux: "); display.print(lux); display.println(" %");
display.print("Fan: "); display.println(fanOn ? "ON" : "OFF");
display.print("Lamp: "); display.println(lampOn ? "ON" : "OFF");
display.display();
}
void handleButton() {
static uint8_t last = HIGH;
static unsigned long deb = 0;
uint8_t cur = digitalRead(BTN_PIN);
if (cur != last && millis() - deb > 40) {
deb = millis(); last = cur;
if (cur == LOW) { // nhấn -> toggle quạt
setRelay(!fanOn);
beep();
Serial.print("[BTN] Fan -> "); Serial.println(fanOn ? "ON" : "OFF");
}
}
}
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("Project #2 – Multi-sensor Smart Home (Local)");
pinMode(RELAY_PIN, OUTPUT); setRelay(false);
pinMode(LED_PIN, OUTPUT); setLamp(false);
pinMode(BUZZ_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
dht.begin();
Wire.begin(OLED_SDA, OLED_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("[OLED] Not found (addr 0x3C).");
} else {
display.clearDisplay(); display.display();
}
}
void loop() {
handleButton();
// stop buzzer
if (tBuzzOff && millis() > tBuzzOff) { ledcWriteTone(0, 0); tBuzzOff = 0; }
if (millis() - tRead >= READ_MS) {
tRead = millis();
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("[DHT] Read failed");
return;
}
uint8_t lux = readLuxPct();
lastT = t; lastH = h; lastLux = lux;
// --- Fan control (hysteresis) ---
bool prevFan = fanOn;
if (!fanOn && t >= TEMP_THRESHOLD_C) {
setRelay(true); beep();
Serial.println("[FAN] ON (temp >= threshold)");
} else if (fanOn && t <= (TEMP_THRESHOLD_C - TEMP_HYSTERESIS)) {
setRelay(false);
Serial.println("[FAN] OFF (temp <= threshold - hyst)");
}
// --- Lamp control by Lux ---
bool prevLamp = lampOn;
setLamp(lux < LUX_THRESHOLD);
if (prevLamp != lampOn) {
Serial.print("[LAMP] "); Serial.println(lampOn ? "ON (dark)" : "OFF (bright)");
}
// --- OLED & Log ---
drawOLED(t, h, lux);
Serial.print("[DATA] T="); Serial.print(t, 1);
Serial.print("C H="); Serial.print(h, 1);
Serial.print("% Lux="); Serial.print(lux);
Serial.print("% Fan="); Serial.print(fanOn ? "ON" : "OFF");
Serial.print(" Lamp="); Serial.println(lampOn ? "ON" : "OFF");
}
}