// Mô phông phân loại sầu riên trên OLED theo mùi VOCs (SGP41 giả lập)
// ESP32 DevKit v1 (38 chân), OLED, 2 nút nhấn, 3 LED (Ri6, MonThong, KhoHoaXanh)
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// LED
#define LED_RI6 14
#define LED_MONTHONG 12
#define LED_KHOHOA 13
// Buttons
#define BTN_MODE 25 // Ghi nhớ / Kiểm tra
#define BTN_ACTION 26 // Hành động (ghi mùi hoặc kiểm mùi)
// Biến mô phỏng nồng độ VOCs cho từng loại (giá trị ví dụ)
int voc_ri6 = 120;
int voc_monthong = 150;
int voc_khohoa = 180;
// Biến ghi nhớ mùi
int saved_voc_ri6 = 0;
int saved_voc_monthong = 0;
int saved_voc_khohoa = 0;
int mode = 0; // 0 = Ghi nhớ, 1 = Kiểm tra
void setup() {
Serial.begin(115200);
pinMode(LED_RI6, OUTPUT);
pinMode(LED_MONTHONG, OUTPUT);
pinMode(LED_KHOHOA, OUTPUT);
pinMode(BTN_MODE, INPUT_PULLUP);
pinMode(BTN_ACTION, INPUT_PULLUP);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("OLED không tìm thấy!"));
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Chon che do...");
display.display();
}
void loop() {
if (digitalRead(BTN_MODE) == LOW) {
mode = 1 - mode; // Chuyển chế độ
delay(500);
display.clearDisplay();
display.setCursor(0, 0);
display.print("Che do: ");
display.print(mode == 0 ? "Ghi nho" : "Kiem tra");
display.display();
}
if (digitalRead(BTN_ACTION) == LOW) {
delay(500);
int sample_voc = simulateVOC();
display.clearDisplay();
display.setCursor(0, 0);
if (mode == 0) {
// Ghi nhớ mùi hiện tại (giả lập theo lượt)
if (saved_voc_ri6 == 0) {
saved_voc_ri6 = sample_voc;
display.print("Da ghi mui: Ri6");
} else if (saved_voc_monthong == 0) {
saved_voc_monthong = sample_voc;
display.print("Da ghi mui: MonThong");
} else if (saved_voc_khohoa == 0) {
saved_voc_khohoa = sample_voc;
display.print("Da ghi mui: KhoHoaXanh");
} else {
display.print("Da ghi 3 giong!");
}
} else {
// So sánh với mùi đã lưu
int delta_ri6 = abs(sample_voc - saved_voc_ri6);
int delta_monthong = abs(sample_voc - saved_voc_monthong);
int delta_khohoa = abs(sample_voc - saved_voc_khohoa);
digitalWrite(LED_RI6, LOW);
digitalWrite(LED_MONTHONG, LOW);
digitalWrite(LED_KHOHOA, LOW);
if (delta_ri6 <= saved_voc_ri6 * 0.1) {
display.print("Day la: Ri6");
digitalWrite(LED_RI6, HIGH);
} else if (delta_monthong <= saved_voc_monthong * 0.1) {
display.print("Day la: MonThong");
digitalWrite(LED_MONTHONG, HIGH);
} else if (delta_khohoa <= saved_voc_khohoa * 0.1) {
display.print("Day la: KhoHoaXanh");
digitalWrite(LED_KHOHOA, HIGH);
} else {
display.print("Khong nhan dang!");
}
}
display.setCursor(0, 20);
display.print("VOC: ");
display.print(sample_voc);
display.display();
}
}
int simulateVOC() {
// Mô phông ngẫu nhiên một trong 3 giá trị VOC gần giống
int type = random(3);
int base = (type == 0) ? voc_ri6 : (type == 1) ? voc_monthong : voc_khohoa;
return base + random(-5, 6); // +/- 5 ppm sên
}