Membuat Nilai Referensi Digital

Melanjutkan oprekan tempo hari yang membuat nilai referensi analog, kali ini saya membuat nilai referensi digital. Soalnya kalau menggunakan nilai referensi analog nilainya fluktuatif alias berubah-ubah sehingga tidak bisa dijadikan acuan absolute.

Ada 3 tombol untuk membuat referensi digital
Ada 3 tombol untuk membuat referensi digital

Namun ternyata membuat nilai referensi digital mudah banget kok. Tinggal menyediakan 3 pin digital, 1 untuk mengubah mode display, 1 untuk menaikkan nilai acuan, sedangkan 1 untuk menurunkan nilai acuan. Jika ada perubahan nilai acuan bawah atau atas, maka nilai akan dituliskan ke EEPROM-nya Arduino (*EEPROM: Electrically Erasable Programmable Read-Only Memory*). Jadi nilai acuan ini bisa menetap di memori permanen walau pun catu daya atau baterai dicabut.

3 tombol dan 1 LED untuk mensimulasikan relay
3 tombol dan 1 LED untuk mensimulasikan relay

Tombol pertama digunakan untuk mengubah mode tampilan:

  1. Mode 0 (Operasional), untuk menampilkan nilai-nilai sensor, yaitu kelembaban tanah, temperature dan kelembaban udara sekitar. Pada mode 0 ini kedua tombol yg lain tidak berfungsi.
  2. Mode 1 (set batas bawah), untuk menampilkan nilai acuan bawah pembacaan sensor kelembaban tanah. Jika pembacaan sensor Soil Moisture di bawah angka ini, maka relay akan diaktifkan sehingga pompa air menyala. Tombol ke-2 dan 3 digunakan untuk mengubah angka acuan ini. Jika nilai acuan berubah, maka nilainya akan disimpan di EEPROM.
  3. Mode 2 (set batas atas), untuk menampilkan nilai acuan atas pembacaan sensor kelembaban tanah. Jika pembacaan sensor Soil Moisture melebih angka ini dan status pompa air menyala, maka relay akan dinonaktifkan untuk mematikan pompa air. Tombol ke-2 dan 3 digunakan untuk mengubah angka acuan ini. Jika nilai acuan berubah, maka nilainya akan disimpan di EEPROM.
Mode 1 untuk mengedit nilai acuan bawah
Mode 1 untuk mengedit nilai acuan bawah

Terima kasih kepada platform Arduino yang membuatnya jadi mudah.

Mode 2 untuk mengedit nilai acuan atas
Mode 2 untuk mengedit nilai acuan atas

Di bawah ini adalah source code untuk membuat nilai referensi digital ini. Tampak di code kalau saya menyimpan angka acuan dalam 4 byte memori. Hanya saja saya belum menemukan metode penyimpanannya yang efisien. Saya masih belum menemukan metode yang menggabungkan 4 byte ini untuk menyimpan angka 0-1023. Dengan metode yang saya pakai, penyimpanan hanya bisa dilakukan sampai angka 1020. Hiks, nampaknya logika pemrograman saya masih sederhana…

Seperti yang sudah-sudah, source code di bawah menganut azas open source. Silakan dipelajari & dikembangkan. Lebih baik jika ada feedback ke saya sehingga kita bisa saling menyempurnakannya.

/*
Soil Moisture Sensor with LCD
Dewo, 27/09/2012
*/

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include <dht11.h>
dht11 DHT;

#include <EEPROM.h>

#define soil_pin 0         // pin sensor soil moisture
//#define soil2_pin 1      // pin ke-2 sensor soil moisture
#define dht_pin 8          // pin sensor humidity & temp DHT11
#define tombol_pin 13      // pin tombol mode
#define up_pin 10          // tombol +
#define down_pin 9         // tombol -
#define jeda_sensor 1000   // jeda pembacaan sensor
#define jeda_tombol 150   // jeda penekanan tombol
#define relay1_pin 7       // relay 1
//#define relay2_pin 6       // relay 2

int mode = 0;
unsigned long prev_millis = 0;
unsigned long prev_sensor = 0;
int batas_bawah;
int batas_atas;

void setup() {
  pinMode(relay1_pin, OUTPUT);
  digitalWrite(relay1_pin, LOW);
  // Baca EEPROM
  batas_bawah = read_batas(0);
  batas_atas = read_batas(4);
  
  // Init LCD
  lcd.begin(16, 2);
  lcd.print("Soil Moisture 01");
  lcd.setCursor(0, 1);
  lcd.print("         by Dewo");
  delay(2000);
 
  // tampilkan sensor2
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 0);
  lcd.print("Soil  Temp  Humd");
}

void loop() {
  read_button();
  read_sensors();  
  
  if (mode == 0) {
    //
  }
  else if (mode == 1) {
    read_button2();
  }
  else {
    read_button2();
  }
}

void read_sensors() {
  if (millis() - prev_sensor > jeda_sensor) {
    // mengindera DHT
    read_dht();
    // mengindera soil moisture
    read_soil();
    delay(10);
    prev_sensor = millis();
  }
}

