Stasiun Monitoring Suhu Digital LENGKAP dengan Alarm & Pengaturan menggunakan arduino

Stasiun monitoring suhu yang komprehensif.

Fitur-fitur yang akan kita tambahkan meliputi:

  1. Alarm Suhu Tinggi/Rendah: Menggunakan LED dan buzzer untuk memberi peringatan jika suhu melebihi batas atas atau turun di bawah batas bawah.

  2. Pengaturan Batas Alarm: Menggunakan tombol UP/DOWN untuk mengatur nilai batas suhu alarm (tinggi dan rendah) langsung dari perangkat, dengan tampilan di LCD.

  3. Mode Tampilan: Menggunakan tombol Mode untuk beralih antara tampilan suhu normal dan tampilan batas alarm.

  4. Penyimpanan Batas Alarm (EEPROM): Menyimpan nilai batas alarm ke memori non-volatil (EEPROM) Arduino, sehingga pengaturan tidak hilang saat daya mati.

  5. Tombol Reset Alarm: Menghentikan alarm (LED dan buzzer) secara manual.


Stasiun Monitoring Suhu Digital LENGKAP dengan Alarm & Pengaturan


Komponen yang Dibutuhkan:

  • Arduino Board (Uno disarankan)

  • Sensor Suhu LM35

  • LCD 16x2 dengan Modul I2C

  • 2x LED (misalnya, 1 merah untuk alarm tinggi, 1 biru untuk alarm rendah)

  • 2x Resistor 220 Ohm (untuk LED)

  • 1x Buzzer Piezo (aktif atau pasif)

  • 4x Tombol Tekan (Push Button): Mode, Up, Down, Reset Alarm

  • 4x Resistor Pull-down (sekitar 10k ohm)

  • Kabel Jumper

Skema Pengkabelan (Tambahan & Ringkasan):

  • LCD 16x2 I2C ke Arduino:

    • SDA LCD ke A4

    • SCL LCD ke A5

    • VCC LCD ke 5V

    • GND LCD ke GND

  • Sensor Suhu LM35 ke Arduino:

    • Vcc ke 5V

    • Vout ke A0

    • GND ke GND

  • LED ke Arduino:

    • LED Alarm Tinggi (Merah): Anoda (+) ke Digital Pin 10 (via resistor 220 Ohm), Katoda (-) ke GND.

    • LED Alarm Rendah (Biru): Anoda (+) ke Digital Pin 11 (via resistor 220 Ohm), Katoda (-) ke GND.

  • Buzzer ke Arduino:

    • Pin Positif (+) Buzzer: Ke Digital Pin 9.

    • Pin Negatif (-) Buzzer: Ke GND.

  • Tombol ke Arduino (semua dengan Resistor Pull-down 10k Ohm ke GND):

    • Tombol Mode: Ke Digital Pin 2.

    • Tombol Up: Ke Digital Pin 3.

    • Tombol Down: Ke Digital Pin 4.

    • Tombol Reset Alarm: Ke Digital Pin 5.


Instalasi Library:

Pastikan Anda sudah menginstal library LiquidCrystal_I2C. Jika belum:

  1. Buka Arduino IDE.

  2. Pilih Sketch > Include Library > Manage Libraries...

  3. Cari "LiquidCrystal I2C" (biasanya oleh Frank de Brabander).

  4. Klik "Install".


Kode Program:

Arduino
// --- Library yang Dibutuhkan ---
#include <Wire.h>          // Diperlukan untuk komunikasi I2C
#include <LiquidCrystal_I2C.h> // Library untuk LCD I2C
#include <EEPROM.h>        // Library untuk membaca/menulis ke memori EEPROM

// --- Konfigurasi Pin ---
const int LM35_PIN = A0;      // Pin analog tempat sensor LM35 terhubung
const int LED_HIGH_ALARM = 10; // LED untuk alarm suhu tinggi
const int LED_LOW_ALARM = 11;  // LED untuk alarm suhu rendah
const int BUZZER_PIN = 9;     // Pin untuk buzzer

const int BUTTON_MODE_PIN = 2;      // Tombol untuk mengganti mode tampilan/pengaturan
const int BUTTON_UP_PIN = 3;        // Tombol untuk menaikkan nilai pengaturan
const int BUTTON_DOWN_PIN = 4;      // Tombol untuk menurunkan nilai pengaturan
const int BUTTON_RESET_ALARM_PIN = 5; // Tombol untuk mereset alarm

// --- Konfigurasi LCD ---
LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C umum: 0x27 atau 0x3F

