TKK_E32221220/Kode_arduino.ino

234 lines
6.0 KiB
C++

#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include <HX711_ADC.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
#include <EEPROM.h>
#endif
// === WIFI & FIREBASE ===
#define WIFI_SSID "..."
#define WIFI_PASSWORD "12345678"
#define API_KEY "AIzaSyDQ0zYJrQqCMrAU0-iO0qtCmXCR3wnG0wc"
#define DATABASE_URL "https://timbangan-ae018-default-rtdb.firebaseio.com/"
#define LEGACY_TOKEN "svzBUSZ6M8ANPs1uGuI4sxNeU2MLq3pEaDiYalgB"
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
// === SENSOR BERAT ===
const int HX711_dout = 23;
const int HX711_sck = 4;
HX711_ADC LoadCell(HX711_dout, HX711_sck);
// === SENSOR ULTRASONIK ===
#define TRIG_PIN 5
#define ECHO_PIN 18
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int calVal_eepromAdress = 0;
unsigned long t = 0;
float calibrationFactor = 21.69;
long customOffset = 0;
#define NUM_SAMPLES 5
float beratBuffer[NUM_SAMPLES];
int bufferIndex = 0;
bool isWeightLocked = false;
float getSmoothedWeight(float newReading) {
beratBuffer[bufferIndex] = newReading;
bufferIndex = (bufferIndex + 1) % NUM_SAMPLES;
float total = 0;
for (int i = 0; i < NUM_SAMPLES; i++) {
total += beratBuffer[i];
}
return total / NUM_SAMPLES;
}
long readDistanceCM() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // timeout 30ms
long distance = duration * 0.034 / 2;
return distance;
}
double hitungBMI(double berat, double tinggi) {
if (tinggi == 0) return 0;
double tinggiMeter = tinggi / 100.0; // Konversi tinggi ke meter
return berat / (tinggiMeter * tinggiMeter); // Rumus BMI
}
String kategoriBMI(double bmi) {
if (bmi < 18.5) return "Kurus";
if (bmi <= 24.9) return "Normal";
if (bmi <= 29.9) return "Berlebih";
return "Obesitas";
}
void setup() {
Serial.begin(115200);
Serial.println("Memulai...");
// Inisialisasi pin ultrasonik
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
// LCD
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Menghubungkan...");
// WiFi
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (millis() - start > 20000) {
Serial.println("Gagal Koneksi WiFi!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Gagal WiFi");
return;
}
}
Serial.println("WiFi Terhubung!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Terhubung");
// Firebase
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
config.signer.tokens.legacy_token = LEGACY_TOKEN;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
// LoadCell
LoadCell.begin();
unsigned long stabilizingtime = 2000;
boolean _tare = true;
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
Serial.println("Timeout HX711");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("HX711 Error");
while (1);
}
LoadCell.setCalFactor(calibrationFactor);
while (!LoadCell.update());
}
void loop() {
static boolean newDataReady = 0;
const int serialPrintInterval = 3000;
if (LoadCell.update()) newDataReady = true;
if (newDataReady && millis() > t + serialPrintInterval && Firebase.ready()) {
// ====== BACA BERAT ======
float berat = LoadCell.getData();
if (berat < 0) berat = 0;
float beratKg = berat / 1000.0;
float rataRataBerat = getSmoothedWeight(beratKg);
if (!isWeightLocked && abs(rataRataBerat - beratKg) < 0.1) {
isWeightLocked = true;
}
// ====== BACA TINGGI DARI ULTRASONIK ======
long jarak = readDistanceCM(); // cm
float tinggi = 201.0 - jarak;
if (jarak > 201 || tinggi < 0) {
tinggi = 0;
}
// ====== HITUNG BMI ======
double bmi = hitungBMI(rataRataBerat, tinggi);
// ====== TAMPILKAN DI LCD ======
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("B: ");
lcd.print(rataRataBerat, 1);
lcd.print("kg T: ");
lcd.print(tinggi, 0);
lcd.print("cm");
lcd.setCursor(0, 1);
char output[10];
dtostrf(bmi, 4, 1, output); // Convert to string with 1 decimal point
lcd.print("BMI: ");
lcd.print(output); // Display BMI on LCD
Serial.printf("Berat: %.2f kg | Tinggi: %.0f cm (Jarak: %ld cm) | BMI: %.1f\n", rataRataBerat, tinggi, jarak, bmi);
// ====== KIRIM KE FIREBASE ======
Firebase.RTDB.setFloat(&fbdo, "/sensor/berat", rataRataBerat);
Firebase.RTDB.setFloat(&fbdo, "/sensor/tinggi", tinggi);
Firebase.RTDB.setFloat(&fbdo, "/sensor/bmi", bmi); // Kirim BMI ke Firebase
newDataReady = 0;
t = millis();
}
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
else if (inByte == 'r') calibrate();
else if (inByte == 'c') changeSavedCalFactor();
}
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}
}
void calibrate() {
Serial.println("* Start calibration... Kirim 't' untuk tare");
}
void changeSavedCalFactor() {
float oldVal = LoadCell.getCalFactor();
boolean _resume = false;
Serial.print("Current: "); Serial.println(oldVal);
Serial.println("Kirim nilai baru:");
float newVal;
while (!_resume) {
if (Serial.available() > 0) {
newVal = Serial.parseFloat();
if (newVal != 0) {
LoadCell.setCalFactor(newVal);
_resume = true;
}
}
}
_resume = false;
Serial.println("Simpan ke EEPROM? y/n");
while (!_resume) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
EEPROM.begin(512);
EEPROM.put(calVal_eepromAdress, newVal);
EEPROM.commit();
Serial.println("Disimpan.");
_resume = true;
} else if (inByte == 'n') {
Serial.println("Tidak disimpan.");
_resume = true;
}
}
}
}