void read_soil() {
  int soil_val = analogRead(soil_pin);
  if (mode == 0) {
    lcd.setCursor(0, 1);
    lcd.print(soil_val);
  }
  
  //lcd.setCursor(0, 0);
  if (soil_val <= batas_bawah) {
    lcd.blink();
    // jalankan pompa
    digitalWrite(relay1_pin, HIGH);
  }
  else if (soil_val >= batas_atas) {
    lcd.noBlink();
    // matikan pompa
    digitalWrite(relay1_pin, LOW);
  }
}

void read_dht() {
  int cek = DHT.read(dht_pin);
  switch(cek) {
    case DHTLIB_OK: break;
    case DHTLIB_ERROR_CHECKSUM:
         lcd.setCursor(6, 1);
         lcd.print("Checksum error");
         break;
    case DHTLIB_ERROR_TIMEOUT:
         lcd.setCursor(6, 1);
         lcd.print("Timeout error");
         break;
    default:
         lcd.setCursor(6, 1);
         lcd.print("Unknown error");
         break;
  }
  
  if (mode == 0) {
    // hapus baris
    lcd.setCursor(0, 1);
    lcd.print("                ");
    // tuliskan nilai sensing
    lcd.setCursor(6, 1);
    lcd.print((float)DHT.temperature, 0);
    lcd.print("'C");
    lcd.setCursor(12, 1);
    lcd.print((float)DHT.humidity, 0);
    lcd.print("%");
  }
}

void refresh_batas(int v) {
  lcd.setCursor(0, 1);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print(v);
  delay(50);
}

void read_button2() {
  int btn_up = digitalRead(up_pin);
  if (btn_up == HIGH && millis() - prev_millis > jeda_tombol) {
    if (mode == 1) {
      batas_bawah++;
      if (batas_bawah > 1020) batas_bawah = 1020;
      refresh_batas(batas_bawah);
    }
    else if (mode == 2) {
      batas_atas++;
      if (batas_atas > 1020) batas_atas = 1020;
      refresh_batas(batas_atas);
    }
    prev_millis = millis();
  }
  
  int btn_down = digitalRead(down_pin);
  if (btn_down == HIGH && millis() - prev_millis > jeda_tombol) {
    if (mode == 1) {
      batas_bawah--;
      if (batas_bawah <= 0) batas_bawah = 0;
      refresh_batas(batas_bawah);
    }
    else if (mode == 2) {
      batas_atas--;
      if (batas_atas <= 0) batas_atas = 0;
      refresh_batas(batas_atas);
    }
    prev_millis = millis();
  }
}

void read_button() {
  int btn = digitalRead(tombol_pin);
  unsigned long mi = millis();
  if (btn == HIGH && mi - prev_millis > jeda_tombol) {
    // Action sebelum ganti mode
    if (mode == 1) {
      int prev_bawah = read_batas(0);
      if (prev_bawah != batas_bawah) {
        write_batas(0, batas_bawah);
        lcd.setCursor(0, 1);
        lcd.print(batas_bawah);
        lcd.print(" -> B");
        delay(1000);
      }
    }
    else if (mode == 2) {
      int prev_atas = read_batas(4);
      if (prev_atas != batas_atas) {
        write_batas(4, batas_atas);
        lcd.setCursor(0, 1);
        lcd.print(batas_atas);
        lcd.print(" -> A");
        delay(1000);
      }
      if (batas_bawah > batas_atas) {
        lcd.clear();
        lcd.print("ERROR NilaiBatas");
        lcd.setCursor(0, 1);
        lcd.print("Bawah > Atas ???");
        delay(2000);
      }
    }
    // Ganti mode
    mode++;
    if (mode >= 3) mode = 0;
    // Action setelah ganti mode
    lcd.clear();
    if (mode == 0) {
      lcd.setCursor(0, 0);
      lcd.print("Soil  Temp  Humd");
      lcd.noBlink();
      delay(1);
    }
    else if (mode == 1) {
      lcd.setCursor(0, 0);
      lcd.print("Batas BAWAH Soil");
      lcd.setCursor(0, 1);
      batas_bawah = read_batas(0);
      refresh_batas(batas_bawah);
    }
    else {
      lcd.setCursor(0, 0);
      lcd.print("Batas ATAS Soil ");
      lcd.setCursor(0, 1);
      batas_atas = read_batas(4);
      refresh_batas(batas_atas);
    }
    prev_millis = millis();
  }
}

int read_batas(int a) {
  int hsl = 0;
  for (int i = a; i < a+4; i++) {
    hsl += EEPROM.read(i);
  }
  return hsl;
}

int tuliskan(int nilai, int i) {
  if (nilai < 255) {
    if (nilai > 0) {
      EEPROM.write(i, nilai);
      return 0;
    }
    else {
      EEPROM.write(i, 0);
      return 0;
    }
  }
  else {
    EEPROM.write(i, 255);
    return nilai - 255;
  }
}

void write_batas(int mulai, int b) {
  int sisa = b;
  for (int i = mulai; i < mulai+4; i++) {
    sisa = tuliskan(sisa, i);
  }
}
Iklan

Satu pemikiran pada “Membuat Nilai Referensi Digital

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout /  Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout /  Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout /  Ubah )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.