// --- Variabel Pembacaan Suhu ---
float temperatureC = 0; // Suhu dalam Celcius
float temperatureF = 0; // Suhu dalam Fahrenheit

// --- Variabel Alarm ---
int highAlarmLimitC; // Batas alarm suhu tinggi (Celcius)
int lowAlarmLimitC;  // Batas alarm suhu rendah (Celcius)
bool alarmActive = false; // Status alarm aktif atau tidak

// --- Variabel untuk Debounce Tombol ---
unsigned long lastButtonModeTime = 0;
unsigned long lastButtonUpTime = 0;
unsigned long lastButtonDownTime = 0;
unsigned long lastButtonResetAlarmTime = 0;
const long DEBOUNCE_DELAY = 50; // Delay debounce dalam milidetik

// --- Variabel Mode Tampilan / Pengaturan ---
enum DisplayMode { NORMAL_TEMP, SET_HIGH_ALARM, SET_LOW_ALARM };
DisplayMode currentDisplayMode = NORMAL_TEMP;

// --- Variabel Update Tampilan ---
unsigned long lastTempUpdateTime = 0;
const long TEMP_UPDATE_INTERVAL = 1000; // Update pembacaan suhu setiap 1 detik

unsigned long lastLCDRefreshTime = 0;
const long LCD_REFRESH_INTERVAL = 250; // Refresh LCD lebih sering untuk responsifitas tombol

// --- Default Alarm Limits (akan disimpan ke EEPROM) ---
const int DEFAULT_HIGH_ALARM = 30; // Default 30 C
const int DEFAULT_LOW_ALARM = 20;  // Default 20 C

// --- Alamat EEPROM untuk menyimpan batas alarm ---
const int EEPROM_HIGH_ADDR = 0;
const int EEPROM_LOW_ADDR = 1;

void setup() {
  // --- Inisialisasi Pin ---
  pinMode(LM35_PIN, INPUT);
  pinMode(LED_HIGH_ALARM, OUTPUT);
  pinMode(LED_LOW_ALARM, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUTTON_MODE_PIN, INPUT);
  pinMode(BUTTON_UP_PIN, INPUT);
  pinMode(BUTTON_DOWN_PIN, INPUT);
  pinMode(BUTTON_RESET_ALARM_PIN, INPUT);

  // Matikan LED dan buzzer saat startup
  digitalWrite(LED_HIGH_ALARM, LOW);
  digitalWrite(LED_LOW_ALARM, LOW);
  noTone(BUZZER_PIN); // Memastikan buzzer mati

  // --- Inisialisasi Serial (Debugging) ---
  Serial.begin(9600);
  Serial.println("Digital Thermometer with Alarm & Settings Started");

  // --- Inisialisasi LCD ---
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Thermo Station");
  lcd.setCursor(0, 1);
  lcd.print("Loading Settings...");
  delay(2000);

  // --- Membaca Batas Alarm dari EEPROM ---
  // Baca batas alarm tinggi (jika nilai valid, gunakan itu)
  highAlarmLimitC = EEPROM.read(EEPROM_HIGH_ADDR);
  if (highAlarmLimitC < -10 || highAlarmLimitC > 99) { // Cek validitas (misal -10C to 99C)
    highAlarmLimitC = DEFAULT_HIGH_ALARM;
    EEPROM.update(EEPROM_HIGH_ADDR, highAlarmLimitC); // Tulis default jika invalid
  }

  // Baca batas alarm rendah
  lowAlarmLimitC = EEPROM.read(EEPROM_LOW_ADDR);
  if (lowAlarmLimitC < -10 || lowAlarmLimitC > 99) {
    lowAlarmLimitC = DEFAULT_LOW_ALARM;
    EEPROM.update(EEPROM_LOW_ADDR, lowAlarmLimitC);
  }

  // Pastikan batas rendah tidak lebih tinggi dari batas tinggi
  if (lowAlarmLimitC >= highAlarmLimitC) {
      lowAlarmLimitC = highAlarmLimitC - 1; // Atur batas rendah 1 di bawah batas tinggi
      EEPROM.update(EEPROM_LOW_ADDR, lowAlarmLimitC);
  }

  Serial.print("Loaded High Alarm: "); Serial.println(highAlarmLimitC);
  Serial.print("Loaded Low Alarm: "); Serial.println(lowAlarmLimitC);

  // Tampilan awal suhu
  readTemperature(); // Baca suhu pertama kali
  displayTemperature(); // Tampilkan di LCD
}

