CODE (C++) SISTEM MONITORING BOBOT (Rancangan Ulul Azmi TPB20)
Code:
// ======================================
// IOT KANCIL BETA 5.1 (STANDALONE)
// MASS + SHT31 + CLOUD + SD BACKUP
// WIFI ICON LCD + SINGLE BUTTON (PIN 25)
// ======================================
#include "HX711.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include "time.h"
#include <ESP_Google_Sheet_Client.h>
#include <GS_SDHelper.h>
#include <SPI.h>
#include <SD.h>
// PUSTAKA SHT31
#include <Adafruit_SHT31.h>
// ======================================
// WIFI
// ======================================
#define WIFI_SSID "BONJOUR"
#define WIFI_PASSWORD "12341234"
// ======================================
// GOOGLE CLOUD
// ======================================
#define PROJECT_ID "masukkan disini"
#define CLIENT_EMAIL "masukkan disini"
const char PRIVATE_KEY[] PROGMEM = R"EOF(
-----BEGIN PRIVATE KEY-----
"masukkan disini"
-----END PRIVATE KEY-----
)EOF";
// ======================================
// SPREADSHEET
// ======================================
const char spreadsheetId[] =
"masukkan disini";
// ======================================
// SD CARD
// ======================================
#define SD_CS 4
File dataFile;
const char* fileName =
"/kancil_log.csv";
bool sdReady = false;
// ======================================
// HX711
// ======================================
#define DT 32
#define SCK 33
HX711 scale;
// ======================================
// SHT31 (Pengganti DHT22)
// ======================================
Adafruit_SHT31 sht31 = Adafruit_SHT31();
float temp;
float hum;
// ======================================
// PUSH BUTTON TUNGGAL (TAMBAHAN BETA 5.1)
// ======================================
#define BUTTON_PIN 25
unsigned long buttonPressTime = 0;
bool lastButtonState = HIGH;
bool buttonHandled = false;
// ======================================
// LCD
// ======================================
LiquidCrystal_I2C lcd(0x27, 16, 2);
// WIFI ICON
byte wifiIcon[8] = {
B00000,
B01110,
B10001,
B00100,
B01010,
B00000,
B00100,
B00000
};
// ======================================
// KALIBRASI
// ======================================
float calibration_factor = 818;
// ======================================
// VARIABEL
// ======================================
float lastMass = 0;
unsigned long lastSerial = 0;
unsigned long lastLog = 0;
const unsigned long logInterval =
30000;
bool loggingAktif = true;
// ======================================
// NTP
// ======================================
const char* ntpServer =
"pool.ntp.org";
unsigned long epochTime;
// ======================================
// GET TIME
// ======================================
unsigned long getTime() {
time_t now;
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return 0;
}
time(&now);
return now;
}
// ======================================
// TOKEN CALLBACK
// ======================================
void tokenStatusCallback(
TokenInfo info
) {
if (info.status ==
token_status_error) {
GSheet.printf(
"Token error: %s\n",
GSheet.getTokenError(info)
.c_str()
);
}
}
// ======================================
// SETUP
// ======================================
void setup() {
Serial.begin(115200);
// Inisialisasi Tombol
pinMode(BUTTON_PIN, INPUT_PULLUP);
Wire.begin(21, 22);
// LCD
lcd.init();
lcd.backlight();
lcd.createChar(0, wifiIcon);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("IOT Kancil");
lcd.setCursor(0, 1);
lcd.print("Beta 5.1"); // Update text
delay(2000);
// HX711
scale.begin(DT, SCK);
scale.set_scale(
calibration_factor
);
// SHT31 INISIALISASI (Alamat default 0x44)
lcd.clear();
lcd.setCursor(0, 0);
if (!sht31.begin(0x44)) {
Serial.println("SHT31 tidak terdeteksi. Cek koneksi kabel I2C.");
lcd.print("SHT31: ERROR!");
} else {
lcd.print("SHT31: OK!");
}
delay(1500);
// WIFI
WiFi.setAutoReconnect(true);
WiFi.begin(
WIFI_SSID,
WIFI_PASSWORD
);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
while (WiFi.status() !=
WL_CONNECTED) {
delay(1000);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Connected");
delay(1000);
// NTP
configTime(0, 0, ntpServer);
// GOOGLE SHEETS
GSheet.setTokenCallback(
tokenStatusCallback
);
GSheet.setPrerefreshSeconds(
10 * 60
);
GSheet.begin(
CLIENT_EMAIL,
PROJECT_ID,
PRIVATE_KEY
);
// SD CARD
lcd.clear();
lcd.setCursor(0, 0);
if (SD.begin(SD_CS)) {
sdReady = true;
Serial.println("SD OK");
lcd.print("SD Card: OK!");
if (!SD.exists(fileName)) {
dataFile =
SD.open(fileName,
FILE_WRITE);
if (dataFile) {
dataFile.println(
"timestamp,mass_g,temp_c,rh"
);
dataFile.close();
}
}
} else {
sdReady = false;
Serial.println("SD Failed");
lcd.print("SD Card: ERROR!");
}
delay(2000);
lcd.clear();
}
// ======================================
// LOOP
// ======================================
void loop() {
bool ready = GSheet.ready();
// WIFI RECONNECT
if (WiFi.status() !=
WL_CONNECTED) {
WiFi.reconnect();
}
// ======================================
// LOGIKA PUSH BUTTON (Pengganti Serial Command)
// ======================================
bool currentButtonState = digitalRead(BUTTON_PIN);
// Deteksi tombol baru mulai ditekan
if (currentButtonState == LOW && lastButtonState == HIGH) {
buttonPressTime = millis();
buttonHandled = false;
}
// Deteksi jika tombol sedang ditahan (> 3 detik)
if (currentButtonState == LOW && !buttonHandled) {
if (millis() - buttonPressTime >= 3000) {
loggingAktif = false;
buttonHandled = true;
Serial.println("Logging stopped");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Logging Stop");
delay(3000);
lcd.clear();
}
}
// Deteksi jika tombol dilepas cepat (< 3 detik)
if (currentButtonState == HIGH && lastButtonState == LOW) {
if (!buttonHandled) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Tare...");
scale.tare(50);
lastMass = 0;
delay(1000);
lcd.clear();
}
}
lastButtonState = currentButtonState;
// READ MASS
float mass =
scale.get_units(5);
// READ SHT31 (Pengganti DHT22)
temp = sht31.readTemperature();
hum = sht31.readHumidity();
// DEAD ZONE
if (mass > -0.3 &&
mass < 0.3 &&
lastMass > -0.3 &&
lastMass < 0.3) {
mass = 0;
}
// HOLD FILTER
if (abs(mass - lastMass)
< 0.1) {
mass = lastMass;
} else {
lastMass = mass;
}
// LOGGING
if (loggingAktif &&
millis() - lastLog >=
logInterval) {
lastLog = millis();
epochTime = getTime();
// SD SAVE
if (sdReady) {
dataFile =
SD.open(fileName,
FILE_APPEND);
if (dataFile) {
dataFile.print(epochTime);
dataFile.print(",");
dataFile.print(mass, 1);
dataFile.print(",");
dataFile.print(temp, 1);
dataFile.print(",");
dataFile.println(hum, 1);
dataFile.close();
Serial.println(
"SD Save OK"
);
} else {
Serial.println(
"SD Save Failed"
);
}
}
// CLOUD UPLOAD
if (ready &&
WiFi.status() ==
WL_CONNECTED) {
FirebaseJson response;
FirebaseJson valueRange;
valueRange.add(
"majorDimension",
"COLUMNS"
);
valueRange.set(
"values/[0]/[0]",
epochTime
);
valueRange.set(
"values/[1]/[0]",
mass
);
valueRange.set(
"values/[2]/[0]",
temp
);
valueRange.set(
"values/[3]/[0]",
hum
);
bool success =
GSheet.values.append(
&response,
spreadsheetId,
"Sheet1!A1",
&valueRange
);
if (success) {
Serial.println(
"Cloud Upload OK"
);
} else {
Serial.println(
"Cloud Upload Failed"
);
Serial.println(
GSheet.errorReason()
);
}
}
}
// SERIAL MONITOR
if (millis() - lastSerial
>= 5000) {
Serial.print("Mass: ");
Serial.print(mass, 1);
Serial.print(" g");
Serial.print(" | Temp: ");
Serial.print(temp, 1);
Serial.print(" C");
Serial.print(" | RH: ");
Serial.print(hum, 1);
Serial.println(" %");
lastSerial = millis();
}
// LCD
lcd.setCursor(0, 0);
lcd.print("M:");
lcd.print(mass, 1);
lcd.print("g ");
// WIFI ICON
if (WiFi.status() == WL_CONNECTED) {
lcd.setCursor(15, 0);
lcd.write(byte(0));
} else {
lcd.setCursor(15, 0);
lcd.print(" ");
}
lcd.setCursor(0, 1);
lcd.print("T:");
lcd.print(temp, 1);
lcd.print(" H:");
lcd.print(hum, 0);
lcd.print(" ");
delay(300);
}
Comments
Post a Comment