Team work : Budhi Prayoga,ST.M.Eng , Muhamad Setyo Adi,.A.M.d.T
0. Background Research
1. Dokumen
2. Alat dan Bahan
- NodeMCu ESP8266 Lolin v3
- PSU Adjustable Stepdown 3A LM2596S + LED Voltmeter
- Contactless Temperature Sensor Module GY-906 DCI MLX90614ESF
- Resistive Soil Moisture SEN-0016
- LCD 20×4 Blue Light
- i2c Module LCD Backpack 20×4
- Active Continuous Buzzer HYD-2312 YD2312 type SFM-20B DC 3-24V
- Bi Color LED 5mm (Red, Blue) Common Anoda, Cathode include Bracket / Holder LED 5mm
- Bi Color LED 5mm (Red, Green) Common Anoda
- Spacer LED 4x4mm
- Antenna DB for ESP8266 WiFi Module
- Box Project X5 Hitam Plastik 160x130x45 mm Case Enclosure for Project
- Metal Push Button Switch Self Locked 12mm Ring LED 12V Waterproof
- Rocker Switch 3 Pin KCD1 Merah 220v 13x95mm
- Spacer Kuningan M3 6mm
- Resistor 330ohm 1/4 watt Metal Film
- Cable Spiral Band 6mm Putih
- Cable Ties 25x100nn 4.0″ Merah
- Kabel Jumper Female to Female, Male to Male, Male to Female 20cm
3. Skematik Rangkaian
4. Arduino Code
/*
* # File Name : Code Mr. M. Setyo A Beta v1
* # Customer : Mr. Muhammad Setyo Adi
* # Judul Research : Monitoring Suhu dan Kelembaban Tanah
* pada Proyek Konstruksi Jalan Raya
* Menggunakan Robotdyn Arduino Uno Built-in
* WiFi berbasis IoT Blynk dan Thinger.io
* # Deskripsi : Perangkat Elektronika yang digunakan
* untuk memonitoring suhu dan kelembaban
* tanah secara realtime terhubung ke internet
* dengan media penyimpanan cloud dapat diakses
* melalui android smartphone melalui aplikasi
* Blynk dan Dashboard IoT 3rd Platform Thinger.io
* pada Personal Computer / Laptop di Control Room
* # Maker by : Budhi Prayoga,.M.Eng
* # Start Created : 09 Maret 2023
* # Last Update : 11 Maret 2023 (2.0)
* : 21 Juni 2023 (3.0)
* # Revisi : 1.0
* # Version : Beta
* # IoT Platform : Blynk, Thinger.io
* # GPIO :
* - Buzzer : 2 (D4 Lolin v3)
* - Sensor Suhu GY-906 DCI : SCL D1, SDA D2
* - Sensor Kelembaban : A0
* - LCD 20x4 I2C : SCL D1, SDA D2
* # Software Requirement
* - Arduino IDE v1.8.13
* # Library
* - ESP8266 version : 2.6.1
* - Blynk version : 1.1.0
* - Thinger version : 2.15.0
* - MLX90614 version : 2.1.3
* - Liquid Crystal : 1.0.7
* # Hardware Requirement
* - Main Core : NodeMCU ESP8266 Lolin v3
* - Input : Contacless Temperature Sensor GY-906 DCI MLX90614ESF
* Resistive Soil Moisture SEN-0016
* - Output : LED 3mm + Holder
* LCD 20x4 Blue Light
* Active Buzzer 12VDC
* - Aksesoris : Antenna DB for ESP8266 WiFi Module
* # Konfigurasi Upload Program
* Versi IDE : 1.8.13
* Board : NodeMCU 1.0(ESP12-E Module)
* Builtin LED : 2
* Upload Speed : 115200
* CPU Frequency : 80 MHz
* Flash Size : 4MB (FS:2MB OTA:~1019KB)
* Reset Method : dtr (aka NodeMCu)
* Debug Port : disable
* Debug Level : none
* lwlp variant : v2 lower memory
* VTable : Flash
* Exceptions : Legacy (new can return nullptr)
* Erase Flash : only sketch
* Espressif : FW nonos-sdk-2.2.1+100
* SSL Support : All SSL Chipher
* Programmer : none
* Baudrate : 115200
*/
#define BLYNK_AUTH_TOKEN "z7eItSK2_tdb3t7wsa-D4vm1Jna10Q3_"
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h
#include <BlynkSimpleEsp8266.h>
#include <ThingerESP8266.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_MLX90614.h>
//konfigurasi Thinger.IO
#define USERNAME "userid"
#define DEVICE_ID "thingerid"
#define DEVIDE_CREDENTIAL "xxx"
//variable untuk thinger.io
ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVIDE_CREDENTIAL);
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "xxx"; // type your wifi name
char pass[] = "xxx"; // type your wifi password
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
LiquidCrystal_I2C lcd(0x27, 20, 4); // set the LCD address to 0x27 for a 16 chars and 2 line display
const int LCD_NB_ROWS = 4;
const int LCD_NB_COLUMNS = 20;
const int buzzer = 2;
const int SoilSensor = A0;
float temp_udara;
float temp_aspal;
float hum_sen0016;
float data1, data2, data3;
BlynkTimer timer;
/* Love Symbol characters */
byte customChar[8] = {
0b00000,
0b01010,
0b11111,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};
/* Personalized characters */
byte START_DIV_0_OF_4[8] = {
B01111,
B11000,
B10000,
B10000,
B10000,
B10000,
B11000,
B01111
}; // Char début 0 / 4
byte START_DIV_1_OF_4[8] = {
B01111,
B11000,
B10000,
B10000,
B10000,
B10011,
B11000,
B01111
}; // Char début 1 / 4
byte START_DIV_2_OF_4[8] = {
B01111,
B11000,
B10000,
B10000,
B10111,
B10011,
B11000,
B01111
}; // Char début 2 / 4
byte START_DIV_3_OF_4[8] = {
B01111,
B11000,
B10000,
B10111,
B10111,
B10011,
B11000,
B01111
}; // Char début 3 / 4
byte START_DIV_4_OF_4[8] = {
B01111,
B11000,
B10011,
B10111,
B10111,
B10011,
B11000,
B01111
}; // Char début 4 / 4
byte DIV_0_OF_8[8] = {
B11111,
B00000,
B00000,
B00000,
B00000,
B00000,
B00000,
B11111
}; // Char milieu 0 / 8
byte DIV_1_OF_8[8] = {
B11111,
B00000,
B00000,
B00000,
B00000,
B11000,
B00000,
B11111
}; // Char milieu 1 / 8
byte DIV_2_OF_8[8] = {
B11111,
B00000,
B00000,
B00000,
B11000,
B11000,
B00000,
B11111
}; // Char milieu 2 / 8
byte DIV_3_OF_8[8] = {
B11111,
B00000,
B00000,
B11000,
B11000,
B11000,
B00000,
B11111
}; // Char milieu 3 / 8
byte DIV_4_OF_8[8] = {
B11111,
B00000,
B11000,
B11000,
B11000,
B11000,
B00000,
B11111
}; // Char milieu 4 / 8
byte DIV_5_OF_8[8] = {
B11111,
B00000,
B11000,
B11000,
B11000,
B11011,
B00000,
B11111
}; // Char milieu 5 / 8
byte DIV_6_OF_8[8] = {
B11111,
B00000,
B11000,
B11000,
B11011,
B11011,
B00000,
B11111
}; // Char milieu 6 / 8
byte DIV_7_OF_8[8] = {
B11111,
B00000,
B11000,
B11011,
B11011,
B11011,
B00000,
B11111
}; // Char milieu 7 / 8
byte DIV_8_OF_8[8] = {
B11111,
B00000,
B11011,
B11011,
B11011,
B11011,
B00000,
B11111
}; // Char milieu 8 / 8
byte END_DIV_0_OF_4[8] = {
B11110,
B00011,
B00001,
B00001,
B00001,
B00001,
B00011,
B11110
}; // Char fin 0 / 4
byte END_DIV_1_OF_4[8] = {
B11110,
B00011,
B00001,
B00001,
B00001,
B11001,
B00011,
B11110
}; // Char fin 1 / 4
byte END_DIV_2_OF_4[8] = {
B11110,
B00011,
B00001,
B00001,
B11101,
B11001,
B00011,
B11110
}; // Char fin 2 / 4
byte END_DIV_3_OF_4[8] = {
B11110,
B00011,
B00001,
B11101,
B11101,
B11001,
B00011,
B11110
}; // Char fin 3 / 4
byte END_DIV_4_OF_4[8] = {
B11110,
B00011,
B11001,
B11101,
B11101,
B11001,
B00011,
B11110
}; // Char fin 4 / 4
String staticMessage = "Welcome Mr. M Setyo!";
String scrollingMessage = "Sistem Monitoring Suhu Tanah Pada Proyek Pengerukan Konstruksi Jalan Berbasis IoT (Blynk dan Thinger.IO)";
bool isRunning = true;
void setup() {
Serial.begin(115200);
lcd.init(); // initialize the lcd
lcd.backlight();
setup_progressbar();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("Connecting to SSID"));
//lcd.print("Progress Connecting");
pinMode(buzzer, OUTPUT);
//hubungkan NodeMCU ke server thinger.io
thing.add_wifi(ssid, pass);
//kirim nilai sensor suhu GY-906-DCI ke Thinger.IO
thing["GY-906-DCI-Env"] >> [](pson & out) {
out["suhu_udara"] = data1;
};
//kirim nilai sensor suhu GY-906-DCI ke Thinger.IO
thing["GY-906-DCI-Object"] >> [](pson & out) {
out["suhu_aspal"] = data2;
};
//kirim nilai sensor kelembaban Resistive Soil Moisture SEN-0016 ke Thinger.IO
thing["SEN-0016"] >> [](pson & out) {
out["kelembaban"] = data3;
};
Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
mlx.begin();
}
void loop() {
thing.handle();
if (isRunning) {
play();
}
Blynk.run();
timer.run();
}
void scrollMessage(int row, String message, int delayTime, int LCD_NB_COLUMNS) {
for (int i = 0; i < LCD_NB_COLUMNS; i++) {
message = " " + message;
}
message = message + " ";
for (int position = 0; position < message.length(); position++) {
lcd.setCursor(0, row);
lcd.print(message.substring(position, position + LCD_NB_COLUMNS));
delay(125);
}
}
void animasiJudul() {
lcd.setCursor(0, 0);
lcd.print(staticMessage);
lcd.setCursor(0, 2);
//lcd.print(F("abcdefghijklmnopqrst"));
lcd.createChar(0, customChar); // create a new custom character
lcd.setCursor(1, 2); // move cursor to (2, 0)
lcd.write((byte)0); // print the custom char at (2, 0)
lcd.print(F(" PT.KPP Indexim"));
lcd.setCursor(18, 2); // move cursor to (2, 0)
lcd.write((byte)0); // print the custom char at (2, 0)
lcd.setCursor(0, 3);
lcd.print(F("- KALTIM JUNI 2023 -"));
scrollMessage(1, scrollingMessage, 250, LCD_NB_COLUMNS);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F(" Start Main Program"));
timer.setInterval(1000L, sendSensor);
}
void sendSensor() {
// put your main code here, to run repeatedly:
int hasilPembacaan = analogRead(SoilSensor);
temp_udara = mlx.readAmbientTempC();
temp_aspal = mlx.readObjectTempC();
hum_sen0016 = (100 - ((hasilPembacaan / 1023.00) * 100));
// Check if any reads failed and exit early (to try again).
/*if (isnan(temp_udara) || isnan(temp_aspal)) {
Serial.println(F("Sensor Suhu GY -906 DCI tidak terhubung!"));
digitalWrite(buzzer, HIGH);
delay(500);
digitalWrite(buzzer, LOW); //LED p4 OFF
delay(500);
lcd.setCursor(0, 0);
lcd.print(F("Temp Udara "));
lcd.setCursor(11, 0);
lcd.print(F("Unconnect"));
lcd.setCursor(0, 1);
lcd.print(F("Temp Aspal "));
lcd.setCursor(11, 1);
lcd.print(F("Unconnect"));
delayMicroseconds(1000000); //Simple 1 Sec Delay
lcd.clear();
return;
}
if (isnan(hum_sen0016)) {
Serial.println(F("Sensor Kelembaban SEN-0016 tidak terhubung!"));
lcd.print(F("Sensor tidak Terhubung"));
delay(2000);
//delayMicroseconds(1000000); //Simple 1 Sec Delay
return;
}*/
Serial.println();
Serial.print(F("Suhu Udara = "));
Serial.print(temp_udara);
Serial.print(F("°C\tSuhu Aspal = "));
Serial.print(temp_aspal);
Serial.println("°C");
Serial.print(F("Persentase Kelembaban Tanah/Aspal= "));
Serial.print(hum_sen0016);
Serial.println(F("%"));
if (mlx.readObjectTempC() > 100) {
alarm();
}
Blynk.virtualWrite(V0, temp_udara);
Blynk.virtualWrite(V1, temp_aspal);
Blynk.virtualWrite(V2, hum_sen0016);
data1 = temp_udara;
data2 = temp_aspal;
data3 = hum_sen0016;
lcd.setCursor(0, 0);
lcd.print(F("Temp Udara "));
lcd.setCursor(11, 0);
lcd.print(temp_udara);
//lcd.setCursor(18,0);
lcd.print((char)223); //Simbol Derajat di LCD
lcd.print(F("C"));
lcd.setCursor(0, 1);
lcd.print(F("Temp Aspal "));
lcd.setCursor(11, 1);
lcd.print(temp_aspal);
//lcd.setCursor(18,1);
lcd.print((char)223); //Simbol Derajat di LCD
lcd.print(F("C"));
lcd.setCursor(0, 2);
lcd.print(F("Kelembaban"));
lcd.setCursor(11, 2);
lcd.print(hum_sen0016);
//lcd.setCursor(18,2);
lcd.print(F(" %"));
delay(1000);
//lcd.clear();
}
void alarm() {
//Blynk.email("[email protected]", "Alert", "Temperature over 50°C!");
Blynk.logEvent("notifikasi", "Suhu diatas 50 Derajat celcius");
Serial.print(F("Suhu aspal melebihi batas ambang 100°C"));
lcd.setCursor(0, 3);
lcd.print(F("Suhu aspal Overheat"));
digitalWrite(buzzer, HIGH); // turn the LED on (HIGH is the voltage level)
delay(500); // wait for a second
digitalWrite(buzzer, LOW); // turn the LED off by making the voltage LOW
delay(500);
Serial.println();
lcd.clear();
delay(150);
//lcd.clear();
}
void play() {
/* Value in percent of the progress bar */
static byte percent = 0;
/* Displays the value */
draw_progressbar(percent, 1);
//for(static byte percent = 0; percent <= 101; percent++){
/* Increases the percentage */
if (++percent == 101) {
// Revient à zéro si le pourcentage dépasse 100%
//draw_progressbar(percent, 1);
percent = 0;
delay(5);
WiFi.begin(ssid, pass); //koneksi ke WiFi
while (WiFi.status() != WL_CONNECTED) { //pengecekan koneksi WiFi
Serial.print(".");
lcd.setCursor(0, 2);
lcd.print(F("."));
delay(500);
}
mainprogram();
isRunning = false;
}
/* Small waiting time */
delay(1);
}
void mainprogram () {
lcd.setCursor(0, 0);
lcd.print(F("Device Connected to "));
lcd.setCursor(0, 2);
lcd.print(ssid);
lcd.setCursor(0, 3);
lcd.print(WiFi.localIP());
delay(3000);
lcd.clear();
animasiJudul();
}
void setup_progressbar() {
lcd.createChar(0, START_DIV_4_OF_4);
lcd.createChar(1, DIV_0_OF_8);
lcd.createChar(2, DIV_8_OF_8);
lcd.createChar(3, END_DIV_0_OF_4);
}
void draw_progressbar(byte percent, byte line) {
lcd.setCursor(0, line); //Move the cursor on the line
/* Map the range ( 0 ~ 100 ) to the range ( 0 ~ ( LCD_NB_COLUMNS - 4 ) * 2 * 4 - 2 * 4 ) */
byte nb_columns = map(percent, 0, 100, 0, (LCD_NB_COLUMNS - 4) * 2 * 4 - 2 * 4);
// Each character displays 2 vertical bars of 4 pixels high, but the first and last character displays only one.
/* Draw each character from the line */
for (byte i = 0; i < LCD_NB_COLUMNS - 4; ++i) {
if (i == 0) { // Premiére case
/* Displays the start tank according to the number of columns */
if (nb_columns > 4) {
lcd.write((byte) 0); // Char début 4 / 4
nb_columns -= 4;
} else if (nb_columns == 4) {
lcd.write((byte) 0); // Char début 4 / 4
nb_columns = 0;
} else {
switch_progressbar_bank(0);
lcd.setCursor(i, line);
lcd.write(nb_columns + 4); // Char début N / 4
nb_columns = 0;
}
}
else if (i == LCD_NB_COLUMNS - 5) { // Derniére case
/* Displays the end tank according to the number of columns */
if (nb_columns > 0) {
switch_progressbar_bank(3);
lcd.setCursor(i, line);
lcd.write(nb_columns + 3); // Char fin N / 4
} else {
lcd.write(3); // Char fin 0 / 4
}
}
else { // Autres cases
/* Displays the appropriate tank according to the number of columns */
if (nb_columns == 0) {
lcd.write(1); // Char div 0 / 8
} else if (nb_columns >= 8) {
lcd.write(2); // Char div 8 / 8
nb_columns -= 8;
} else if (nb_columns >= 4 && nb_columns < 8) {
switch_progressbar_bank(2);
lcd.setCursor(i, line);
lcd.write(nb_columns); // Char div N / 8
nb_columns = 0;
} else if (nb_columns < 4) {
switch_progressbar_bank(1);
lcd.setCursor(i, line);
lcd.write(nb_columns + 3); // Char div N / 8
nb_columns = 0;
}
}
}
/* Displays the percentage */
char tmp[5];
sprintf(tmp, "%3d%%", percent);
lcd.print(tmp);
}
void switch_progressbar_bank(byte bank) {
// IMPORTANT: It is necessary to make a lcd.clear ( ) or a lcd.setCursor ( ) after each change of bank.
/* Change of character bank */
switch (bank) {
case 0:
lcd.createChar(4, START_DIV_0_OF_4);
lcd.createChar(5, START_DIV_1_OF_4);
lcd.createChar(6, START_DIV_2_OF_4);
lcd.createChar(7, START_DIV_3_OF_4);
break;
case 1:
lcd.createChar(4, DIV_1_OF_8);
lcd.createChar(5, DIV_2_OF_8);
lcd.createChar(6, DIV_3_OF_8);
lcd.createChar(7, DIV_4_OF_8);
break;
case 2:
lcd.createChar(4, DIV_4_OF_8);
lcd.createChar(5, DIV_5_OF_8);
lcd.createChar(6, DIV_6_OF_8);
lcd.createChar(7, DIV_7_OF_8);
break;
case 3:
lcd.createChar(4, END_DIV_1_OF_4);
lcd.createChar(5, END_DIV_2_OF_4);
lcd.createChar(6, END_DIV_3_OF_4);
lcd.createChar(7, END_DIV_4_OF_4);
break;
}
//lcd.setCursor(0,2);
//lcd.print(F("switch_progressbar"));
}
5. Galeri
Demo IoT 3rd Platform Blynk (Desktop Version)
Isometric View
Top View
Front View
Right View
Left View
Back View
6. Data Hasil Percobaan
7. Video Demo
8. Kesimpulan