void loop() {
  unsigned long currentTime = millis();

  // --- Pembacaan Suhu (Non-blocking) ---
  if (currentTime - lastTempUpdateTime >= TEMP_UPDATE_INTERVAL) {
    lastTempUpdateTime = currentTime;
    readTemperature();
    // Cek alarm hanya saat suhu diperbarui
    checkAlarm();
  }

  // --- Penanganan Tombol ---
  handleButtons(currentTime);

  // --- Pembaruan Tampilan LCD (lebih sering dari pembacaan suhu) ---
  if (currentTime - lastLCDRefreshTime >= LCD_REFRESH_INTERVAL) {
    lastLCDRefreshTime = currentTime;
    if (currentDisplayMode == NORMAL_TEMP) {
      displayTemperature();
    } else if (currentDisplayMode == SET_HIGH_ALARM) {
      displaySetAlarm("HIGH", highAlarmLimitC);
    } else if (currentDisplayMode == SET_LOW_ALARM) {
      displaySetAlarm("LOW ", lowAlarmLimitC);
    }
  }

  // --- Alarm Tanda Visual/Auditory ---
  if (alarmActive) {
    if (temperatureC > highAlarmLimitC) {
      digitalWrite(LED_HIGH_ALARM, HIGH);
      digitalWrite(LED_LOW_ALARM, LOW); // Pastikan LED lain mati
      tone(BUZZER_PIN, 1000); // Nada 1000 Hz
    } else if (temperatureC < lowAlarmLimitC) {
      digitalWrite(LED_LOW_ALARM, HIGH);
      digitalWrite(LED_HIGH_ALARM, LOW); // Pastikan LED lain mati
      tone(BUZZER_PIN, 500); // Nada 500 Hz
    }
  } else {
    digitalWrite(LED_HIGH_ALARM, LOW);
    digitalWrite(LED_LOW_ALARM, LOW);
    noTone(BUZZER_PIN);
  }
}

// --- Fungsi-fungsi Pembantu ---

void readTemperature() {
  int analogValue = analogRead(LM35_PIN);
  float voltage_mV = (analogValue / 1024.0) * 5000.0;
  temperatureC = voltage_mV / 10.0;
  temperatureF = (temperatureC * 9 / 5) + 32;
}

void checkAlarm() {
  if (temperatureC > highAlarmLimitC || temperatureC < lowAlarmLimitC) {
    alarmActive = true;
  } else {
    alarmActive = false;
  }
}

void resetAlarm() {
    alarmActive = false;
    digitalWrite(LED_HIGH_ALARM, LOW);
    digitalWrite(LED_LOW_ALARM, LOW);
    noTone(BUZZER_PIN);
    Serial.println("Alarm manually reset.");
}

void displayTemperature() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Temp: ");
  lcd.print(temperatureC, 1);
  lcd.print((char)223); // Karakter derajat
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("      "); // Untuk membersihkan sisa angka jika ada
  lcd.setCursor(0, 1);
  lcd.print(temperatureF, 1);
  lcd.print((char)223);
  lcd.print("F");
}

void displaySetAlarm(const char* label, int limit) {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SET ALARM ");
  lcd.print(label);

  lcd.setCursor(0, 1);
  lcd.print("Limit: ");
  lcd.print(limit);
  lcd.print((char)223);
  lcd.print("C");
}

