MONSTER ARDUINO
Panduan Praktis Belajar Arduino untuk Pemula
Versi 2
HARI SANTOSO
www.elangsakti.com
i
KOBARKAN SEMANGAT INDONESIA!
ii
MONSTER ARDUINO 2
Ebook ini merupakan lanjutan dari ebook sebelumnya
yang berjudul “Panduan Praktis Belajar Arduino untuk
Pemula” yang kita bagikan secara gratis. Dengan terbitnya
ebook terbaru ini, maka ebook tersebut akan kita rapikan
kembali dan akan kita beri nama MONSTER ARDUINO 1.
Ebook edisi pertama berisi tentang pengenalan Arduino,
cara instalasi Arduino IDE, setting driver, bahasa yang yang
dipakai, tipe-tipe data, dan semua hal yang sifatnya dasar
terkait dasar-dasar untuk memulai pemrograman Arduino.
Pada MONSTER ARDUINO 2, kita akan membahas
sedikit lebih dalam terkait teknik dan tips dalam
memprogram serta contoh pemrograman sensor, display,
dan pengolah data di Arduino.
Kedepan, serial ebook MONSTER ARDUINO akan kita
kembangkan lagi dengan pembahasan yang lebih dalam
dan lebih spesifik. Masih banyak yang harus dipelajari agar
kita dapat berinovasi dengan Arduino.
Masukan ide, kritik, dan saran yang membangun boleh
dikirim ke hari@elangsakti.com. Kita tunggu email dari
Anda.
Salam hangat,
Hari.
iii
KOBARKAN SEMANGAT INDONESIA!
iv
CATATAN PENULIS
Hari Elangsakti
v
KOBARKAN SEMANGAT INDONESIA!
vi
DAFTAR ISI
ix
10.1 Program Simulasi EEPROM .........................................................128
10.2 Program EEPROM 5 Tombol 5 LED ...............................................131
#11 PIN OUTPUT YANG MELIMPAH ........................................................137
11.1 Rangkaian Dasar IC 74HC595.......................................................140
11.2 Project LED Berjalan ..................................................................141
11.2.1 Rangkaian LED Berjalan........................................................141
11.2.2 Program LED Berjalan ..........................................................142
11.2.3 Rangkaian Shift Register dengan SPI.......................................145
11.2.4 Program Shift Register dengan SPI .........................................146
#12 SERBA-SERBI DISPLAY 7 SEGMENT....................................................149
12.1 Seven Segment 1 Digit................................................................151
12.1.1 Rangkaian Seven Segment 1 Digit ..........................................152
12.1.2 Program Seven Segment 1 Digit.............................................153
12.2 Seven Segment 4 Digit................................................................160
12.2.1 Rangkaian Seven Segment 4 Digit ..........................................160
12.2.2 Program Seven Segment 4 Digit.............................................162
12.2.3 Program Seven Segment Rata Kanan ......................................169
12.3 Seven Segment dengan Library SevSeg..........................................170
12.3.1 Program Seven Segment dengan Sevseg .................................170
12.4 Seven Segment dengan Shift Register ...........................................172
12.4.1 Rangkaian 7 Segment 1 Digit dengan Shift Register ..................172
12.4.2 Program 7 Segment 1 Digit dengan Shift Register ....................173
12.4.3 Rangkaian Seven Segment 2 Digit dengan Shift Register ............176
12.4.4 Program Seven Segment 2 Digit dengan Shift Register ..............177
x
12.4.5 Rangkaian Seven Segment 4 Digit dengan Shift Register ........... 180
12.4.6 Program Seven Segment 4 Digit dengan Shift Register ............. 182
#13 LEBIH CANTIK DENGAN LCD1602 .................................................... 187
13.1 Sekilas Modul I2C LCD ............................................................... 187
13.2 Rangkaian Dasar Modul I2C LCD ................................................. 189
13.3 Program Mencari Alamat Modul I2C ............................................ 191
13.4 Program Mengontrol Lampu Backlight LCD.................................. 194
13.5 Program Format Teks LCD.......................................................... 197
13.6 Program Efek Teks NgeBlink....................................................... 200
13.7 Program Format Teks dan NgeBlink............................................. 202
13.8 Program Teks Bergerak ............................................................. 205
13.9 Program Membuat Custom Karakter LCD ..................................... 210
#14 ALARM SENSOR PIR....................................................................... 214
14.1 Sensor PIR HC-SR501 ................................................................ 216
14.2 Rangkaian Sensor HC-SR501....................................................... 219
14.3 Program Alarm Sensor PIR ......................................................... 220
14.4 Program Identifikasi Delay Sensor PIR.......................................... 221
14.5 Program Custom Delay Alarm Sensor PIR ..................................... 224
#15 SENSOR DHT11 & KUMBUNG JAMUR ............................................... 228
15.1 Sensor DHT11 .......................................................................... 228
15.2 Akuisi Data Sensor DHT11 .......................................................... 230
15.2.1 Rangkaian Dasar Sensor DHT11 ............................................ 230
15.2.2 Program Akuisisi Data Sensor DHT11 ..................................... 231
xi
15.3 Menampilkan Data pada LCD ......................................................234
15.3.1 Program Sensor Suhu dan Kelembaban Digital .........................235
15.4 Project Kumbung Jamur Sederhana ..............................................238
15.4.1 Rangkaian Project Kumbung Jamur ........................................239
15.4.2 Program Kumbung Jamur Sederhana......................................240
#16 APLKASI REALTIME DENGAN RTC .....................................................247
16.1 Rangkaian Dasar RTC DS1307 ......................................................249
16.2 Menampilkan Waktu di Serial Monitor ..........................................250
16.3 Menampilkan Jam di Seven Segment ............................................253
16.3.1 Rangkaian Menampilkan Jam di Seven Segment .......................253
16.3.2 Program Menampilkan Jam di Seven Segment .........................255
16.4 Menampilkan Waktu di LCD ........................................................261
16.4.1 Rangkan Menampilkan Waktu di LCD......................................261
16.4.2 Program Menampilkan Waktu di LCD .....................................262
16.5 Menampilkan Nama Hari dan Bulan .............................................265
16.5.1 Program Menampilkan Nama Hari dan Bulan...........................266
16.6 Menampilkan Tanggal Bergerak ...................................................271
16.6.1 Program Menampilkan Tanggal Bergerak ................................271
16.7 Project Timer Pagi Sore ..............................................................278
16.7.1 Rangkaian Timer Pagi Sore ...................................................280
16.7.2 Program Timer Pagi Sore......................................................281
#17 KENDALI DENGAN REMOTE INFRARED..............................................291
17.1 Mengidentifikasi Tombol Remote .................................................292
17.1.1 Rangkaian Modul Receiver Infrared ........................................292
xii
17.1.2 Program Identifikasi Tombol Remote ..................................... 293
17.2 Project Remote Kontrol Karakter LCD........................................... 296
17.2.1 Rangkaian Remote Kontrol Karakter LCD ................................ 297
17.2.2 Program Remote Kontrol Karakter LCD .................................. 298
#18 PENGENALAN SERVO .................................................................... 306
18.1 Motor Servo Dasar .................................................................... 307
18.1.1 Rangkain Servo dan Arduino................................................. 307
18.1.2 Program Servo Sederhana.................................................... 308
18.2 Kendali Servo dengan Potensiometer ........................................... 310
18.2.1 Rangkaian Kendali Servo...................................................... 310
18.2.2 Program Kendali Servo ........................................................ 311
18.3 Kendali Servo dengan Remote .................................................... 312
18.3.1 Rangkaian Kendali Servo dan IR Receiver................................ 313
18.3.2 Program Kendali Servo dengan Remote IR .............................. 314
Tentang Penulis .................................................................................. 320
xiii
Bagian #00
SEBELUM MULAI
2
Bagian #01
MEMINANG ARDUINO
___
***
3
Belajar pemrograman Arduino, berarti Anda akan belajar
tentang logika, algoritma, sintaks bahasa C/C++, konsep
elektronika, dan sedikit banyak tentang karakteristik
hardware Arduino yang Anda pakai.
4
Untuk belajar Arduino, Anda hanya butuh membuat
programnya, upload, jika ada yang error atau aneh, segera
tanya teman, atau cari solusinya di internet.
Pin
Jenis Proc. Speed EEPROM SRAM Flash
A/D/PWM
101 Intel® Curie 32MHz - 24kB 196kB 6/14/4
Gemma Attiny85 8MHz 0.5kB 0.5kB 8kB 1/3/2
LilyPad ATmega168V 8MHz 0.5kB 1kB 16kB 6/14/6
ATmega328P
Mega 2560 ATmega2560 16MHz 4kB 8kB 256kB 16/54/15
Mega ADK ATmega2560 16MHz 4kB 8kB 256kB 16/54/15
Pro Mini ATmega328P 8/16MHz 1kB 2kB 32kB 16/14/6
Uno ATmega328P 16MHz 1kB 2kB 32kB 6/14/6
Zero ATSAMD21G18 48MHz - 32kB 256kB 6/14/10
Due ATSAM3X8E 84MHz - 96kB 512kB 12/54/12
Nano ATmega168 16MHz 0.5kB 1kB 16kB 8/14/6
ATmega328P 1kB 2kB 32kB
Yun ATmega32U4 16MHz 1 2.5kB 32kB 12/20/7
AR9331 Linux 400MHz 16MB 64MB
5
yang dipakai, kecepatan, kapasitas EEPROM, SRAM, memory
flash, serta jumlah pin Analog, Digital, dan PWM.
Berdasarkan tabel tersebut, kita bisa memilih Arduino sesuai
kebutuhan project kita.
6
menggunakan Arduino Nano. Kenapa tidak menggunakan
Arduino Pro Mini?
7
Namun jika yang dibutuhkan adalah jumlah input yang
banyak, Anda bisa menggunakan Arduino Mega, entah
Mega 2560 atau Mega ADK. Terdapat 54 pin I/O yang bisa
dipakai pada Arduino Mega.
9
memori flash tidak akan hilang, kecuali ditimpa dengan
program yang lain.
2. EEPROM, memori untuk menyimpan data program.
Data yang disimpan pada memori ini tidak akan hilang
meski arduino dimatikan.
3. SRAM, memori yang digunakan untuk manipulasi data
variabel-variabel yang kita gunakan dalam program.
Data yang tersimpan pada memori ini akan hilang ketika
Arduino direset atau dimatikan.
10
kapasitas yang tersedia. Sedangkan data yang diolah selama
program running (penggunaan variabel) menghabiskan 208
bytes, sekitar 10% dari kapasitas yang tersedia. Silakan pilih
Arduino sesuai kebutuhan ukuran program Anda.
11
Bagian #02
___
12
Jika kita mau memprogram IC mikrokontroller, sebut
saja keluarga AT89Sxx, ATMega, atau PIC, maka kita butuh
alat tambahan (hardware) yang biasa dikenal dengan istilah
programmer atau downloader. Contoh downloader untuk
AVR dan PIC seperti gambar di bawah ini.
13
Program bootloader biasanya dipasang pada alamat
memori 0x0000 sehingga program tersebut menjadi
program yang pertama kali dieksekusi. Anda bisa
memperhatikan perbedaan antara proses memprogram
mikrokontroller biasa dengan mikrokontroller yang telah
dipasangi bootloader Arduino pada Gambar di bawah ini.
14
2. Saat awal start, jika Arduino menerima kiriman
program dari komputer. Maka tugas bootloader
adalah menyimpan kiriman program tersebut pada
memory flash yang tidak dipakai bootloader, misal
alamat memory 0x00AB.
3. Jika tidak ada kiriman program dari komputer, maka
eksekusi program akan langsung lompat ke alamat
0x00AB untuk menjalankan program utama.
***
16
2.2.1 Install Bootloader dengan USBAsp
Dalam hal ini, kita menganggap Anda sudah bisa install
driver USBAsp. Proses instalasi bootloader akan dilakukan
dengan mode grafis menggunakan aplikasi PROGISP dan
command line dengan avrdude. Jika Anda belum familiar
dengan kedua program tersebut, Anda boleh googling dan
mempelajari secukupnya.
1. AVR Programmer x 1
2. IC ATMega8/168/328 x 1
3. Project board x 1
4. XTAL 16MHz x 1
5. Kapasitor 22pf x 2
6. Resistor (ukurannya 220, 330, 1k, 4k7, atau 10k) x 1
7. Kabel jumper secukupnya
17
Gambar 2.3 Rangkaian untuk install bootloader IC ATMega8/168/328
1. Board Arduino x 1
2. Downloader USBAsp x 1
3. Kabel secukupnya x 1
18
Gambar 2.4 Rangkaian untuk install bootloader langsung ke board Arduino
Fuse Data
Low 0xFF
High 0xDA
Extended 0xFD
19
Gambar 2.5 Penyesuaian fuse bit pada Progisp
21
Selanjutnya, install bootloader dengan menekan tombol
Auto. Tunggu hingga proses instalasi selesai. Untuk
mengecek hasil instalasi, silakan lihat sub bab berikutnya.
Gambar 2.10 Isi folder avrdude dan perintah untuk menginstall bootloader
23
2.2.2 Arduino Sebagai ISP Programmer
Selain menggunakan hardware programmer seperti
USBAsp, kita juga bisa menjadikan Arduino sebagai
programmer. Cara yang bisa digunakan untuk mengubah
Arduino menjadi programmer adalah dengan menginstall
program ArduinoISP.
24
Selanjutnya, Arduino Anda bisa digunakan untuk
menginstall bootloader atau mengupload program ke
Arduino lainnya langsung dari aplikasi Arduino IDE.
Penting!!!
Jika Anda mengupload Sketch ke IC yang terinstall
bootloader dengan “Upload Using Programmer”, maka
bootloadernya akan ditimpa oleh Sketch tadi!
25
2.2.3 Install Bootloader dengan Arduino
2.2.3.1 Rangkaian untuk IC ATMega8 /168/328
26
Gambar 2.14 Rangkaian untuk install bootloader dengan Arduino
27
GND GND
28
5. Jika muncul error, Anda bisa langsung googling atau
tanya di grup Facebook MONSTER ARDUINO.
29
Bagian #03
HELLO BUZZER
___
30
1. Arduino Uno x 1
2. Kabel Jumper Male to Female x 2
3. Buzzer Aktif x 1
Arduino Buzzer
Pin 2 GND
VCC VCC
Gambar 3.2 Buzzer aktif dan pasif tampak dari atas (kiri) dan dari bawah (kanan)
34
16 unsigned long waktu_kirim = 0;
17
18 void setup() {
19
20 // aktifkan komunikasi serial
21 // pada baudrate 19200
22 Serial.begin(19200);
23
24 // tunggu hinga Serial siap digunakan
25 while(!Serial);
26
27 // pin buzzer sebagai output
28 pinMode(PIN_BUZZER, OUTPUT);
29
30 // pastikan buzzer maat saat pertama kali start
31 digitalWrite(PIN_BUZZER, BUZZER_OFF);
32
33 // catat waktu kirim pertama kali
34 waktu_kirim = millis();
35
36 }
37
38 void loop() {
39
40 // kirim data
41 KirimData();
42
43 // bunyi tilit tilit
44 TilitTilit();
45
46 }
47
48 void TilitTilit(){
49 // Tit pertama
50 digitalWrite(PIN_BUZZER, BUZZER_ON);
51 delay(200);
52 // mati sebentar
53 digitalWrite(PIN_BUZZER, BUZZER_OFF);
54 delay(100);
55
56 // Tit kedua
57 digitalWrite(PIN_BUZZER, BUZZER_ON);
58 delay(200);
35
59 // mati agak lama
60 digitalWrite(PIN_BUZZER, BUZZER_OFF);
61 delay(1000);
62
63 // tambahan delay supaya pas 3 detik :v
64 delay(1500);
65 }
66
67 // fungsi untuk mengirim data
68 void KirimData(){
69
70 // cetak selisih waktu kirim sebelumnya
71 // dengan pengiriman saat ini
72 Serial.print("Selisih Waktu : ");
73 Serial.println( millis() - waktu_kirim );
74
75 // catat waktu kirim data
76 waktu_kirim = millis();
77 }
37
Bagian #04
___
int LedPin = 2;
int SwitchPin = A0;
40
4.2 Char atau Unsigned Char, 1 Byte
Jika butuh data negatif tapi dibawah angka ratusan,
bisa pakai char. Char adalah tipe data 1 byte yang bisa
digunakan untuk mengolah angka dari -128 sampai 127.
Selain itu, char juga bisa dipakai untuk sebuah karakter
dalam ASCII. Sedangkan unsigned char sama dengan tipe
data byte, angka yang bisa dimuat adalah 0 – 255. Tipe ini
tidak terlalu banyak masalah bagi penulis.
41
4.4 Long dan Unsigned Long, 4 Byte
Sejujurnya, penulis lebih sering menggunakan unsigned
long daripada long. Sebab, unsigned long sering penulis
gunakan untuk menampun informasi waktu, entah itu dari
millis() atau micros(). Kapasitas tipe data ini 4 byte. Artinya,
jika tidak memperhatikan tanda negatif, jumlah angka yang
dapat ditampung dengan tipe data ini adalah 4.294.967.295,
empat ribu juta lebih.
42
variabel yang kita buat tetap disimpan di RAM, bukan di
register. Untuk apa?
***
4.7 PROGMEM
Sebelumnya sudah penulis singgung tentang data
dummy sensor, yaitu data buatan yang seolah-olah keluaran
dari sebuah sensor. Jika kita butuh 1000 data dummy
bertipe integer (2kB), maka SRAM Arduino Uno tidaklah
44
cukup. Solusinya, upgrade Arduino atau gunakan keyword
PROGMEM.
46
Bagian #05
OPTIMALISASI DELAY
___
47
alihkan pekerjaan Arduino untuk melakukan hal lain seperti
mengecek nilai sensor, ganti tampilan LCD, atau aktivitas
lainnya.
***
48
27 }
28
29 void loop() {
30
31 // ambil 100 sampel data
32 // catat dalam variabel delay_sum
33 delay_sum = 0;
34 for(byte i=0; i<delay_count; i++){
35 // catat awal eksekusi
36 delay_first = micros();
37 // ubah logika pin_led
38 digitalWrite(PIN_LED,flip);
39 // catat akhir eksekusi
40 delay_last = micros();
41 // tambahkan selisihnya pada variabel
42 delay_sum += (delay_last - delay_first);
43 }
44
45 // total selisih dibagi 100 (sampel)
46 // untuk mendapatkan rata-ratanya
47 Serial.print("Delay : ");
48 Serial.print( delay_sum/delay_count );
49 Serial.println(" us");
50
51 // balik logika flip
52 flip = !flip;
53 delay(1000);
54 }
49
penggunaan fungsi delay dalam program, kecuali memang
sangat dibutuhkan.
50
dalam kirim data_time_last (lihat baris 109). Selanjutnya,
waktu terus dicek apakah sejak pengiriman terakhir tadi
sudah lewat 3 detik atau tidak (lihat baris 98). Jika sudah
lewat 3 detik, kirim data. Jika belum lewat 3 detik, abaikan.
53
Bunyi buzzer Tilit Tilit juga demikian, pengecekannya
berdasarkan waktu eksekusi terakhir. Hanya saja, terdapat 4
kondisi yang membedakan antara ON/OFF buzzer dan delay
yang harus ditunggu (lihat baris 19-20).
54
3. Setelah waktu tunggu State 1 habis, maka buzzer
menyusul masuk ke State 1, sehingga logika berubah
menjadi OFF.
4. Begitu seterusnya hingga masuk ke State 4.
57
yang bernama nonblocking_delay() yang fungsinya bisa
menggantikan delay. Blok program 29 – 32 akan
menghasilkan bunyi yang sama dengan baris 37 – 40.
Bedanya, baris 29 – 32 sifatnya responsive, sedangkan baris
37 – 40 tidak responsive.
58
Bagian #06
RESPONSIVE DENGAN
TIMER INTERRUPT
___
59
Gambar 6.1 Perbedaan program dengan interupsi dan tanpa interupsi
60
10 // hitung register untuk dicocokkan
11 long INT_REGISTER = (16000000L / (Data_Hz*1024L)) - 1;
12
13 volatile int counter = 0;
14
15 void setup() {
16
17 Serial.begin(19200);
18 while(!Serial);
19
20 // setting interrupt
21 cli(); //stop interrupts
22
23 TCCR1A = 0; // set TCCR1A register = 0
24 TCCR1B = 0; // set TCCR1B register = 0
25 TCNT1 = 0; // inisialisasi counter = 0
26 OCR1A = INT_REGISTER; // untuk 10kHz
27 TCCR1B |= (1 << WGM12); // aktifkan CTC mode
28 TCCR1B |= (1 << CS12) | (1 << CS10); // Set CS12&CS10 bits=1024 prescaler
29 TIMSK1 |= (1 << OCIE1A); // aktifkan timer compare interrupt
30
31 sei(); //allow interrupts
32
33 }
34
35 void loop() {
36
37 delay(100000);
38
39 }
40
41 // ======================================
42 // eksekusi sesuai timer interrupt
43 // ======================================
44 ISR(TIMER1_COMPA_vect){
45 cli(); //stop interrupts
46 Serial.print("Counter: ");
47 Serial.println(counter);
48 counter++;
49 sei(); //allow interrupts
50 }
61
Perhatikan Program 6.1, pada fungsi loop() tidak ada
perintah untuk mengirim data serial monitor. Perintah untuk
mengirim data dipicu dalam fungsi yang menangani timer
interrupt (lihat baris 44).
62
3. Tentukan konfigurasi register yang berhubungan
dengan timer interrupt (lihat baris 23 - 29).
4. Sebelum register dikonfigurasi, interrupt harus
dimatikan dulu dengan perintah cli() (lihat baris 21).
5. Setelah mengkonfigurasi register, interrupt harus
diaktifkan dengan perintah sei() (lihat baris 31).
6. Setelah melakukan konfigurasi, siapkan fungsi ISR
seperti pada baris 44.
Penting!!!
Setiap variabel yang akan dimodifikasi dalam fungsi ISR
harus didefinisikan sebagai variabel volatile.
Jika ingin menggunakan fungsi yang berkaitan dengan
interrupt seperti Serial.print(), millis(), atau micros(), maka
interrupt harus dimatikan dahulu. Jika tidak, program pasti
error. Perhatikan baris 45 dan 49.
65
98 // 1 adalah matinya bip pertama 100ms
99 // 2 adalah bip kedua 200ms
100 // 3 adalah matinya bip kedua
101 // jika buzzer_state_counter >= 4,
102 // maka blok program ini tdk dieksekusi.
103 if( buzzer_state_counter < sizeof(buzzer_state) ){
104
105 // catat waktu saat ini
106 buzzer_time = millis();
107 // cek apakah delay pada index state sudah terpenuhi
108 if(buzzer_time - buzzer_time_last >=
buzzer_delay[buzzer_state_counter]){
109 // aktifkan atau matika buzzer sesuai
110 // logika pada index state
111 digitalWrite(PIN_BUZZER, buzzer_state[buzzer_state_counter]);
112 // pindah state berikutnya
113 buzzer_state_counter++;
114 // catat waktu tadi sebagai waktu eksekusi terakhir
115 buzzer_time_last = buzzer_time;
116 }
117
118 }
119
120 }
121
122 // fungsi untuk mengirim data
123 void KirimData(){
124
125 // catat waktu sekarang
126 kirimdata_time = millis();
127 // apabila waktu kirim terakhir dan waktu sekarang sudah 3 detik
128 // eksekusi blok program berikut
129 if( kirimdata_time - kirimdata_time_last >= kirimdata_delay ){
130
131 // cetak selisih waktu kirim sebelumnya
132 // dengan pengiriman saat ini
133 Serial.print("Selisih Waktu : ");
134 Serial.println( millis() - waktu_kirim );
135
136 // catat waktu kirim data
137 waktu_kirim = millis();
138
139 // catat waktu kirim data terakhir
140 kirimdata_time_last = kirimdata_time;
66
141
142 // setelah ngirim data
143 // reset state buzzer menjadi 0
144 // sehingga blok program pada
145 // baris 72 dieksekusi
146 buzzer_state_counter = 0;
147
148 }
149 }
Gambar 6.3 Hasil perbaikan program Dummy Logger dengan Timer Interrupt
67
Bagian #07
___
***
70
ebook versi ini, silakan Anda baca keterangan di setiap
barisnya untuk memahami.
71
34
35 Serial.begin(19200);
36 while(!Serial);
37
38 //
39 // kunfigurasi lainnya jika ada
40 //
41
42 Serial.println("==== Start Program!");
43
44 // aktifkan wdt dg waktu tunggu 8 detik
45 wdt_enable(WDTO_8S);
46 }
47
48 void loop() {
49
50 // lama makan krupuk sesuai giliran
51 delay( lama_makan_krupuk[giliran] );
52 // giliran berikutnya
53 giliran++;
54
55 Serial.print("Krupuk No. ");
56 Serial.print(giliran);
57 Serial.println(", habis!");
58
59 // reset wdt, krupuk sudah habis
60 wdt_reset();
61 }
72
Gambar 7.1 Output Program WDT dasar
73
17
18 Serial.begin(19200);
19 while(!Serial);
20
21 //
22 // kunfigurasi lainnya jika ada
23 //
24
25 Serial.println("==== Start Program!");
26
27 // aktifkan wdt dg waktu tunggu 4 detik
28 wdt_enable(WDTO_4S);
29 }
30
31 void loop() {
32
33 Serial.print("Counter: ");
34 Serial.print(counter);
35 Serial.print(" => ");
36
37 if( counter == 0 ){
38 // blok program 2 detik
39 Serial.println(" 2 detik.");
40 delay(2000);
41 } else if( counter == 1 ){
42 // blok program 6 detik
43 Serial.println(" 6 detik.");
44 delay(1000);
45 delay(1000);
46 delay(1000);
47 wdt_reset();
48 delay(1000);
49 delay(1000);
50 delay(1000);
51 wdt_reset();
52 } else if( counter == 2 ){
53 // blok program 11 detik
54 Serial.println(" 11 detik.");
55 for(byte i=0; i<11; i++){
56 delay(1000);
57 wdt_reset();
58 }
59 } else {
60 // blok program 4.5 detik
74
61 Serial.println(" 4.5 detik.");
62 delay(4500);
63 }
64
65 counter++;
66
67 // reset wdt, krupuk sudah habis
68 wdt_reset();
69 }
75
Bagian #08
MODUL RELAY
Orang yang paling tidak bahagia ialah mereka yang yang paling takut
pada perubahan. (Mignon McLaughlin)
___
76
disebut juga sebagai saklar elektronik, yaitu saklar dapat
dikontrol dengan alat elektronik lainnya seperti Arduino.
77
2. Satu kaki sumber C (common), kaki ini yang akan
dihubungkan ke kaki NC atau NO. Jika relay akan
digunakan untuk mengontrol lampu rumah, maka
kaki C disambung ke salah satu jalur listrik dari PLN.
3. Kaki NC (Normally Close), sebelum relay aktif, kaki NC
nyambung ke kaki C (perhatikan gambar). Tapi kalai
relaynya aktif, kaki NC terputus dari kaki C.
4. Kaki NO (Normally Open), sebelum relay aktif, kaki
NO tidak nyambung ke mana-mana. Tapi ketika relay
aktif, kaki NO terhubung ke kaki C.
78
8.1 Active Low atau Active High
Gambar 8.5 Polaritas kaki kumparan saat aktif dan sesaat setelah diputus
80
Interference). Untuk hal ini, Anda bisa googling tentang EMI
dan Latch-Up pada mikrokontroller.
81
Gambar 8.6 Isolasi power supply Relay
83
Pada relay, gerakan tuas untuk ON-OFF dikendalikan
oleh magnet. Sedangkan pada SSR, proses ON-OFF
dikendalikan oleh cahaya. Bagian input akan memancarkan
cahaya ketika diaktifkan, pada bagian output terdapat
Optocoupler yang nantinya akan memicu kontaktor.
84
Bagian #09
Apabil dalam diri seseorang masih ada rasa malu dan takut untuk
berbuat sesuatu kebaikan, maka jaminan bagi orang tersebut adalah
tidak akan bertemunya ia dengan kemajuan selangkah pun.
(Ir. Soekarno)
___
86
Nah, kondisi seperti itu disebut floating. Logika pada pin
bisa dibilang kacau, HIGH dan LOW bergantian. Logika
pada pin INPUT seakan digantung, nggak jelas. Sehingga
kita butuh resistor untuk menentukan kondisi defaultnya,
apakah akan dibuat default HIGH atau default LOW.
1. Arduino x 1
2. Push button x 1
3. Kabel jumper secukupnya
87
Gambar 9.2 Rangkaian untuk testing Internal Pullup Resistor
88
24 void loop() {
25 // baca data tombol
26 data = digitalRead(PIN_TOMBOL);
27 // jika data berbeda dari data sebelumnya
28 // cetak ke serial monitor
29 if(data != data_last){
30 Serial.println( data );
31
32 // simpan data sebagai data sebelumnya
33 data_last = data;
34 }
35 }
89
9.1.3 Program Tombol dengan Internal Pullup Resistor
Program 9.2 Program Tombol dengan Internal Pullup Resistor
1 /*
2 * MONSTER ARDUINO V2
3 * Program Tombol dengan Internal Pullup Resistor
4 * www.ElangSakti.com
5 */
6
7 // tombol pada pin 2
8 const byte PIN_TOMBOL = 2;
9
10 // variabel penyimpan data dari tombol
11 // dan data sebelumnya
12 boolean data = HIGH;
13 boolean data_last = data;
14
15 void setup() {
16 // buka koneksi ke serial
17 Serial.begin(19200);
18 while(!Serial);
19
20 // tombol sebagai input dengan pullup resistor
21 pinMode(PIN_TOMBOL,INPUT_PULLUP);
22 }
23
24 void loop() {
25 // baca data tombol
26 data = digitalRead(PIN_TOMBOL);
27 // jika data berbeda dari data sebelumnya
28 // cetak ke serial monitor
29 if(data != data_last){
30 Serial.println( data );
31
32 // simpan data sebagai data sebelumnya
33 data_last = data;
34 }
35 }
91
9.2.1 Program Tombol yang Manusiawi
Mungkin penamaannya aneh. Tapi nggak masalah, yang
penting kita bisa membedakan berbagai program dalam
buku ini berdasarkan nama programnya.
93
2 kali yaitu perubahan dari OFF ke ON ketika tombol mulai
ditekan dan perubahan dari ON ke OFF saat tombol dilepas.
94
20 boolean logika = data;
21
22 // delay untuk penekanan tombol.
23 // setelah tombol ditekan, maka selama 150 ms
24 // tidak bisa ditekan.
25 // delay ini berguna untuk menghindari 2 kali eksekusi
26 unsigned long delay_press = 150; // dalam ms
27 unsigned long delay_press_last = 0;
28
29 void setup() {
30 // buka koneksi ke serial
31 Serial.begin(19200);
32 while(!Serial);
33
34 // tombol sebagai input dengan pullup resistor
35 pinMode(PIN_TOMBOL,INPUT_PULLUP);
36 }
37
38 void loop() {
39
40 // jika selisih waktu penekanan tombol
41 // lebih besar dari waktu delay tombol
42 // baca tombol lagi, jika tidak tombol tdk dibaca
43 if( millis() - delay_press_last > delay_press ){
44
45 // baca data tombol
46 data = digitalRead(PIN_TOMBOL);
47
48 // jika data berbeda dari data sebelumnya
49 // cetak ke serial monitor
50 if(data != data_last){
51
52 // jika data = ON
53 if(data == ON){
54
55 // balik status logika tolbol
56 logika = !logika;
57
58 // jika ON, cetak ON
59 // jika OFF, cetak OFF
60 if( logika == ON ){
61 Serial.println("ON");
62 } else {
95
63 Serial.println("OFF");
64 }
65 }
66
67 // simpan data sebagai data sebelumnya
68 data_last = data;
69 // catat waktu penekanan tombol terakhir
70 delay_press_last = millis();
71 }
72 }
73 }
***
97
10
11 // tombol pada pin 2
12 const byte PIN_TOMBOL = 2;
13
14 // data awal ada OFF
15 // dan data sebelumnya juga OFF
16 boolean data = OFF;
17 boolean data_last = data;
18
19 // variabel untuk lock status
20 boolean logika = data;
21
22 // delay untuk penekanan tombol.
23 // setelah tombol ditekan, maka selama 150 ms
24 // tidak bisa ditekan.
25 // delay ini berguna untuk menghindari 2 kali eksekusi
26 unsigned long delay_press = 150; // dalam ms
27 unsigned long delay_press_last = 0;
28
29 void setup() {
30 // buka koneksi ke serial
31 Serial.begin(19200);
32 while(!Serial);
33
34 // tombol sebagai input dengan pullup resistor
35 pinMode(PIN_TOMBOL,INPUT_PULLUP);
36 }
37
38 void loop() {
39
40 // baca logika tombol
41 TombolListener();
42
43 }
44
45 // fungsi TombolListener
46 void TombolListener(){
47
48 // jika selisih waktu penekanan tombol
49 // lebih besar dari waktu delay tombol
50 // baca tombol lagi, jika tidak tombol tdk dibaca
51 if( millis() - delay_press_last > delay_press ){
52
53 // baca data tombol
98
54 data = digitalRead(PIN_TOMBOL);
55
56 // jika data berbeda dari data sebelumnya
57 // cetak ke serial monitor
58 if(data != data_last){
59
60 // jika data = ON
61 if(data == ON){
62
63 // balik status logika tolbol
64 logika = !logika;
65
66 // eksekusi aksi tombol sesuai logika
67 AksiTombol(logika);
68 }
69
70 // simpan data sebagai data sebelumnya
71 data_last = data;
72
73 // catat waktu penekanan tombol terakhir
74 delay_press_last = millis();
75 }
76 }
77 }
78
79 // Fungsi AksiTombol
80 // INPUT : boolean tombol
81 void AksiTombol(boolean tombol){
82
83 // jika ON, cetak ON
84 // jika OFF, cetak OFF
85 if( tombol == ON ){
86 Serial.println("ON");
87 } else {
88 Serial.println("OFF");
89 }
90 }
100
22 // dan data sebelumnya juga OFF
23 boolean data = OFF;
24 boolean data_last = data;
25
26 // variabel untuk lock status
27 boolean logika = data;
28
29 // jadikan menu sebagai array supaya lebih mudah
30 const byte MENU[] = {MENU_0,MENU_1,MENU_2,MENU_3};
31 // siapkan teks nama-nama menu
32 const String TEKS_MENU[] = {
33 "Menu Utama",
34 "Menu 1 Setting",
35 "Menu 2 Inpu Data",
36 "Menu 3 Exit"
37 };
38
39 // cata menu yang aktif saat ini
40 // saat start, menu yg aktif adalah menu_3
41 byte MENU_COUNTER = MENU_3;
42
43 // delay untuk penekanan tombol.
44 // setelah tombol ditekan, maka selama 150 ms
45 // tidak bisa ditekan.
46 // delay ini berguna untuk menghindari 2 kali eksekusi
47 unsigned long delay_press = 150; // dalam ms
48 unsigned long delay_press_last = 0;
49
50 void setup() {
51 // buka koneksi ke serial
52 Serial.begin(19200);
53 while(!Serial);
54
55 // tombol sebagai input dengan pullup resistor
56 pinMode(PIN_TOMBOL,INPUT_PULLUP);
57 }
58
59 void loop() {
60
61 // baca logika tombol
62 TombolListener();
63
64 }
101
65
66 // fungsi TombolListener
67 void TombolListener(){
68
69 // jika selisih waktu penekanan tombol
70 // lebih besar dari waktu delay tombol
71 // baca tombol lagi, jika tidak tombol tdk dibaca
72 if( millis() - delay_press_last > delay_press ){
73
74 // baca data tombol
75 data = digitalRead(PIN_TOMBOL);
76
77 // jika data berbeda dari data sebelumnya
78 // cetak ke serial monitor
79 if(data != data_last){
80
81 // jika data = ON
82 if(data == ON){
83
84 // pilih menu selanjutnya
85 MENU_COUNTER++;
86
87 // jika menu melebihi jumlah menu yg ada
88 // pilih menu awal
89 if( MENU_COUNTER >= sizeof(MENU) ){
90 MENU_COUNTER = 0;
91 }
92
93 // eksekusi aksi tombol sesuai logika
94 AksiTombol(MENU_COUNTER);
95 }
96
97 // simpan data sebagai data sebelumnya
98 data_last = data;
99 // catat waktu penekanan tombol terakhir
100 delay_press_last = millis();
101 }
102 }
103 }
104
105 // Fungsi AksiTombol
106 // INPUT : byte tombol
107 void AksiTombol(byte tombol){
108
102
109 // print sesuai menu yang dipilih
110 switch(tombol){
111 case MENU_0:
112 // proses sesuatu
113 Serial.println(TEKS_MENU[MENU_0]);
114 break;
115
116 case MENU_1:
117 // proses sesuatu
118 Serial.println(TEKS_MENU[MENU_1]);
119 break;
120
121 case MENU_2:
122 // proses sesuatu
123 Serial.println(TEKS_MENU[MENU_2]);
124 break;
125
126 case MENU_3:
127 // proses sesuatu
128 Serial.println(TEKS_MENU[MENU_3]);
129 break;
130 }
131 }
103
Program 9.6 akan menampilkan menu secara
bergantian. Boleh diperhatikan input data pada fungsi
AksiTombol() adalah byte tombol (baris 107), bukan lagi
boolean tombol sebagaimana pada program 9.5 baris 81.
104
timer. Setiap penekanan tombol tidak boleh langsung
diputuskan untuk melakukan aksi. Namun, setiap penekanan
tombol akan ditunggu hingga tombol dilepas.
107
100 // jika lama ditekan >= 10 detik
101 MENU_COUNTER = MENU_3;
102 } else if( selisih >= TOMBOL_DELAY[MENU_2] ){
103
104 // jika lama ditekan >= 5 detik
105 MENU_COUNTER = MENU_2;
106 } else if( selisih >= TOMBOL_DELAY[MENU_1] ){
107
108 // jika lama ditekan >= 3 detik
109 MENU_COUNTER = MENU_1;
110 } else {
111
112 // jika antara 0 - 3 detik
113 MENU_COUNTER = MENU_0;
114 }
115
116 // eksekusi aksi tombol sesuai logika
117 AksiTombol(MENU_COUNTER);
118
119 } else {
120
121 // reset waktu yang tercatat
122 start_press = millis();
123 }
124
125 // simpan data sebagai data sebelumnya
126 data_last = data;
127 // catat waktu penekanan tombol terakhir
128 delay_press_last = millis();
129 }
130 }
131 }
132
133 // Fungsi AksiTombol
134 // INPUT : byte tombol
135 void AksiTombol(byte tombol){
136
137 // print sesuai menu yang dipilih
138 switch(tombol){
139 case MENU_0:
140 // proses sesuatu
141 Serial.println(TEKS_MENU[MENU_0]);
142 break;
143
108
144 case MENU_1:
145 // proses sesuatu
146 Serial.println(TEKS_MENU[MENU_1]);
147 break;
148
149 case MENU_2:
150 // proses sesuatu
151 Serial.println(TEKS_MENU[MENU_2]);
152 break;
153
154 case MENU_3:
155 // proses sesuatu
156 Serial.println(TEKS_MENU[MENU_3]);
157 break;
158 }
159 }
109
Program 9.7 relatif simpel, kalaupun belum terbiasa,
sekaranglah waktunya untuk membiasakan berpikir
kerasss!!!
110
Pada Gambar 9.5, ketika tombol S1 – S5 ditekan, maka
output akan menghasilkan voltase yang berbeda-beda yang
dapat dihitung berdasarkan konsep pembagi tegangan.
Perbedaan voltase inilah yang diterima oleh pin Analog.
Tabel 9.1 Tabel Perhitungan Ouput Tombol berdasarkan Konsep Pembagi Tegangan
Tombol Output
Resistor Aktif
Ditekan Volt Data (analogRead())
S1 R1, R2, R3, R4, R5 5V/5 = 1V 1*(1023/5) = 204.6
S2 R1, R3, R4, R5 5V/4 = 1.25V 1.25*(1023/5) = 255.75
S3 R1, R4, R5 5V/3 = 1.67V 1.67*(1023/5) = 341.68
S4 R1, R5 5V/2 = 2.5V 2.5*(1023/5) = 511.5
S5 R1 5V/1 = 5V 5*(1023/5) = 1023
1. Arduino x 1
2. Push button x 5
3. Resistor dengan nilai seragam x 5
4. Project board x 1
5. Kabel jumper secukupnya
112
9.4.2 Program Analisis Output Tombol
Program 9.8 Program Analisis Output Tombol
1 /*
2 * MONSTER ARDUINO V2
3 * Program Analisis Output Tombol
4 * www.ElangSakti.com
5 */
6
7 // output tombol di pin A0
8 const byte PIN_TOMBOL = A0;
9
10 // data saat ini dan data sebelumnya
11 int data = 0;
12 int data_last = 0;
13
14 // delay untuk penekanan tombol.
15 // setelah tombol ditekan, maka selama 150 ms
16 // tidak bisa ditekan.
17 // delay ini berguna untuk menghindari 2 kali eksekusi
18 unsigned long delay_press = 150; // dalam ms
19 unsigned long delay_press_last = 0;
20
21 void setup() {
22 // buka koneksi ke serial
23 Serial.begin(19200);
24 while(!Serial);
25
26 // tombol sebagai input
27 pinMode(PIN_TOMBOL,INPUT);
28 }
29
30 void loop() {
31
32 // panggil fungsi utk membaca tombol
33 TombolListener();
34
35 }
36
37 void TombolListener(){
38
39 // jika selisih waktu penekanan tombol
113
40 // lebih besar dari waktu delay tombol
41 // baca tombol lagi, jika tidak tombol tdk dibaca
42 if( millis() - delay_press_last > delay_press ){
43
44 // baca data tombol
45 data = analogRead(PIN_TOMBOL);
46
47 // jika data lebih kecil dari 10 abaikan
48 if( data < 10 ) return;
49
50 // jika data berbeda dari data sebelumnya
51 // cetak ke serial monitor
52 if(data != data_last){
53 Serial.println(data);
54 data_last = data;
55 delay_press_last = millis();
56 }
57 }
58 }
117
111
112 case TOMBOL4:
113 // proses sesuatu
114 Serial.println("Menu 4");
115 break;
116
117 case TOMBOL5:
118 // proses sesuatu
119 Serial.println("Menu 5");
120 break;
121 }
122 }
118
Gambar 9.8 Output program Menu 5 Tombol
1. Arduino Uno x 1
119
2. Push button x 5
3. Resistor x 10 (bebas)
4. LED x 10
5. Project Board x 1
6. Jumper secukupnya
Arduino Rangkaian
Pin A0 Output push button (sisi lain dari sisi tombol
yang terhubung ke resistor pembagi tegangan)
Pin 2, 3, 4, 5, dan 6 Kaki positif LED 1, 2, 3, 4, dan 5
VCC Resistor pada tombol pembagi tegangan
GND - Resistor pada tombol pembagi tegangan
- Resistor pada kaki negatif LED
120
9.4.5 Program 5 Tombol 5 LED
Program 9.10 Program 5 Tombol 5 LED
1 /*
2 * MONSTER ARDUINO V2
3 * Program 5 Tombol 5 LED
4 * www.ElangSakti.com
5 */
6
7 // led setting active high
8 #define LED_ON HIGH
9 #define LED_OFF !LED_ON
10
11 // definisikan 5 tombol
12 #define TOMBOL_NONE 0
13 #define TOMBOL1 1
14 #define TOMBOL2 2
15 #define TOMBOL3 3
16 #define TOMBOL4 4
17 #define TOMBOL5 5
18
19 // output tombol di pin A0
20 // pin led di pin 2 - 6
21 const byte PIN_TOMBOL = A0;
22 const byte PIN_LED[] = {2,3,4,5,6};
23
24 // nilai data tombol sesuai tabel
25 // dan nilai toleransi 15
26 const int TOMBOL_VAL[] = {204,255,341,511,1023};
27 const byte TOLERANSI = 15;
28
29 // status led untuk lock status
30 byte STATUS_LED[] = {LED_OFF,LED_OFF,LED_OFF,LED_OFF,LED_OFF};
31
32 // tombol dalam array
33 const byte TOMBOL[] = {
34 TOMBOL1, TOMBOL2, TOMBOL3,
35 TOMBOL4, TOMBOL5 };
36
37 // tombol saat ini dan tombol sebelumnya
38 byte tombol = 0;
39 byte tombol_last = 0;
121
40
41 // data saat ini dan data sebelumnya
42 int data = 0;
43 int data_last = 0;
44
45 // delay untuk penekanan tombol
46 unsigned long delay_press = 400; // dalam ms
47 unsigned long delay_press_last = 0;
48
49 void setup() {
50 // buka koneksi ke serial
51 Serial.begin(19200);
52 while(!Serial);
53
54 // tombol sebagai input
55 pinMode(PIN_TOMBOL,INPUT);
56
57 // pin sebagai output, defaultnya OFF
58 for(byte i=0; i<sizeof(PIN_LED); i++){
59 pinMode(PIN_LED[i],OUTPUT);
60 digitalWrite(PIN_LED[i],LED_OFF);
61 }
62 }
63
64 void loop() {
65
66 // panggil fungsi utk membaca tombol
67 TombolListener();
68 }
69
70 void TombolListener(){
71
72 // jika selisih waktu penekanan tombol
73 // lebih besar dari waktu delay tombol
74 // baca tombol lagi, jika tidak tombol tdk dibaca
75 if( millis() - delay_press_last > delay_press ){
76
77 // baca data analog tombol
78 data = analogRead(PIN_TOMBOL);
79 // reset tombol sebelumnya
80 tombol = TOMBOL_NONE;
81 // cocokkan data dengan ke-5 data tombol
82 for(byte i=0; i<sizeof(TOMBOL); i++){
83 // hitung koreksi data tombol
122
84 // jika ada yang cocok,
85 // catat tombol yang sesuai, lalu
86 // hentikan looping.
87 if( abs(data - TOMBOL_VAL[i]) < TOLERANSI ){
88 tombol = TOMBOL[i];
89 break;
90 }
91 }
92
93 // jika ada tombol yang cocok
94 // cetak tombol, panggil aksi tombol
95 // lalu catat waktu pembacaan tombol
96 if(tombol != TOMBOL_NONE){
97 Serial.println(tombol);
98
99 AksiTombol(tombol);
100
101 tombol_last = tombol;
102 delay_press_last = millis();
103 }
104 }
105 }
106
107 // fungsi AksiTombol
108 // INPUT : byte tombol
109 void AksiTombol(byte tombol){
110
111 // konversi dari nomer tombol menjadi index tombol
112 byte index_led = tombol-1;
113
114 // balik status LED sesuai index/led yang cocok
115 // jika HIGH, ubah jadi LOW, dan sebaliknya
116 STATUS_LED[index_led] = !STATUS_LED[index_led];
117
118 // cetak sesuai tombol yang terpilih
119 switch(tombol){
120 case TOMBOL1:
121 // proses sesuatu
122 if( STATUS_LED[index_led] == LED_ON ){
123 Serial.println("Nyalakan LED 1");
124 } else {
125 Serial.println("Matikan LED 1");
126 }
123
127 break;
128
129 case TOMBOL2:
130 // proses sesuatu
131 if( STATUS_LED[index_led] == LED_ON ){
132 Serial.println("Nyalakan LED 2");
133 } else {
134 Serial.println("Matikan LED 2");
135 }
136 break;
137
138 case TOMBOL3:
139 // proses sesuatu
140 if( STATUS_LED[index_led] == LED_ON ){
141 Serial.println("Nyalakan LED 3");
142 } else {
143 Serial.println("Matikan LED 3");
144 }
145 break;
146
147 case TOMBOL4:
148 // proses sesuatu
149 if( STATUS_LED[index_led] == LED_ON ){
150 Serial.println("Nyalakan LED 4");
151 } else {
152 Serial.println("Matikan LED 4");
153 }
154 break;
155
156 case TOMBOL5:
157 // proses sesuatu
158 if( STATUS_LED[index_led] == LED_ON ){
159 Serial.println("Nyalakan LED 5");
160 } else {
161 Serial.println("Matikan LED 5");
162 }
163 break;
164 }
165
166 // hidup matikan led, sesuai status led
167 digitalWrite(PIN_LED[index_led],STATUS_LED[index_led]);
168 }
124
Cara kerja Program 9.10 adalah: Anda boleh membaca
source code di atas sendiri ya. Penjelasan lengkap bisa
ditunggu pada edisi revisi. Btw, semakin sering Anda
membaca source code, Anda akan semakin mahir
memahami cara kerjanya. Silakan pahami maksud dari
setiap baris programnya. :D
125
Bagian #10
___
127
10.1 Program Simulasi EEPROM
Program ini tidak membutuhkan rangkaian khusus
karena kita hanya simulasi dengan counter dan EEPROM
yang sudah ada di internal Arduino. Jika Anda baru saja
mencoba rangkaian lain, biarkan saja rangkaian tersebut
karena tidak akan mempengaruhi program.
129
Gambar 10.1 Ouput program simulasi EEPROM
130
6. Arduino membaca data sebelumnya pada alamat 0
(lihat baris 48), apabila data nilainya lebih besar dari
nilai maksimum counter, reset counter menjadi 0. Jika
tidak, data tersebut adalah data yang terakhir
disimpan.
133
101 }
102 }
103
104 // jika ada tombol yang cocok
105 // cetak tombol, panggil aksi tombol
106 // lalu catat waktu pembacaan tombol
107 if(tombol != TOMBOL_NONE){
108 Serial.println(tombol);
109
110 AksiTombol(tombol);
111
112 tombol_last = tombol;
113 delay_press_last = millis();
114 }
115 }
116 }
117
118 // fungsi AksiTombol
119 // INPUT : byte tombol
120 void AksiTombol(byte tombol){
121
122 // konversi dari nomer tombol menjadi index tombol
123 byte index_led = tombol-1;
124
125 // balik status LED sesuai index/led yang cocok
126 // jika HIGH, ubah jadi LOW, dan sebaliknya
127 STATUS_LED[index_led] = !STATUS_LED[index_led];
128
129 // cetak sesuai tombol yang terpilih
130 switch(tombol){
131 case TOMBOL1:
132 // proses sesuatu
133 if( STATUS_LED[index_led] == LED_ON ){
134 Serial.println("Nyalakan LED 1");
135 } else {
136 Serial.println("Matikan LED 1");
137 }
138 break;
139
140 case TOMBOL2:
141 // proses sesuatu
142 if( STATUS_LED[index_led] == LED_ON ){
143 Serial.println("Nyalakan LED 2");
144 } else {
134
145 Serial.println("Matikan LED 2");
146 }
147 break;
148
149 case TOMBOL3:
150 // proses sesuatu
151 if( STATUS_LED[index_led] == LED_ON ){
152 Serial.println("Nyalakan LED 3");
153 } else {
154 Serial.println("Matikan LED 3");
155 }
156 break;
157
158 case TOMBOL4:
159 // proses sesuatu
160 if( STATUS_LED[index_led] == LED_ON ){
161 Serial.println("Nyalakan LED 4");
162 } else {
163 Serial.println("Matikan LED 4");
164 }
165 break;
166
167 case TOMBOL5:
168 // proses sesuatu
169 if( STATUS_LED[index_led] == LED_ON ){
170 Serial.println("Nyalakan LED 5");
171 } else {
172 Serial.println("Matikan LED 5");
173 }
174 break;
175 }
176
177 // hidup matikan led, sesuai status led
178 digitalWrite(PIN_LED[index_led],STATUS_LED[index_led]);
179 // simpan status led pada EEPROM sesuai alamat
180 EEPROM.write(ADDR_LED[index_led],STATUS_LED[index_led]);
181 }
182
183 // fungsi PrepareLED
184 // untuk membaca data EEPROM saat awal start
185 void PrepareLED(){
186 for(byte i=0; i<sizeof(ADDR_LED); i++){
187 // baca alamat EEPROM ke i
135
188 STATUS_LED[i] = EEPROM.read(ADDR_LED[i]);
189 // status led adalah boolean 0 atau 1
190 // jika data yg tersimpan > 1, reset ke 0
191 if(STATUS_LED[i] > 1) STATUS_LED[i] = 0;
192 // kondisikan LED sesuai data yg tersimpan
193 digitalWrite(PIN_LED[i],STATUS_LED[i]);
194 }
195 }
136
Bagian #11
___
137
Shift Register (register geser) adalah teknik pergeseran
bit data yang berfungsi untuk mengonversi data serial ke
paralel atau dari paralel ke serial.
139
konversi dari paralel ke serial (lihat gambar 11.2 kanan),
input data dari 4 jalur, sedangkan outputnya jadi satu jalur.
140
mari kita membuat program lampu “berjalan”, maksudnya
lampu LED yang nyala satu-satu bergantian.
1. Arduino x 1
2. IC Shift Register 74HC595 x 1
3. LED x 8
4. Resistor dengan nilai seragam x 8
5. Project board x 1
141
6. Kabel jumper secukupnya
142
8 const byte DataPin = 2; // DS data serial
9 const byte LatchPin = 3; // ST_CP
10 const byte ClockPin = 4; // SH_CP
11
12 // menampung data
13 byte data = 0;
14
15 void setup() {
16
17 // konfigurasi pin sebagai ouput
18 pinMode(LatchPin, OUTPUT);
19 pinMode(ClockPin, OUTPUT);
20 pinMode(DataPin, OUTPUT);
21
22 }
23
24 void loop() {
25
26 // delay 200ms
27 if ( nonblocking_delay(200) ){
28 // geser kiri
29 data <<= 1;
30 // jika data == 0 (gesernya sudah habis)
31 // ulangi dari awal
32 if( data == 0 ) data = 1;
33
34 // mulai transfer
35 digitalWrite(LatchPin, LOW);
36 // kirim data
37 shiftOut(DataPin, ClockPin, MSBFIRST, data);
38 // stop transfer
39 digitalWrite(LatchPin, HIGH);
40 }
41 }
42
43 // tambahan untuk membuat delay non blocking
44 unsigned long nonblocking_time = millis();
45 unsigned long nonblocking_last = millis();
46 boolean nonblocking_delay(long milidetik){
47 nonblocking_time = millis();
48 if(nonblocking_time - nonblocking_last >= milidetik){
49 nonblocking_last = nonblocking_time;
50 return true;
143
51 }
52 return false;
53 }
145
latch, data, dan clock yang menghubungkan antara Arduino
dan IC 74HC595.
147
52 unsigned long nonblocking_last = millis();
53 boolean nonblocking_delay(long milidetik){
54 nonblocking_time = millis();
55 if(nonblocking_time - nonblocking_last >= milidetik){
56 nonblocking_last = nonblocking_time;
57 return true;
58 }
59 return false;
60 }
148
Bagian #12
___
150
negatifnya, maka disebut dengan Common Cathode (CC).
Anda boleh memperhatikan dengan seksama gabar di
bawah ini.
151
12.1.1 Rangkaian Seven Segment 1 Digit
1. Arduino x 1
2. Display 7 Segment 1 Digit CC x 1
3. Resistor 1k x 1
4. Project Board x 1
5. Kabel jumper secukupnya
153
9 #define COMMON_CATHODE LOW
10 #define ON HIGH
11 #define BRIGHTNESS 100
12
13 // konfigurasi seven segment CC
14 // CC : active low
15 boolean COMMON = COMMON_CATHODE;
16 boolean SEGMENT_ON = LOW;
17 boolean SEGMENT_OFF = !SEGMENT_ON;
18
19 // pin 2-9 untuk segmen A – DP
20 const byte SegA = 2; // A
21 const byte SegB = 3; // B
22 const byte SegC = 4; // C
23 const byte SegD = 5; // D
24 const byte SegE = 6; // E
25 const byte SegF = 7; // F
26 const byte SegG = 8; // G
27 const byte SegDp = 9; // DP
28
29 // jadikan array biar mudah
30 const byte SEGMENT[] = {SegA, SegB, SegC, SegD, SegE, SegF, SegG, SegDp};
31
32 // pengaturan untuk brightness
33 unsigned long brightness_now = 0;
34 unsigned long brightness_last = 0;
35 unsigned long brightness_limit = 0;
36
37 // data counter untuk ditampilkan
38 byte counter = 0;
39
40 void setup() {
41
42 // sesuaikan active low/high
43 // dengan tipe Common Anode atau Common Cathode
44 if( COMMON == COMMON_ANODE ){
45 SEGMENT_ON = !ON;
46 } else {
47 SEGMENT_ON = ON;
48 }
49 SEGMENT_OFF = !SEGMENT_ON;
50
51 // set segment sebagai output
52 for(byte i=0; i<sizeof(SEGMENT); i++){
154
53 pinMode(SEGMENT[i],OUTPUT);
54 }
55 }
56
57 void loop() {
58
59 // counter data setiap 1 detik
60 // jika lebih besar dr 9, reset ke 0
61 if( nonblocking_delay(1000) ){
62 counter++;
63 if(counter > 9) counter = 0;
64 }
65
66 // tampilkan angka di seven segment
67 Digit(counter, SEGMENT_OFF, BRIGHTNESS);
68
69 }
70
71 // fungsi Digit
72 // untuk menampilkan angka pada seven segment
73 void Digit(byte data, boolean dp, int brightness){
74
75 // delay nyala segment, efeknya pada brigthness
76 brightness_limit = constrain(brightness,1,100);
77 brightness_limit = map(brightness_limit,1,100,1,5000);
78
79 brightness_now = micros();
80 if(brightness_now – brightness_last < brightness_limit){
81 // nyalakan 7 segmen sesuai angka
82 switch(data){
83 case 0:
84 digitalWrite(SegA, SEGMENT_ON);
85 digitalWrite(SegB, SEGMENT_ON);
86 digitalWrite(SegC, SEGMENT_ON);
87 digitalWrite(SegD, SEGMENT_ON);
88 digitalWrite(SegE, SEGMENT_ON);
89 digitalWrite(SegF, SEGMENT_ON);
90 digitalWrite(SegG, SEGMENT_OFF);
91 digitalWrite(SegDp, dp);
92 break;
93
94 case 1:
95 digitalWrite(SegA, SEGMENT_OFF);
155
96 digitalWrite(SegB, SEGMENT_ON);
97 digitalWrite(SegC, SEGMENT_ON);
98 digitalWrite(SegD, SEGMENT_OFF);
99 digitalWrite(SegE, SEGMENT_OFF);
100 digitalWrite(SegF, SEGMENT_OFF);
101 digitalWrite(SegG, SEGMENT_OFF);
102 digitalWrite(SegDp, dp);
103 break;
104
105 case 2:
106 digitalWrite(SegA, SEGMENT_ON);
107 digitalWrite(SegB, SEGMENT_ON);
108 digitalWrite(SegC, SEGMENT_OFF);
109 digitalWrite(SegD, SEGMENT_ON);
110 digitalWrite(SegE, SEGMENT_ON);
111 digitalWrite(SegF, SEGMENT_OFF);
112 digitalWrite(SegG, SEGMENT_ON);
113 digitalWrite(SegDp, dp);
114 break;
115
116 case 3:
117 digitalWrite(SegA, SEGMENT_ON);
118 digitalWrite(SegB, SEGMENT_ON);
119 digitalWrite(SegC, SEGMENT_ON);
120 digitalWrite(SegD, SEGMENT_ON);
121 digitalWrite(SegE, SEGMENT_OFF);
122 digitalWrite(SegF, SEGMENT_OFF);
123 digitalWrite(SegG, SEGMENT_ON);
124 digitalWrite(SegDp, dp);
125 break;
126
127 case 4:
128 digitalWrite(SegA, SEGMENT_OFF);
129 digitalWrite(SegB, SEGMENT_ON);
130 digitalWrite(SegC, SEGMENT_ON);
131 digitalWrite(SegD, SEGMENT_OFF);
132 digitalWrite(SegE, SEGMENT_OFF);
133 digitalWrite(SegF, SEGMENT_ON);
134 digitalWrite(SegG, SEGMENT_ON);
135 digitalWrite(SegDp, dp);
136 break;
137
138 case 5:
139 digitalWrite(SegA, SEGMENT_ON);
156
140 digitalWrite(SegB, SEGMENT_OFF);
141 digitalWrite(SegC, SEGMENT_ON);
142 digitalWrite(SegD, SEGMENT_ON);
143 digitalWrite(SegE, SEGMENT_OFF);
144 digitalWrite(SegF, SEGMENT_ON);
145 digitalWrite(SegG, SEGMENT_ON);
146 digitalWrite(SegDp, dp);
147 break;
148
149 case 6:
150 digitalWrite(SegA, SEGMENT_ON);
151 digitalWrite(SegB, SEGMENT_OFF);
152 digitalWrite(SegC, SEGMENT_ON);
153 digitalWrite(SegD, SEGMENT_ON);
154 digitalWrite(SegE, SEGMENT_ON);
155 digitalWrite(SegF, SEGMENT_ON);
156 digitalWrite(SegG, SEGMENT_ON);
157 digitalWrite(SegDp, dp);
158 break;
159
160 case 7:
161 digitalWrite(SegA, SEGMENT_ON);
162 digitalWrite(SegB, SEGMENT_ON);
163 digitalWrite(SegC, SEGMENT_ON);
164 digitalWrite(SegD, SEGMENT_OFF);
165 digitalWrite(SegE, SEGMENT_OFF);
166 digitalWrite(SegF, SEGMENT_OFF);
167 digitalWrite(SegG, SEGMENT_OFF);
168 digitalWrite(SegDp, dp);
169 break;
170
171 case 8:
172 digitalWrite(SegA, SEGMENT_ON);
173 digitalWrite(SegB, SEGMENT_ON);
174 digitalWrite(SegC, SEGMENT_ON);
175 digitalWrite(SegD, SEGMENT_ON);
176 digitalWrite(SegE, SEGMENT_ON);
177 digitalWrite(SegF, SEGMENT_ON);
178 digitalWrite(SegG, SEGMENT_ON);
179 digitalWrite(SegDp, dp);
180 break;
181
182 case 9:
157
183 digitalWrite(SegA, SEGMENT_ON);
184 digitalWrite(SegB, SEGMENT_ON);
185 digitalWrite(SegC, SEGMENT_ON);
186 digitalWrite(SegD, SEGMENT_ON);
187 digitalWrite(SegE, SEGMENT_OFF);
188 digitalWrite(SegF, SEGMENT_ON);
189 digitalWrite(SegG, SEGMENT_ON);
190 digitalWrite(SegDp, dp);
191 break;
192 }
193 }else{
194 // matikan semua 7 segment
195 for(byte d=0; d<sizeof(SEGMENT); d++){
196 digitalWrite(SEGMENT[d], SEGMENT_OFF);
197 }
198 brightness_last = brightness_now;
199 }
200 }
201
202 // tambahan untuk membuat delay non blocking
203 unsigned long nonblocking_time = millis();
204 unsigned long nonblocking_last = millis();
205 boolean nonblocking_delay(long milidetik){
206 nonblocking_time = millis();
207 if(nonblocking_time – nonblocking_last >= milidetik){
208 nonblocking_last = nonblocking_time;
209 return true;
210 }
211 return false;
212 }
159
195 – 197 untuk segment OFF seluruhnya. Silakan
coba ubah-ubah angkanya supaya Anda bisa bisa
memahaminya lebih baik…
Gambar 12.6 Seven segment 4 digit tampak depan dan belakang dan skemanya
161
12.2.2 Program Seven Segment 4 Digit
Program 12.2 Program Seven Segment 4 Digit
1 /*
2 * MONSTER ARDUINO V2
3 * Program Seven Segment 4 Digit
4 * www.ElangSakti.com
5 */
6
7 // definisikan CC, CA, ON, dan Brightness
8 #define COMMON_ANODE HIGH
9 #define COMMON_CATHODE LOW
10 #define ON HIGH
11 #define BRIGHTNESS 100
12
13 // konfigurasi seven segment CC
14 // CC : active low
15 boolean COMMON = COMMON_CATHODE;
16 boolean SEGMENT_ON = LOW;
17 boolean SEGMENT_OFF = !SEGMENT_ON;
18 boolean DIGIT_ON = HIGH;
19 boolean DIGIT_OFF = !DIGIT_ON;
20
21 // pin 2-9 untuk segmen A - DP
22 const byte SegA = 2; // A
23 const byte SegB = 3; // B
24 const byte SegC = 4; // C
25 const byte SegD = 5; // D
26 const byte SegE = 6; // E
27 const byte SegF = 7; // F
28 const byte SegG = 8; // G
29 const byte SegDp = 9; // DP
30
31 // pin A0-A3 untuk digit 1-4
32 const byte Digit1 = A0;
33 const byte Digit2 = A1;
34 const byte Digit3 = A2;
35 const byte Digit4 = A3;
36
37 // jadikan array biar mudah
38 const byte SEGMENT[] = {SegA, SegB, SegC, SegD, SegE, SegF, SegG, SegDp};
39 const byte DIGIT[] = {Digit1, Digit2, Digit3, Digit4};
40
162
41 // digit terpilih - 0 dari digit satuan (kanan)
42 byte DIGIT_SELECT = 0;
43
44 // pengaturan untuk brightness
45 unsigned long brightness_now = 0;
46 unsigned long brightness_last = 0;
47 unsigned long brightness_limit = 0;
48
49 // counter dari -50
50 int counter = -50;
51
52 // string angka
53 String str_data_last = "";
54
55
56 void setup() {
57
58 // sesuaikan active low/high
59 // dengan tipe Common Anode atau Common Cathode
60 if( COMMON == COMMON_ANODE ){
61 SEGMENT_ON = !ON;
62 DIGIT_ON = ON;
63 } else {
64 SEGMENT_ON = ON;
65 DIGIT_ON = !ON;
66 }
67 SEGMENT_OFF = !SEGMENT_ON;
68 DIGIT_OFF = !DIGIT_ON;
69
70 // set pin segment sebagai output
71 for(byte i=0; i<sizeof(SEGMENT); i++){
72 pinMode(SEGMENT[i],OUTPUT);
73 }
74
75 // set pin digit sebagai output
76 for(byte i=0; i<sizeof(DIGIT); i++){
77 pinMode(DIGIT[i],OUTPUT);
78 }
79 }
80
81 void loop() {
82
83 // counter data setiap 100 ms
163
84 // jika lebih besar dr 200, reset ke -50
85 if( nonblocking_delay(100) ){
86 counter++;
87 if(counter > 200) counter = -50;
88 }
89
90 // tampilkan angka di seven segment
91 Digit(counter, SEGMENT_OFF, BRIGHTNESS);
92
93 }
94
95 void Digit(int data, boolean dp, int brightness){
96
97 // delay nyala segment, efeknya pada brigthness
98 brightness_limit = constrain(brightness,1,100);
99 brightness_limit = map(brightness_limit,1,100,1,5000);
100
101 // konversi angka menjadi string
102 // lalu cek lebar angkannya
103 String str_data = String(data);
104 byte len_data = str_data.length();
105
106 brightness_now = micros();
107 if(brightness_now - brightness_last < brightness_limit){
108
109 // replace data sesuai digit yang terpilih
110 if( DIGIT_SELECT < len_data ){
111
112 // jika data < 0, berarti ada tanda - di depan
113 if( data < 0 && DIGIT_SELECT == 0){
114 data = '-';
115 } else {
116 // ambil data sesuai index digitnya
117 data = (str_data.substring(DIGIT_SELECT,DIGIT_SELECT+1)).toInt();
118 }
119
120 // nyalakan digit yang terpilih
121 digitalWrite(DIGIT[DIGIT_SELECT],DIGIT_ON);
122 }
123
124 // nyalakan 7 segmen sesuai angka
125 switch(data){
126 case 0:
127 digitalWrite(SegA, SEGMENT_ON);
164
128 digitalWrite(SegB, SEGMENT_ON);
129 digitalWrite(SegC, SEGMENT_ON);
130 digitalWrite(SegD, SEGMENT_ON);
131 digitalWrite(SegE, SEGMENT_ON);
132 digitalWrite(SegF, SEGMENT_ON);
133 digitalWrite(SegG, SEGMENT_OFF);
134 digitalWrite(SegDp, dp);
135 break;
136
137 case 1:
138 digitalWrite(SegA, SEGMENT_OFF);
139 digitalWrite(SegB, SEGMENT_ON);
140 digitalWrite(SegC, SEGMENT_ON);
141 digitalWrite(SegD, SEGMENT_OFF);
142 digitalWrite(SegE, SEGMENT_OFF);
143 digitalWrite(SegF, SEGMENT_OFF);
144 digitalWrite(SegG, SEGMENT_OFF);
145 digitalWrite(SegDp, dp);
146 break;
147
148 case 2:
149 digitalWrite(SegA, SEGMENT_ON);
150 digitalWrite(SegB, SEGMENT_ON);
151 digitalWrite(SegC, SEGMENT_OFF);
152 digitalWrite(SegD, SEGMENT_ON);
153 digitalWrite(SegE, SEGMENT_ON);
154 digitalWrite(SegF, SEGMENT_OFF);
155 digitalWrite(SegG, SEGMENT_ON);
156 digitalWrite(SegDp, dp);
157 break;
158
159 case 3:
160 digitalWrite(SegA, SEGMENT_ON);
161 digitalWrite(SegB, SEGMENT_ON);
162 digitalWrite(SegC, SEGMENT_ON);
163 digitalWrite(SegD, SEGMENT_ON);
164 digitalWrite(SegE, SEGMENT_OFF);
165 digitalWrite(SegF, SEGMENT_OFF);
166 digitalWrite(SegG, SEGMENT_ON);
167 digitalWrite(SegDp, dp);
168 break;
169
170 case 4:
165
171 digitalWrite(SegA, SEGMENT_OFF);
172 digitalWrite(SegB, SEGMENT_ON);
173 digitalWrite(SegC, SEGMENT_ON);
174 digitalWrite(SegD, SEGMENT_OFF);
175 digitalWrite(SegE, SEGMENT_OFF);
176 digitalWrite(SegF, SEGMENT_ON);
177 digitalWrite(SegG, SEGMENT_ON);
178 digitalWrite(SegDp, dp);
179 break;
180
181 case 5:
182 digitalWrite(SegA, SEGMENT_ON);
183 digitalWrite(SegB, SEGMENT_OFF);
184 digitalWrite(SegC, SEGMENT_ON);
185 digitalWrite(SegD, SEGMENT_ON);
186 digitalWrite(SegE, SEGMENT_OFF);
187 digitalWrite(SegF, SEGMENT_ON);
188 digitalWrite(SegG, SEGMENT_ON);
189 digitalWrite(SegDp, dp);
190 break;
191
192 case 6:
193 digitalWrite(SegA, SEGMENT_ON);
194 digitalWrite(SegB, SEGMENT_OFF);
195 digitalWrite(SegC, SEGMENT_ON);
196 digitalWrite(SegD, SEGMENT_ON);
197 digitalWrite(SegE, SEGMENT_ON);
198 digitalWrite(SegF, SEGMENT_ON);
199 digitalWrite(SegG, SEGMENT_ON);
200 digitalWrite(SegDp, dp);
201 break;
202
203 case 7:
204 digitalWrite(SegA, SEGMENT_ON);
205 digitalWrite(SegB, SEGMENT_ON);
206 digitalWrite(SegC, SEGMENT_ON);
207 digitalWrite(SegD, SEGMENT_OFF);
208 digitalWrite(SegE, SEGMENT_OFF);
209 digitalWrite(SegF, SEGMENT_OFF);
210 digitalWrite(SegG, SEGMENT_OFF);
211 digitalWrite(SegDp, dp);
212 break;
213
214 case 8:
166
215 digitalWrite(SegA, SEGMENT_ON);
216 digitalWrite(SegB, SEGMENT_ON);
217 digitalWrite(SegC, SEGMENT_ON);
218 digitalWrite(SegD, SEGMENT_ON);
219 digitalWrite(SegE, SEGMENT_ON);
220 digitalWrite(SegF, SEGMENT_ON);
221 digitalWrite(SegG, SEGMENT_ON);
222 digitalWrite(SegDp, dp);
223 break;
224
225 case 9:
226 digitalWrite(SegA, SEGMENT_ON);
227 digitalWrite(SegB, SEGMENT_ON);
228 digitalWrite(SegC, SEGMENT_ON);
229 digitalWrite(SegD, SEGMENT_ON);
230 digitalWrite(SegE, SEGMENT_OFF);
231 digitalWrite(SegF, SEGMENT_ON);
232 digitalWrite(SegG, SEGMENT_ON);
233 digitalWrite(SegDp, dp);
234 break;
235
236 case '-':
237 digitalWrite(SegA, SEGMENT_OFF);
238 digitalWrite(SegB, SEGMENT_OFF);
239 digitalWrite(SegC, SEGMENT_OFF);
240 digitalWrite(SegD, SEGMENT_OFF);
241 digitalWrite(SegE, SEGMENT_OFF);
242 digitalWrite(SegF, SEGMENT_OFF);
243 digitalWrite(SegG, SEGMENT_ON);
244 digitalWrite(SegDp, dp);
245 break;
246 }
247 }else{
248 // matikan semua digit
249 for(byte d=0; d<sizeof(DIGIT); d++){
250 digitalWrite(DIGIT[d], DIGIT_OFF);
251 }
252
253 // matikan semua segment
254 for(byte d=0; d<sizeof(SEGMENT); d++){
255 digitalWrite(SEGMENT[d], SEGMENT_OFF);
256 }
257
167
258 // lanjut ke digit berikutnya
259 DIGIT_SELECT++;
260 // jika semua digit sudah ditampilkan, reset ke 0
261 if( DIGIT_SELECT >= len_data) DIGIT_SELECT = 0;
262
263 brightness_last = brightness_now;
264 }
265 }
266
267
268 // tambahan untuk membuat delay non blocking
269 unsigned long nonblocking_time = millis();
270 unsigned long nonblocking_last = millis();
271 boolean nonblocking_delay(long milidetik){
272 nonblocking_time = millis();
273 if(nonblocking_time - nonblocking_last >= milidetik){
274 nonblocking_last = nonblocking_time;
275 return true;
276 }
277 return false;
278 }
169
12.3 Seven Segment dengan Library SevSeg
Libray SevSeg adalah library untuk mempermudah
penggunaan seven segment, terserah kita mau punya
berapa digit. Library ini dibuat oleh Dean Reading. Link
downloadnya tidak penulis sertakan di sini karena info
pembuatnya sudah penulis informasikan. Silakan googling!
170
27 // konfigurasi sevseg
28 SevSegment.begin(HW_Config, sizeof(Digit), Digit, Segments,
29 R_Segments);
30
31 }
32
33 void loop() {
34
35 // counter data setiap 200ms
36 if( nonblocking_delay(200) ){
37 counter++;
38 if(counter > 200) counter = -50;
39 // ganti angka yang akan ditampilkan
40 SevSegment.setNumber(counter);
41 }
42
43 // refresh tampilan angka
44 SevSegment.refreshDisplay();
45
46 }
47
48 // tambahan untuk membuat delay non blocking
49 unsigned long nonblocking_time = millis();
50 unsigned long nonblocking_last = millis();
51 boolean nonblocking_delay(long milidetik){
52 nonblocking_time = millis();
53 if(nonblocking_time - nonblocking_last >= milidetik){
54 nonblocking_last = nonblocking_time;
55 return true;
56 }
57 return false;
}
171
12.4 Seven Segment dengan Shift Register
Sebelumnya kita telah mengontrol seven segment
dengan kaki arduino langsung sehingga jumlah kaki arduino
yang tersisa semakin sedikit. Sebagaimana telah kita pelajari
sebelumnya, solusi untuk menghemat kaki Arduino adalah
dengan shift register. Mari kita gunakan shift register untuk
mengatur tampilan seven segment!
1. Arduino x 1
2. IC Shift Register 74HC595 x 1
3. Display 7 Segment 1 Digit CC x 1
4. Project board x 1
5. Resistor 1k x 1
6. Kabel jumper secukupnya
172
Gambar 12.8 Rangkain seven segment dengan shift register
175
Jika sudah paham, mari lanjut dengan 2 digit seven
segment.
1. Arduino x 1
2. IC Shift Register 74HC595 x 2
3. Display Seven Segment 1 Digit x 2
4. Resistor 1k x 2
5. Kabel jumper secukupnya
176
Gambar 12.9 Rangkain seven segment 2 digit dengan shift register
179
90 unsigned long nonblocking_time = millis();
91 unsigned long nonblocking_last = millis();
92 boolean nonblocking_delay(long milidetik){
93 nonblocking_time = millis();
94 if(nonblocking_time - nonblocking_last >= milidetik){
95 nonblocking_last = nonblocking_time;
96 return true;
97 }
98 return false;
99 }
1. Arduino x 1
2. IC Shift Register 74HC595 x 1
180
3. Display Seven Segment 4 Digit CC x 1
4. Resistor dengan nilai seragam x 4
5. Project board
6. Kabel jumper secukupnya
183
84 counter++;
85 if( counter >= 10000 ) counter = 0;
86
87 }
88
89 // cetak angka
90 PrintDigit(counter, jumlah_digit);
91 }
92
93 // fungsi untuk mencetak angka
94 // INPUT : angka dan jumlah_digit
95 void PrintDigit(int angka, byte jumlah_digit){
96
97 // delay nyala segment, efeknya pada brigthness
98 brightness_limit = constrain(BRIGHTNESS,1,100);
99 brightness_limit = map(brightness_limit,1,100,1,5000);
100
101 // konversi angka jadi string
102 String numstr = String(angka);
103 byte lenstr = numstr.length();
104
105 // mulai transfer
106 digitalWrite(LatchPin, LOW);
107 brightness_now = micros();
108 if(brightness_now - brightness_last < brightness_limit){
109
110 // nyalakan digit yang terpilih
111 digitalWrite(DIGIT[DIGIT_SELECT],LOW);
112
113 if( DIGIT_SELECT < lenstr ){
114 // jika digit yang terpilih < jumlah angka
115 // cetak angka pada digit tersebut
116 byte angka = ( numstr.substring( DIGIT_SELECT, DIGIT_SELECT +
1)).toInt();
117 shiftOut(DataPin, ClockPin, LSBFIRST, Angka[ angka ]);
118 } else {
119 // jika tidak, matikan semua segment
120 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
121 }
122
123 }else{
124
125 // matikan semua digit
126 for(byte d=0; d<sizeof(DIGIT); d++){
184
127 digitalWrite(DIGIT[d], HIGH);
128 }
129
130 // matikan semua segment
131 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
132
133 DIGIT_SELECT++;
134 if( DIGIT_SELECT >= lenstr) DIGIT_SELECT = 0;
135
136 brightness_last = brightness_now;
137 }
138
139 // stop transfer
140 digitalWrite(LatchPin, HIGH);
141 }
142
143 // tambahan untuk membuat delay non blocking
144 unsigned long nonblocking_time = millis();
145 unsigned long nonblocking_last = millis();
146 boolean nonblocking_delay(long milidetik){
147 nonblocking_time = millis();
148 if(nonblocking_time - nonblocking_last >= milidetik){
149 nonblocking_last = nonblocking_time;
150 return true;
151 }
152 return false;
153 }
185
Perbedaan tersebut tampak pada pemanggilan fungsi
PrintDigit(). Perhatikan pada Program seven segment 2
Digit dengan Shift register dan program seven segment 4
digit dengan shift register.
186
Bagian #13
187
modul ini, kita hanya butuh 2 pin untuk menampilkan data
di LCD. Lebih hemat kan? :D
Gambar 13.2 Modul belum dipasang pada LCD dan belum disolder
188
Two-Write Serial Interface (TWI). Pada Arduino Uno
dan Nano, SDA dan SCA ada pada pin A4 dan A5.
3. Jumper Backlight (lihat no. 1), Jika jumper dilepas,
maka lampu backlight LCD tidak bisa dinyala-
hidupkan dengan program.
4. Pengatur Kontras LCD, (lihat no. 2), Jika tampilan
tulisannya kurang jelas atau malah berbentuk kotak,
silakan putar-putar VR ini.
1. Arduino x 1
2. Modul LCD yang sudah terpasang modul I2C x 1
3. Kabel jumper secukupnya
189
Sambungan pin Arduino dan LCD 1602 adalah :
194
24 // status backlight lcd
25 boolean status_backlight = BACKLIGHT_ON;
26
27 void setup() {
28
29 // Settingan LCD
30 lcd.begin(LCD_COL,LCD_ROW);
31
32 // Nyalakan Backlight
33 lcd.setBacklight(BACKLIGHT_ON);
34
35 // letakkan kursor pada baris 0 kolom 0
36 // lalu kirim tulisan ELANGSAKTI.COM (14 karakter)
37 lcd.setCursor(0,0);
38 lcd.print("ELANGSAKTI.COM");
39
40 // arahkan kursor pada baris 1 kolom 0
41 // lalu kirim tulisan BACKLIGHT: (10 karakter)
42 lcd.setCursor(0,1);
43 lcd.print("BACKLIGHT:");
44 }
45
46 void loop() {
47
48 if( nonblocking_delay(2000) ) {
49
50 // balik logika
51 status_backlight = !status_backlight;
52
53 // letakkan kursor pada baris 1 kolom 10
54 // (setelah tulisan BACKLIGHT:)
55 lcd.setCursor(10,1);
56
57 // jika status ON, tulis ON, nyalakan backlight
58 // jika status OFF, tulis OFF, matikan backlight
59 if( status_backlight == BACKLIGHT_ON ){
60
61 // spasi " " setelah tulisan "ON "
62 // berguna untuk menutupi
63 // huruf "F" paling akhir pada tulisan "OFF"
64 lcd.print("ON ");
65 lcd.setBacklight(BACKLIGHT_ON);
66 } else {
195
67 lcd.print("OFF");
68 lcd.setBacklight(BACKLIGHT_OFF);
69 }
70 }
71 }
72
73 // tambahan untuk membuat delay non blocking
74 unsigned long nonblocking_time = millis();
75 unsigned long nonblocking_last = millis();
76 boolean nonblocking_delay(long milidetik){
77 nonblocking_time = millis();
78 if(nonblocking_time - nonblocking_last >= milidetik){
79 nonblocking_last = nonblocking_time;
80 return true;
81 }
82 return false;
83 }
196
4. Perlu diperhatikan, angka 2, 1, 0, 4, 5, 6, 7, dan 3
bukanlah kaki pin Arduino, tapi pin di IC modul I2C.
5. Selanjutnya, bisa Anda pelajari di masing-masing
baris code di atas.
199
4. hapus, jika bernilai true, maka tampilan LCD akan
dibersihkan (clear) sebelum menulis teks.
200
26
27 void setup() {
28
29 // Settingan LCD
30 lcd.begin(LCD_COL,LCD_ROW);
31
32 // Nyalakan Backlight
33 lcd.setBacklight(BACKLIGHT_ON);
34
35 }
36
37 void loop() {
38
39 // string steks, kolom 0, baris 0, waktu on 500 (ms), waktu off 500 (ms)
40 BlinkDisplay("ELANGSAKTI.COM",0,0,500,500);
41
42 }
43
44 // fungsi untuk menampilkan teks blink di lcd
45 // input : teks, baris, kolom, waktu on, waktu off
46 void BlinkDisplay(String data, byte baris, byte kolom, unsigned long on_time,
unsigned long off_time){
47
48 byte len = data.length();
49
50 if( blink_state == true ){
51
52 if( millis() - blink_timer < on_time ) return;
53
54 data = "";
55 for(byte i=0; i<len; i++) data.concat(" ");
56
57 } else {
58
59 if( millis() - blink_timer < off_time ) return;
60
61 }
62
63 blink_timer = millis();
64 blink_state = !blink_state;
65
66 lcd.setCursor(kolom,baris);
67 lcd.print(data);
201
68
69 }
70
71 // tambahan untuk membuat delay non blocking
72 unsigned long nonblocking_time = millis();
73 unsigned long nonblocking_last = millis();
74 boolean nonblocking_delay(long milidetik){
75 nonblocking_time = millis();
76 if(nonblocking_time - nonblocking_last >= milidetik){
77 nonblocking_last = nonblocking_time;
78 return true;
79 }
80 return false;
81 }
202
10 #define BACKLIGHT_ON HIGH
11 #define BACKLIGHT_OFF !BACKLIGHT_ON
12
13 // jumlah kolom dan baris LCD (16x2)
14 #define LCD_COL 16
15 #define LCD_ROW 2
16
17 #define ALIGN_LEFT 1 // teks rata kiri
18 #define ALIGN_CENTER 2 // teks center
19 #define ALIGN_RIGHT 3 // teks rata kanan
20 #define CLEAR true // clear screen
21
22 // ===== Konfigurasi LCD ===========
23
24 // LCD1602 dengan Modul I2C
25 // Alamat I2C di 0x27
26 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
27 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
28
29 // pilihat format penulisan teks
30 byte tipe_format[] = {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
31 byte format = ALIGN_LEFT;
32
33 boolean blink_state = true;
34 unsigned long blink_timer = 0;
35
36 void setup() {
37
38 // Settingan LCD
39 lcd.begin(LCD_COL,LCD_ROW);
40
41 // Nyalakan Backlight
42 lcd.setBacklight(BACKLIGHT_ON);
43
44 }
45
46 void loop() {
47
48 SetDisplay( BlinkDisplay("ELANGSAKTI.COM",500,1000) , 0, ALIGN_CENTER,
!CLEAR);
49
50 }
51
203
52
53 // fungsi untuk menampilkan teks blink di lcd
54 // input : teks, baris, kolom, waktu on, waktu off
55 String BlinkDisplay(String data, unsigned long on_time, unsigned long
off_time){
56
57 byte len = data.length();
58
59 if( blink_state == true ){
60
61 data = "";
62 for(byte i=0; i<len; i++) data.concat(" ");
63
64 if( millis() - blink_timer < on_time ) return data;
65
66 } else {
67
68 if( millis() - blink_timer < off_time ) return data;
69
70 }
71
72 blink_timer = millis();
73 blink_state = !blink_state;
74
75 }
76
77 // fungsi untuk menampilkan teks pada lcd sesuai format
78 void SetDisplay(String data, byte baris, byte format, boolean hapus){
79 if(hapus) lcd.clear();
80 int cols = data.length();
81 if( cols > LCD_COL) format = ALIGN_LEFT;
82 if(format == ALIGN_CENTER){
83 if(cols%2 == 1) cols++;
84 cols = (LCD_COL/2) - (cols/2);
85 }else if(format == ALIGN_RIGHT){
86 cols = LCD_COL - cols;
87 }else{
88 cols = 0;
89 }
90 lcd.setCursor(cols,baris);
91 lcd.print(data);
92 }
93
94 // tambahan untuk membuat delay non blocking
204
95 unsigned long nonblocking_time = millis();
96 unsigned long nonblocking_last = millis();
97 boolean nonblocking_delay(long milidetik){
98 nonblocking_time = millis();
99 if(nonblocking_time - nonblocking_last >= milidetik){
100 nonblocking_last = nonblocking_time;
101 return true;
102 }
103 return false;
104 }
105
207
96
97 lcd.setCursor(0,baris);
98 real_cols = data.length();
99 if( posisi_kolom < 0 ){
100 data = data.substring( abs(posisi_kolom) );
101 }
102 cols = data.length();
103 for(byte i=0; i<LCD_COL; i++){
104 if( posisi_kolom < 0 ){
105 if( i == 0 ){
106 lcd.print(data);
107 i = cols;
108 }else{
109 lcd.print(' ');
110 }
111 } else {
112 if( i == posisi_kolom ){
113 lcd.print(data);
114 i += cols-1;
115 } else {
116 lcd.print(' ');
117 }
118 }
119 }
120
121 posisi_kolom--;
122 if( (real_cols + posisi_kolom) == 0) posisi_kolom = LCD_COL-1;
123
124 break;
125
126 case MOVE_RIGHT:
127
128 lcd.setCursor(0,baris);
129 for(byte i=0; i<LCD_COL; i++) lcd.print(' ');
130
131 lcd.setCursor(0,baris);
132 real_cols = data.length();
133 if( posisi_kolom < 0 ){
134 data = data.substring( abs(posisi_kolom) );
135 }
136 cols = data.length();
137 for(byte i=0; i<LCD_COL; i++){
138 if( posisi_kolom < 0 ){
139 if( i == 0 ){
208
140 lcd.print(data);
141 i = cols;
142 }else{
143 lcd.print(' ');
144 }
145 } else {
146 if( i == posisi_kolom ){
147 lcd.print(data);
148 i += cols;
149 } else {
150 lcd.print(' ');
151 }
152 }
153 }
154
155 posisi_kolom++;
156 if( posisi_kolom > LCD_COL ) posisi_kolom = -real_cols+1;
157
158 break;
159 }
160 moving_timer = millis();
161 }
162
163
164 // fungsi untuk menampilkan teks pada lcd sesuai format
165 void SetDisplay(String data, byte baris, byte format, boolean hapus){
166 if(hapus) lcd.clear();
167 int cols = data.length();
168 if( cols > LCD_COL) format = ALIGN_LEFT;
169 if(format == ALIGN_CENTER){
170 if(cols%2 == 1) cols++;
171 cols = (LCD_COL/2) - (cols/2);
172 }else if(format == ALIGN_RIGHT){
173 cols = LCD_COL - cols;
174 }else{
175 cols = 0;
176 }
177 lcd.setCursor(cols,baris);
178 lcd.print(data);
179 }
180
181 // tambahan untuk membuat delay non blocking
182 unsigned long nonblocking_time = millis();
209
183 unsigned long nonblocking_last = millis();
184 boolean nonblocking_delay(long milidetik){
185 nonblocking_time = millis();
186 if(nonblocking_time - nonblocking_last >= milidetik){
187 nonblocking_last = nonblocking_time;
188 return true;
189 }
190 return false;
191 }
210
15 #define LCD_ROW 2
16
17 // ===== Konfigurasi LCD ===========
18
19 // LCD1602 dengan Modul I2C
20 // Alamat I2C di 0x27
21 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
22 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
23
24 byte mangap_arr[] = {
25 B00000,
26 B01110,
27 B01011,
28 B11111,
29 B00011,
30 B10011,
31 B01110,
32 B00000
33 };
34
35 byte mingkem_arr[] = {
36 B00000,
37 B01110,
38 B01011,
39 B11111,
40 B11111,
41 B01111,
42 B00000,
43 B00000
44 };
45
46 byte counter = 0;
47 byte char_mangap = 0;
48 byte char_mingkem = 0;
49 boolean char_state = 0;
50 int posisi_kolom = LCD_COL;
51
52 void setup() {
53
54 // Settingan LCD
55 lcd.begin(LCD_COL,LCD_ROW);
56
57 // Nyalakan Backlight
211
58 lcd.setBacklight(BACKLIGHT_ON);
59
60 lcd.createChar(0, mingkem_arr);
61 lcd.createChar(1, mangap_arr);
62 }
63
64 void loop() {
65
66 if( nonblocking_delay(200) ){
67
68 char_state = !char_state;
69 lcd.clear();
70 lcd.setCursor(posisi_kolom,0);
71
72 if( char_state == true ){
73 lcd.write( byte(0) );
74 } else {
75 lcd.write( byte(1) );
76 }
77
78 counter++;
79 if( counter == 3 ){
80 posisi_kolom--;
81 if( posisi_kolom < 0 ){
82 posisi_kolom = LCD_COL;
83 }
84 counter = 0;
85 }
86 }
87 }
88
89 // tambahan untuk membuat delay non blocking
90 unsigned long nonblocking_time = millis();
91 unsigned long nonblocking_last = millis();
92 boolean nonblocking_delay(long milidetik){
93 nonblocking_time = millis();
94 if(nonblocking_time - nonblocking_last >= milidetik){
95 nonblocking_last = nonblocking_time;
96 return true;
97 }
98 return false;
99 }
212
Bagian penting membuat karakter sendiri adalah :
213
Bagian #14
Saya tidak pernah takut pada orang yang menguasai 10.000 jurus
tapi saya takut pada orang yang menguasai 1 jurus
tapi melatihnya 10.000 kali. (Bruce Lee)
___
214
Pada sensor PIR terdapat filter frekuensi yang
dicocokkan dengan karakteristik pancaran sinar inframerah
dari tubuh manusia, yaitu 9 – 10 mikrometer. Filter pada
sensor PIR didesain untuk mendeteksi sinar inframerah
dengan panjang gelombang 8 – 14 mikrometer. Jika ada
benda, hewan, atau makhluk yang memancarkan sinar
inframerah dalam rentang tersebut, maka sensor PIR aktif.
215
3. Sinar infrared yang difokuskan oleh lensa Fresnel
akan menimpa sensor Pyroelectric. Sensor ini mirip
dengan solar cell. Jika terkena sinar infrared, partikel
pada sensor bereaksi dan menghasilkan arus listrik.
4. Arus yang dihasilkan Pyroelectric masih lemah,
sehingga diperkuat dengan Amplifier.
5. Output dari Amplifier akan dicocokkan polanya
dengan Komparator. Pencocokan pola ini
dissesuaikan dengan karakteristik sinar infrared yang
dipancarkan oleh tubuh manusia sesuai gelombang
yang telah disebutkan sebelumnya.
216
Gambar 14.3 Sensor HC-SR501 tampak belakang
Penting!!!
Kelemahan sensor HC-SR501 adalah ada jeda sekitar
5 detik sebelum sensor bisa mendeteksi gerakan
berikutnya.
218
14.2 Rangkaian Sensor HC-SR501
1. Arduino x 1
2. Sensor PIR x 1
3. Buzzer x 1
4. Project board x 1
5. Kabel jumper secukupnya
220
Setelah program diupload, buzzer akan berbunyi ketika
sensor mendeteksi gerakan. Buzzer akan diam setelah time
delay habis. Silakan bermain-main dengan kombinasi
pengaturan time delay dan sensitifitas untuk memperoleh
respon yang diinginkan.
221
29 }
30
31 void loop() {
32
33 // baca sensor pir
34 logika_pir = digitalRead(PIN_PIR);
35
36 // kondisikan buzzer sesuai logika sensor pir
37 digitalWrite(PIN_BUZZER,logika_pir);
38
39 // jika output sensor berubah
40 // dari HIGH ke LOW, atau dari LOW ke HIGH
41 if( logika_pir_last != logika_pir){
42
43 if ( logika_pir == HIGH ){
44
45 // sensor baru saja aktif
46 Serial.println("Sensor ON");
47 timer_pir = millis();
48
49 } else {
50
51 // sensor baru saja tidak aktif
52 Serial.println("Sensor OFF");
53 Serial.print("Delay : ");
54 Serial.print( millis() - timer_pir);
55 Serial.print(" ms");
56 Serial.println();
57 }
58 }
59
60 // catat kondisi sensor sebelumnya
61 logika_pir_last = logika_pir;
62
63 }
222
Untuk hasil yang lebih valid tentang delay minimal dan
maksimal sensor PIR yang kita punya, maka kita harus
mengubah mode Trigger menjadi No Repeat Trigger.
Caranya, ubah jumper pada no. 5 ke posisi L. Jika ingin
mengetahui delay tercepat pada sensor PIR, lakukan
langkah-langkah berikut:
223
Gambar 14.5 Output program identifikasi delay sensor PIR
225
24 // delay bunyi buzzer yang diinginkan dalam ms
25 unsigned long DELAY_BUZZER = 5000;
26 // variabel untuk mencatat waktu buzzer
27 unsigned long timer_buzzer = 0;
28
29 void setup() {
30
31 // aktifkan komunikasi serial di baud 19200
32 Serial.begin(19200);
33
34 // buzzer sebagai output
35 // sensor pir sebagai input
36 pinMode(PIN_BUZZER,OUTPUT);
37 pinMode(PIN_PIR,INPUT);
38
39 }
40
41 void loop() {
42
43 // baca sensor pir
44 logika_pir = digitalRead(PIN_PIR);
45
46 // jika output sensor berubah
47 // dari HIGH ke LOW, atau dari LOW ke HIGH
48 if( logika_pir_last != logika_pir){
49
50 if ( logika_pir == HIGH ){
51
52 // sensor baru saja aktif
53 Serial.println("Buzzer ON");
54 timer_pir = millis();
55 timer_buzzer = millis();
56
57 buzzer_aktif = true;
58
59 }
60 }
61
62 // jika buzzer aktif, periksa delay
63 if( buzzer_aktif ){
64
65 // buzzer nyala sesuai delay yang ditentukan
66 if( millis() - timer_buzzer >= DELAY_BUZZER){
67
226
68 // matikan buzzer
69 buzzer_aktif = false;
70
71 Serial.println("Buzzer OFF");
72 Serial.print("Delay : ");
73 Serial.print( millis() - timer_pir);
74 Serial.print(" ms");
75 Serial.println();
76
77 }
78 }
79
80 // aktifkan buzzer sesuai logika buzzer_aktif
81 digitalWrite(PIN_BUZZER, buzzer_aktif);
82
83 // catat kondisi sensor sebelumnya
84 logika_pir_last = logika_pir;
85
86 }
227
Bagian #15
___
229
15.2 Akuisi Data Sensor DHT11
1. Arduino x 1
2. Sensor DHT11 x 1
3. Resistor 10k x 1
230
4. Project board x 1
5. Kabel Jumper secukupnya
233
Selanjutnya, data suhu dan kelembaban akan kita
tampilkan pada display LCD 1602. Jika Anda sudah
memahami program-program sebelumnya, mungkin Anda
sudah terbiasa menampilkan data pada LCD.
1. Arduino x 1
2. Sensor DHT11 x 1
3. LCD1602 dengan Modul I2C LCD x 1
4. Project board x 1
5. Kabel jumper secukupnya
234
Gambar 15.4 Rangkaian untuk menampilkan data sensor di LCD1602
237
106 unsigned long nonblocking_last = millis();
boolean nonblocking_delay(long milidetik){
nonblocking_time = millis();
if(nonblocking_time - nonblocking_last >= milidetik){
nonblocking_last = nonblocking_time;
return true;
}
return false;
}
238
6. Selama pompa aktif, alarm atau buzzer akan berbunyi
dengan nada putus-putus.
1. Arduino x 1
2. Sensor DHT11 x 1
3. Modul relay 2 channel atau 1 channel x 1
4. Buzzer aktif x 1
5. LCD1602 dengan modul I2C x1
6. Jumper secukupnya
239
Gambar 15.5 Rangkain project kumbung jamur sederhana
240
17 #define BUZZER_ON HIGH
18 #define BUZZER_OFF !BUZZER_ON
19 #define RUNNING true
20 #define NOT_RUNNING !RUNNING
21 #define YES true
22 #define NO !YES
23 #define BACKLIGH_ON HIGH
24 #define BACKLIGH_OFF !BACKLIGH_ON
25
26
27 // pin output DHT11, buzzer, dan relay
28 const byte PIN_DHT = 2;
29 const byte PIN_BUZZER = 3;
30 const byte PIN_RELAY = 4;
31
32
33 // ===== Sensor DHT11 ===========
34
35 // buat instan dari class DHT
36 dht DHT;
37
38 // variabel untuk sensor suhu dan kelembaban
39 int suhu = 0;
40 int kelembaban = 0;
41
42
43 // ===== Konfigurasi LCD ===========
44
45 // LCD1602 dengan Modul I2C
46 // Alamat I2C di 0x27
47 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7);
48
49 // jumlah kolom dan baris LCD (16x2)
50 const byte LCD_COL = 16;
51 const byte LCD_ROW = 2;
52
53
54 // Setpoint Suhu dan Kelembaban
55 // jika suhu >= 28 atau kelembaban <= 70
56 // aktifkan pompa
57 const int MAX_SUHU = 28;
58 const int MIN_KELEMBABAN = 70;
59
241
60 // status logika relay dan buzzer
61 boolean status_relay = BUZZER_OFF;
62 boolean status_buzzer = RELAY_OFF;
63
64 // status pompa
65 boolean pompa_running = NOT_RUNNING;
66 boolean pompa_running_last = pompa_running;
67
68 boolean wait_after_pompa_running = NO;
69
70
71 // delay pompa on dan waktu tunggu setelah off dalam ms
72 unsigned long pompa_running_time = 5 * 60000L;
73 unsigned long pompa_wait_time = 10 * 60000L;
74
75 // pencatat timer lama pompa on dan setelah off
76 unsigned long pompa_running_start = 0;
77 unsigned long pompa_running_stop = 0;
78
79 // delay buzzer on dan off
80 unsigned int buzzer_on_delay = 300;
81 unsigned int buzzer_off_delay = 2000;
82 unsigned long buzzer_timer = 0;
83
84 boolean sensor_ready = NO;
85
86
87 void setup() {
88
89 // jika DEBUG = true
90 // Aktifkan komunikasi serial di baud 19200
91 if( DEBUG ) Serial.begin(19200);
92
93 // buzzer dan relay sebagai output
94 pinMode(PIN_BUZZER,OUTPUT);
95 pinMode(PIN_RELAY,OUTPUT);
96
97 // matikan buzzer dan relay saat pertama start
98 digitalWrite(PIN_BUZZER,BUZZER_OFF);
99 digitalWrite(PIN_RELAY,RELAY_OFF);
100
101 // Settingan LCD
102 lcd.begin(LCD_COL,LCD_ROW);
103 // backlight active high
242
104 lcd.setBacklightPin(3, POSITIVE);
105 // Nyalakan Backlight
106 lcd.setBacklight(BACKLIGH_ON);
107
108 }
109
110 void loop() {
111
112 // jika sensor normal
113 if( DHT.read11(PIN_DHT) == DHTLIB_OK ){
114
115 // ambil data suhu dan kelembaban
116 // setiap delay 1000 ms (1 detik)
117 if( nonblocking_delay(1000) ){
118
119 // akses data suhu dan kelembaban
120 suhu = DHT.temperature;
121 kelembaban = DHT.humidity;
122
123 // hapus tulisan di LCD
124 lcd.clear();
125
126 // pindah kursor ke baris 0, kolom 0
127 // tulis suhu
128 lcd.setCursor(0,0);
129 lcd.print("Suhu: ");
130 lcd.print(suhu);
131
132 // pindah kursor ke baris 1, kolom 0
133 // tulis kelembaban
134 lcd.setCursor(0,1);
135 lcd.print("Kelembaban: ");
136 lcd.print(kelembaban);
137
138 // jika DEBUG = true
139 if ( DEBUG ) {
140 // cetak di serial terminal
141 Serial.print("Suhu:");
142 Serial.print(suhu);
143 Serial.print(" Kelembaban:");
144 Serial.print(kelembaban);
145 Serial.println();
146 }
243
147
148 sensor_ready = YES;
149 }
150 }
151
152 // jika sensor belum stabil
153 // abaikan pengecekan suhu dan kelembaban
154 if( sensor_ready == NO ) return;
155
156 // jika pompa sedang tidak running
157 if ( pompa_running == NO ){
158
159 // buzzer dan relay di-off kan
160 status_buzzer = BUZZER_OFF;
161 status_relay = RELAY_OFF;
162
163 // jika pompa dalam status menunggu setelah running
164 if ( wait_after_pompa_running == YES ) {
165
166 // jika waktu tunggu setelah running selesai
167 if ( millis() - pompa_running_stop >= pompa_wait_time ){
168 wait_after_pompa_running = false;
169 }
170
171 // matikan lcd selama waktu tunggu
172 lcd.setBacklight(BACKLIGH_OFF);
173
174 } else {
175
176 // jika sudah tidak dalam waktu tunggu
177
178 // periksa apakah suhu dan kelembaban di bawah batas maksimal
179 if( suhu >= MAX_SUHU || kelembaban <= MIN_KELEMBABAN ){
180
181 // jika diatas/sama dengan batas maksimal
182 // nyalakan pompa
183 pompa_running = YES;
184 pompa_running_start = millis();
185
186 }
187
188 // hidupkan lampu lcd
189 lcd.setBacklight(BACKLIGH_ON);
190
244
191 }
192
193 } else {
194
195 // pompa dalam kondisi running
196 // hidupkan buzzer
197 buzzer_sound();
198 // aktifkan relay
199 status_relay = RELAY_ON;
200
201 // cek lama waktu pompa running
202 if ( millis() - pompa_running_start >= pompa_running_time ){
203
204 // jika lama pompa running sudah sesuai
205 // matikan pompa, catat waktu, dan aktifkan waktu tunggu
206 pompa_running = NO;
207 pompa_running_stop = millis();
208 wait_after_pompa_running = YES;
209 }
210 }
211
212 // sesuaikan status relay dan buzzer
213 digitalWrite(PIN_RELAY, status_relay);
214 digitalWrite(PIN_BUZZER, status_buzzer);
215
216 }
217
218
219 // bunyi buzzer sesuai waktu
220 void buzzer_sound(){
221
222 if( status_buzzer == BUZZER_ON ){
223 if( millis() - buzzer_timer >= buzzer_on_delay ){
224 status_buzzer = BUZZER_OFF;
225 buzzer_timer = millis();
226 }
227 } else {
228 if( millis() - buzzer_timer >= buzzer_off_delay ){
229 status_buzzer = BUZZER_ON;
230 buzzer_timer = millis();
231 }
232 }
233
245
234 }
235
236 // tambahan untuk membuat delay non blocking
237 unsigned long nonblocking_time = millis();
238 unsigned long nonblocking_last = millis();
239 boolean nonblocking_delay(long milidetik){
240 nonblocking_time = millis();
241 if(nonblocking_time - nonblocking_last >= milidetik){
242 nonblocking_last = nonblocking_time;
243 return true;
244 }
245 return false;
246 }
246
Bagian #16
___
Gambar 16.1 RTC Tiny DS1307 tampak dari depan dan belakang
Seperti modul I2C LCD, data dari RTC DS1307 ini dapat
diakses dengan komunikasi I2C. Bagian-bagian modul yang
perlu minimal dipahami yaitu:
248
Sebagai informasi tambahan, jantung utama RTC adalah
komponen Crystal dan baterai. Crystal digunakan untuk
mencacah waktu dengan akurat. Detik, menit, jam, dan
tanggal yang disimpan dalam memori ditentukan
berdasarkan hasil cacahan ini.
1. Arduino x 1
2. TinyRTC D1307 x 1
3. Kabel jumper secukupnya
249
Gambar 16.2 Rangkaian dasar RTC DS1307 dan Arduino
251
68 // tampilkan menit
69 if( now.minute() < 10 ) Serial.print(0);
70 Serial.print(now.minute(), DEC);
71 Serial.print(':');
72 // tampilkan detik
73 if( now.second() < 10 ) Serial.print(0);
74 Serial.print(now.second(), DEC);
75 Serial.println();
76 }
77
78 // tambahan untuk membuat delay non blocking
79 unsigned long nonblocking_time = millis();
80 unsigned long nonblocking_last = millis();
81 boolean nonblocking_delay(long milidetik){
82 nonblocking_time = millis();
83 if(nonblocking_time - nonblocking_last >= milidetik){
84 nonblocking_last = nonblocking_time;
85 return true;
86 }
87 return false;
88 }
252
4. Untuk merapikan tampilan, apabila angka lebih kecil
dari angka 10, tampilkan angka 0 di depannya. Hal
ini sangat berguna ketika menggunakan display LCD.
1. Arduino x 1
2. TinyRTC DS1307 x 1
3. IC Shift Register 74HC595 x 1
4. Display Seven Segment 4 Digit CC x 1
5. Project board x 1
6. Kabel jumper secukupnya
253
Sambungan pin Arduino, TinyRTC, 74HC595, dan 7
segement yaitu :
254
16.3.2 Program Menampilkan Jam di Seven Segment
Program 16.2 Program Menampilkan Jam di Seven Segment
1 /*
2 * MONSTER ARDUINO V2
3 * Program Menampilkan Jam di Seven Segment
4 * www.ElangSakti.com
5 */
6
7 // include library Wire dan RTCLib
8 #include <Wire.h>
9 #include <RTClib.h>
10
11 // common cathode
12 #define OFF 0B00000000
13
14 // kecerahan led segmen
15 #define BRIGHTNESS 100
16
17 // konversi angka
18 // 8 bit data : A B C D E F G DP
19 const byte Angka[] = {
20 B11111100,
21 B01100000,
22 B11011010,
23 B11110010,
24 B01100110,
25 B10110110,
26 B10111110,
27 B11100000,
28 B11111110,
29 B11110110,
30 B00000010
31 };
32
33 // konfigurasi pin Arduino
34 const byte DataPin = 2; // data
35 const byte LatchPin = 3; // ST_CP
36 const byte ClockPin = 4; // SH_CP
37
38 // untuk mengontrol digit,
39 // kita masih pakai pin arduino
255
40 // untuk lebih menghemat, bisa tambah
41 // IC shift register lagi
42 const byte Digit1 = A0;
43 const byte Digit2 = A1;
44 const byte Digit3 = A2;
45 const byte Digit4 = A3;
46 const byte DIGIT[] = {Digit1, Digit2, Digit3, Digit4};
47
48 // jumlah digit seven segment
49 const byte jumlah_digit = sizeof(DIGIT);
50
51 // digit terpilih untuk diaktifkan
52 byte DIGIT_SELECT = 0;
53
54 // pengaturan untuk brightness
55 unsigned long brightness_now = 0;
56 unsigned long brightness_last = 0;
57 unsigned long brightness_limit = 0;
58
59 // onject untuk RTC
60 RTC_DS1307 RTC;
61
62 // teks jam
63 String teks_jam = "";
64
65 // titik dua ngeblink utk detik
66 boolean blink_detik = false;
67
68 void setup() {
69 // buka koneksi ke serial monitor
70 // untuk debug
71 Serial.begin(19200);
72 while(!Serial);
73
74 // buka koneksi ke RTC
75 Wire.begin();
76 RTC.begin();
77 delay(1000);
78
79 // jika RTC belum disetting & running
80 if (! RTC.isrunning()) {
81 // set waktu RTC sesuai waktu di komputer
82 RTC.adjust(DateTime(__DATE__, __TIME__));
83 Serial.println("RTC is NOT Running");
256
84 } else {
85 // RTC normal
86 Serial.println("RTC OK!");
87 }
88
89 // konfigurasi pin sebagai ouput
90 pinMode(LatchPin, OUTPUT);
91 pinMode(ClockPin, OUTPUT);
92 pinMode(DataPin, OUTPUT);
93
94 // pastikan bahwa display mati
95 for(byte i=0; i<sizeof(DIGIT); i++){
96 pinMode(DIGIT[i],OUTPUT);
97 digitalWrite(DIGIT[i],HIGH);
98 }
99
100 // pastikan semua segment mati
101 // mulai transfer
102 digitalWrite(LatchPin, LOW);
103 // kirim data
104 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
105 // stop transfer
106 digitalWrite(LatchPin, HIGH);
107 }
108
109 void loop() {
110
111 // update setiap detik
112 if( nonblocking_delay(1000) ){
113 // logika untuk blink titik 2
114 blink_detik = !blink_detik;
115 // konversi jam menjadi teks
116 teks_jam = JamMenit();
117 // cetak ke serial monitor
118 Serial.println(teks_jam);
119 }
120
121 // cetak jam di seven segment
122 PrintDigit(teks_jam, jumlah_digit);
123 }
124
125 // fungsi JamMenit
126 // mengambil data jam dan menit
257
127 // mengkonversinya jadi string
128 String JamMenit(){
129 DateTime now = RTC.now();
130 teks_jam = "";
131 if( now.hour() < 10 ) teks_jam.concat(0);
132 teks_jam.concat(now.hour());
133 if( now.minute() < 10 ) teks_jam.concat(0);
134 teks_jam.concat(now.minute());
135 return teks_jam;
136 }
137
138 // fungsi PrintDigit
139 // fungsi untuk mencetak banyak angka ke
140 // seven segment
141 void PrintDigit(String numstr, byte jumlah_digit){
142
143 // delay nyala segment, efeknya pada brigthness
144 brightness_limit = constrain(BRIGHTNESS,1,100);
145 brightness_limit = map(brightness_limit,1,100,1,5000);
146
147 // hitung lebar string
148 byte lenstr = numstr.length();
149 // mulai transfer
150 digitalWrite(LatchPin, LOW);
151
152 brightness_now = micros();
153 if(brightness_now - brightness_last < brightness_limit){
154
155 digitalWrite(DIGIT[DIGIT_SELECT],LOW);
156 if( DIGIT_SELECT < lenstr ){
157 // jika digit yang terpilih < jumlah angka
158 // cetak angka pada digit tersebut
159 byte angka = ( numstr.substring( DIGIT_SELECT, DIGIT_SELECT + 1 )
).toInt();
160
161 // ambil logika segment sesuai indeks angka
162 byte number = Angka[ angka ];
163
164 // jika waktunya ngeblink
165 if ( blink_detik == true ){
166 // jika digit yg terpilih adalah
167 // digit nomer 2 (digit yg ada titik duanya)
168 // maka tambahkan angkanya dengan 1,
169 // untuk mengubah logika DP menjadi 1
258
170 if(DIGIT_SELECT == 2) number += 1;
171 }
172 // cetak angka di digit
173 shiftOut(DataPin, ClockPin, LSBFIRST, number);
174 } else {
175 // matika digit
176 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
177 }
178
179 }else{
180
181 // matikan semua digit
182 for(byte d=0; d<sizeof(DIGIT); d++){
183 digitalWrite(DIGIT[d], HIGH);
184 }
185
186 // matikan semua segment
187 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
188
189 DIGIT_SELECT++;
190 if( DIGIT_SELECT >= lenstr) DIGIT_SELECT = 0;
191
192 brightness_last = brightness_now;
193 }
194
195 // stop transfer
196 digitalWrite(LatchPin, HIGH);
197 }
198
199 // tambahan untuk membuat delay non blocking
200 unsigned long nonblocking_time = millis();
201 unsigned long nonblocking_last = millis();
202 boolean nonblocking_delay(long milidetik){
203 nonblocking_time = millis();
204 if(nonblocking_time - nonblocking_last >= milidetik){
205 nonblocking_last = nonblocking_time;
206 return true;
207 }
208 return false;
209 }
259
1. Mengambil informasi jam dan menit di RTC (lihat
baris 116), lalu mengonversinya menjadi String.
Contoh, misal jam 3 sore lewat 2 menit, maka hasil
konversi ke stringnya adalah “1502”. Proses ini
dilakukan oleh fungsi JamMenit pada baris 128.
2. Untuk menampilkan titik dua yang berkedip yaitu
dengan memanfaatkan perubahan logika blink_detik
yang setiap detik statusnya bergantian dari true ke
false (lihat baris 114).
3. Pada seven segment 4 digit, titik 2 (DP) ada di digit
nomer 2 dari kiri atau indeks nomer 2 dari kanan.
4. Ketika kondisi blink_detik = true (lihat baris 165),
maka harus dicek, posisi scan digit saat ini ada di
digit yang mana.
5. Jika posisi digit ada di nomer 2 (lihat baris 170),
maka hidupkan segment DP.
6. Kalau diperhatikan bit-bit segment pada baris 20 –
30, bit DP ada di bit yang paling kanan. Logika
bitnya semuanya 0. Berdasarkan konsep konversi
bilangan dari desimal ke biner, bit yang paling kanan
adalah LSB, nilainya adalah 1. Oleh sebab itu untuk
mengaktifkan logika DP, angka yang akan dikirim ke
shift register harus ditambahkan dengan 1 (lihat
baris 170).
7. Untuk melihat nilai angka pada masing-masing bit,
Anda bisa tengok kembali Gambar 11.5.
260
16.4 Menampilkan Waktu di LCD
1. Arduino x 1
2. TinyRTC DS1307 x 1
3. LCD1602 dengan Modul I2C x 1
4. Project board x 1
5. Kabel jumper secukupnya
261
Perhatikan rangkan kaki SDA dan SCL pada modul I2C
LCD dan modul RTC. Kedua modul tersebut dihubungkan
secara paralel. Rangkaian paralel ini telah kita bahas pada
Gambar 13.4.
263
75 // rata tengah
76 SetDisplay(Tanggal(), 0, ALIGN_CENTER, CLEAR);
77 // tanpa clear, langsung cetak jam di baris 2
78 SetDisplay(Jam(), 1, ALIGN_CENTER, !CLEAR);
79 }
80 }
81
82 // fung Jam, mengonversi jam ke string
83 String Jam(){
84 DateTime now = RTC.now();
85 teks_jam = "";
86 if( now.hour() < 10 ) teks_jam.concat(0);
87 teks_jam.concat(now.hour());
88 teks_jam.concat(":");
89 if( now.minute() < 10 ) teks_jam.concat(0);
90 teks_jam.concat(now.minute());
91 teks_jam.concat(":");
92 if( now.second() < 10 ) teks_jam.concat(0);
93 teks_jam.concat(now.second());
94 return teks_jam;
95 }
96
97 // fungsi tanggal
98 // mengonversi tanggal ke String
99 String Tanggal(){
100 DateTime now = RTC.now();
101 String teks_tanggal = "";
102 if( now.day() < 10 ) teks_tanggal.concat(0);
103 teks_tanggal.concat(now.day());
104 teks_tanggal.concat("/");
105 if( now.month() < 10 ) teks_tanggal.concat(0);
106 teks_tanggal.concat(now.month());
107 teks_tanggal.concat("/");
108 if( now.year() < 10 ) teks_tanggal.concat(0);
109 teks_tanggal.concat(now.year());
110 return teks_tanggal;
111 }
112
113 // fungsi untuk menampilkan teks pada lcd sesuai format
114 void SetDisplay(String data, byte baris, byte format, boolean hapus){
115 if(hapus) lcd.clear();
116 int cols = data.length();
117 if( cols > LCD_COL) format = ALIGN_LEFT;
118 if(format == ALIGN_CENTER){
264
119 if(cols%2 == 1) cols++;
120 cols = (LCD_COL/2) - (cols/2);
121 }else if(format == ALIGN_RIGHT){
122 cols = LCD_COL - cols;
123 }else{
124 cols = 0;
125 }
126 lcd.setCursor(cols,baris);
127 lcd.print(data);
128 }
129
130 // tambahan untuk membuat delay non blocking
131 unsigned long nonblocking_time = millis();
132 unsigned long nonblocking_last = millis();
133 boolean nonblocking_delay(long milidetik){
134 nonblocking_time = millis();
135 if(nonblocking_time - nonblocking_last >= milidetik){
136 nonblocking_last = nonblocking_time;
137 return true;
138 }
139 return false;
140 }
267
84 Wire.begin();
85 RTC.begin();
86 delay(1000);
87
88 // jika RTC belum disetting & running
89 if (! RTC.isrunning()) {
90 // set waktu RTC sesuai waktu di komputer
91 RTC.adjust(DateTime(__DATE__, __TIME__));
92 Serial.println("RTC is NOT Running");
93 } else {
94 // RTC normal
95 Serial.println("RTC OK!");
96 }
97
98 // Settingan LCD
99 lcd.begin(LCD_COL,LCD_ROW);
100
101 // Nyalakan Backlight
102 lcd.setBacklight(BACKLIGHT_ON);
103
104 }
105
106 void loop() {
107 // catat waktu
108 WAKTU = RTC.now();
109
110 // jika detik berubah
111 if( WAKTU.second() != DETIK ){
112 // tampilkan tanggal berdsarkan waktu saat ini
113 SetDisplay(Tanggal(WAKTU), 0, ALIGN_CENTER, !CLEAR);
114 // tampilkan jam berdasarkan waktu saat ini
115 SetDisplay(Jam(WAKTU), 1, ALIGN_CENTER, !CLEAR);
116 // catat detik terakhir
117 DETIK = WAKTU.second();
118 }
119 }
120
121 // fung Jam, mengonversi jam ke string
122 String Jam(DateTime waktu){
123 teks_jam = "";
124 if( waktu.hour() < 10 ) teks_jam.concat(0);
125 teks_jam.concat(waktu.hour());
126 teks_jam.concat(":");
127 if( waktu.minute() < 10 ) teks_jam.concat(0);
268
128 teks_jam.concat(waktu.minute());
129 teks_jam.concat(":");
130 if( waktu.second() < 10 ) teks_jam.concat(0);
131 teks_jam.concat(waktu.second());
132 return teks_jam;
133 }
134
135 // fungsi tanggal
136 // mengonversi tanggal ke String
137 // termasuk nama hari dan bulan
138 String Tanggal(DateTime waktu){
139 String teks_tanggal = "";
140 teks_tanggal.concat( NAMA_HARI[waktu.dayOfTheWeek()] );
141 teks_tanggal.concat(", ");
142 if( waktu.day() < 10 ) teks_tanggal.concat(0);
143 teks_tanggal.concat(waktu.day());
144 teks_tanggal.concat(" ");
145 teks_tanggal.concat( NAMA_BULAN[waktu.month()] );
146 teks_tanggal.concat(" ");
147 if( waktu.year() < 10 ) teks_tanggal.concat(0);
148 teks_tanggal.concat(waktu.year());
149 return teks_tanggal;
150 }
151
152 // fungsi untuk menampilkan teks pada lcd sesuai format
153 void SetDisplay(String data, byte baris, byte format, boolean hapus){
154 if(hapus) lcd.clear();
155 int cols = data.length();
156 if( cols > LCD_COL) format = ALIGN_LEFT;
157 if(format == ALIGN_CENTER){
158 if(cols%2 == 1) cols++;
159 cols = (LCD_COL/2) - (cols/2);
160 }else if(format == ALIGN_RIGHT){
161 cols = LCD_COL - cols;
162 }else{
163 cols = 0;
164 }
165 lcd.setCursor(cols,baris);
166 lcd.print(data);
167 }
168
169 // tambahan untuk membuat delay non blocking
170 unsigned long nonblocking_time = millis();
269
171 unsigned long nonblocking_last = millis();
172 boolean nonblocking_delay(long milidetik){
173 nonblocking_time = millis();
174 if(nonblocking_time - nonblocking_last >= milidetik){
175 nonblocking_last = nonblocking_time;
176 return true;
177 }
178 return false;
179 }
270
3. Untuk menampilkan nama hari dan nama bulan
dilakukan saat mengon versi tanggal ke string, yaitu
pada baris 140 dan 145.
271
13
14 #define BACKLIGHT_ON HIGH
15 #define BACKLIGHT_OFF !BACKLIGHT_ON
16
17 // jumlah kolom dan baris LCD (16x2)
18 #define LCD_COL 16
19 #define LCD_ROW 2
20
21 #define ALIGN_LEFT 1 // teks rata kiri
22 #define ALIGN_CENTER 2 // teks center
23 #define ALIGN_RIGHT 3 // teks rata kanan
24 #define CLEAR true // clear screen
25
26 #define MOVE_NONE 0 // tidak bergerak
27 #define MOVE_UP 1 // bergerak ke atas
28 #define MOVE_DOWN 2 // bergrak ke bawah
29 #define MOVE_LEFT 3 // bergerak ke kiri
30 #define MOVE_RIGHT 4 // bergerak ke kanan
31
32 // ===== Konfigurasi LCD ===========
33
34 // LCD1602 dengan Modul I2C
35 // Alamat I2C di 0x27
36 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
37 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
38
39 // pilihat format penulisan teks
40 byte tipe_format[] = {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
41 byte format = ALIGN_LEFT;
42
43 // pilihat format penulisan teks
44 byte pilihan_move[] = {MOVE_UP, MOVE_DOWN, MOVE_LEFT,
MOVE_RIGHT};
45 byte moving = MOVE_NONE;
46
47 boolean moving_state = true;
48 unsigned long moving_timer = 0;
49
50 // temporary untuk move_up dan move_down
51 String tmp_teks = "";
52
53 // temporary untuk move_left dan move_right
54 int posisi_kolom = 0;
55
272
56 // instance RTC
57 RTC_DS1307 RTC;
58
59 // nama hari lengkap
60 const String NAMA_HARI[] = {
61 "Minggu",
62 "Senin",
63 "Selasa",
64 "Rabu",
65 "Kamis",
66 "Jumat",
67 "Sabtu"
68 };
69
70 // nama bulan lengkap
71 const String NAMA_BULAN[] = {
72 "",
73 "Januari",
74 "Februari",
75 "Maret",
76 "April",
77 "Mei",
78 "Juni",
79 "Juli",
80 "Agustus",
81 "September",
82 "Oktober",
83 "Nopember",
84 "Desember"
85 };
86
87 // pencatat waktu
88 DateTime WAKTU;
89 byte DETIK = 0;
90
91 // teks jam
92 String teks_jam = "";
93
94 void setup() {
95 // buka koneksi ke serial monitor
96 Serial.begin(19200);
97 while(!Serial);
98
273
99 // buka koneksi ke RTC
100 Wire.begin();
101 RTC.begin();
102 delay(1000);
103
104 // jika RTC belum disetting & running
105 if (! RTC.isrunning()) {
106 // set waktu RTC sesuai waktu di komputer
107 RTC.adjust(DateTime(__DATE__, __TIME__));
108 Serial.println("RTC is NOT Running");
109 } else {
110 // RTC normal
111 Serial.println("RTC OK!");
112 }
113
114 // Settingan LCD
115 lcd.begin(LCD_COL,LCD_ROW);
116
117 // Nyalakan Backlight
118 lcd.setBacklight(BACKLIGHT_ON);
119
120 }
121
122 void loop() {
123 // catat waktu
124 WAKTU = RTC.now();
125
126 // baris pertama teks tanggal bergerak ke kiri
127 MoveText(Tanggal(WAKTU), 0, MOVE_LEFT, 250);
128
129 if( WAKTU.second() != DETIK ){
130 // baris kedua jam
131 SetDisplay(Jam(WAKTU), 1, ALIGN_CENTER, !CLEAR);
132 // catat detik terakhir
133 DETIK = WAKTU.second();
134 }
135 }
136
137 // fung Jam, mengonversi jam ke string
138 String Jam(DateTime waktu){
139 teks_jam = "";
140 if( waktu.hour() < 10 ) teks_jam.concat(0);
141 teks_jam.concat(waktu.hour());
142 teks_jam.concat(":");
274
143 if( waktu.minute() < 10 ) teks_jam.concat(0);
144 teks_jam.concat(waktu.minute());
145 teks_jam.concat(":");
146 if( waktu.second() < 10 ) teks_jam.concat(0);
147 teks_jam.concat(waktu.second());
148 return teks_jam;
149 }
150
151 // fungsi tanggal
152 // mengonversi tanggal ke String
153 // termasuk nama hari dan bulan
154 String Tanggal(DateTime waktu){
155 String teks_tanggal = "";
156 teks_tanggal.concat( NAMA_HARI[waktu.dayOfTheWeek()] );
157 teks_tanggal.concat(", ");
158 if( waktu.day() < 10 ) teks_tanggal.concat(0);
159 teks_tanggal.concat(waktu.day());
160 teks_tanggal.concat(" ");
161 teks_tanggal.concat( NAMA_BULAN[waktu.month()] );
162 teks_tanggal.concat(" ");
163 if( waktu.year() < 10 ) teks_tanggal.concat(0);
164 teks_tanggal.concat(waktu.year());
165 return teks_tanggal;
166 }
167
168 // fungsi untuk menampilkan teks pada lcd sesuai format
169 void SetDisplay(String data, byte baris, byte format, boolean hapus){
170 if(hapus) lcd.clear();
171 int cols = data.length();
172 if( cols > LCD_COL) format = ALIGN_LEFT;
173 if(format == ALIGN_CENTER){
174 if(cols%2 == 1) cols++;
175 cols = (LCD_COL/2) - (cols/2);
176 }else if(format == ALIGN_RIGHT){
177 cols = LCD_COL - cols;
178 }else{
179 cols = 0;
180 }
181 lcd.setCursor(cols,baris);
182 lcd.print(data);
183 }
184
185 void MoveText(String data, byte baris, byte pilih_moving, unsigned long
275
186 moving_delay){
187
188 if( millis() - moving_timer < moving_delay ) return;
189
190 int cols = 0;
191 int real_cols = 0;
192
193 switch(pilih_moving){
194 case MOVE_UP:
195
196 SetDisplay(tmp_teks, 0, ALIGN_LEFT, CLEAR);
197 SetDisplay(data, 1, ALIGN_LEFT, !CLEAR);
198 tmp_teks = data;
199
200 break;
201
202 case MOVE_DOWN:
203
204 SetDisplay(tmp_teks, 1, ALIGN_LEFT, CLEAR);
205 SetDisplay(data, 0, ALIGN_LEFT, !CLEAR);
206 tmp_teks = data;
207
208 break;
209
210 case MOVE_LEFT:
211
212 lcd.setCursor(0,baris);
213 for(byte i=0; i<LCD_COL; i++) lcd.print(' ');
214
215 lcd.setCursor(0,baris);
216
217 real_cols = data.length();
218 if( posisi_kolom < 0 ){
219 data = data.substring( abs(posisi_kolom) );
220 }
221 cols = data.length();
222 for(byte i=0; i<=LCD_COL; i++){
223 if( posisi_kolom < 0 ){
224 if( i == 0 ){
225 lcd.print(data);
226 i = cols;
227 }else{
228 lcd.print(' ');
229 }
276
230 } else {
231 if( i == posisi_kolom ){
232 lcd.print(data);
233 i += cols-1;
234 } else {
235 lcd.print(' ');
236 }
237 }
238 }
239
240 posisi_kolom--;
241 if( (real_cols + posisi_kolom) == 0) posisi_kolom = LCD_COL-1;
242
243 break;
244
245 case MOVE_RIGHT:
246
247 lcd.setCursor(0,baris);
248 for(byte i=0; i<LCD_COL; i++) lcd.print(' ');
249
250 lcd.setCursor(0,baris);
251 real_cols = data.length();
252 if( posisi_kolom < 0 ){
253 data = data.substring( abs(posisi_kolom) );
254 }
255 cols = data.length();
256 for(byte i=0; i<LCD_COL; i++){
257 if( posisi_kolom < 0 ){
258 if( i == 0 ){
259 lcd.print(data);
260 i = cols;
261 }else{
262 lcd.print(' ');
263 }
264 } else {
265 if( i == posisi_kolom ){
266 lcd.print(data);
267 i += cols;
268 } else {
269 lcd.print(' ');
270 }
271 }
272 }
277
273
274 posisi_kolom++;
275 if( posisi_kolom > LCD_COL ) posisi_kolom = -real_cols+1;
276
277 break;
278 }
279 moving_timer = millis();
280 }
281
282 // tambahan untuk membuat delay non blocking
283 unsigned long nonblocking_time = millis();
284 unsigned long nonblocking_last = millis();
285 boolean nonblocking_delay(long milidetik){
286 nonblocking_time = millis();
287 if(nonblocking_time - nonblocking_last >= milidetik){
288 nonblocking_last = nonblocking_time;
289 return true;
290 }
291 return false;
292 }
278
sore, dan mematikan lampu ketika sudah pagi. Untuk
mengontrol lampu, kita butuh relay sebagai pengendali
listrik AC dari PLN. Cara kerja alat ini adalah :
279
16.7.1 Rangkaian Timer Pagi Sore
1. Arduino x 1
2. TinyRTC DS1307 x 1
3. LCD1602 dengan modul I2C x 1
4. Modul relay 2 channel atau 1 channel x 1
5. Project board
6. Kabel jumper secukupnya
280
16.7.2 Program Timer Pagi Sore
Program 16.6 Program Timer Pagi Sore
1 /*
2 * MONSTER ARDUINO V2
3 * Program Timer Pagi Sore
4 * www.ElangSakti.com
5 */
6
7 // include library Wire dan RTCLib
8 #include <Wire.h>
9 #include <RTClib.h>
10
11 // input RELAY di pin 2
12 const byte PIN_RELAY = 2;
13
14 // logika untuk relay
15 #define RELAY_ON HIGH
16 #define RELAY_OFF !RELAY_ON
17
18 // library LCD dengan modul I2C
19 #include <LiquidCrystal_I2C.h>
20
21 // backlight lcd
22 #define BACKLIGHT_ON HIGH
23 #define BACKLIGHT_OFF !BACKLIGHT_ON
24
25 // jumlah kolom dan baris LCD (16x2)
26 #define LCD_COL 16
27 #define LCD_ROW 2
28
29 #define ALIGN_LEFT 1 // teks rata kiri
30 #define ALIGN_CENTER 2 // teks center
31 #define ALIGN_RIGHT 3 // teks rata kanan
32 #define CLEAR true // clear screen
33
34 // ===== Konfigurasi LCD ===========
35
36 // LCD1602 dengan Modul I2C
37 // Alamat I2C di 0x27
38 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
39 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
281
40
41 // pilihat format penulisan teks
42 byte tipe_format[] = {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
43 byte format = ALIGN_LEFT;
44
45 // instance RTC
46 RTC_DS1307 RTC;
47
48 // Teks jam dan teks informasi relay di lcd
49 String teks_jam = "";
50 String teks_relay = "";
51
52 // status relay
53 boolean status_relay = RELAY_OFF;
54 boolean status_relay_last = status_relay;
55
56 // jam sore lampu nyala
57 const int SORE = 1700; // jam 17:00
58 // jam pagi lampu mati
59 const int PAGI = 500; // jam 5:00
60
61 // hasil konversi jam ke angka jam:menit
62 int angka_jam = 0;
63
64 // pencatat waktu
65 DateTime WAKTU;
66 byte DETIK = 0;
67
68 // teks bergerak
69 #define MOVE_NONE 0 // tidak bergerak
70 #define MOVE_UP 1 // bergerak ke atas
71 #define MOVE_DOWN 2 // bergrak ke bawah
72 #define MOVE_LEFT 3 // bergerak ke kiri
73 #define MOVE_RIGHT 4 // bergerak ke kanan
74
75 // pilihat format penulisan teks
76 byte pilihan_move[] = {MOVE_UP, MOVE_DOWN, MOVE_LEFT,
MOVE_RIGHT};
77 byte moving = MOVE_NONE;
78
79 boolean moving_state = true;
80 unsigned long moving_timer = 0;
81
82 // temporary untuk move_up dan move_down
282
83 String tmp_teks = "";
84
85 // temporary untuk move_left dan move_right
86 int posisi_kolom = 0;
87
88 void setup() {
89 // buka koneksi ke serial monitor
90 Serial.begin(19200);
91 while(!Serial);
92
93 // buka koneksi ke RTC
94 Wire.begin();
95 RTC.begin();
96 delay(1000);
97
98 // jika RTC belum disetting & running
99 if (! RTC.isrunning()) {
100 // set waktu RTC sesuai waktu di komputer
101 RTC.adjust(DateTime(__DATE__, __TIME__));
102 Serial.println("RTC is NOT Running");
103 } else {
104 // RTC normal
105 Serial.println("RTC OK!");
106 }
107
108 // Settingan LCD
109 lcd.begin(LCD_COL,LCD_ROW);
110
111 // Nyalakan Backlight
112 lcd.setBacklight(BACKLIGHT_ON);
113
114 // tampilkan info startup di display
115 // serta status sistem ketika mengkonfigurasi
116 StartUp();
117
118 }
119
120 void loop() {
121 // catat waktu
122 WAKTU = RTC.now();
123
124 if( WAKTU.second() != DETIK ){
125 // informasi tanggal di baris 1 rata tengah
283
126 SetDisplay(Tanggal(WAKTU), 0, ALIGN_CENTER, !CLEAR);
127 // informasi jam di baris 2 rata kiri
128 SetDisplay(Jam(WAKTU), 1, ALIGN_LEFT, !CLEAR);
129 DETIK = WAKTU.second();
130 }
131 // aksi untuk perubahan relay berdasarkan waktu
132 RelayAction(WAKTU);
133 }
134
135 // fung Jam, mengonversi jam ke string
136 String Jam(DateTime waktu){
137 teks_jam = "";
138 if( waktu.hour() < 10 ) teks_jam.concat(0);
139 teks_jam.concat(waktu.hour());
140 teks_jam.concat(":");
141 if( waktu.minute() < 10 ) teks_jam.concat(0);
142 teks_jam.concat(waktu.minute());
143 teks_jam.concat(":");
144 if( waktu.second() < 10 ) teks_jam.concat(0);
145 teks_jam.concat(waktu.second());
146 return teks_jam;
147 }
148
149 // fungsi tanggal
150 // mengonversi tanggal ke String
151 String Tanggal(DateTime waktu){
152 String teks_tanggal = "";
153 if( waktu.day() < 10 ) teks_tanggal.concat(0);
154 teks_tanggal.concat(waktu.day());
155 teks_tanggal.concat("/");
156 if( waktu.month() < 10 ) teks_tanggal.concat(0);
157 teks_tanggal.concat(waktu.month());
158 teks_tanggal.concat("/");
159 if( waktu.year() < 10 ) teks_tanggal.concat(0);
160 teks_tanggal.concat(waktu.year());
161 return teks_tanggal;
162 }
163
164 // fungsi get_angka
165 // untuk mengkonversi jam dan menit menjadi sebuah angka
166 // contoh jam 3:06 sore akan dikonversi menjadi angka 1506
167 // 15 mewakili jam 15, 06 untuk menit
168 int get_angka(DateTime waktu){
169 // konversi jam dalam ratusan, menit dalam puluhan dan satuan
284
170 return (waktu.hour() * 100) + waktu.minute();
171 }
172
173 // aksi untuk relay
174 // sekaligus menampilkan informasi relay di LCD
175 void RelayAction(DateTime waktu){
176 // L = Lampu
177 teks_relay = " L:";
178
179 angka_jam = get_angka(waktu);
180
181 // relay disetting normally close
182 // relay ON => lampu mati
183 // relay OFF => lampu nyala
184 // -----
185 // PAGI - SORE => relay ON
186 // SORE - PAGI => relay OFF
187 if(angka_jam >= PAGI && angka_jam <= SORE){
188 digitalWrite(PIN_RELAY, RELAY_ON);
189 teks_relay.concat("OFF"); // RELAY ON, LAMPU OFF
190 } else {
191 digitalWrite(PIN_RELAY, RELAY_OFF);
192 teks_relay.concat("ON"); // RELAY OFF, LAMPU ON
193 }
194
195 // tampilkan informasi relay di baris 2 rata kanan
196 SetDisplay(teks_relay, 1, ALIGN_RIGHT, !CLEAR);
197 }
198
199 // fungsi untuk menampilkan teks pada lcd sesuai format
200 void SetDisplay(String data, byte baris, byte format, boolean hapus){
201 if(hapus) lcd.clear();
202 int cols = data.length();
203 if( cols > LCD_COL) format = ALIGN_LEFT;
204 if(format == ALIGN_CENTER){
205 if(cols%2 == 1) cols++;
206 cols = (LCD_COL/2) - (cols/2);
207 }else if(format == ALIGN_RIGHT){
208 cols = LCD_COL - cols;
209 }else{
210 cols = 0;
211 }
212 lcd.setCursor(cols,baris);
285
213 lcd.print(data);
214 }
215
216 // fungsi untuk informasi startup
217 // hanya dummy... bisa diganti dengan informasi lainnya
218 void StartUp(){
219 // konfigurasi....
220 // tampilkan nama project dan nama pembuatnya
221 SetDisplay(F("NAMA PROJECT"), 0, ALIGN_CENTER, CLEAR);
222 SetDisplay(F("PEMBUAT"), 1, ALIGN_CENTER, !CLEAR);
223 delay(5000);
224
225 // teks bergerak bergantian...
226 MoveText(F("Starting..."), 1, MOVE_UP, 0);
227 delay(2000);
228 MoveText(F("System Started..."), 1, MOVE_UP, 0);
229 delay(2000);
230 MoveText(F("Configuring..."), 1, MOVE_UP, 0);
231 delay(2000);
232 MoveText(F("Checking System..."), 1, MOVE_UP, 0);
233 delay(2000);
234 MoveText(F("Testing..."), 1, MOVE_UP, 0);
235 delay(3000);
236 MoveText(F("Please wait..."), 1, MOVE_UP, 0);
237 delay(5000);
238
239 // clear lcd
240 lcd.clear();
241 }
242
243 void MoveText(String data, byte baris, byte pilih_moving, unsigned long
moving_delay){
244
245 if( millis() - moving_timer < moving_delay ) return;
246
247 int cols = 0;
248 int real_cols = 0;
249
250 switch(pilih_moving){
251 case MOVE_UP:
252
253 SetDisplay(tmp_teks, 0, ALIGN_LEFT, CLEAR);
254 SetDisplay(data, 1, ALIGN_LEFT, !CLEAR);
255 tmp_teks = data;
286
256
257 break;
258
259 case MOVE_DOWN:
260
261 SetDisplay(tmp_teks, 1, ALIGN_LEFT, CLEAR);
262 SetDisplay(data, 0, ALIGN_LEFT, !CLEAR);
263 tmp_teks = data;
264
265 break;
266
267 case MOVE_LEFT:
268
269 lcd.setCursor(0,baris);
270 for(byte i=0; i<LCD_COL; i++) lcd.print(' ');
271
272 lcd.setCursor(0,baris);
273
274 real_cols = data.length();
275 if( posisi_kolom < 0 ){
276 data = data.substring( abs(posisi_kolom) );
277 }
278 cols = data.length();
279 for(byte i=0; i<=LCD_COL; i++){
280 if( posisi_kolom < 0 ){
281 if( i == 0 ){
282 lcd.print(data);
283 i = cols;
284 }else{
285 lcd.print(' ');
286 }
287 } else {
288 if( i == posisi_kolom ){
289 lcd.print(data);
290 i += cols-1;
291 } else {
292 lcd.print(' ');
293 }
294 }
295 }
296
297 posisi_kolom--;
298 if( (real_cols + posisi_kolom) == 0) posisi_kolom = LCD_COL-1;
287
299
300 break;
301
302 case MOVE_RIGHT:
303
304 lcd.setCursor(0,baris);
305 for(byte i=0; i<LCD_COL; i++) lcd.print(' ');
306
307 lcd.setCursor(0,baris);
308 real_cols = data.length();
309 if( posisi_kolom < 0 ){
310 data = data.substring( abs(posisi_kolom) );
311 }
312 cols = data.length();
313 for(byte i=0; i<LCD_COL; i++){
314 if( posisi_kolom < 0 ){
315 if( i == 0 ){
316 lcd.print(data);
317 i = cols;
318 }else{
319 lcd.print(' ');
320 }
321 } else {
322 if( i == posisi_kolom ){
323 lcd.print(data);
324 i += cols;
325 } else {
326 lcd.print(' ');
327 }
328 }
329 }
330
331 posisi_kolom++;
332 if( posisi_kolom > LCD_COL ) posisi_kolom = -real_cols+1;
333
334 break;
335 }
336 moving_timer = millis();
337 }
288
1. Inisialisasi jam pagi ada di baris 59.
2. Jam sore ditentukan pada baris 57.
3. Kondisi lampu ON pada kondisi sistem mati,
ditentukan berdasarkan sambungan fisik, tidak
hanya berdasarkan program. Boleh Anda cek koneksi
lampu di Gambar 16.5 yang dihubungkan ke pin NC.
289
Ada yang menarik degan project ini? Mari kita
diskusikan di grup.
290
Bagian #17
___
1. Arduino x 1
2. Modul receiver infrared (model KY-022) x 1
3. Kabel jumper secukupnya
292
Sambungan pin Arduino dan modul IR receiver adalah :
Arduino IR Receiver
Pin 2 Pin S (signal)
VCC VCC
GND GND
294
Gambar 17.4 Output tombol 0 – 9
295
Yap, masing-masing tombol sudah diketahui kodenya.
Selanjutnya apa? Selanjutnya buat program untuk
menangani perintah berdasarkan tombol yang dipilih. Untuk
program selanjutnya, kita bisa saja membuat alat
pengontrol lampu (entah pakai LED atau relay), tapi itu
terlalu mainstream. Kita coba buat project yang lain. Kita
akan membuat remote kontrol karakter di dalam LCD.
Anggap saja kita akan membuat game Pacman.
296
Informasi status backlight dan arah gerakan karakter
harus tersimpan di sistem. Sehingga ketika sistem diaktifkan,
karakter akan bergerak sesuai arah yang tersimpan
sebelumnya dan backlight akan mengeksekusi status
sebelumnya juga. Siap dengan program ini? Mari langsung
merangkai dan membuat programnya!
297
Gambar 17.5 Rangkain pengontrol karakter LCD
298
22 #define TOMBOL_3 0xFFE21D
23 #define TOMBOL_4 0xFF22DD
24 #define TOMBOL_5 0xFF02FD
25 #define TOMBOL_6 0xFFC23D
26 #define TOMBOL_7 0xFFE01F
27 #define TOMBOL_8 0xFFA857
28 #define TOMBOL_9 0xFF906F
29 #define TOMBOL_0 0xFF9867
30 #define TOMBOL_STAR 0xFF6897 // *
31 #define TOMBOL_HASH 0xFFB04F // #
32 #define TOMBOL_ATAS 0xFF18E7 // panah ke atas
33 #define TOMBOL_BAWAH 0xFF4AB5 // panah ke bawah
34 #define TOMBOL_OK 0xFF38C7 // ok
35 #define TOMBOL_KIRI 0xFF10EF // panah ke kiri
36 #define TOMBOL_KANAN 0xFF5AA5 // panah ke kanan
37
38 // alamat untuk menyimpan status backlight
39 #define ADDR_BACKLIGHT 0
40 #define ADDR_ARAH 1
41
42 // library LCD dengan modul I2C
43 #include <LiquidCrystal_I2C.h>
44
45 #define BACKLIGHT_ON HIGH
46 #define BACKLIGHT_OFF !BACKLIGHT_ON
47
48 // jumlah kolom dan baris LCD (16x2)
49 #define LCD_COL 16
50 #define LCD_ROW 2
51
52 // LCD1602 dengan Modul I2C
53 // Alamat I2C di 0x27
54 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
55 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
56
57 // status backlight LCD
58 boolean backlight = BACKLIGHT_ON;
59
60
61 // karakter di LCD
62 byte mangap_arr[] = {
63 B00000,
64 B01110,
299
65 B01011,
66 B11111,
67 B00011,
68 B10011,
69 B01110,
70 B00000
71 };
72
73 byte mingkem_arr[] = {
74 B00000,
75 B01110,
76 B01011,
77 B11111,
78 B11111,
79 B01111,
80 B00000,
81 B00000
82 };
83
84 #define ARAH_DIAM 0
85 #define ARAH_KIRI 1
86 #define ARAH_KANAN 2
87 #define ARAH_ATAS 3
88 #define ARAH_BAWAH 4
89
90 byte arah = ARAH_DIAM;
91
92 boolean Nganga = false;
93 byte Nganga_counter = 0;
94 const byte Nganga_pindah = 2;
95
96 int posisi_baris = 0;
97 int posisi_kolom = 0;
98
99 void setup() {
100 // buka koneksi ke serial monitor
101 Serial.begin(19200);
102
103 // Settingan LCD
104 lcd.begin(LCD_COL,LCD_ROW);
105
106 // baca informasi status backlight terakhir
107 backlight = EEPROM.read(ADDR_BACKLIGHT);
108 // jika backlight > 1 reset ke 1
300
109 if( backlight > 1) backlight = 1;
110
111 // baca informasi arah gerakan
112 arah = EEPROM.read(ADDR_ARAH);
113 // jika arah > 4, maka diam
114 if( arah > ARAH_BAWAH) arah = ARAH_DIAM;
115
116 // buat karakter baru
117 lcd.createChar(0, mingkem_arr);
118 lcd.createChar(1, mangap_arr);
119
120 // Nyalakan Backlight
121 lcd.setBacklight(backlight);
122
123 // aktifkan penerima infrared
124 irrecv.enableIRIn();
125 }
126
127 void loop() {
128 // jika menerima data dan berhasil mendecode data
129 if(irrecv.decode(&results)) {
130 // cetak ke serial monitor dg format Hex
131 Serial.println(results.value, HEX);
132
133 // eksekusi aksi sesuai tombol yang dipilih
134 IRAction(results.value);
135
136 // hapus history hasil sebelumnya
137 irrecv.resume();
138 }
139
140 // gerakkan karakter lcd
141 MoveChar();
142 }
143
144 // fungsi aksi penekanan tombol
145 void IRAction(unsigned long tombol){
146
147 // ketika anti arah atau ganti mode backlight
148 // simpan data ke EEPROM
149 switch(tombol){
150 // setting backlight
151 case TOMBOL_STAR:
301
152 // balik logika backlight
153 backlight = !backlight;
154 lcd.setBacklight(backlight);
155 // simpan konfigurasi backlight
156 EEPROM.write(ADDR_BACKLIGHT,backlight);
157 break;
158
159 case TOMBOL_ATAS:
160 arah = ARAH_ATAS;
161 EEPROM.write(ADDR_ARAH,arah);
162 break;
163
164 case TOMBOL_BAWAH:
165 arah = ARAH_BAWAH;
166 EEPROM.write(ADDR_ARAH,arah);
167 break;
168
169 case TOMBOL_OK:
170 arah = ARAH_DIAM;
171 EEPROM.write(ADDR_ARAH,arah);
172 break;
173
174 case TOMBOL_KIRI:
175 arah = ARAH_KIRI;
176 EEPROM.write(ADDR_ARAH,arah);
177 break;
178
179 case TOMBOL_KANAN:
180 arah = ARAH_KANAN;
181 EEPROM.write(ADDR_ARAH,arah);
182 break;
183 }
184 }
185
186 // fungsi untuk menggerakkan karakter di lcd
187 void MoveChar(){
188
189 // animasi menanga setiap 150ms
190 if( nonblocking_delay(150) ){
191
192 // balik logika kondisi nganga
193 Nganga = !Nganga;
194
195 // bersihkan lcd, kemudian set posisi kursor
302
196 lcd.clear();
197 lcd.setCursor(posisi_kolom, posisi_baris);
198
199 // jika ngaga = true
200 // tampilkan karakter menganga
201 // jika false, tampilkan karakter biasa
202 if( Nganga == true ){
203 lcd.write(byte(0));
204 } else {
205 lcd.write(byte(1));
206 }
207
208 // setiap jumlah nganga = nganga_pindah
209 // maka mindah posisi karakter
210 if ( Nganga_counter == Nganga_pindah ){
211
212 // pindah posisi karakter sesuai
213 // dengan arah yang dipilih tombol remote
214 PilihArah(arah);
215
216 Nganga_counter = 0;
217 } else {
218 Nganga_counter++;
219 }
220 }
221 }
222
223 // fungsi untuk memilih arah gerakan
224 void PilihArah(byte arah){
225 switch(arah){
226 case ARAH_KANAN:
227 // jika arah kanan, tambah posisi kolom
228 // jika posisi melebihi jumlah kolom,
229 // kembali ke 0
230 posisi_kolom++;
231 if(posisi_kolom >= LCD_COL){
232 posisi_kolom = 0;
233 }
234 break;
235
236 case ARAH_KIRI:
237 // jika arah kiri, kurangi posisi kolom
238 // jika posisi < posisi 0
303
239 // kembali ke kanan (posisi LCD_COL-1)
240 posisi_kolom--;
241 if(posisi_kolom < 0){
242 posisi_kolom = LCD_COL-1;
243 }
244 break;
245
246 case ARAH_ATAS:
247 // jika arah atas, kurangi posisi baris
248 // ingat, 0 ada di atas
249 // jika posisi lebih kecil 0,
250 // kembali ke index row (LCD_ROW-1)
251 posisi_baris--;
252 if(posisi_baris < 0){
253 posisi_baris = LCD_ROW-1;
254 }
255 break;
256
257 case ARAH_BAWAH:
258 // jika arah bawah, tambah posisi baris
259 // jika posisi melebihi jumlah baris,
260 // kembali ke 0
261 posisi_baris++;
262 if(posisi_baris >= LCD_ROW){
263 posisi_baris = 0;
264 }
265 break;
266 }
267 }
268
269 // tambahan untuk membuat delay non blocking
270 unsigned long nonblocking_time = millis();
271 unsigned long nonblocking_last = millis();
272 boolean nonblocking_delay(long milidetik){
273 nonblocking_time = millis();
274 if(nonblocking_time - nonblocking_last >= milidetik){
275 nonblocking_last = nonblocking_time;
276 return true;
277 }
278 return false;
279 }
304
Cara kerja program diatas jika disesuaikan dengan
kebutuhan sistem yaitu :
305
Bagian #18
PENGENALAN SERVO
___
306
dipastikan Anda akan bisa menggunakan tipe servo sejenis
lainnya. Yang penting Anda paham batasan sudut servo
yang dipakai.
1. Arduino x 1
2. Servo SG90 x 1
3. Kabel jumper secukupnya
307
Sambungan pin Arduino dan Servo adalah :
309
4. Program ini simpel, selanjutkan kita akan
mengendalikan servo dengan potensiomenter. Jadi
gerakan servo bisa kita ubah dengan cepat.
1. Arduino x 1
2. Servo SG90 x 1
3. Potensiometer x 1
4. Project board x 1
5. Kabel jumper secukupnya
310
Gambar 18.3 Rangkain kendali servo dengan potensiometer
311
24 myservo.attach(PIN_SERVO);
25 }
26
27 void loop() {
28 // posisikan servo sesuai data potensio
29 int data = analogRead(PIN_POTENSIO);
30 // normalisasi data potensio sesuai sudut servo
31 posisi = map( data, 0, 1024, 0, 180 );
32 // kontrol servo
33 myservo.write(posisi);
34 }
312
18.3.1 Rangkaian Kendali Servo dan IR Receiver
1. Arduino x 1
2. Servo SG90 x 1
3. LCD1602 dengan Modul I2C x 1
4. Modul receiver infrared x 1
5. Remote infrared x 1
6. Project board dan kabel jumper secukupnya
315
84 lcd.begin(LCD_COL,LCD_ROW);
85
86 // Nyalakan Backlight
87 lcd.setBacklight(BACKLIGHT_ON);
88
89 // aktfikan servo
90 myservo.attach(PIN_SERVO);
91
92 // aktifkan penerima infrared
93 irrecv.enableIRIn();
94 }
95
96 void loop() {
97
98 // jika menerima data dan berhasil mendecode data
99 if(irrecv.decode(&results)) {
100 // cetak ke serial monitor dg format Hex
101 Serial.println(results.value, HEX);
102
103 // eksekusi aksi sesuai tombol yang dipilih
104 // jika tombol terdeteksi adalah 0xFFFFFFFF
105 // berarti tombol yang ditekan sama dengan
106 // tombol sebelumnya
107 if( results.value != TOMBOL_REPEAT ){
108 tombol = results.value;
109 }
110 IRAction(tombol);
111
112 // hapus history hasil sebelumnya
113 irrecv.resume();
114 }
115
116 // jika posisi berubah
117 if( posisi_last != posisi ){
118
119 // putar servo sesuai sudut masing-masing
120 myservo.write(posisi);
121
122 // teks sudut servo dan simbol derajat
123 teks_servo = "SUDUT:";
124 teks_servo.concat(posisi);
125 teks_servo.concat((char)223);
126
127 // jika lebar teks berubah, clear lcd sebelum cetak
316
128 if( String(posisi).length() != String(posisi_last).length() ){
129 SetDisplay( teks_servo, 0, ALIGN_LEFT, CLEAR);
130 } else {
131 SetDisplay( teks_servo, 0, ALIGN_LEFT, !CLEAR);
132 }
133 posisi_last = posisi;
134 }
135 }
136
137 // fungsi aksi penekanan tombol
138 void IRAction(unsigned long tombol){
139
140 // simpan data ke EEPROM
141 switch(tombol){
142
143 case TOMBOL_ATAS:
144 posisi = 180;
145 break;
146
147 case TOMBOL_BAWAH:
148 posisi = 0;
149 break;
150
151 case TOMBOL_KIRI:
152 if(posisi > 1) posisi--;
153 break;
154
155 case TOMBOL_KANAN:
156 if(posisi < 180) posisi++;
157 break;
158 }
159 }
160
161 // fungsi untuk menampilkan teks pada lcd sesuai format
162 void SetDisplay(String data, byte baris, byte format, boolean hapus){
163 if(hapus) lcd.clear();
164 int cols = data.length();
165 if( cols > LCD_COL) format = ALIGN_LEFT;
166 if(format == ALIGN_CENTER){
167 if(cols%2 == 1) cols++;
168 cols = (LCD_COL/2) - (cols/2);
169 }else if(format == ALIGN_RIGHT){
170 cols = LCD_COL - cols;
317
171 }else{
172 cols = 0;
173 }
174 lcd.setCursor(cols,baris);
175 lcd.print(data);
176 }
318
MONSTER ARDUINO 3
Semua ide Anda tentang usulan konten yang perlu
dibahas pada ebook MONSTER ARDUINO 3 boleh dikirim
ke hari@elangsakti.com, semua usulan kita tampung dan
direalisasikan sesuai kondisi.
319
Tentang Penulis
320