#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Servo.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
// ===== BLYNK SETTINGS =====
#define BLYNK_TEMPLATE_ID "TMPL6qIwCe5WN"
#define BLYNK_TEMPLATE_NAME "Tong Sampah Canggih"
#define BLYNK_AUTH_TOKEN "odEHAm8urnqWgi-ZuJiZiS7-v6jEslos"
char ssid[] = "Wokwi-GUEST"; // WiFi Wokwi
char pass[] = "";
// OLED size
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Servo myServo;
// Pins
const int trigPin = 18;
const int echoPin = 19;
const int pirPin = 21;
const int servoPin = 13;
const int ledMerah = 23;
const int ledHijau = 22;
const int ledBiru = 15;
const int maxDistance = 100; // cm
// Icon bitmap
const unsigned char smart_bin_icon_48 [] PROGMEM = {
// [icon bytes truncated for brevity, tetap dari kode awal kamu]
};
void setup() {
Serial.begin(9600);
// Blynk start
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// Pin setup
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(pirPin, INPUT);
pinMode(ledMerah, OUTPUT);
pinMode(ledHijau, OUTPUT);
pinMode(ledBiru, OUTPUT);
myServo.attach(servoPin, 500, 2400);
myServo.write(0);
Wire.begin(16, 17);
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED gagal dimulai");
while (true);
}
// Splash screen 3 detik
oled.clearDisplay();
oled.drawBitmap(40, 0, smart_bin_icon_48, 48, 48, WHITE);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(10, 50);
oled.println("Tong Sampah Canggih");
oled.display();
delay(3000);
}
int getDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
int duration = pulseIn(echoPin, HIGH);
int distance = duration * 0.034 / 2;
return distance;
}
void cetakTengah(String teks, int y) {
int x = (128 - (teks.length() * 6)) / 2;
oled.setCursor(x, y);
oled.print(teks);
}
void tampilkanGrafik(int kapasitas) {
int barWidth = map(kapasitas, 0, 100, 0, 100);
oled.clearDisplay();
oled.setTextSize(1);
cetakTengah("Tong Sampah Canggih", 0);
oled.setCursor(0, 12);
oled.println("Status:");
String status = "Tersedia";
if (kapasitas >= 98) {
oled.println("PENUH!");
digitalWrite(ledMerah, LOW);
digitalWrite(ledHijau, HIGH);
digitalWrite(ledBiru, LOW);
status = "Penuh";
} else if (kapasitas >= 85) {
oled.println("Hampir Penuh");
digitalWrite(ledMerah, HIGH);
digitalWrite(ledHijau, HIGH);
digitalWrite(ledBiru, LOW);
status = "Hampir Penuh";
} else {
oled.println("Tersedia");
digitalWrite(ledMerah, HIGH);
digitalWrite(ledHijau, LOW);
digitalWrite(ledBiru, LOW);
}
// Kirim ke Blynk
Blynk.virtualWrite(V0, kapasitas);
Blynk.virtualWrite(V1, status);
cetakTengah("Kapasitas Tong", 36);
int barX = 10;
int barY = 46;
int barHeight = 10;
int barMaxWidth = 100;
oled.drawRect(barX, barY, barMaxWidth, barHeight, SSD1306_WHITE);
oled.fillRect(barX, barY, barWidth, barHeight, SSD1306_WHITE);
int textWidth = 6 * String(kapasitas).length() + 6;
int textX = barX + (barMaxWidth / 2) - (textWidth / 2);
int textY = barY + 1;
// Warna angka dinamis
if (kapasitas >= 40 && kapasitas <= 49) {
oled.setTextColor(SSD1306_BLACK);
oled.setCursor(textX, textY);
oled.print("4");
oled.setTextColor(SSD1306_WHITE);
oled.print(String(kapasitas).substring(1));
oled.print("%");
} else if (kapasitas >= 50) {
oled.setTextColor(SSD1306_BLACK);
oled.setCursor(textX, textY);
oled.print(kapasitas);
oled.print("%");
} else {
oled.setTextColor(SSD1306_WHITE);
oled.setCursor(textX, textY);
oled.print(kapasitas);
oled.print("%");
}
oled.setTextColor(SSD1306_WHITE);
oled.display();
}
void animasiBukaTutup() {
for (int pos = 0; pos <= 90; pos += 10) {
myServo.write(pos);
delay(100);
}
delay(3000); // tahan lebih lama terbuka
for (int pos = 90; pos >= 0; pos -= 10) {
myServo.write(pos);
delay(100);
}
}
unsigned long lastUpdate = 0;
int tampilState = 0;
void loop() {
Blynk.run();
int jarak = getDistance();
int kapasitas = constrain(100 - (jarak * 100 / maxDistance), 0, 100);
int motion = digitalRead(pirPin);
unsigned long now = millis();
if (tampilState == 0 && now - lastUpdate > 6000) {
tampilkanGrafik(kapasitas);
lastUpdate = now;
tampilState = 1;
} else if (tampilState == 1 && now - lastUpdate > 3000) {
// tampilan logo ulang (opsional)
oled.clearDisplay();
oled.drawBitmap(40, 0, smart_bin_icon_48, 48, 48, WHITE);
oled.setCursor(10, 50);
oled.println("Tong Sampah Canggih");
oled.display();
lastUpdate = now;
tampilState = 0;
}
if (kapasitas >= 98 && motion == HIGH) {
oled.clearDisplay();
oled.setCursor(0, 0);
oled.println("Sampah penuh!");
oled.println("Tidak bisa buka.");
oled.display();
delay(3000);
} else if (motion == HIGH) {
oled.clearDisplay();
oled.setCursor(0, 0);
oled.println("Gerakan Terdeteksi");
oled.println("Membuka Tutup...");
oled.display();
animasiBukaTutup();
delay(500);
}
}