#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include "ThingSpeak.h"
// Pin Definitions
#define DHTPIN 27 // DHT11 data pin connected to GPIO 4
#define DHTTYPE DHT11 // Define DHT type as DHT11
#define SOIL_MOISTURE_PIN 34 // Soil moisture sensor connected to analog pin 32
#define LIGHT_SENSOR_PIN 32 // Photosensitive light sensor connected to analog pin 35
#define LED_PIN 2 // LED connected to GPIO 2
// OLED display dimensions
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// DHT sensor object
DHT dht(DHTPIN, DHTTYPE);
// WiFi and ThingSpeak
const char* ssid = "Wokwi-GUEST";
const char* password = "";
WiFiClient client;
unsigned long myChannelNumber = 2613917;
const char *myWriteAPIKey = "3DJGO1ZU3E6UCHU6";
// Timing variables
unsigned long previousMillis_ts = 0;
unsigned long previousMillis_display = 0;
const long ts_update_interval = 20000; // update data setiap 20 detik
const long display_interval = 1000; // update display setiap 1 detik
// Icons
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 sukses
const unsigned char Update_NOK[] PROGMEM = {
0x01, 0x80, 0x0e, 0x70, 0x10, 0x08, 0x20, 0x04, 0x48, 0x32, 0x44, 0x62, 0xc2, 0xc2, 0x81, 0x82,
0x83, 0x82, 0xc6, 0x42, 0x4c, 0x22, 0x48, 0x16, 0x20, 0x04, 0x10, 0x18, 0x0e, 0xf0, 0x01, 0x80}; // Ikon update gagal
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 terhubung
const unsigned char wifi_dc[] PROGMEM = {
0x00, 0x00, 0x00, 0x04, 0x03, 0xce, 0x1f, 0xdc, 0x7f, 0xba, 0xf8, 0x77, 0x60, 0xe6, 0x05, 0xc0,
0x0b, 0xb0, 0x07, 0x70, 0x0e, 0x20, 0x1c, 0x00, 0x1b, 0x80, 0x03, 0xc0, 0x01, 0x80, 0x00, 0x00}; // Ikon WiFi terputus
void setup() {
Serial.begin(115200);
// Initialize DHT11 sensor
dht.begin();
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
// Intro display
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(30,20);
display.println(F("ThinkSpeak"));
display.setCursor(30,30);
display.println(F("Smartgarden"));
display.display();
display.setCursor(35,40);
display.println(F("by chio"));
display.display();
delay(3000);
// WiFi and ThingSpeak initialization
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client);
ConnectWIFI();
// Sensor pins setup
pinMode(SOIL_MOISTURE_PIN, INPUT);
pinMode(LIGHT_SENSOR_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
// Update display every 1 second
if (currentMillis - previousMillis_display >= display_interval) {
previousMillis_display = currentMillis;
updateDisplay();
}
// Update ThingSpeak every 20 seconds
if (currentMillis - previousMillis_ts >= ts_update_interval) {
previousMillis_ts = currentMillis;
updateThingSpeak();
}
// Monitor soil moisture and control LED
int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
float soilMoisturePercent = map(soilMoistureValue, 1023, 0, 0, 100);
if (soilMoisturePercent < 30) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
}
// Function to update OLED display
void updateDisplay() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
float soilMoisturePercent = map(soilMoistureValue, 1023, 0, 0, 100);
int lightIntensity = analogRead(LIGHT_SENSOR_PIN);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Temp: ");
display.print(temperature);
display.println(" C");
display.print("Humidity: ");
display.print(humidity);
display.println(" %");
display.print("Soil Moisture: ");
display.print(soilMoisturePercent);
display.println(" %");
display.print("Light: ");
display.print(lightIntensity);
display.display();
}
// Function to update ThingSpeak
void updateThingSpeak() {
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
float soilMoisturePercent = map(soilMoistureValue, 1023, 0, 0, 100);
int lightIntensity = analogRead(LIGHT_SENSOR_PIN);
ThingSpeak.setField(1, temperature);
ThingSpeak.setField(2, humidity);
ThingSpeak.setField(3, soilMoisturePercent);
ThingSpeak.setField(4, lightIntensity);
int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if (x == 200) {
Serial.println("Data updated successfully");
display.drawBitmap(90, 0, Update_OK, 16, 16, WHITE);
} else {
Serial.println("Problem updating data. HTTP error code " + String(x));
display.drawBitmap(90, 0, Update_NOK, 16, 16, WHITE);
}
display.display();
}
// Function to connect WiFi
void ConnectWIFI() {
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Connecting to WiFi...");
WiFi.begin(ssid, password);
int attempt = 0;
while (WiFi.status() != WL_CONNECTED && attempt < 30) {
delay(500);
Serial.print(".");
attempt++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("WiFi Connected!");
display.clearDisplay();
display.drawBitmap(52, 15, wifi_icon, 16, 16, WHITE);
display.setCursor(33, 38);
display.print("Connected!");
display.display();
} else {
Serial.println("Failed to connect to WiFi.");
display.clearDisplay();
display.drawBitmap(52, 15, wifi_dc, 16, 16, WHITE);
display.setCursor(20, 38);
display.print("WiFi Failed!");
display.display();
}
}
}