commit ac387e5f4ff675772099ad35090b742bbdf14c02 Author: alia Date: Thu Jul 31 12:11:38 2025 +0700 first commit diff --git a/sketch_buzzer.ino b/sketch_buzzer.ino new file mode 100644 index 0000000..925cfd6 --- /dev/null +++ b/sketch_buzzer.ino @@ -0,0 +1,215 @@ +#include +#include +#include +#include "MAX30105.h" +#include "heartRate.h" +#include +#include +#include +#define BUZZER_PIN 27 + +// --- WiFi & Thinger --- +#define SSID "AR ID" +#define PASSWORD "012345678" +#define USERNAME "amalia_lia" +#define DEVICE_ID "esp32-mood" +#define DEVICE_CREDENTIAL "esp32-mood" + +ThingerESP32 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL); + +// --- MAX30102 --- +MAX30105 particleSensor; +const int SDA_PIN = 21; +const int SCL_PIN = 22; +const int GSR_PIN = 34; + +// --- TFT ST7789 --- +#define TFT_CS 5 +#define TFT_DC 2 +#define TFT_RST 4 +Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST); + +// --- Variabel Global --- +float beatAvg = 0; +float gsrLevel = 0; +String currentMood = "Unknown"; + +// --- Fungsi Mood --- +String determineMood(float bpm, float gsr) { + if (bpm == 0 || gsr == 0) return "Gagal"; + String moodHR = (bpm <= 90) ? "Tenang" : (bpm <= 100 ? "Cemas" : "Tegang"); + String moodGSR = (gsr <= 4.0) ? "Tenang" : (gsr <= 6.0 ? "Cemas" : "Tegang"); + + if (moodHR == "Tenang" && moodGSR == "Tenang") return "Tenang"; + if (moodHR == "Cemas" && moodGSR == "Cemas") return "Cemas"; + if (moodHR == "Tegang" || moodGSR == "Tegang") return "Tegang"; + return "Cemas"; +} + +// --- TFT Gambar Wajah --- +void drawArc(int x, int y, int r1, int r2, int start_angle, int end_angle, uint16_t color) { + for (int angle = start_angle; angle <= end_angle; angle++) { + float rad = angle * PI / 180; + int x1 = x + cos(rad) * r1; + int y1 = y + sin(rad) * r1; + int x2 = x + cos(rad) * r2; + int y2 = y + sin(rad) * r2; + tft.drawLine(x1, y1, x2, y2, color); + } +} + +void drawFace(String mood) { + uint16_t faceColor = ST77XX_WHITE; + if (mood == "Tenang") faceColor = ST77XX_YELLOW; + else if (mood == "Cemas") faceColor = 0xFD20; + else if (mood == "Tegang") faceColor = ST77XX_RED; + + tft.fillScreen(ST77XX_BLACK); + tft.fillCircle(120, 90, 50, faceColor); + + // Mata + if (mood == "Tegang") { + tft.fillCircle(100, 75, 8, ST77XX_BLACK); + tft.fillCircle(140, 75, 8, ST77XX_BLACK); + tft.fillCircle(85, 60, 4, ST77XX_BLUE); + tft.fillCircle(155, 60, 3, ST77XX_BLUE); + } else { + tft.fillCircle(100, 75, 5, ST77XX_BLACK); + tft.fillCircle(140, 75, 5, ST77XX_BLACK); + } + + // Mulut + if (mood == "Tenang") { + drawArc(120, 105, 18, 21, 45, 135, ST77XX_BLACK); + } else if (mood == "Cemas") { + tft.fillRect(105, 110, 30, 4, ST77XX_BLACK); + } else if (mood == "Tegang") { + drawArc(120, 120, 18, 21, 225, 315, ST77XX_BLACK); + } + + tft.setTextColor(ST77XX_WHITE); + tft.setTextSize(2); + tft.setCursor(10, 160); tft.print("HR : "); tft.print(beatAvg, 1); tft.println(" BPM"); + tft.setCursor(10, 185); tft.print("GSR : "); tft.print(gsrLevel, 2); + tft.setCursor(10, 210); tft.print("Mood : "); tft.println(mood); +} + +// --- SETUP --- +void setup() { + Serial.begin(115200); + WiFi.begin(SSID, PASSWORD); + Wire.begin(SDA_PIN, SCL_PIN); + pinMode(GSR_PIN, INPUT); + pinMode(BUZZER_PIN, OUTPUT); + digitalWrite(BUZZER_PIN, LOW); // Awalnya mati + + if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) { + Serial.println("[ERROR] MAX30102 tidak terdeteksi!"); + while (1); + } + + particleSensor.setup(0x1F, 4, 2, 100, 411, 4096); + SPI.begin(18, -1, 23); + tft.init(240, 240); tft.setRotation(1); tft.fillScreen(ST77XX_BLACK); + + thing.add_wifi(SSID, PASSWORD); + thing["mood"] >> [](pson &out) { + out["bpm"] = beatAvg; + out["gsr"] = gsrLevel; + out["mood"] = currentMood; + }; + + Serial.println("[READY] Silakan sentuhkan jari ke sensor."); +} + +// --- LOOP --- +void loop() { + Serial.println("=== Mulai Pengukuran (10 detik) ==="); + + unsigned long startTime = millis(); + unsigned long lastBeat = 0; + float bpmSum = 0; + int validBeats = 0; + unsigned long gsrSum = 0; + int gsrSamples = 0; + + while (millis() - startTime < 10000) { + particleSensor.check(); + long irValue = particleSensor.getIR(); + int gsrValue = analogRead(GSR_PIN); + + gsrSum += gsrValue; + gsrSamples++; + + if (checkForBeat(irValue)) { + unsigned long now = millis(); + if (lastBeat > 0) { + float delta = (now - lastBeat) / 1000.0; + float bpm = 60.0 / delta; + if (bpm >= 40 && bpm <= 180) { + bpmSum += bpm; + validBeats++; + Serial.print("[BEAT] BPM valid: "); + Serial.println(bpm, 1); + } + } + lastBeat = now; + } + + delay(10); + } + + // Hitung rata-rata + beatAvg = (validBeats > 0) ? bpmSum / validBeats : 0; + float avgGSR = gsrSum / gsrSamples; + bool isFingerDetected = (avgGSR > 200); + + if (!isFingerDetected || beatAvg == 0) { + beatAvg = 0; + gsrLevel = 0; + currentMood = "Gagal"; + + tft.fillScreen(ST77XX_BLACK); + tft.setTextColor(ST77XX_WHITE); + tft.setTextSize(2); + tft.setCursor(20, 100); + tft.println("Tempel jari Anda"); + tft.setCursor(20, 130); + tft.println("untuk mulai"); + } else { + gsrLevel = map(avgGSR, 300, 2500, 100, 700) / 100.0; + gsrLevel = constrain(gsrLevel, 1.0, 7.0); + currentMood = determineMood(beatAvg, gsrLevel); + drawFace(currentMood); + if (currentMood == "Tegang") { + // Buzzer bunyi panjang (beepppppppppp) + digitalWrite(BUZZER_PIN, HIGH); + delay(2000); // 2 detik + digitalWrite(BUZZER_PIN, LOW); + } else if (currentMood == "Cemas") { + // Buzzer bunyi pendek berulang (beep beep beep) + for (int i = 0; i < 3; i++) { + digitalWrite(BUZZER_PIN, HIGH); + delay(300); // 0.3 detik bunyi + digitalWrite(BUZZER_PIN, LOW); + delay(300); // 0.3 detik jeda + } + } + } + + // Kirim ke Thinger.io + thing.write_bucket("Emotion_data", "mood", [](pson &data) { + data["bpm"] = beatAvg; + data["gsr"] = gsrLevel; + data["mood"] = currentMood; + }); + + thing.handle(); + + Serial.print("BPM: "); Serial.println(beatAvg, 1); + Serial.print("GSR: "); Serial.println(gsrLevel, 2); + Serial.print("Mood: "); Serial.println(currentMood); + Serial.println("========================="); + + delay(1000); +}