void handleButtons(unsigned long currentTime) {
  // --- Tombol Mode ---
  if (digitalRead(BUTTON_MODE_PIN) == HIGH && (currentTime - lastButtonModeTime > DEBOUNCE_DELAY)) {
    lastButtonModeTime = currentTime;
    resetAlarm(); // Reset alarm saat mengganti mode

    // Pindah ke mode berikutnya
    if (currentDisplayMode == NORMAL_TEMP) {
      currentDisplayMode = SET_HIGH_ALARM;
    } else if (currentDisplayMode == SET_HIGH_ALARM) {
      currentDisplayMode = SET_LOW_ALARM;
    } else if (currentDisplayMode == SET_LOW_ALARM) {
      currentDisplayMode = NORMAL_TEMP;
    }
    Serial.print("Mode changed to: "); Serial.println(currentDisplayMode);
    lastLCDRefreshTime = 0; // Force refresh LCD immediately
  }

  // --- Tombol UP (hanya di mode pengaturan) ---
  if (currentDisplayMode == SET_HIGH_ALARM || currentDisplayMode == SET_LOW_ALARM) {
    if (digitalRead(BUTTON_UP_PIN) == HIGH && (currentTime - lastButtonUpTime > DEBOUNCE_DELAY)) {
      lastButtonUpTime = currentTime;
      if (currentDisplayMode == SET_HIGH_ALARM) {
        highAlarmLimitC++;
        if (highAlarmLimitC > 99) highAlarmLimitC = 99; // Batasi max
        if (highAlarmLimitC <= lowAlarmLimitC) highAlarmLimitC = lowAlarmLimitC + 1; // Pastikan high > low
        EEPROM.update(EEPROM_HIGH_ADDR, highAlarmLimitC); // Simpan ke EEPROM
      } else if (currentDisplayMode == SET_LOW_ALARM) {
        lowAlarmLimitC++;
        if (lowAlarmLimitC > 99) lowAlarmLimitC = 99; // Batasi max
        if (lowAlarmLimitC >= highAlarmLimitC) lowAlarmLimitC = highAlarmLimitC - 1; // Pastikan low < high
        EEPROM.update(EEPROM_LOW_ADDR, lowAlarmLimitC); // Simpan ke EEPROM
      }
      Serial.print("Limit set to: "); Serial.println(currentDisplayMode == SET_HIGH_ALARM ? highAlarmLimitC : lowAlarmLimitC);
      lastLCDRefreshTime = 0; // Force refresh LCD
    }

    // --- Tombol DOWN (hanya di mode pengaturan) ---
    if (digitalRead(BUTTON_DOWN_PIN) == HIGH && (currentTime - lastButtonDownTime > DEBOUNCE_DELAY)) {
      lastButtonDownTime = currentTime;
      if (currentDisplayMode == SET_HIGH_ALARM) {
        highAlarmLimitC--;
        if (highAlarmLimitC < -10) highAlarmLimitC = -10; // Batasi min
        if (highAlarmLimitC <= lowAlarmLimitC) highAlarmLimitC = lowAlarmLimitC + 1; // Pastikan high > low
        EEPROM.update(EEPROM_HIGH_ADDR, highAlarmLimitC); // Simpan ke EEPROM
      } else if (currentDisplayMode == SET_LOW_ALARM) {
        lowAlarmLimitC--;
        if (lowAlarmLimitC < -10) lowAlarmLimitC = -10; // Batasi min
        if (lowAlarmLimitC >= highAlarmLimitC) lowAlarmLimitC = highAlarmLimitC - 1; // Pastikan low < high
        EEPROM.update(EEPROM_LOW_ADDR, lowAlarmLimitC); // Simpan ke EEPROM
      }
      Serial.print("Limit set to: "); Serial.println(currentDisplayMode == SET_HIGH_ALARM ? highAlarmLimitC : lowAlarmLimitC);
      lastLCDRefreshTime = 0; // Force refresh LCD
    }
  }

  // --- Tombol Reset Alarm ---
  if (digitalRead(BUTTON_RESET_ALARM_PIN) == HIGH && (currentTime - lastButtonResetAlarmTime > DEBOUNCE_DELAY)) {
    lastButtonResetAlarmTime = currentTime;
    resetAlarm(); // Panggil fungsi reset alarm
  }
}

