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.

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.

Tombol pertama digunakan untuk mengubah mode tampilan:
- 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.
- 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.
- 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.

Terima kasih kepada platform Arduino yang membuatnya jadi mudah.

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); } }
[…] Sisa 5 ini terpakai untuk 1 sensor Soil Moisture, 1 relay, dan 3 tombol (tombol ini digunakan untuk membuat referensi digital). Kurang 1 I/O untuk termometer. Pikir punya pikir, akhirnya saya mengakalinya dengan berbagi pakai […]