#include <SPI.h>
#include <Wire.h> // Library untuk komunikasi I2C yang dibutuhkan OLED
#include <Adafruit_GFX.h> // Library grafis dasar untuk menggambar di display
#include <Adafruit_SSD1306.h> // Library khusus untuk OLED controller SSD1306
#include <WiFi.h>
#include "DHT.h"
#include <WiFi.h>
#include <ThingSpeak.h>
#define DHTPIN 4 // Pin ESP32 yang tersambung ke pin Data DHT22
#define DHTTYPE DHT22 // Jenis sensor DHT22 (AM2302, AM2321)
DHT dht(DHTPIN, DHTTYPE);
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
const char* ssid = "Wokwi-GUEST"; // WiFi wokwi
const char* pass = ""; // Kata sandi (kosong untuk jaringan terbuka)
int keyIndex = 0; // Indeks kunci jaringan (hanya untuk WEP)
WiFiClient client;
// Konfigurasi ThingSpeak
unsigned long channelNumber = 3063083; // Nomor channel ThingSpeak
const char* writeAPIKey = "J5PO4XOMR5BGOBFT"; // Kunci API untuk menulis data
// timing
unsigned long previousMillis = 0; // Waktu sebelumnya untuk penghitungan interval
const long updateInterval = 20000; // update tiap 20s
float hum = 0; // variabel untuk menyimpan nilai kelembaban
float temp = 0; // variabel untuk menyimpan nilai suhu
float hic = 0; // heat index dalam celcius
// Thermometer icon 55x55px (monochrome)
const unsigned char thermo [] PROGMEM = {
0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x0e, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
0x0c, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1f,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x38, 0x60, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00, 0x00,
0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c,
0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x60,
0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00,
0x00, 0x00, 0x0c, 0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xfe, 0x70, 0x00, 0x00, 0x00, 0x00,
0x3c, 0xfe, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xbc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xde, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xef, 0x00, 0x00, 0x00,
0x00, 0xef, 0xff, 0xef, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xef, 0x00, 0x00, 0x00, 0x00, 0xef,
0xff, 0xef, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xef, 0x00, 0x00, 0x00, 0x00, 0xef, 0xff, 0xef,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf7, 0xff, 0xde, 0x00, 0x00,
0x00, 0x00, 0xfb, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xff, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x7e, 0xfe, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00,
0x00
};
// Ikon WiFi Terhubung - 16x16px
const unsigned char wifi_icon[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x1f, 0xf8, 0x7c, 0x3e, 0xe7, 0xe7,
0xdf, 0xfb, 0x39, 0x1c, 0x37, 0xec, 0x0f, 0xf0, 0x0f, 0xf0, 0x03, 0xc0,
0x03, 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00
};
// Ikon WiFi Terputus - 16x16px
const unsigned char wifi_dc[] PROGMEM = {
0x00, 0x00, 0x00, 0x04, 0x03, 0xce, 0xff, 0xdc, 0x7f, 0xba, 0xf8, 0x77,
0x60, 0xe6, 0x05, 0xc0, 0x0b, 0xbb, 0x07, 0x70, 0x0e, 0x20, 0x1c, 0x00,
0x1b, 0x80, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00
};
// Ikon Update Berhasil - 16x16px
const unsigned char Update_OK[] PROGMEM = {
0x01, 0x80, 0x0f, 0xf2, 0x10, 0x18, 0x20, 0x0c, 0x40, 0x1e, 0x40, 0x32,
0x40, 0x62, 0x84, 0x63, 0x83, 0xc3, 0x41, 0x82, 0x40, 0x02, 0x40, 0x06,
0x20, 0x04, 0x10, 0x08, 0x0e, 0x70, 0x01, 0x80
};
// Ikon Update Gagal - 16x16px
const unsigned char Update_NOK[] PROGMEM = {
0x01, 0x80, 0x0e, 0x70, 0x10, 0x08, 0x20, 0x04, 0x48, 0x32, 0x44, 0x62,
0x62, 0x82, 0x81, 0x82, 0x83, 0x82, 0xc6, 0x42, 0x4c, 0x22, 0x48, 0x16,
0x20, 0x04, 0x10, 0x18, 0x0e, 0xf0, 0x01, 0x80
};
void setup() {
Serial.begin(9600);
Serial.println(F("DHT22 test program!"));
dht.begin();
// Inisialisasi OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // berhenti di sini kalau OLED gagal
}
// Intro tampilan
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(38, 20);
display.println(F("TEST"));
display.setCursor(32, 35);
display.println(F("TEST PROGRAM"));
display.display();
delay(3000);
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client); //inisialisasi thingspeak
ConnectWIFI();
}
void loop() {
hum = dht.readHumidity();
temp = dht.readTemperature(); // membaca suhu dalam Celsius
// Cek apakah pembacaan valid
if (isnan(hum) || isnan(temp)) {
Serial.println(F("Gagal mendapat data dari sensor DHT!"));
return;
}
// Hitung heat index dalam Celsius
hic = dht.computeHeatIndex(temp, hum, false);
if (WiFi.status() != WL_CONNECTED) {
display.drawBitmap(110, 0, wifi_dc, 16, 16, WHITE); // Tampilkan ikon WiFi terputus
} else {
display.drawBitmap(110, 0, wifi_icon, 16, 16, WHITE); // Tampilkan ikon WiFi terhubung
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= updateInterval) {
previousMillis = currentMillis;
// Periksa dan sambungkan ulang WiFi jika terputus
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, pass, 6); // coba pakai channel 6;
int attemptCount = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
attemptCount++;
if (attemptCount == 20) {
Serial.println("\nFailed to connect to WiFi.");
break;
}
}
}
ThingSpeak.setField(1, hum); // Field ke-1: Humidity
ThingSpeak.setField(2, temp); // Field ke-2: Temperature
ThingSpeak.setField(3, hic); // Field ke-3: Heat Index
int x = ThingSpeak.writeFields(channelNumber, writeAPIKey);
if (x == 200) {
Serial.println("Sukses Update Channel.");
display.drawBitmap(90, 0, Update_OK, 16, 16, WHITE);
} else {
Serial.print("Update Channel Bermasalah. HTTP error code: ");
Serial.println(x);
display.drawBitmap(90, 0, Update_NOK, 16, 16, WHITE);
}
}
display.display();
delay(2000);
}
}
void ConnectWIFI(){
if(WiFi.status() != WL_CONNECTED){
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, pass); // coba ganti ke WiFi.begin(ssid, pass, 6); jika perlu
int i=0;
int a=0;
while(WiFi.status() != WL_CONNECTED){
Serial.print(".");
display.clearDisplay();
display.setTextSize(1);
if (a==0){
display.drawBitmap(52, 15, wifi_icon, 16, 16, WHITE);
a=1;
} else {
display.drawBitmap(52, 15, wifi_icon, 16, 16, BLACK);
a=0;
}
display.setCursor(25,38);
display.print("Connecting ...");
display.display();
delay(1000);
++i;
if (i==60){ // tadinya 30, saya ganti jadi 60 detik
i=0;
Serial.println("\nFailed to Connect.");
break;
}
}
}
if(WiFi.status() == WL_CONNECTED){
Serial.println("\nConnected!");
display.clearDisplay();
display.setTextSize(1);
display.drawBitmap(52, 15, wifi_icon, 16, 16, WHITE);
display.setCursor(33,38);display.print("Connected!");
display.display();
}else{
display.clearDisplay();
display.setTextSize(1);
display.drawBitmap(52, 15, wifi_dc, 16, 16, WHITE);
display.setCursor(20,38);display.print("Wifi Connection");
display.setCursor(36,48);display.print("Failed!");
display.display();
}
delay(3000);
}