Penjelasan Fitur Baru & Modifikasi:

  1. Library EEPROM.h:

    • Diimpor untuk memungkinkan penyimpanan data (batas alarm) ke memori EEPROM non-volatil Arduino. Data yang disimpan di EEPROM tidak akan hilang saat Arduino dimatikan.

  2. Pin Alarm & Tombol Baru:

    • LED_HIGH_ALARM, LED_LOW_ALARM, BUZZER_PIN untuk output alarm.

    • BUTTON_MODE_PIN, BUTTON_UP_PIN, BUTTON_DOWN_PIN, BUTTON_RESET_ALARM_PIN untuk input kontrol.

  3. Variabel Alarm:

    • highAlarmLimitC, lowAlarmLimitC: Menyimpan batas suhu alarm (Celcius).

    • alarmActive: true jika alarm sedang berbunyi/menyala, false jika tidak.

  4. Variabel & Logika Debounce Tombol:

    • Diimplementasikan untuk setiap tombol baru untuk menghindari pembacaan ganda.

  5. Variabel & Enum DisplayMode:

    • enum DisplayMode { NORMAL_TEMP, SET_HIGH_ALARM, SET_LOW_ALARM };: Mendefinisikan mode-mode tampilan/pengaturan yang berbeda.

    • currentDisplayMode: Menyimpan mode aktif saat ini.

  6. setup() Function:

    • Inisialisasi Pin Output: Semua pin LED dan buzzer diatur sebagai OUTPUT.

    • Inisialisasi Pin Input: Semua pin tombol diatur sebagai INPUT (dengan asumsi pull-down eksternal).

    • Membaca dari EEPROM:

      • EEPROM.read(address) digunakan untuk membaca nilai yang tersimpan.

      • Ada validasi nilai yang dibaca dari EEPROM. Jika nilai yang dibaca aneh (di luar rentang -10C hingga 99C), itu berarti EEPROM mungkin kosong atau korup, jadi kita set ke nilai default dan menyimpannya (EEPROM.update()).

      • EEPROM.update(address, value): Mirip dengan EEPROM.write(), tapi update() hanya menulis jika nilai berbeda dari yang sudah ada, memperpanjang masa pakai EEPROM.

    • Menyesuaikan Batas: Memastikan lowAlarmLimitC selalu lebih rendah dari highAlarmLimitC secara otomatis.

  7. loop() Function:

    • Pembacaan Suhu: Dilakukan setiap TEMP_UPDATE_INTERVAL (1 detik) menggunakan millis() (non-blocking).

    • checkAlarm(): Dipanggil setelah pembacaan suhu untuk menentukan apakah alarm harus aktif.

    • handleButtons(): Fungsi terpisah untuk memproses semua input tombol, menjaga loop() tetap rapi.

    • Pembaruan Tampilan LCD: Sekarang diperbarui lebih sering (LCD_REFRESH_INTERVAL, 250ms) untuk responsifitas tombol di mode pengaturan, tetapi pembacaan suhu hanya setiap 1 detik.

    • Logika Alarm Visual/Auditory: Menyalakan LED dan buzzer sesuai kondisi alarm (temperatureC vs. highAlarmLimitC/lowAlarmLimitC). Nada buzzer berbeda untuk alarm tinggi dan rendah.

  8. Fungsi Pembantu Baru:

    • readTemperature(): Fungsi untuk membaca sensor LM35.

    • checkAlarm(): Fungsi untuk menentukan apakah kondisi alarm terpenuhi.

    • resetAlarm(): Fungsi untuk mematikan LED dan buzzer alarm secara manual. Ini dipanggil oleh tombol reset dan saat mengubah mode.

    • displayTemperature(): Fungsi untuk menampilkan suhu normal di LCD.

    • displaySetAlarm(const char* label, int limit): Fungsi untuk menampilkan mode pengaturan batas alarm di LCD.

    • handleButtons(unsigned long currentTime): Mengelola semua logika penekanan tombol dan debounce.

  9. Logika Pengaturan Batas Alarm di handleButtons():

    • Tombol Mode:

      • Saat ditekan, ia memutar (NORMAL_TEMP -> SET_HIGH_ALARM -> SET_LOW_ALARM -> NORMAL_TEMP).

      • Juga memanggil resetAlarm() saat mode diubah.

    • Tombol UP/DOWN:

      • Hanya aktif saat currentDisplayMode adalah SET_HIGH_ALARM atau SET_LOW_ALARM.

      • Menambah/mengurangi batas alarm yang sesuai (highAlarmLimitC atau lowAlarmLimitC).

      • Ada batas minimum/maksimum (-10C hingga 99C) dan aturan highAlarmLimitC harus selalu lebih besar dari lowAlarmLimitC.

      • Setiap perubahan batas disimpan langsung ke EEPROM menggunakan EEPROM.update().

    • Tombol Reset Alarm: Memanggil fungsi resetAlarm() untuk mematikan indikator alarm.

Sebelum Mengunggah Program:

  1. Pastikan Semua Pengkabelan Benar: Verifikasi setiap pin dan sambungan. Ingat keselamatan listrik saat berurusan dengan komponen AC (jika ini bagian dari sistem yang lebih besar) dan LED/Buzzer.

  2. Instal Library: Pastikan LiquidCrystal_I2C terinstal. EEPROM adalah library bawaan.

  3. Periksa Alamat I2C LCD: Jika LCD tidak berfungsi, periksa alamat I2C di LiquidCrystal_I2C lcd(0x27, 16, 2);.

  4. Pilih Board dan Port: Di Arduino IDE, pilih board dan port yang benar.

  5. Unggah Kode: Klik tombol "Upload".

Setelah program diunggah, Anda akan memiliki stasiun monitoring suhu digital yang sangat fungsional. Anda bisa melihat suhu, mengatur batas alarm, dan sistem akan memberi peringatan jika suhu keluar dari batas yang aman.

Komentar