#include <LiquidCrystal_I2C.h> // Memasukkan library untuk mengontrol LCD dengan protokol I2C
#include <HX711.h> // Memasukkan library untuk mengontrol sensor berat HX711

#define DOUT A3 // Mendefinisikan pin DOUT dari sensor berat sebagai pin analog A3
#define CLK A2 // Mendefinisikan pin CLK dari sensor berat sebagai pin analog A2
#define TOMBOL_RESET 7 // Mendefinisikan pin digital 7 sebagai pin untuk menarik sensor berat
#define TOMBOL_SATUAN 8 // Mendefinisikan pin digital 8 sebagai pin untuk mengubah unit berat
#define PIN_ALARM 9 // Mendefinisikan pin digital 9 sebagai pin untuk mengontrol LED

enum Satuan {GRAM, OZ}; // Mendefinisikan tipe data enumerasi bernama Satuan dengan dua nilai: GRAM dan OZ

HX711 scale; // Membuat objek scale dari kelas HX711
LiquidCrystal_I2C lcd(0x27, 16, 2); // Membuat objek lcd dari kelas LiquidCrystal_I2C dengan alamat 0x27 dan ukuran 16x2

float calibration_factor = 412.6; // Mendefinisikan faktor kalibrasi untuk sensor berat
float gram_to_oz = 0.035274; // Mendefinisikan konversi dari gram ke ounce
float batas_berat = 4000; // Mendefinisikan ambang batas berat dalam gram
float berat_terakhir; // Mendefinisikan variabel untuk menyimpan data berat terakhir
float berat; // Mendefinisikan variabel untuk menyimpan data berat saat ini
Satuan satuan = GRAM; // Mendefinisikan variabel satuan dengan nilai awal GRAM

void setup() {
  lcd.init(); // Menginisialisasi objek lcd
  lcd.backlight(); // Menyalakan lampu latar lcd
  lcd.clear(); // Membersihkan layar lcd

  Serial.begin(9600); // Menginisialisasi komunikasi serial dengan baud rate 9600

  scale.begin(DOUT, CLK); // Menginisialisasi objek scale dengan pin DOUT dan CLK
  scale.set_scale(calibration_factor); // Mengatur skala objek scale dengan faktor kalibrasi
  scale.tare(); // Menarik objek scale untuk mengatur nilai nol

  pinMode(TOMBOL_RESET, INPUT_PULLUP); // Mengatur pin TOMBOL_RESET sebagai input dengan resistor pull-up
  pinMode(TOMBOL_SATUAN, INPUT_PULLUP); // Mengatur pin TOMBOL_SATUAN sebagai input dengan resistor pull-up
  pinMode(PIN_ALARM, OUTPUT); // Mengatur pin PIN_ALARM sebagai output

  lcd.print("   Timbangan    "); // Menampilkan teks "   Timbangan    " di baris pertama lcd
  lcd.setCursor(0, 1); // Mengatur kursor lcd ke kolom 0 dan baris 1
  lcd.print("Digital  Arduino"); // Menampilkan teks "Digital  Arduino" di baris kedua lcd
  delay(3000); // Menunggu selama 3 detik
  lcd.clear(); // Membersihkan layar lcd
  lcd.print("By Haris.Ayuning"); // Menampilkan teks "By Haris.Ayuning" di baris pertama lcd
  lcd.setCursor(0, 1); // Mengatur kursor lcd ke kolom 0 dan baris 1
  lcd.print("Anilasari. Desta"); // Menampilkan teks "Anilasari. Desta" di baris kedua lcd
  delay(3000); // Menunggu selama 3 detik
  lcd.clear(); // Membersihkan layar lcd
}

void loop() {
  berat = scale.get_units(15); // Mendapatkan data berat dari objek scale dengan 15 pembacaan
  lcd.setCursor(0, 0); // Mengatur kursor lcd ke kolom 0 dan baris 0
  lcd.print("Berat : "); // Menampilkan teks "Berat : " di baris pertama lcd
  if (satuan == GRAM) { // Jika satuan berat adalah GRAM
    lcd.print(berat, 0); // Menampilkan data berat dalam gram dengan 0 angka desimal
    lcd.setCursor(0, 1); // Mengatur kursor lcd ke kolom 0 dan baris 1
    lcd.print("Satuan: gram"); // Menampilkan teks "Satuan: gram" di baris kedua lcd
  } else { // Jika satuan berat adalah OZ
    lcd.print(berat * gram_to_oz, 1); // Menampilkan data berat dalam ounce dengan 1 angka desimal
    lcd.setCursor(0, 1); // Mengatur kursor lcd ke kolom 0 dan baris 1
    lcd.print("Satuan: oz"); // Menampilkan teks "Satuan: oz" di baris kedua lcd
  }

  if (digitalRead(TOMBOL_RESET) == LOW) { // Jika pin TOMBOL_RESET ditekan
    berat_terakhir = berat; // Menyimpan data berat saat ini ke variabel berat_terakhir
    scale.tare(); // Menarik objek scale untuk mengatur nilai nol
    lcd.setCursor(0, 1); // Mengatur kursor lcd ke kolom 0 dan baris 1
    lcd.print("Reset  Berhasil!"); // Menampilkan teks "Reset  Berhasil!" di baris kedua lcd
    delay(2000); // Menunggu selama 2 detik
    lcd.clear(); // Membersihkan layar lcd
  }

  if (digitalRead(TOMBOL_SATUAN) == LOW) { // Jika pin TOMBOL_SATUAN ditekan
    satuan = (Satuan)(1 - satuan); // Mengubah nilai satuan dari GRAM ke OZ atau sebaliknya
    lcd.setCursor(0, 1); // Mengatur kursor lcd ke kolom 0 dan baris 1
    lcd.print("Satuan  Diganti!"); // Menampilkan teks "Satuan  Diganti!" di baris kedua lcd
    delay(2000); // Menunggu selama 2 detik
    lcd.clear(); // Membersihkan layar lcd
  }

  blink_led(); // Memanggil fungsi blink_led untuk mengontrol LED
}

void blink_led() {
  if (satuan == GRAM) { // Jika satuan berat adalah GRAM
    if (berat + berat_terakhir >= batas_berat) { // Jika total berat lebih dari atau sama dengan ambang batas
      digitalWrite(PIN_ALARM, HIGH); // Menyalakan LED
      delay(300); // Menunggu selama 0.3 detik
      digitalWrite(PIN_ALARM, LOW); // Mematikan LED
      delay(300); // Menunggu selama 0.3 detik
    }
  } else { // Jika satuan berat adalah OZ
    if (berat + berat_terakhir >= batas_berat * gram_to_oz) { // Jika total berat lebih dari atau sama dengan ambang batas dikalikan dengan konversi
      digitalWrite(PIN_ALARM, HIGH); // Menyalakan LED
      delay(300); // Menunggu selama 0.3 detik
      digitalWrite(PIN_ALARM, LOW); // Mematikan LED
      delay(300); // Menunggu selama 0.3 detik
    }
  }
}
$abcdeabcde151015202530354045505560fghijfghij