Anda di halaman 1dari 336

i

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

Penulis sangat bersyukur, atas rahmat Allah, penulis


masih diberi kemampuan untuk melanjutkan penulisan buku
tentang Arduino versi 2 setelah beberapa bulan vakum.
Semoga versi berikutnya bisa rilis lebih cepat.

Terima kasih penulis ucapkan kepada istri tercinta, Aprillia


Dewi Kreswanti, yang telah merelakan waktu keluarga demi
terselesaikannya penulisan ebook ini.

Terima kasih juga kepada kawan-kawan yang sudah request


untuk join ke grup facebook MONSTER ARDUINO, berkat
kalian penulis menjadi lebih bersemangat untuk berbagi
pengalaman melalui media sosial.

Selanjutnya, semoga ebook ini bermanfaat bagi penggiat


Arduino, bagi yang ingin berinovasi di ranah teknologi,
robotika, dan IoT.

Salam hangat penuh semangat!

Malang, 11 September 2017,

Hari Elangsakti

v
KOBARKAN SEMANGAT INDONESIA!

vi
DAFTAR ISI

MONSTER ARDUINO 2 .............................................................................iii


CATATAN PENULIS .................................................................................. v
DAFTAR ISI............................................................................................ vii
#00 SEBELUM MULAI ............................................................................... 1
#01 MEMINANG ARDUINO ....................................................................... 3
1.1 Jenis Arduino untuk Pemula ............................................................. 6
1.2 Project yang Butuh Banyak Pin I/O .................................................... 7
1.3 Program dengan Clock Tinggi .......................................................... 8
1.4 Project dengan Ukuran Program Besar .............................................. 9
1.5 Saatnya Memilih!.......................................................................... 11
#02 ARDUINO DAN BOOTLOADER ........................................................... 12
2.1 Sekilas tentang Bootloader ............................................................ 12
2.2 Cara Install Bootloader Arduino ...................................................... 16
2.2.1 Install Bootloader dengan USBAsp ............................................ 17
2.2.2 Arduino Sebagai ISP Programmer ............................................. 24
2.2.3 Install Bootloader dengan Arduino ............................................ 26
2.2.4 Pengecekan Hasil Instalasi Bootloader ....................................... 29
#03 HELLO BUZZER ............................................................................... 30
3.1 Project Hello Buzzer ..................................................................... 30
3.1.1 Rangkaian Hello Buzzer........................................................... 30
vii
3.1.2 Program Hello Buzzer............................................................. 31
3.2 Buzzer Aktif dan Buzzer Pasif ......................................................... 33
3.3 Project Dummy Logger ................................................................. 34
#04 TIPS MEMILIH TIPE DATA ................................................................. 38
4.1 Byte dan Boolean, 1 Byte ............................................................... 39
4.2 Char atau Unsigned Char, 1 Byte.................................................... 41
4.3 Integer dan Unsigned Integer, 2 Byte............................................... 41
4.4 Long dan Unsigned Long, 4 Byte ..................................................... 42
4.5 Float atau Double, 4 Byte............................................................... 42
4.6 Volatile & Interrupt ...................................................................... 42
4.7 PROGMEM .................................................................................. 44
4.8 String dengan F( ) ........................................................................ 45
#05 OPTIMALISASI DELAY ...................................................................... 47
5.1 Seberapa Cepatkah 16MHz itu? ...................................................... 47
5.2 Project Perbaikan Dummy Logger ................................................... 50
5.3 Program Simpel Delay yang Responsive ........................................... 56
#06 RESPONSIVE DENGAN TIMER INTERRUPT ........................................... 59
6.1 Seperti Apa Timer Interrupt? .......................................................... 59
6.2 Program Timer Interrupt Sederhana ................................................ 60
6.3 Dummy Logger dengan Timer Interrupt ........................................... 63
#07 WDT & PROGRAM ANTIMACET ......................................................... 68
7.1 Program WDT Sederhana .............................................................. 71
7.2 Program WDT Lanjutan ................................................................. 73
#08 MODUL RELAY................................................................................ 76
viii
8.1 Active Low atau Active High ........................................................... 79
8.2 Masalah yang Sering Muncul.......................................................... 80
8.3 Mengisolasi Power Supply ............................................................. 81
8.4 Sekilas tentang SSR (Solid State Relay) ............................................. 83
#09 EKSPLORASI TOMBOL PUSH BUTTON ................................................. 85
9.1 Internal Pullup Resistor ................................................................. 86
9.1.1 Rangkaian Testing Pullup Resistor ............................................ 87
9.1.2 Program Tombol tanpan Pullup Resistor .................................... 88
9.1.3 Program Tombol dengan Internal Pullup Resistor........................ 90
9.2 Membuat Tombol Multikondisi ....................................................... 91
9.2.1 Program Tombol yang Manusiawi ............................................. 92
9.2.2 Program Tombol dengan Lock Status......................................... 94
9.2.3 Program Tombol Modular ....................................................... 97
9.2.4 Program Satu Tombol Banyak Menu........................................ 100
9.3 Membuat Aksi Tombol yang Ditekan Lama ..................................... 104
9.3.1 Program Aksi Tombol Berdasarkan Lama Ditekan ...................... 105
9.4 Mengelola Banyak Tombol dengan Satu Pin.................................... 110
9.4.1 Rangkaian Program untuk Membaca 5 Tombol ......................... 112
9.4.2 Program Analisis Output Tombol ............................................ 113
9.4.3 Program Menu 5 Tombol....................................................... 115
9.4.4 Rangkain 5 Tombol 5 LED ...................................................... 119
9.4.5 Program 5 Tombol 5 LED....................................................... 121
#10 EEPROM SEBAGAI BLACKBOX.......................................................... 126

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

Untuk mendapatkan hasil maksimal dalam belajar, maka


Anda harus praktek. Jika kesulitan dalam memahami
program yang ada dalam ebook ini, Anda bisa tanya di grup
facebook MONSTER ARDUINO. Silakan cari postingan yang
berkaitan dengan program yang ingin ditanyakan.

Selain itu, silakan hubungi penulis jika berkenan miliki


paket belajar pendukung khusus ebook ini. Daftar peralatan
yang digunakan dalam ebook ini yaitu :

1. Arduino Uno R3 DIP x 1


2. Kabel Data Arduino x 1
3. Paket Belajar Burning Bootloader, terdiri dari :
- IC ATMega328P x 1
- Capasitor 22pf x 2
- XTAL 16MHz x 1
4. Project Board besar MB102 x 1
5. Timer Tiny RTC x 1
6. Sensor PIR x 1
7. Sensor DHT11 x 1
8. Motor Servo SG90 x 1
9. Remote IR 1 paket x 1
1
10. IC Shift Register 74HC595 x 2
11. LCD 1602 x 1
12. Modul LCD I2C x 1
13. 7 segment 1 Digit x 1
14. 7 segment 4 Digit x 1
15. Relay 2 Channel x 1
16. Buzzer aktif x 1
17. Tombol Push Button DIP x 1
18. Potensiometer x 1
19. Resistor 220 x 10
20. Resistor 1k x 10
21. Resistor 4k7 x 10
22. LED merah x 10
23. LED kuning x 10
24. LED hijau x 10
25. Kabel Jumper 20cm (30mm + 10 mf) x 1

ElangSakti.com TIDAK bekerja sama dengan toko


manapun dalam penyusunan ebook ini. Oleh sebab itu, jika
ada yang mengatasnamakan ElangSakti.com dalam menjual
paket belajar sesuai isi ebook ini, kami pastikan bahwa itu
bukan dari kami. Sebab, support dari kami hanya diinfokan
di website project.elangsakti.com, fanpage ElangSakti.com,
atau grup facebook MONSTER ARDUINO. Kami tidak
bertanggungjawab apabila ada pihak yang dirugikan yang
mengatasnamakan ElangSakti.com.

2
Bagian #01

MEMINANG ARDUINO

Saat kita mulai bangga dan merasa bisa,


itulah tanda bahwa keilmuan kita akan segera kadaluarsa.

___

Kekurangan dari produk open source adalah varian yang


kadang terlalu banyak dan membingungkan. Belum khatam
mempelajari varian A, sudah muncul varian B. Baru dapet
produk varian B, sudah muncul varian C dan D. Arrgggh
mau nggak mau, kita harus menjadi fast learner, mampu
belajar lebih cepat dari kebanyakan orang.

Ada banyak varian dari board Arduino, baik yang hanya


minimum board atau yang sudah dilengkapi dengan sensor.
Sebut saja Arduino Uno, Nano, Pro Mini, Mega, Intel, Due,
Wemos, Lilypad, Zero, atau yang lainnya. Dari deretan varian
tersebut, mana yang lebih cocok untuk Anda? Mana yang
lebih cocok untuk pemula?

***

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.

Sedikit banyak Anda perlu tahu kapasitas memori,


penggunaan register, ADC, DAC, serta jumlah dan
karakteristik kaki input/output yang tersedia. Merasa berat
dengan semua yang harus Anda pelajari?

Santai saja, sebab semua orang yang levelnya sudah


expert, pasti berawal dari level pemula. Level tersebut akan
Anda dapat tanpa terasa seiring berjalannya waktu.

Yang Anda butuhkan adalah fokus belajar dan


bersabar, bersabar lebih lama dari biasanya!

Kalau dalam belajar Anda merasa pusing, berbahagialah,


itu artinya otak Anda sedang bertumbuh. Itu agak mirip
ketika ada gigi yang mau tumbuh, sehingga gusi kadang
bengkak dan sakit. Begitu juga dengan otak kita. Jika
jaringan di otak kita berusaha membuat simpul-simpul
keilmuan dan pengalaman baru, kadang kita akan merasa
pusing. Percayalah

4
Untuk belajar Arduino, Anda hanya butuh membuat
programnya, upload, jika ada yang error atau aneh, segera
tanya teman, atau cari solusinya di internet.

Begitu juga ketika Anda mencoba sensor : cari contoh


program, sesuaikan variabel dan pin-pinya, upload, jika ada
yang error atau aneh, coba betulkan, jika tetap error, cari
solusinya dari teman atau internet. Banyak sekali pemula
yang belajar Arduino di Indonesia, jadi Anda tidak perlu
takut untuk mulai belajar Arduino. Anda juga bisa gabung di
grup Facebook MONSTER ARDUINO. Jika belum join, Anda
boleh join di https://goo.gl/1PcSEq.

Tabel 1.1 Perbandingan Spesifikasi Beberapa Jenis Arduino

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

Tabel 1.1 menunjukkan spesifikasi beberapa jenis


Arduino berdasarkan jenis processor atau IC mikrokontroller

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.

1.1 Jenis Arduino untuk Pemula


Ini murni pendapat pribadi, berdasarkan pengalaman
ketika mulai belajar Arduino. Awalnya, Anda bisa mulai
dengan Arduino Uno atau Nano. Kenapa? Sebab harganya
relatif terjangkau dan referensi yang berkaitan dengan
kedua jenis Arduino ini lebih banyak daripada jenis lainnya.

Dulu, penulis belajar dengan Arduino Uno. Selanjutnya,


ketika mengerjakan project, penulis biasanya menggunakan
Arduino nano karena harganya lebih murah, setidaknya dua
kali lebih murah daripada Arduino Uno. Ada sekitar 7 buah
Arduino Nano yang siap digunakan untuk mengerjakan
pesanan program dari customer. Kan nggak asik kalau mau
nyoba program harus lepas-pasang arduino.

Kalaupun Anda ingin langsung mulai belajar dengan


Arduino Nano, penulis sarankan sekalian beli mini project
board sehingga lebih mudah kalau mau pasang kabel
jumper. Untuk project yang jumlahnya banyak dan hanya
butuh sedikit program, penulis lebih menyarankan untuk

6
menggunakan Arduino Nano. Kenapa tidak menggunakan
Arduino Pro Mini?

Gambar 1.1 Arduino Nano dengan mini project board

Arduino Pro Mini tidak memiliki jack USB yang bisa


langsung dipasang ke komputer. Jadi misal mau update
program, lebih simpel jika pakai Arduino Nano. Hanya saja,
jika power supply yang ingin Anda gunakan adalah 3.3v,
Anda bisa memilih Arduino Pro Mini yang 3.3v.

1.2 Project yang Butuh Banyak Pin I/O


Jika pin I/O yang Anda butuhkan hanya sebagai
OUTPUT, maka Anda bisa menambahkan shift register.
Dengan IC shift register, Anda hanya membutuhkan 3 buah
pin Arduino untuk dikonversi menjadi 8, 16, atau 24 pin
output. Asik kan? Pembahasan tentang IC shift register ini
juga kita bahas pada buku ini.

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.

Gambar 1.2 Arduino Mega 2560 dan Mega ADK

1.3 Program dengan Clock Tinggi


Varian Arduino memiliki kecepatan dari 8Mhz 400Mhz.
Arduino Uno, Nano, dan Mega beroperasi pada kecepatan
16Mhz. Arduino Pro Mini bisa pilih yang 8Mhz atau yang
16Mhz. Jika butuh kecepatan sekitar 32Mhz, Anda bisa
gunakan Arduino 101. Jika butuh kecepatan 48Mhz, Anda
bisa pilih Arduino Zero.

Selanjutnya ada Arduino Due dengan kecepatan 84Mhz,


dan Arduino Yun dengan kecepatan 400Mhz. Silakan
gunakan sesuai kebutuhan.
8
Gambar 1.3 Arduino Due dan Yun

1.4 Project dengan Ukuran Program Besar


Jika program yang dibuat < 32 kB, Anda bisa
menggunakan Arduino Uno, Nano, atau Pro Mini. Kalau
butuh yang lebih besar, Anda bisa gunakan Arduino Mega,
Due, atau Yun.

Oiya, selain memori untuk menyimpan program.


Arduino juga memiliki 2 buah memori lainnya yaitu EEPROM
dan SRAM. Apa bedanya? Semoga penjelasan tentang
memori ini bisa diterima dengan baik:

1. Memori Flash, memori untuk menyimpan program.


Program yang yang kita buat, setelah dikompilasi akan
disimpan dalam memori ini. Data yang disimpan pada

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.

Kalau boleh diibaratkan, memori flash dan EEPROM


mirip seperti hardisk pada komputer, dimana program dan
data bisa disimpan di sana. Sedangkan SRAM mirip seperti
RAM (DDR, DDR2, dst) sebab data akan hilang apabila
komputer dimatikan.

Untuk Arduino Uno, memori flash berkapasitas 32kB,


EEPROM 1kB, dan SRAM kapasitasnya 2kB. Apakah cukup?
Cukup tergantung kompleksitas program kita.

Gambar 1.4 Informasi penggunaan memory saat program dicompile

Informasi tentang penggunaan memori flash dan SRAM


bisa diketahui saat kita compile program. Pada Gambar 1.4,
besar program hanya 1892 bytes, sekitar 5% dan total

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.

1.5 Saatnya Memilih!


Anda jadi memilih yang mana? Apapun pilihan Anda,
silakan gabung di grup facebook MONSTER ARDUINO.
Sebagai pengingat, harapan dibuatnya group tersebut
adalah untuk belajar lebih dalam tentang materi yang ada di
buku ini.

Target kita tidak hanya jadi Master Arduino,


tapi, jadilah MONSTER ARDUINO!

Monster yang siap mengubah Indonesia lebih baik


dengan adanya teknologi, penggagas ide-ide kreatif yang
dimulai dan dirancang dengan Arduino. Orang-orang
Indonesia itu kreatif, jika kita arahkan untuk merancang
dengan serius, kita bisa mendahului negara-negara maju
lainnya. Hehehe Mimpi bangng?! IYA!!!

Kalau kita mimpinya rame-rame, semoga bisa jadi


kenyataan!

11
Bagian #02

ARDUINO DAN BOOTLOADER

Untuk Indonesia, jadilah Legenda!


(Superman Is Dead)

___

2.1 Sekilas tentang Bootloader

Beberapa pertanyaan tentang bootloader di bawah ini


sering muncul tidak hanya dari programmer pemula seperti
penulis, bahkan kadang programmer veteran pun pernah
mempertanyakannya. Mungkin dalam pikiran Anda juga
pernah tersirat salah satu atau beberapa pertanyaan di
bawah ini:

1. Apa sih fungsi bootloader pada arduino?


2. Bisa nggak, misal bikin arduino tanpa bootloader?
3. Kalau nggak pakai bootloader, Arduino tetep bisa
jalan nggak?
4. Apa kita bisa bikin bootloader sendiri untuk arduino?

Anda bisa menjawab sendiri pertanyaan di atas setelah


memahami cara kerja arduino berdasarkan ilustrasi berikut.

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.

Gambar 2.1 USBAsp untuk AVR dan PIC Programmer

Jika Anda menggunakan Arduino, Anda sudah tidak


memerlukan downloader lagi. Anda bisa langsung
memasang program pada IC melalui software Arduino IDE
di komputer. Fungsi downloader sudah ditangani oleh
bootloader dalam IC. Program yang dikirim komputer ke
Arduino akan ditangkap dan disimpankan oleh bootloader
dalam memori program yang masih kosong.

Program mikrokontroller akan disimpan dalam memori


flash atau flash memory. Setiap mikrokontroller dijalankan,
biasanya alamat program yang pertama dieksekusi adalah
alamat 0x0000 di flash memory.

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.

Gambar 2.2 Perbedaan cara kerja mikrokontroller konvensional


dan cara kerja Arduino

Pada mikrokontroller biasa, yang bertugas menyimpan


program adalah programmer yang berupa hardware.
Sedangkan pada Arduino, proses penyimpanan program ke
memori flash dikerjakan oleh bootloader. Lebih detailnya,
bootloader memiliki cara kerja seperti berikut:

1. Bootloader hanya dieksekusi saat Arduino


dinyalakan. Oleh sebab itu, proses penyimpanan
program oleh bootloader hanya bisa dilakukan
sesaat setelah Arduino direset.

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.

***

Selain berfungsi untuk mengatur program yang akan


diinstal dalam IC, bootloader juga berperan sebagai
pengatur konfigurasi awal arduino seperti clock yang akan
digunakan, mode komunikasi dengan serial komputer,
timer, dan konfigurasi lainnya. Meskipun demikian,
konfigurasi-konfgurasi tersebut tetap bisa kita ubah melalui
program yang kita upload.

Misal kita punya board arduino, tapi IC yang dipasang


tidak ada bootloadernya. Kita tidak bisa langsung
memprogramnya dengan Arduino IDE, sebab perantara
(bootloader) yang bisa menyimpankan program tidak ada.

Kita juga bisa membuat bootloader Arduino versi kita.


Sebagai informasi tambahan, bootloader arduino yang
terbaru berukuran setengah kB dan dikenal juga dengan
istilah optiboot. Anda bisa lihat beberapa versinya di folder
15
instalasi arduino, yaitu pada /hardware/avr/bootloaders atau
bisa cek di https://goo.gl/sjrHYo.

Sebelum Anda lanjut praktek pada bab-bab selanjutnya,


Anda boleh simak pesan-pesan ini. Mari belajar dengan
lebih serius, sebab negeri kita butuh banyak programmer
dan inovator teknologi. Ada banyak pedangan, petani,
nelayan, peternak, dan UKM yang butuh sentuhan teknologi
agar menghasilkan produk yang lebih berkualitas, lebih
cepat, lebih murah, dan lebih banyak, demi kesejahteraan
negeri. Semoga pesan ini bisa diterima dan diingat-ingat.

Sekali lagi, kita butuh para Monster untuk


menggoyang negeri ini dengan inovasi teknologi.

2.2 Cara Install Bootloader Arduino

Setidaknya ada dua cara untuk menginstall bootloader


Arduino, atau istilah lainnya burning bootloader. Yang
pertama, kita bisa menggunakan downloader AVR, di buku
ini kita akan menggunakan USBAsp. Sedangkan cara yang
kedua yaitu menggunakan board Arduino yang sudah ada.

Menggunakan AVR downloader atau Arduino, inti


rangkaian keduanya sama, yaitu menggunakan pin SCK,
MOSI, MISO, dan RST. Detail rangkaian dapat dilihat pada
masing-masing sub pembahasan berikutnya.

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.

2.2.1.1 Rangkaian IC ATMega8 /168/328


Siapkan peralatan dan rangkaian seperti di bawah ini:

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

Sambungan pin antara Programmer dan ATMega:


AVR Programmer IC ATMega8/168/328
Pin MOSI Pin 17 (MOSI)
Pin MISO Pin 18 (MISO)
Pin SCK/CLOCK Pin 19 (SCK/CLOCK)
Pin SS / RST Pin 1 (RST)
VCC VCC
GND GND

17
Gambar 2.3 Rangkaian untuk install bootloader IC ATMega8/168/328

2.2.1.2 Rangkaian untuk Board Arduino

Instalasi bootloader Arduino seperti ini biasanya ketika


IC rusak, atau program dalam IC mengalami bootloop.
Bootloop adalah istilah dimana arduino restart terus-
menerus karena kesalahan program, seperti akibat karena
kesalahan konfigurasi register. Yang perlu disiapkan adalah:

1. Board Arduino x 1
2. Downloader USBAsp x 1
3. Kabel secukupnya x 1

Sambungan pin antara Programmer dan Arduino:


AVR Programmer Arduino Uno/Nano
MOSI Pin 11 (MOSI)
MISO Pin 12 (MISO)
SCK/CLOCK Pin 13 (SCK/CLOCK)
SS / RST Pin RESET (RST)
VCC VCC
GND GND

18
Gambar 2.4 Rangkaian untuk install bootloader langsung ke board Arduino

2.2.1.3 Install Bootloader dengan Progisp

Yang paling penting saat menginstall dengan Progisp


adalah konfigurasi fuse bit. Informasi fuse bit bisa
didapatkan dari file boards.txt dalam folder instalasi Arduino
IDE, yaitu dalam sub folder /hardware/arduino/avr :

Fuse Data
Low 0xFF
High 0xDA
Extended 0xFD

19
Gambar 2.5 Penyesuaian fuse bit pada Progisp

Gambar 2.6 Isi folder /hardware/arduino/avr/bootloder/atmega

Setelah mengatur fuse bit, klik tombol Load Flash untuk


memilih file .hex bootloader di folder program Arduino IDE,
pada subfolder /hardware/arduino/avr/bootloder/atmega.
Pilih file ATmegaBOOT_168_atmega328.hex. File tersebut
adalah bootloader untuk Arduino Uno, Nano, dan Pro Mini
yang 16MHz.
20
Gambar 2.7 Load file .hex bootloader

Gambar 2.8 Proses instalasi bootloader Arduino

21
Selanjutnya, install bootloader dengan menekan tombol
Auto. Tunggu hingga proses instalasi selesai. Untuk
mengecek hasil instalasi, silakan lihat sub bab berikutnya.

2.2.1.4 Install Bootloader dengan AVRDUDE

Untuk menginstall dengan avrdude, Anda bisa pakai


avrdude yang sudah ada di master Arduino IDE, atau Anda
bisa download dari https://goo.gl/Np9MBH. Pastikan Anda
download versi yang terbaru. Setelah berhasil download,
silakan ekstrak di folder yang mudah dijangkau dengan
aplikasi command prompt supaya Anda masuk ke foldernya
tidak capek ngetik, hehe.

Setelah diekstrak, copy file bootloader dari folder


/hardware/arduino/avr/bootloder/atmega. Untuk Arduino
Uno, Nano, Pro Mini 16MHz kita bisa menggunakan file
ATmegaBOOT_168_atmega328.hex. Copy file tersebut,
kemudian paste di folder hasil ekstrakan dari avrdude tadi.

Gambar 2.9 Contoh isi folder avdude dan bootloader Arduino

Selanjutnya, buka command prompt dan ketik perintah


berikut untuk melakukan instalasi bootloader.
22
avrdude -b19200 -c usbasp -p m328p -v -e -U
flash:w:ATmegaBOOT_168_atmega328.hex -U lock:w:0x0F:m

Gambar 2.10 Isi folder avrdude dan perintah untuk menginstall bootloader

Gambar 2.11 Proses instalasi bootloader selesai

Setelah proses instalasi selesai, cek hasil instalasi


dengan cara yang dijelaskan pada subbab selanjutnya.

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.

Gambar 2.12 File program ArduinoISP

Program ArduinoISP sudah ada di sampel program


dalam aplikasi Arduino IDE. Pilih menu File > Examples >
ArduinoISP. Setelah source codenya terbuka, upload dan
tunggu hingga selesai. Setelah ArduinoISP berhasil diinstall,
Arduino Anda sudah berubah menjadi programmer.

24
Selanjutnya, Arduino Anda bisa digunakan untuk
menginstall bootloader atau mengupload program ke
Arduino lainnya langsung dari aplikasi Arduino IDE.

Gambar 2.13 Upload Sketch dengan Arduino sebagai ISP Programmer

Penting!!!
Jika Anda mengupload Sketch ke IC yang terinstall
bootloader dengan Upload Using Programmer, maka
bootloadernya akan ditimpa oleh Sketch tadi!

Jika Anda ingin menupload Sketch dengan arduino


sebagai programmer, maka settinglah programmer sebagai
Arduino as ISP, siapkan sketch yang akan diupload,
kemudian pilih menu Sketch > Upload using Programmer.

25
2.2.3 Install Bootloader dengan Arduino
2.2.3.1 Rangkaian untuk IC ATMega8 /168/328

Siapkan part dan peralatan di bawah ini:

1. Arduino Uno / Nano 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 x 1 (ukurannya 220, 330, 1k, 4k7, atau 10k)
7. Kabel jumper secukupnya

Sambungan pin antara Arduino dan ATMega :

Arduino Uno/Nano IC ATMega8/168/328


Pin 11 (MOSI) Pin 17 (MOSI)
Pin 12 (MISO) Pin 18 (MISO)
Pin 13 (SCK/CLOCK) Pin 19 (SCK/CLOCK)
Pin RESET (RST) Pin 1 (RST)
VCC VCC
GND GND

26
Gambar 2.14 Rangkaian untuk install bootloader dengan Arduino

2.2.3.2 Rangkaian untuk Board Arduino

Ada banyak kombinasi yang bisa dilakukan, misalnya


ingin menginstall bootloader Arduino Uno dengan Uno,
Nano dengan Uno, Uno dengan Nano, Nano dengan Nano,
bahkan Mega dengan Nano. Namun inti dari semua
rangkaian ini adalah pin CLK/SCK dihubungkan ke CLK/SCK,
MOSI ke MOSI, MISO ke MISO, dan pin 10 ke RESET.

Sambungan pin antar Arduino :


Arduino Programmer Arduino Target
Pin 11 (MOSI) Pin 11 (MOSI)
Pin 12 (MISO) Pin 12 (MISO)
Pin 13 (SCK/CLOCK) Pin 13 (SCK/CLOCK)
Pin 10 Pin RESET (RST)
VCC VCC

27
GND GND

Gambar 2.15 Rangkaian install board arduino dengan arduino lainnya

2.2.3.3 Instalasi Bootloader dengan Arduino

Proses instalasi bootloader dengan Arduino dilakukan


dengan tahapan berikut melalui menu Tools:

1. Pastikan pilihan jenis board Arduino disesuaikan


dengan Arduino Target. Jika targetnya Uno, pilih
Uno. Jika Targetnya Nano, pilih Nano.
2. Pilih koneksi Port yang sesuai dengan port Arduino
sebagai Programmer. Ingat, port harus disesuaikan
dengan Port Arduino sebagai Programmer.
3. Ganti settingan Arduino menjadi Arduino as ISP.
4. Pilih Burn Bootloader, lalu tunggu hingga proses
burning atau instalasi bootloader selesai.

28
5. Jika muncul error, Anda bisa langsung googling atau
tanya di grup Facebook MONSTER ARDUINO.

Gambar 2.16 Proses konfigurasi dan instalasi bootloader

2.2.4 Pengecekan Hasil Instalasi Bootloader


Instalasi berhasil ketika LED di pin 13 Arduino berkedip
pelan. Cobalah upload program dari Arduino IDE, jika
berhasil, berarti Anda telah sukses menginstall.

29
Bagian #03

HELLO BUZZER

Tanpa cinta, kecerdasan itu berbahaya,


dan tanpa kecerdasan, cinta itu berbahaya. (B.J Habibie)

___

Kalau dalam bahasa pemgoraman, program pertama


yang dibuat adalah untuk menampilkan Hello World!.
Untuk mikrokontroller umumnya adalah lampu flip-flop.
Tapi kita bisa memulainya dengan cara yang berbeda, kita
pakai Buzzer!

Komponen utama dari program Hello Buzzer adalah


Arduino dan buzzer, aktif buzzer. Apakah kita akan
membahas teori tentang buzzer dahulu? Tidak, kita praktek
dulu. :D

3.1 Project Hello Buzzer


3.1.1 Rangkaian Hello Buzzer
Silakan buat rangkaian seperti berikut. Alat, bahannya
dan skemanya sebagai berikut:

30
1. Arduino Uno x 1
2. Kabel Jumper Male to Female x 2
3. Buzzer Aktif x 1

Sambungan pin antara Arduino dan Buzzer :

Arduino Buzzer
Pin 2 GND
VCC VCC

Gambar 3.1 Rangkaian Project Hello Buzzer

3.1.2 Program Hello Buzzer


Program 3.1 Program Hello Buzzer
1 /*
2 * MONSTER ARDUINO V2
3 * Program Hello Buzzer
4 * www.ElangSakti.com
5 */
6
7 // buzzer disetting active low
8 // BUZZER_OFF kebalikan dari BUZZER_ON
9 #define BUZZER_ON LOW
10 #define BUZZER_OFF !BUZZER_ON
31
11
12 // GND buzzer dihubungkan ke pin 2
13 const byte PIN_BUZZER = 2;
14
15 void setup() {
16
17 // pin buzzer sebagai output
18 pinMode(PIN_BUZZER, OUTPUT);
19
20 }
21
22 void loop() {
23
24 // Tit pertama
25 digitalWrite(PIN_BUZZER, BUZZER_ON);
26 delay(200);
27 // mati sebentar
28 digitalWrite(PIN_BUZZER, BUZZER_OFF);
29 delay(100);
30
31 // Tit kedua
32 digitalWrite(PIN_BUZZER, BUZZER_ON);
33 delay(200);
34 // mati agak lama
35 digitalWrite(PIN_BUZZER, BUZZER_OFF);
36 delay(1000);
37
38 }

Berdasarkan rangkaian pada Gambar 3.1, buzzer


disetting supaya aktif ketika pin 2 berlogika LOW. Sebab,
kaki positif buzzer langsung dihubungkan pada VCC +5v.
Rangkaian ini sengaja penulis balik supaya tidak sama
dengan referensi pada umumnya. Supaya Anda bingung. =))

Jika Anda tidak bingung, Selamat berarti pemahaman


Anda tentang elektronika sudah baik. Tapi jika Anda merasa
bingung, mari dicerna pelan-pelan.
32
3.2 Buzzer Aktif dan Buzzer Pasif
Buzzer yang kita gunakan pada adalah buzzer aktif. Apa
bedanya dengan buzzer pasif? Buzzer aktif adalah buzzer
yang langsung bunyi ketika kita aliri arus listrik. Sedangkan
buzzer pasif adalah buzzer yang akan berbunyi ketika kita
tentukan frekuensi bunyinya.

Maksudnya begini, jika buzzer pasif hanya dialiri arus


listrik atau dihubungkan ke sumber tegangan, ia tidak akan
bunyi. Buzzer pasif akan berbunyi ketika kita berikan nada
atau frekuensi tertentu. Buzzer pasif sama dengan speaker
yang biasanya kita pakai untuk membunyikan musik. Dulu,
di Ebook Versi 1 telah kita bahas, yaitu tentang Tone.

Gambar 3.2 Buzzer aktif dan pasif tampak dari atas (kiri) dan dari bawah (kanan)

Buzzer aktif dan pasif bentuknya agak mirip, tapi kita


bisa membedakannya dengan bagian bawahnya. Pada
buzzer aktif, bagian biasanya terpasang label putih dan
bagian bawahnya tertutup full. Pada buzzer pasif, bagian
atasnya biasanya tanpa label, sedangkan bagian bawah
33
masih ada bagian yang terbuka sehingga papan PCB nya
terlihat. Sebenarnya cara membedakan ini bisa saja tidak
valid, hanya saja dari semua buzzer yang ada, ciri-cirinya
biasanya seperti itu.

3.3 Project Dummy Logger

Kali ini kita akan membuat program yang akan


mengirim data setiap 3 detik. Setiap mengirim data, buzzer
akan berbunyi tilit. Bisakah Anda pura-pura mendengar dan
membayangkannya?

Jika kita perhatikan, program Hello Buzzer dipenuhi


dengan fungsi delay(). Padahal, fungsi delay harus kita
hindari selagi bisa. Sebab, jika kita terlalu banyak
menggunakan delay(), programnya jadi aneh.

Program 3.2 Program Dummy Logger


1 /*
2 * MONSTER ARDUINO V2
3 * Program Dummy Logger
4 * www.ElangSakti.com
5 */
6
7 // buzzer disetting active low
8 // BUZZER_OFF kebalikan dari BUZZER_ON
9 #define BUZZER_ON LOW
10 #define BUZZER_OFF !BUZZER_ON
11
12 // GND buzzer dihubungkan ke pin 2
13 const byte PIN_BUZZER = 2;
14
15 // variabel untuk cek waktu kirim

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 }

Gambar 3.3 Hasil eksekusi program kirim data setiap 3 detik

Program Hello Buzzer bisa dimodifikasi seperti program


di atas. Supaya bisa genap 3 detik, maka harus ditambah
36
delay sekitar 1.5 detik (lihat baris 64). Namun, tidak
sesederhana itu! Program akan bermasalah ketika ada
penambahan source code baru.

Program di atas tidaklah relevan, akan sangat


bermasalah apabila logika program di atas digunakan untuk
data logger. Teknik untuk menyelesaikan project ini kita
bahas pada bab selanjutnya, yaitu tentang optimalisasi
fungsi delay yang umumnya dikenal dengan istilah non-
blocking delay.

37
Bagian #04

TIPS MEMILIH TIPE DATA

Anda tidak bisa mengajari sesuatu kepada seseorang;


Anda hanya dapat membantu orang itu menemukan sesuatu dalam
dirinya. (Galileo Galilei)

___

Jika Anda hanya ingin membuat program sederhana


dan merasa sudah paham cara memilih tipe data yang
cocok, Anda boleh lompati bab ini. Pada bab ini, kita akan
berbagi pengalaman bagaimana cara menggunakan tipe
data dalam memprogram Arduino.

Kenapa memilih tipe data yang cocok menjadi suatu


keharusan?

Arduino tidak sama dengan komputer biasa yang


memiliki kapasitas memori dan media penyimpanan yang
besar. Contoh, pada Arduino Uno, kita hanya diberi ruang
memori sebanyak 1kB untuk menyimpan data, 2kB sebagai
RAM, 32 kB untuk menyimpan program.

Jika Anda membuat data array dengan tipe data long,


maka kapasitas SRAM habis hanya dengan 512 data. Belum
38
lagi jika Anda banyak menggunakan teks atau String.
Bagaimana jika Anda butuh ratusan atau ribuan data
dummy untuk uji coba? Atau bagaimana jika kita perlu
mencetak banyak teks data di serial monitor untuk
keperluan debugging?

Hal ini berbeda ketika kita membuat aplikasi web,


android, atau aplikasi untuk komputer desktop. Dengan
demikian, kita ditantang untuk bijak dalam memilih tipe
data.

Mari kita bahas satu-persatu, semoga Anda bisa


bersabar mempelajari hal-hal remeh semacam ini. Ya, hal
remeh tapi sangat penting untuk pengembangan keilmuan
kita, agar tidak membuat program asal jadi. Mari kita
bongkar secara blak-blakan apa yang penulis pahami
tentang tipe data dan apa saja tips-tipsnya.

4.1 Byte dan Boolean, 1 Byte

Banyak contoh di internet, termasuk di website


arduino.cc yang membuat variabel untuk pin seperti ini:

int LedPin = 2;
int SwitchPin = A0;

Penulis kurang setuju dengan penggunaan tipe data


seperti itu. Kenapa? Karena mengunakan tipe integer untuk
39
diisi dengan pin Arduino itu kurang hemat. Jumlah kaki
Arduino ada berapa? Tidak lebih dari 200. Sedangkan
kapasistas untuk tipe data integer berapa? Kapasitas tipe
integer adalah 65535 (jika mengabaikan tanda negatif).

Sebenarnya, jika hanya untuk pin Arduino, penggunaan


tipe data byte atau unsigned char sudah cukup. Lebih
menghemat memori karena byte kapasitasnya 1 byte.
Sedangkan integer adalah 2 byte. Jika kita memprogram
Arduino Mega dengan tipe data integer untuk 50 pin,
berarti kita menghabis 100 byte hanya untuk nama pinnya
saja, dan itu sudah 5% dari total SRAM-nya Uno. Belum
variabel yang lain.

Penulis lebih senang menggunakan:


const byte LedPin = 2;

Kenapa pakai const (konstanta) dan byte? Sebab LedPin


tidak pernah diubah-ubah dan jumlah pin Arduino PASTI
positif. Kita tidak butuh tipe data negatif. Apalagi tipe data
byte sudah cukup untuk menampung 256 pin Arduino
karena kapasitas untuk data byte adalah 0 255. Tipe data
boolean, true, false, high, dan low sama-sama berkapasitas 1
byte. Jadi tidak ada masalah dengan tipe data ini.

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.

4.3 Integer dan Unsigned Integer, 2 Byte


Penulis hanya menggunakan tipe data ini jika angka
yang akan diolah > 255 dan < 65535, jika datanya hanya
positif. Jika data negatif, maka acuan untuk menggunakan
data ini adalah > 127 dan < 32767, begitu juga untuk data
negatifnya.

Dulu pernah menemukan contoh program yang


menggunakan tipe data int (bukan unsigned int) untuk
menampung data millis(). Hasilnya ya tidak sesuai. Sebab,
millis() pakai tipe data unsigned long yang kapasitasnya 4
byte yang mampu menampung data hingga 4000-an JUTA
angka! Sementara integer maksimal 32 ribuan saja.

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.

4.5 Float atau Double, 4 Byte


Penulis menggunakan tipe data ini hanya untuk data
yang berkoma. Lebarnya sama-sama 4 byte. Yang
membedakan keduanya adalah kepresisiannya. Ada
referensi yang menyebutkan bahwa jika ingin presisi,
gunakan double. Tapi sayang, penulis tidak terlalu
memperhatikan kedua tipe data ini.

4.6 Volatile & Interrupt


Sudah pernah pakai volatile? Jika belum, kemungkinan
besar Anda belum pernah menggunakan interrupt.

Volatile sebenarnya bukan tipe data. Volatile hanyalah


kata kunci atau keyword, atau mungkin bisa penulis
terjemahkan sebagai perintah pada compiler agar data dari

42
variabel yang kita buat tetap disimpan di RAM, bukan di
register. Untuk apa?

Interrupt adalah perintah dadakan yang harus segera


dikerjakan. Contohnya begini, ketika Anda makan, pasti
Anda menyediakan air di dekat Anda. Atau minimal, Anda
sudah memastikan bahwa nanti ada air yang bisa diminum.
Selama Anda menikmati makan, lalu tiba-tiba keselek! Nah,
itu! Itu contoh interrupt! =))

Peristiwa keselek ini adalah peristiwa yang memaksa


Anda untuk segera mencari air untuk minum. Apa yang akan
terjadi jika di dekat Anda tidak ada air???

Boleh Anda bayangkan dan rasakan :D

***

Berikut penjelasan peristiwa makan, keselek, dan minum


yang jika dihubungkan konsep interrupt dan volatile dalam
mikrokontroller:

1. Proses makan adalah program utama.


2. Keselek adalah pemicu interrupt (bisa dari external
interrupt atau dari timer interrupt).
3. Kondisi harus minum adalah interrupt yang harus
dikerjakan.
4. Air adalah data yang harus segera diproses. Jika
airnya masih di dalam sumur, bisa-bisa Anda mati
43
sebelum minum. Begitu juga dengan data, jika
datanya disimpan di register, terlalu lama untuk
memprosesnya, bisa jadi datanya tidak dapat diolah
dengan baik.

Maka, data tersebut harus disimpan di RAM. Agar


data disimpan di RAM, maka kita harus menandainya
dengan keyword volatile. Contoh,

volatile double sensor_data = 0;

Variabel sensor_data bertipe double dengan


keyword volatile menyebabkan 4 byte data untuk
sensor_data disimpan di RAM, bukan memori
register.

Semoga Anda bisa memahami. Bisa Anda perhatikan


pada contoh-contoh program selanjutnya, mungkin Anda
akan bertemu dengan keyword volatile ini, khususnya yang
memabahasa tentang interrupt.

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.

Dengan perintah PROGMEM, maka data akan disimpan


di memori flash. Sekali lagi, data akan disimpan di memori
flash!

Memor flash adalah memori untuk menyimpan


program. untuk Arduino Uno, kapasitasnya 32kB. Jika
bootloader dan program menghabiskan 10 kB, berarti masih
sisah 22 kB lagi yang bisa dipakai.

Contoh program untuk PROGMEM akan dibahas pada


buku serial selanjutnya. Pada kesempatan ini, Anda cukup
tahu dulu dan bisa googling untuk mencari informasi
tentang PROGMEM ini.

4.8 String dengan F( )


Cobalah membuat program yang menampilkan banyak
tulisan di serial terminal. Penulis yakin, ketika jumlah huruf
dalam satu string lebih dari 2000 huruf, pasti ada warning
atau malah error. Kenapa demikian?

Karena kapasitas SRAM hanya 2048 byte.

Untuk mengatasi hal tersebut, Anda bisa menggunakan


PROGMEM atau fungsi F(), eh bukan fungsi, tapi makro F().
45
Makro F() berguna untuk menyimpan tipe data
(contohnya tipe String) ke memori flash. Fungsi makro F()
sama dengan PROGMEM. Bedanya, makro F() bisa dipakai
layaknya sebuah fungsi, sedangkan PROGMEM hanya untuk
inisialisasi. Makro F() bisa dipanggil di bagian mana saja
dalam program.

Seperti itulah beberapa hal yang dapat penulis share


tentang tipe data. untuk pertanyaan lebih lanjut atau
mungkin contoh-contoh juga akan dibahas di grup
Facebook MONSTER ARDUINO.

Selanjutnya, mari kita bahas hal-hal yang menarik


lainnya yang mungkin belum Anda ketahui.

46
Bagian #05

OPTIMALISASI DELAY

Modal bisa memenjarakan manusia,


membuat manusia bekerja tanpa henti dari jam 5 subuh sampai jam 8
malam untuk kekayaan orang lain. (Tan Malaka)

___

5.1 Seberapa Cepatkah 16MHz itu?


Arduino Uno dengan kecepatan 16MHz mampu
mengeksekusi 16.000.000 instruksi dalam 1 detik. Jika Anda
menggunakan delay 1 detik dengan perintah delay(1000),
berarti dia nganggur dalam 1 detik tersebut.

Sebagai gambaran, perintah digitalWrite(13,HIGH);


membutuhkan waktu eksekusi sekitar 5-7 mikrodetik. Jika
kita anggap rata-ratanya 6 mikrodetik yang setara dengan
0.000006 detik, maka kita bisa mengeksekusi sekitar 166.666
lebih perintah digitalWrite() dalam 1 detik. Banyak? Iya!

Daripada Anda memerintahkan Arduino untuk diam


dengan memberikan perintah delay(), lebih baik Anda

47
alihkan pekerjaan Arduino untuk melakukan hal lain seperti
mengecek nilai sensor, ganti tampilan LCD, atau aktivitas
lainnya.

***

Mungkin Anda ingin bertanya, bagaimana penulis bisa


tahu perintah pada kode di atas butuh waktu eksekusi
sekitar 6 mikrodetik? Berikut adalah sketch yang penulis
buat untuk simulasi.

Program 5.1 Program Waktu Eksekusi DigitalWrite


1 /*
2 * MONSTER ARDUINO V2
3 * Program Waktu Eksekusi DigitalWrite
4 * www.ElangSakti.com
5 */
6
7 // pin 13 sebagai output
8 const byte PIN_LED = 13;
9
10 // jumlah sampel data
11 int delay_count = 100;
12
13 // pencatat waktu
14 unsigned long delay_sum = 0;
15 unsigned long delay_first = 0;
16 unsigned long delay_last = 0;
17
18 // logika untuk flip flop
19 boolean flip = true;
20
21 void setup() {
22 // buka koneksi serial
23 // lalu jadikan pin_led sebagai output
24 Serial.begin(19200);
25 while(!Serial);
26 pinMode(PIN_LED,OUTPUT);

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 }

Output program ini dapat dilihat pada Gambar 5.1.


Sebagai tambahan informasi, waktu 6 mikrodetik adalah
waktu rata-rata total eksekusi program dan waktu untuk
load program ke register. Jika program sudah ada dalam
register, maka waktu eksekusi akan lebih cepat.

Kesimpulan dari pembahasan tentang fungsi delay()


adalah: Untuk mendapatkan sistem yang responsive, hindari

49
penggunaan fungsi delay dalam program, kecuali memang
sangat dibutuhkan.

Gambar 5.1 Hasil eksekusi Program Waktu Eksekusi DigitalWrite

5.2 Project Perbaikan Dummy Logger


Rangkain untuk program ini masih sama dengan
rangkain Project Dummy Logger. Sedangkan untuk program
perbaikannya seperti di bawah ini.

Program perbaikannya sama sekali tidak menggunakan


delay(). Untuk menentukan timer 3 detik dan timer untuk
mengaktifkan buzzer menggunakan permainan waktu.

Misalnya, pada waktu pengiriman data dalam 3 detik.


Setiap mengirimkan data, maka waktu pengiriman dicatat

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.

Program 5.2 Program Perbaikan Dummy Logger


1 /*
2 * MONSTER ARDUINO V2
3 * Program Perbaikan Dummy Logger
4 * www.ElangSakti.com
5 */
6
7 // buzzer disetting active low
8 // BUZZER_OFF kebalikan dari BUZZER_ON
9 #define BUZZER_ON LOW
10 #define BUZZER_OFF !BUZZER_ON
11
12 // GND buzzer dihubungkan ke pin 2
13 const byte PIN_BUZZER = 2;
14
15 // variabel untuk cek waktu kirim
16 unsigned long waktu_kirim = 0;
17
18 // logika buzzer
19 const unsigned long buzzer_delay[] = {0,200,100,200};
20 const boolean buzzer_state[] = {BUZZER_ON, BUZZER_OFF, BUZZER_ON,
BUZZER_OFF};
21 byte buzzer_state_counter = sizeof(buzzer_state);
22
23 // pencatat waktu timer buzzer
24 unsigned long buzzer_time = 0;
25 unsigned long buzzer_time_last = 0;
26
27 // pencatat waktu timer kirim data
28 unsigned long kirimdata_time = 0;
29 unsigned long kirimdata_time_last = 0;
30
31 // delay kirim data 3 detik
32 const long kirimdata_delay = 3000;
33
51
34
35 void setup() {
36
37 // aktifkan komunikasi serial
38 // pada baudrate 19200
39 Serial.begin(19200);
40
41 // tunggu hinga Serial siap digunakan
42 while(!Serial);
43
44 // pin buzzer sebagai output
45 pinMode(PIN_BUZZER, OUTPUT);
46 digitalWrite(PIN_BUZZER, BUZZER_OFF);
47
48 // catat waktu kirim pertama kali
49 waktu_kirim = millis();
50
51 }
52
53 void loop() {
54
55 // kirim data
56 KirimData();
57
58 // bunyi tilit tilit
59 TilitTilit();
60
61 }
62
63 void TilitTilit(){
64
65 // state ada 4 kondisi : 0 1 2 dan 3
66 // 0 adalah bip pertama 200ms
67 // 1 adalah matinya bip pertama 100ms
68 // 2 adalah bip kedua 200ms
69 // 3 adalah matinya bip kedua
70 // jika buzzer_state_counter >= 4,
71 // maka blok program ini tdk dieksekusi.
72 if( buzzer_state_counter < sizeof(buzzer_state) ){
73
74 // catat waktu saat ini
75 buzzer_time = millis();
76 // cek apakah delay pada index state sudah terpenuhi
77 if(buzzer_time - buzzer_time_last >=
52
buzzer_delay[buzzer_state_counter]){
78 // aktifkan atau matika buzzer sesuai
79 // logika pada index state
80 digitalWrite(PIN_BUZZER, buzzer_state[buzzer_state_counter]);
81 // pindah state berikutnya
82 buzzer_state_counter++;
83 // catat waktu tadi sebagai waktu eksekusi terakhir
84 buzzer_time_last = buzzer_time;
85 }
86
87 }
88
89 }
90
91 // fungsi untuk mengirim data
92 void KirimData(){
93
94 // catat waktu sekarang
95 kirimdata_time = millis();
96 // apabila waktu kirim terakhir dan waktu sekarang sudah 3 detik
97 // eksekusi blok program berikut
98 if( kirimdata_time - kirimdata_time_last >= kirimdata_delay ){
99
100 // cetak selisih waktu kirim sebelumnya
101 // dengan pengiriman saat ini
102 Serial.print("Selisih Waktu : ");
103 Serial.println( millis() - waktu_kirim );
104
105 // catat waktu kirim data
106 waktu_kirim = millis();
107
108 // catat waktu kirim data terakhir
109 kirimdata_time_last = kirimdata_time;
110
111 // setelah ngirim data
112 // reset state buzzer menjadi 0
113 // sehingga blok program pada
114 // baris 72 dieksekusi
115 buzzer_state_counter = 0;
116
117 }
118 }

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).

Jika fungsi TilitTilit() divisualisasikan dalam time


diagram, maka bentuknya akan tampak seperti Gambar 5.2.

Gambar 5.2 Time diagram untuk kondisi State delay

Nilai State dan delay bisa dicocokan dengan inisialisasi


program pada baris 19-20. Cara kerjanya adalah sebagai
berikut:

1. Saat State direset menjadi 0, yaitu pada baris 115,


maka periksa delay yang pada indeks 0 ms.
2. Jika delay pada State 0 habis (0 ms), buzzer masuk
ke State 0 = kondisi ON. Sementara waktu tunggu
masuk ke State 1, yaitu waktu tunggu 200 ms.

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.

Gambar 5.3 adalah hasil dari program setelah perbaikan.


Hasilnya, waktu pengiriman data lebih pas 3 detik.
Kelebihannya, program ini hanya sedikit terpengaruh
apabila ada penambahan blok program baru. Namun akan
terpengaruh apabila ada bagian blok program yang
menggunakan delay yang melebihi 3 detik. Lalu bagaimana
solusinya?

Gambar 5.3 Hasil perbaikan program Dummy Logger

Salah satu solusinya adalah menggunakan Timer


Interrupt yang akan kita bahas pada bab selanjutnya.
55
Namun sebelum kita membahas tentang timer interrupt,
penulis akan berbagi tentang salah satu source code yang
dapat digunakan sebagai pengganti delay.

Source code tersebut bisa kita sebut delay yang


resposive. Kita sebut delay yang responsive sebab delay ini
tidak memblok dan menghentikan eksekusi bagian program
lainnya sebagaimana fungsi delay().

5.3 Program Simpel Delay yang Responsive


Program 5.3 Program Delay Responsive
1 /*
2 * MONSTER ARDUINO V2
3 * Program Delay Responsive
4 * www.ElangSakti.com
5 */
6
7 // buzzer disetting active low
8 // BUZZER_OFF kebalikan dari BUZZER_ON
9 #define BUZZER_ON LOW
10 #define BUZZER_OFF !BUZZER_ON
11
12 // GND buzzer dihubungkan ke pin 2
13 const byte PIN_BUZZER = 2;
14
15 // logika buzzer
16 boolean DATA_BUZZER = BUZZER_OFF;
17
18 void setup() {
19
20 // pin buzzer sebagai output
21 pinMode(PIN_BUZZER, OUTPUT);
22 // matikan buzzer
23 digitalWrite(PIN_BUZZER, DATA_BUZZER);
24
25 }
56
26
27 void loop() {
28
29 // buzzer akan nyala setiap 1 detik
30 if( nonblocking_delay(1000) ){
31 DATA_BUZZER = !DATA_BUZZER;
32 digitalWrite(PIN_BUZZER, DATA_BUZZER);
33 }
34
35 // program di baris 30-33 memiliki fungsi yg sama
36 // dengan program berikut:
37
38 // digitalWrite(PIN_BUZZER, BUZZER_ON);
39 // delay(1000);
40 // digitalWrite(PIN_BUZZER, BUZZER_OFF);
41 // delay(1000);
42
43 }
44
45 // tambahan untuk membuat delay non blocking
46 unsigned long nonblocking_time = millis();
47 unsigned long nonblocking_last = millis();
48 boolean nonblocking_delay(long milidetik){
49 nonblocking_time = millis();
50 if(nonblocking_time - nonblocking_last >= milidetik){
51 nonblocking_last = nonblocking_time;
52 return true;
53 }
54 return false;
55 }

Cara kerja program : Buzzer akan menyala satu detik,


mati satu detik, dan begitu seterusnya.

Biasanya, dulu kalau membuat LED flip flop, banyak


referensi yang menggunakan blok program seperti pada
baris 37 40. Nah, karena kita harus terbiasa untuk
menghindari fungsi delay, maka penulis membuat fungsi

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.

Cara menggunakan fungsi ini cukup dimasukkan dalam


fungsi if(), kemudian tentukan delay yang diinginkan.
Dengan demikian, program akan dieksekusi secara simultan
sesuai delay atau durasi yang diinputkan.

Fungsi nonblocking_delay() memanfaatkan catatan


waktu eksekusi, khususnya dalam satuan milidetik. Waktu
eksekusi terakhir akan dibandingkan dengan waktu eksekusi
saat ini (lihat baris 49). Jika selisihnya lebih besar atau sama
dengan nilai delay yang telah ditentukan, maka output dari
fungsi ini adalah true. Namun jika belum sampai pada
selisih waktu yang ditentukan, fungsi ini akan menghasilkan
output false.

Blok program pada baris 45 54 akan sering kita


gunakan pada program dan project selanjutnya. Jadi,
pastikan Anda memahami cara kerja fungsi tersebut.

Jika Anda menginginkan timer yang presisi, Anda bisa


gunakan timer interrupt. Mari kita bahas timer interrupt,
silakan lanjut ke bab berikutnya.

58
Bagian #06

RESPONSIVE DENGAN
TIMER INTERRUPT

Orang yang menginginkan impiannya menjadi kenyataan, harus


menjaga diri agar tidak tertidur. (Richard Wheeler)

___

6.1 Seperti Apa Timer Interrupt?


Simpelnya, timer interrupt adalah salah satu dari ISR
(Interrupt Service Routine) yang merupakan interupsi yang
dilakukan berdasarkan pewaktu atau timer. Bagian program
yang dieksekusi sebagai interupsi akan dianggap lebih
penting daripada program yang sedang berjalan.

Oleh sebab itu, bagian program yang sedang berjalan


akan dijeda sementara sehingga alur program dialihkan ke
bagian program yang diinterupsikan. Setelah program
interupsi selesai, maka bagian program yang tadinya dijeda,
akan dilanjutkan lagi.

59
Gambar 6.1 Perbedaan program dengan interupsi dan tanpa interupsi

Berdasarkan ilustrasi tersebut, kita bisa menginterupsi


setiap sekian milidetik atau bahkan setiap mikrodetik.
Bahkan ketika kita mengeksekusi perintah delay() sekalipun,
interupsi tetap dijalankan. Mau bukti? Mari kita langsung
coba dengan Arduino.

6.2 Program Timer Interrupt Sederhana


Program 6.1 Program Timer Interrupt Sederhana
1 /*
2 * MONSTER ARDUINO V2
3 * Program Timer Interrupt Sederhana
4 * www.ElangSakti.com
5 */
6
7 // timer interrupt 1Hz
8 int Data_Hz = 1; // per 1 S
9

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).

Gambar 6.2 Hasil eksekusi program dengan timer Interrupt

Jika ingin menggunakan timer interrupt, maka yang


harus dilakukan adalah:

1. Memilih waktu interrupt, interrupt akan dilakukan


dalam durasi berapa lama? Pada contoh di program,
interrupt dilakukan setiap 1 detik (lihat baris 8).
2. Setelah menentukan waktu interrupt, hitung alamat
register yang akan dimasukkan untuk konfigurasi
waktu yang telah kita pilih tadi (lihat baris 11).

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.

6.3 Dummy Logger dengan Timer Interrupt


Program 6.2 Program Dummy Logger dengan Timer Interrupt
1 /*
2 * MONSTER ARDUINO V2
3 * Program Dummy Logger dengan Timer Interrupt
4 * www.ElangSakti.com
5 */
6
7 // buzzer disetting active low
8 // BUZZER_OFF kebalikan dari BUZZER_ON
9 #define BUZZER_ON LOW
10 #define BUZZER_OFF !BUZZER_ON
11
63
12 // GND buzzer dihubungkan ke pin 2
13 const byte PIN_BUZZER = 2;
14
15 // variabel untuk cek waktu kirim
16 unsigned long waktu_kirim = 0;
17
18 // logika buzzer
19 const unsigned long buzzer_delay[] = {0,200,100,200};
20 const boolean buzzer_state[] = {BUZZER_ON, BUZZER_OFF, BUZZER_ON,
BUZZER_OFF};
21 byte buzzer_state_counter = sizeof(buzzer_state);
22
23 // pencatat waktu timer buzzer
24 unsigned long buzzer_time = 0;
25 unsigned long buzzer_time_last = 0;
26
27 // pencatat waktu timer kirim data
28 unsigned long kirimdata_time = 0;
29 unsigned long kirimdata_time_last = 0;
30
31 // delay kirim data 3 detik
32 const long kirimdata_delay = 3000;
33
34
35 // timer interrupt 10kHz
36 int Data_Hz = 10000; // per 0.1 S
37
38 // hitung register untuk dicocokkan
39 long INT_REGISTER = (16000000L / (Data_Hz*1024L)) - 1;
40
41
42 void setup() {
43
44 // aktifkan komunikasi serial
45 // pada baudrate 19200
46 Serial.begin(19200);
47
48 // tunggu hinga Serial siap digunakan
49 while(!Serial);
50
51 // pin buzzer sebagai output
52 pinMode(PIN_BUZZER, OUTPUT);
53 digitalWrite(PIN_BUZZER, BUZZER_OFF);
54
64
55
56 // catat waktu kirim pertama kali
57 waktu_kirim = millis();
58
59 // setting interrupt
60 cli(); //stop interrupts
61
62 TCCR1A = 0; // set TCCR1A register = 0
63 TCCR1B = 0; // set TCCR1B register = 0
64 TCNT1 = 0; // inisialisasi counter = 0
65 OCR1A = INT_REGISTER; // untuk 10kHz
66 TCCR1B |= (1 << WGM12); // aktifkan CTC mode
67 TCCR1B |= (1 << CS12) | (1 << CS10); // Set CS12&CS10bits=1024 prescaler
68 TIMSK1 |= (1 << OCIE1A); // aktifkan timer compare interrupt
69
70 sei(); //allow interrupts
71
72
73 }
74
75 void loop() {
76
77 // program utama
78 delay(30000);
79
80 }
81
82 // ======================================
83 // eksekusi sesuai timer interrupt
84 // ======================================
85 ISR(TIMER1_COMPA_vect){
86 cli(); //stop interrupts
87 // kirim data
88 KirimData();
89 // bunyi tilit tilit
90 TilitTilit();
91 sei(); //allow interrupts
92 }
93
94 void TilitTilit(){
95
96 // state ada 4 kondisi : 0 1 2 dan 3
97 // 0 adalah bip pertama 200ms

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

WDT & PROGRAM ANTIMACET

Banyak hal yang bisa menjatuhkanmu.


Tapi satu-satunya hal yang benar-benar dapat menjatuhkanmu adalah
sikapmu sendiri. (Raden Ajeng Kartini)

___

Program antimacet. Ya, jika kita mampu menggunakan


WDT pada program kita, kita bisa membuat program yang
antimacet. WDT adalah singkatan dari watchdog timer atau
timer watchdog. WDT akan otomatis mereset program
apabila program macet atau hang.

Jika kita membuat alat yang mudah dijangkau, mungkin


WDT tidak terlalu terasa pentingnya. Jika alat kita
bermasalah karena program error, kita bisa memantaunya
dari dekat dan tinggal pencet tombol reset untuk
menormalkannya kembali.

Namun, jika alat yang Anda buat diletakkan di atas


loteng, di atas tower, atau di atas gunung, apakah Anda
tidak keberatan jika harus bersusah-susah naik ke sana
hanya untuk mencet tombol reset?!
68
Ilmu tentang WDT ini sepele, tapi efeknya bisa
menghemat biaya dan waktu. Bisa dibayangkan jika Anda
membuat alat untuk mengisi air bak mandi otomatis yang
dapat dikontrol melalui internet. Eh, tiba-tiba tengah malam
alatnya macet, padahal relay pompanya sedang aktif. Apa
yang terjadi? Banjiiiiirrrr :D

***

Konsep WDT bisa dijelaskan dengan perumpamaan


seperti ini: Anggap saja Anda sedang ikut lomba makan 101
buah krupuk. Kemudian Mukidi yang bertugas menghitung
dari 1 sampai 10. Aturannnya lombanya adalah :

1. Setiap 1 krupuk harus habis sebelum hitungan ke 10.


Apabila Anda berhasil menghabiskan krupuk pada
hitungan ke 6, Anda bisa lanjut makan krupuk nomer
2, dan hitungan Mukidi mulai dari angka 1 lagi.
2. Pada krupuk-krupuk selanjutnya, jika pada hitungan
ke-5 Anda keselek hingga hitungan ke-10, maka
Anda kena pinalti. Anda harus mulai dari awal lagi,
makan krupuk dari nomer 1 lagi. Nah, kurang lebih
seperti itu cara kerja WDT. Jika WDT gagal
mengihitung counter, program harus reset dari awal.

Ilustrasi di atas dapat dijabarkan seperti ini : Anda


adalah program Arduino yang sedang dieksekusi. Mukidi
adalah WDT. WDT adalah timer yang bisa dipicu dari
69
internal mikrokontroller atau bisa juga dari eksternal
mikrokontroller. Counter pada WDT tidak pernah berhenti
meski program sedang error atau macet.

Ketika WDT diaktifkan, ia bertugas merestart


Arduino sesuai durasi yang telah ditentukan.

Jika kita mengaktifkan WDT dengan durasi 8 detik, maka


Arduino akan restart setiap 8 detik. Akan aneh kalau alat kita
restart setiap 8 detik kan? hehe.

Dengan demikian, kita harus mereset hitungan timer


WDT sebelum mencapai 8 detik. Seperti kasus Mukidi, kita
harus segera menghabiskan krupuk sebelum hitungan
Mukidi mencapai angka 10.

Jadi, sebelum hitungan WDT yang 8 detik habis, kita


harus mereset WDT menjadi 0 lagi. Proses reset timer WDT
biasanya dilakukan di dalam fungsi loop(). Dengan demikian,
kita harus memastikan bahwa program yang ada di dalam
fungsi loop() tidak membutuhkan waktu lebih dari 8 detik.
Kalau lebih dari 8 detik, entah karena program error atau
delay terlalu lama, maka Arduino akan restart. Simpel kan?

Selanjutnya, mari kita langsung praktek.

Oiya, untuk penjelasan program pada bab 7 akan


dijelaskan pada edisi revisi. Oleh sebab itu, untuk versi

70
ebook versi ini, silakan Anda baca keterangan di setiap
barisnya untuk memahami.

7.1 Program WDT Sederhana


Program 7.1 Program WDT Sederhana
1 /*
2 * MONSTER ARDUINO V2
3 * Program WDT Sederhana
4 * www.ElangSakti.com
5 */
6
7 // include library wdt
8 #include <avr/wdt.h>
9
10 // counter
11 const byte jumlah_krupuk = 10;
12
13 // lama delay makan krupuk dal ms
14 int lama_makan_krupuk[jumlah_krupuk] = {
15 3000,
16 3500,
17 2000,
18 5500,
19 4000,
20 9000, // keselek, jadi lama
21 2000,
22 3000,
23 4000,
24 5000
25 };
26
27 byte giliran = 0;
28
29 void setup() {
30 // disable wdt
31 // lalu tunggu hingga stabil
32 wdt_disable();
33 delay(2000);

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

7.2 Program WDT Lanjutan


Program 7.2 Program WDT Lanjutan
1 /*
2 * MONSTER ARDUINO V2
3 * Program WDT Lanjutan
4 * www.ElangSakti.com
5 */
6
7 // include library wdt
8 #include <avr/wdt.h>
9
10 byte counter = 0;
11
12 void setup() {
13 // disable wdt
14 // lalu tunggu hingga stabil
15 wdt_disable();
16 delay(2000);

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 }

Gambar 7.2 Output Program WDT lanjutan

Penjelasan lebih banyak tentang WDT akan dilejaskan


saat kita membahas tentang interrupt secara keseluruhan
pada edisi selanjutnya. Untuk saat ini, Anda bisa mencoba-
coba program yang khusus WDT dahulu.

75
Bagian #08

MODUL RELAY

Orang yang paling tidak bahagia ialah mereka yang yang paling takut
pada perubahan. (Mignon McLaughlin)

___

Relay adalah komponen yang dapat digunakan sebagai


saklar elektronik. Secara singkat, cara kerja relay adalah
memanfaatkan magnet buatan untuk memicu kontaktor dari
keadaan off menjadi on, atau sebaliknya.

Gambar 8.1 Skema Relay

Ibaratnya begini, jika ingin menghidupkan lampu, kita


harus pencet saklar yang nempel di tembok. Tapi jika
menggunakan relay, kita bisa menghidupkan atau
mematikan lampu tanpa menyentuh saklar lagi. Relay

76
disebut juga sebagai saklar elektronik, yaitu saklar dapat
dikontrol dengan alat elektronik lainnya seperti Arduino.

Gambar 8.2 Relay 2 Channel tampak depan

Gambar 8.3 Relay 2 Channel tampak belakang

Relay umumnya punya 5 pin atau kaki., yang terdiri dari:

1. Dua kaki untuk listrik + dan GND, jika arus dan


tegangannya cukup, maka relay akan aktif yang
ditandai dengan bunyi tek.

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.

Sebelum mencoba relay yang sudah dirangkai dalam


sebuah modul, istilah yang perlu kita pahami yaitu : Active
Low dan Active High. Active Low artinya, relay akan aktif
kalau input diberi logika LOW atau GND. Sedangkan Active
High artinya, relay akan aktif apabila input diberi logika
HIGH atau +5v.

78
8.1 Active Low atau Active High

Gambar 8.4 Skema untuk testing Relay

Relay Active Low atau Active High bisa dicek pada


spesifikasi yang telah ditentukan oleh pabriknya. Jika Anda
ragu, Anda bisa cek langsung modul relaynya dengan
beberapa komponen dan power supply yang cocok.
Perhatikan Gambar 8.4.

Selain untuk menentukan Active Low atau Active High,


cara ini biasa penulis gunakan untuk menentukan apakah
relay berfungsi dengan baik atau tidak. Untuk relay Active
Low, relay akan aktif jika input dihubungkan ke GND. Jika
relay Active High, relay aktif jika input dihubungkan ke VCC.

Namun jika relay tidak merespon ketika diberi input


GND atau VCC, pastikan kabel-kabelnya terhubung dengan
benar. Kalau semua sudah benar, tapi tetap tidak ada
respon. Kemungkinan besar ada komponen yang rusak.
79
8.2 Masalah yang Sering Muncul
Kontaktor relay diaktifkan dengan elektromagnetik yang
dihasilkan oleh kumparan pada relay. Setiap alat yang
memiliki kumparan, sifat elektromagnetik pada kumparan
akan dikembalikan menjadi listrik lagi apabila sumber
tegangannya diputus. Artinya, sesaat setelah sumber
tegangan diputus, maka medan elektromagnetik yang
menyelubungi kumparan akan diserap lagi oleh kumparan
sehingga terbentuklah listrik yang polaritasnya berkebalikan
dengan sumber tegangan. Listrik yang terbentuk dan
berbalik arah ini disebut Back Electromotive Force, atau
bisa disingkat Back EMF.

Gambar 8.5 Polaritas kaki kumparan saat aktif dan sesaat setelah diputus

Bukti adanya Back EMF bisa dilihat di video ini :


https://youtu.be/EtJGgHNe7iY

Apa masalahnya kalau ada Back EMF? Back EMF dapat


mengganggu sistem kelistrikan Arduino, entah karena listrik
yang dihasilkan atau munculnya EMI (Electromagnetic

80
Interference). Untuk hal ini, Anda bisa googling tentang EMI
dan Latch-Up pada mikrokontroller.

Untuk mengatasi adanya Back EMF dan EMI,


dipasanglah dioda pada kaki kumparan dan tambahan
kapasitor untuk memfilter. Hanya saja, proteksi ini kadang
gagal. Sehingga mengakibatkan sistem kelistrikan tetap
terganggu. Efek nyatanya, Arduino akan RESTART sesaat
setelah relay dimatikan.

Jika Anda membuat sistem yang agak sensitif terhadap


medan elektromagnet, Anda bisa mengisolasi power supply
relay dari power supply Arduino. Selain itu, Anda juga bisa
mengganti relay dengan SSR (Solid State Relay). Cara
mengisolasi power supply pada relay yang akan dipakai
akan kita jelaskan pada sub bab berikutnya.

8.3 Mengisolasi Power Supply


Pada modul Relay, ada jumper JD-VCC, VCC, dan GND.
Jangan pernah memasang jumper antara VCC dan GND, ya..
. Jika jumper dipasang antara JD-VCC dan VCC, berarti
sumber tegangan untuk Relay adalah sesuai VCC di sebelah
IN1 dan IN2. Tapi jika ingin menggunakan sumber tegangan
dari luar, silakan lepas jumpernya. Kemudian dirangkai
seperti gambar 8.6.

81
Gambar 8.6 Isolasi power supply Relay

JD-VCC dihubungkan ke kabel positif power supply,


GND ke GND. Untuk bagian input, GND TIDAK dihubungkan
ke GND Arduino. Kenapa? Jika GND dihubungkan ke GND
Arduino, maka rangkaiannya tidak terisolasi lagi. Jika Anda
masih masih bingung kenapa rangkaiannya seperti itu, coba
pelajari skema pada Gambar 8.7.

Gambar 8.7 Skema internal optocoupler modul Relay

Skema rangkaian di atas menunjukkan bahwa sisi kiri


(VCC dan IN2) dan sisi kanan (JD-VCC dan GND) dipisah
82
oleh optocoupler U3. Jadi rangkaian Relay benar-benar
terisolasi dari rangkaian Arduino. Selanjutnya, mari kita ulas
sedikit tentang SSR.

8.4 Sekilas tentang SSR (Solid State Relay)


Kalau relay adalah saklar elektronik, maka SSR adalah
relay elektronik. Bingung? Tidak kan ya

Relay bisa dibilang termasuk alat elektro mekanik, sebab


ada bagian yang harus bergerak saat ia diaktifkan. Ketika
relay aktif, logam menjadi magnet, lalu tuas tertarik magnet
dan menyambungkan kaki NO dan C.

Gambar 8.8 Contoh Solid State Relay

Sedangkan pada SSR, tidak ada magnet, tidak ada


kumparan, tidak ada tuas yang bergerak. Komponen yang
digunakan sebagai saklar adalah semikonduktor seperti SCR,
TRIAC, atau transistor seperti MOSFET.

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.

Jika dibandingkan dengan Relay biasa, SSR lebih cepat


responnya, kisaran 10us. Sedangkan Relay kisar 10ms. Jika
Anda butuh sistem yang sangat cepat respon dan tanpa
BACK EMF, gunakan SSR. SSR lebih tahan terhadap getaran
dan goncangan. Hal ini disebabkan komponen SSR yang
tidak memiliki tuas dan perangkat mekanik lainnya. Yang
menjadi kelebihan lagi dari SSR adalah: harganya lebih
tinggi dari Relay biasa.

Semakin tinggi harganya, semakin berkualitas


barangnya.

Mungkin Anda setuju dengan pernyataan di atas,


mungkin juga tidak. Relatif kan ya? Semua orang juga tahu
bahwa harga berbanding lurus dengan kualitas.

Selanjutnya, kita akan membahas bagaimana tips dan


teknik memprogram tombol push button supaya fungsinya
tidak monoton. Silakan langsung lompat ke bab selanjutnya.

84
Bagian #09

EKSPLORASI TOMBOL PUSH BUTTON

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)

___

Pada buku versi pertama, kita telah belajar tentang push


button atau tombol. Kita juga telah belajar tentang
bagaimana sebuah tombol dijadikan sebagai INPUT dan
merangkai tombol dengan pullup resistor. Pada buku ini kita
akan membahas tentang:

1. Cara menggunakan internal Pullup Resistor


2. Membuat tombol multikondisi
3. Membuat aksi ketika tombol ditekan lama
4. Menangani banyak tombol dengan sebuah pin
Analog

Di bawah ini adalah gambar push button dengan kaki


panjang, lebih enak jika kita menggunakan project board.
Tidak sulit pas nancepin.
85
Gambar 9.1 DIP Push button, tombol berkaki panjang

9.1 Internal Pullup Resistor


Dengan adanya internal pullup resistor, kita tidak perlu
lagi menambahkan resistor pada tombol sebagai pullup.
Cukup mengaktifkan internal pullup resistor dengan
program.

Mungkin ada bertanya, buat apa sih pullup resistor?

Jika pin Arduino diset sebagai INPUT, maka logika yang


terbaca oleh Arduino tergantung INPUT yang diberikan. Jika
pin dihubungkan ke VCC, logika yang terbaca adalah HIGH.
Jika pin dhibungkan ke GND, maka logika yang terbaca
adalah LOW. Lalu bagaimana jika pin tidak dihubungkan ke
VCC atau GND?

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.

Ngomong-ngomong, apakah perasaan Anda pernah


digantung sama orang? =)) *abaikan

Untuk mengaktifkan internal pullup resistor, pin Arduino


tidak didefinisikan dengan INPUT lagi, tapi INPUT_PULLUP.
Langsung buat rangkaian seperti di bawah ini. Setelah itu,
coba kedua program di bawah untuk melihat perbedaan
antara penggunaan INPUT dan INPUT_PULLUP.

9.1.1 Rangkaian Testing Pullup Resistor

Peralatan dan rangkaian yang perlu disiapkan adalah:

1. Arduino x 1
2. Push button x 1
3. Kabel jumper secukupnya

Sambungan pin Antara Arduino dan push button :

Arduino Push Button


Pin 2 Kaki 1
GND Kaki 2

87
Gambar 9.2 Rangkaian untuk testing Internal Pullup Resistor

9.1.2 Program Tombol tanpan Pullup Resistor


Program 9.1 Program Tombol tanpa Pullup Resistor
1 /*
2 * MONSTER ARDUINO V2
3 * Program Tombol tanpa 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
21 pinMode(PIN_TOMBOL,INPUT);
22 }
23

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 }

Setelah program diupload, Anda boleh cek di Serial


Monitor dengan baud rate 19200. Nilai apa yang keluar, 0
atau 1? Atau tampilannya kacau? Saya sengaja tidak
menampilkan hasilnya di sini supaya Anda mencobanya
sendiri.

Ketika pin Arduino dalam kondisi floating (tidak jelas


apakah defaultnya 0 atau 1), maka dia akan kebingungan.
Sehingga yang muncul di Serial Monitor adalah 0 dan1
bergantian, meski tombol tidak diapa-apakan.

Selanjutnya edit baris 21 hingga menjadi program


selanjutnya, dan bandingkan hasilnya.

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 }

Pada program yang kedua, data akan muncul jika


tombol ditekan. Berdasarkan logika program, data dicetak
90
ke serial monir apabila data berubah (logika yang diterima
berbeda dengan logika sebelumnya), lihat baris 29.

Dengan tambahan pengetahuan ini, Anda telah belajar


bagaimana menangani input berupa tombol dan mengerti
tentang pullup resistor yang ada dalam internal Arduino.

9.2 Membuat Tombol Multikondisi


Apa maksud dari tombol multikondisi? Normalnya,
tombol push button hanya punya dua logika, ON dan OFF,
namun kondisi ON tidak dapat terkunci. Jika kita
menggukan switch ON/OFF seperi saklar, kondisi ON akan
terkunci dengan mudah karena proses pengunciannya
secara fisik.

Jika kita pakai tombol push button, akan susah kalau


kita ingin mengunci kondisi ON. Sebab logika tombol akan
langsung berubah menjadi OFF ketika tombol kita lepas.

Untuk mengawali belajar tentang tombol multikondisi,


pertama kita akan membuat program yang lebih manusiawi.
Program yang lebih manusiawi maksudnya adalah informasi
yang muncul di serial monitor bukan angka 0 atau 1, tapi
tulisan yang lebih bisa dipahami.

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.

Program 9.3 Program Tombol yang Manusiawi


1 /*
2 * MONSTER ARDUINO V2
3 * Program Tombol yang Manusiawi
4 * www.ElangSakti.com
5 */
6
7 // kita set supaya tombol active low
8 #define ON LOW
9 #define OFF !ON
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 void setup() {
20 // buka koneksi ke serial
21 Serial.begin(19200);
22 while(!Serial);
23
24 // tombol sebagai input dengan pullup resistor
25 pinMode(PIN_TOMBOL,INPUT_PULLUP);
26 }
27
28 void loop() {
29 // baca data tombol
30 data = digitalRead(PIN_TOMBOL);
31
32 // jika data berbeda dari data sebelumnya
33 // cetak ke serial monitor
34 if(data != data_last){
92
35
36 // jika ON, cetak ON
37 // jika OFF, cetak OFF
38 if(data == ON){
39 Serial.println("ON");
40 } else {
41 Serial.println("OFF");
42 }
43
44 // simpan data sebagai data sebelumnya
45 data_last = data;
46 }
47 }

Gambar 9.3 Hasil Program Multikondisi yang Manusiawi

Pada output Program 9.3, muncul tulisan ON ketika


tombol ditekan. Lalu akan muncul tulisan OFF ketika
penekanan tombol dilepas. Mungkin sesekali akan muncul
tulisan ON dan OFF dua kali. Hal tersebut bisa menjadi
masalah, sebab memang perubahaan data memang terjadi

93
2 kali yaitu perubahan dari OFF ke ON ketika tombol mulai
ditekan dan perubahan dari ON ke OFF saat tombol dilepas.

Kita bisa memodifikasi karakteristik tombol di atas


supaya mirip dengan switch ON/OFF. Jadi, ketika tombol
ditekan, maka kondisi akan ON. Jika tombol ditekan lagi,
kondisi berubah menjadi OFF. Jika tombol ditekan lagi,
kondisi menjadi ON lagi, dan seterusnya.

Jadi status ON dan OFF-nya seakan bisa dikunci seperti


switch atau saklar. Silakan langsung coba program
selanjunya.

9.2.2 Program Tombol dengan Lock Status

Program 9.4 Program Tombol dengan Lock Status


1 /*
2 * MONSTER ARDUINO V2
3 * Program Tombol dengan Lock Status
4 * www.ElangSakti.com
5 */
6
7 // kita set supaya tombol active low
8 #define ON LOW // active low
9 #define OFF !ON
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

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 }

Pada Program 9.4, status ON atau OFF tombol tidak


didasarkan pada data yang dibaca oleh digitalRead(). Akan
tetapi, status ON atau OFF ditentukan dengan variabel
logika (lihat baris 20). Cara kerjanya seperti ini :

1. Pertama kali, variabel logika berstatus OFF.


2. Jika tombol ditekan, data variabel logika dibalik
menjadi OFF.
3. Jika tombol ditekan lagi, data variabel logika dibalik
lagi menjadi ON. Begitu seterusnya.
4. Proses pembalikan logika dilakukan pada baris 56.
5. Untuk membalik logika, kita hanya butuh
mendeteksi penekanan tombol, yaitu ketika kondisi
tombol = ON. Lihat baris 53.

Program 9.4 sudah tidak lagi menampilkan dua kali


eksekusi untuk sekali penekanan tombol. Pencegahan dua
kali eksekusi dilakukan dengan menambahkan pemeriksaan
apakah logika tombol berubah atau tidak (lihat baris 50).
Terakhir kali menekan tombol dicatat pada baris 70.
96
Jadi, selama logika tombol tidak berubah, maka Arduino
akan mengunci status dan tombol tidak akan pernah
terbaca berkali-kali. Kecuali tombol dilepas, baru status akan
kembali berubah.

***

Selanjutnya, mari kita pisah fungsi untuk membaca


tombol dan fungsi yang mengeksekusi aksi dari penekanan
tombol. Kenapa harus dipisah? Bukannya kalau bersatu kita
bisa teguh???

Dengan pemisahan menjadi beberapa fungsi, akan lebih


mudah ketika kita ingin modifikasi dan pengembangan
program. Lalu, akan lebih mudah juga jika kita menemukan
error, sebab bagian-bagian program sudah terlokalisasi
sesuai fungsinya. Setiap fungsi dijadikan modul-modul, atau
bisa juga disebut sabagai modular.

9.2.3 Program Tombol Modular


Program 9.5 Program Tombol Modular
1 /*
2 * MONSTER ARDUINO V2
3 * Program Tombol Modular
4 * www.ElangSakti.com
5 */
6
7 // kita set supaya tombol active low
8 #define ON LOW // active low
9 #define OFF !ON

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 }

Program multikondisi kita pecah menjadi dua buah


fungsi. Fungsi pertama untuk membaca logika tombol.
Sedangkan fungsi satunya lagi untuk menangani aksi
99
penekanan tombol. Misal kita ingin mendisable aksi
penekanan tombol cukup dengan mendisable baris 67
dengan menambahkan dua garis miring didepannya. Jika
ingin mendisable fungsi pembacaan tombol, kita tinggal
mendisable baris 41. Lebih simpel daripada menghapus atau
mendisable banyak baris program.

Selanjutnya, kita akan membuat program yang memiliki


banyak menu, tapi dipilih dengan sebuah tombol. Apakah
bisa? Bisa dong

9.2.4 Program Satu Tombol Banyak Menu


Program 9.6 Program Satu Tombol Banyak Menu
1 /*
2 * MONSTER ARDUINO V2
3 * Program Satu Tombol Banyak Menu
4 * www.ElangSakti.com
5 */
6
7 // kita set supaya tombol active low
8 #define ON LOW // active low
9 #define OFF !ON
10
11 // definisikan 4 buah menu
12 // menu 0 - 3
13 #define MENU_0 0
14 #define MENU_1 1
15 #define MENU_2 2
16 #define MENU_3 3
17
18 // tombol pada pin 2
19 const byte PIN_TOMBOL = 2;
20
21 // data awal ada OFF

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 }

Gambar 9.4 Hasil Program Satu Tombol Banyak Menu

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.

Dengan demikian, variasi jumlah logika atau kondisi bisa


lebih lebih banyak lagi, mau 200 menu pun bisa.

Inti dari perubahan menu ini ada pada perubahan


variabel MENU_COUNTER pada baris 85 90. Setiap
tombol ditekan, angka MENU_COUNTER terus bertambah,
jika melebihi jumlah menu yang ada, maka akan direset
menjadi 0. Selain itu, penyesuaian dilakukan pada fungsi
AksiTombol(). Menu akan dicetak sesuai data yang diterima
oleh tombol (lihat baris 110 130).

Jika Anda sudah mulai paham dengan logika program


9.6, mari kita lanjut untuk membuat aksi jika tombol lama
ditekan. Aksi ini seperti kita mau matiin ponsel, setelah kita
tekan tombol power sekian detik, ponsel baru mati. Mari
lanjut ke Program selanjutnya.

9.3 Membuat Aksi Tombol yang Ditekan Lama


Untuk membuat tombol yang bisa melakukan sesuai
ketika terjadi penekanan yang lama ada banyak cara sesuai
kondisi. Namun, inti dari program ini adalah penyisipan

104
timer. Setiap penekanan tombol tidak boleh langsung
diputuskan untuk melakukan aksi. Namun, setiap penekanan
tombol akan ditunggu hingga tombol dilepas.

Jadi, kondisi tombol ditentukan saat tombol dilepas.


Dalam banyak pemrograman komputer ada aksi yang
disebut onKeyUp, artinya aksi yang dikerjakan apabila
tombol dilepas. Dengan begitu, kita bisa menghitung
berapa lama tombol ditekan. Selanjutnya kita akan
membuat program tombol dengan karakteristik berikut:

1. Jika tombol ditekan sebentar, muncul menu utama


2. Jika tombol ditekan > 3 detik, akan muncul menu 1
3. Jika tombol ditekan > 5 detik , akan muncul menu 2
4. Jika tombol ditekan > 10 detik atau lebih, akan
muncul menu 3

9.3.1 Program Aksi Tombol Berdasarkan Lama Ditekan


Program 9.7 Program Aksi Tombol Berdasarkan Lama Ditekan
1 /*
2 * MONSTER ARDUINO V2
3 * Program Aksi Tombol Berdasarkan Lama Ditekan
4 * www.ElangSakti.com
5 */
6
7 // kita set supaya tombol active low
8 #define ON LOW // active low
9 #define OFF !ON
10
11 // definisikan 4 buah menu
12 // menu 0 - 3
105
13 #define MENU_0 0
14 #define MENU_1 1
15 #define MENU_2 2
16 #define MENU_3 3
17
18 // tombol pada pin 2
19 const byte PIN_TOMBOL = 2;
20
21 // data awal ada OFF
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 // pemetaan delay terhadap aksi menu
30 // delay 0 - 3000 => muncul menu_0
31 // delay 3000 - 5000 => muncul menu_1
32 // delay 5000 - 10000=> muncul menu_2
33 // delay > 10000 => muncul menu_3
34 const unsigned int TOMBOL_DELAY[] = {0, 3000, 5000, 10000}; // dalam ms
35
36 // jadikan menu sebagai array supaya lebih mudah
37 const byte MENU[] = {MENU_0,MENU_1,MENU_2,MENU_3};
38 // siapkan teks nama-nama menu
39 const String TEKS_MENU[] = {
40 "Menu Utama",
41 "Menu 1 Setting",
42 "Menu 2 Input Data",
43 "Menu 3 Exit"
44 };
45
46 // cata menu yang aktif saat ini
47 // saat start, menu yg aktif adalah menu_3
48 byte MENU_COUNTER = MENU_3;
49
50 // delay untuk penekanan tombol.
51 // setelah tombol ditekan, maka selama 150 ms
52 // tidak bisa ditekan.
53 // delay ini berguna untuk menghindari 2 kali eksekusi
54 unsigned long delay_press = 150; // dalam ms
55 unsigned long delay_press_last = 0;
56
106
57 // variabel untuk mencatat awal tombol ditekan
58 unsigned long start_press = 0;
59
60 void setup() {
61 // buka koneksi ke serial
62 Serial.begin(19200);
63 while(!Serial);
64
65 // tombol sebagai input dengan pullup resistor
66 pinMode(PIN_TOMBOL,INPUT_PULLUP);
67 }
68
69 void loop() {
70
71 // baca logika tombol
72 TombolListener();
73
74 }
75
76 // fungsi TombolListener
77 void TombolListener(){
78
79 // jika selisih waktu penekanan tombol
80 // lebih besar dari waktu delay tombol
81 // baca tombol lagi, jika tidak tombol tdk dibaca
82 if( millis() - delay_press_last > delay_press ){
83
84 // baca data tombol
85 data = digitalRead(PIN_TOMBOL);
86
87 // jika data berbeda dari data sebelumnya
88 // cetak ke serial monitor
89 if(data != data_last){
90
91 // ketika OFF / onKeyUp
92 if(data == OFF){
93
94 // catat selisih antara
95 // awal tombol ditekan hingga dilepas
96 unsigned long selisih = millis() - start_press;
97
98 if( selisih >= TOMBOL_DELAY[MENU_3] ){
99

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 }

Cara kerja program 9.7 yaitu :


1. Pertama kali tombol ditekan, waktu penekanan
dicatat oleh start_press (lihat baris 122).
2. Selama tombol ditekan, kondisi pada baris 89 bernilai
false. Sehingga blok program di dalam if() tersebut
tidak pernah dieksekusi.
3. Ketika tombol dilepas, kondis if() pada baris 89
bernilai true, karena logika tombol berubah dari true
menjadi false.
4. Karena logika tombol adalah false, maka blok
program pada baris 96 117 akan dieksekusi. Selisih
waktu dihitung, lalu menu dipilih sesuai index tombol
yang telah didefinisikan pada baris 34.
5. Setelah tombol terpilih, eksekusi aksi berdasarkan
tombol yang terpilih tersebut.

109
Program 9.7 relatif simpel, kalaupun belum terbiasa,
sekaranglah waktunya untuk membiasakan berpikir
kerasss!!!

Selanjutnya, mari kita membuat banyak tombol, tapi


dengan sebuah pin INPUT. Bisa kah? Bisa.. asalkan PIN
input yang digunakan adalah Analog. Mari lanjut ke
pembahasan berikutnya.

9.4 Mengelola Banyak Tombol dengan Satu Pin

Gambar 9.5 Rangkaian dasar banyak tombol dengan satu pin

Syarat untuk mengelola tombol dengan sebuah pin


Input adalah pin tersebut harus Analog. Di Arduino Uno, kita
bisa menggunakan pin A0 A5. Kenapa harus analog?
Sebab, kita akan mengimplementasikan konsep pembagi
tegangan dan data diterima dengan pin analog. Anda boleh
memperhatikan gambar 9.5, sebab konsep yang akan kita
pakai akan seperti gambar tersebut.

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.

Jika semua resistor memiliki nilai resistansi yang sama,


maka secara teori data output bisa dihitung seperti Tabel
9.1. Berapapun nilai resistornya, yang penting nilainya
seragam, maka hasilnya akan seperti tabel ini.

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

Berdasarkan tabel di atas, jika data dari analogRead()


adalah sekitar 204, berarti tombol S1 ditekan. Jika data dari
analogRead() adalah sekitar 511, berarti tombol S4 ditekan.
Saya sebut kira-kira karena bisa jadi nilai resistansi resistor
agak berbeda, jadi bisa kurang bisa lebih.

Untuk mengatasi kurang lebih nilai tersebut, kita bisa


ambil nilai toleransi 10 20. Misal untuk tombol S1, berarti
nilai untuk mengidentifikasi tombolnya adalah antara 194
214. Selanjutnya, mari kita buktikan dengan program.
111
9.4.1 Rangkaian Program untuk Membaca 5 Tombol

Peralatan dan rangkaian yang perlu disiapkan adalah:

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

Sambungan pin antara Arduino dan push button :

Arduino Rangkaian Push Button


Pin A0 Output push button (sisi lain dari sisi tombol
yang terhubung ke resistor pembagi tegangan)
VCC Resistor pembagi tegangan
GND Resistor pembagi tegangan sekaligus sebagai
pullup resistor untuk pin A0

Gambar 9.6 Rangkaian program 1 input banyak tombol

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 }

Gambar 9.7 Output program analisis output tombol

Output pada serial monitor masing-masing muncul dua


kali. Data pertama ketika ditekan, data kedua muncul ketika
dilepas. Berdasarkan data tersebut, kita bisa menggunakan
toleransi 20. Sebab jika menggunakan toleransi 10, nilai
114
untuk SW2 mungkin tidak akan terdeteksi. Berdasarkan
perhitungan, nilai output untuk SW2 adalah 255, sementara
yang muncul di serial monitor adalah 246 atau 243. Jika
menggunakan selisih 10, tentu angka 243 tidak terdeteksi
sebagai SW2.

Kurang lebih seperti itu cara kerja dan perhitungannya.


Selanjutnya, mari kita lanjut ke program untuk menampilkan
menu sesuai tombol yang ditekan.

9.4.3 Program Menu 5 Tombol


Program 9.9 Program Menu 5 Tombol
1 /*
2 * MONSTER ARDUINO V2
3 * Program Menu 5 Tombol
4 * www.ElangSakti.com
5 */
6
7 // definisikan 5 tombol
8 #define TOMBOL_NONE 0
9 #define TOMBOL1 1
10 #define TOMBOL2 2
11 #define TOMBOL3 3
12 #define TOMBOL4 4
13 #define TOMBOL5 5
14
15 // output tombol di pin A0
16 const byte PIN_TOMBOL = A0;
17
18 // nilai data tombol sesuai tabel
19 const int TOMBOL_VAL[] = {204,255,341,511,1023};
20
21 // nilai koreksi
22 const byte KOREKSI = 15;
23
115
24 // tombol dalam array
25 const byte TOMBOL[] = {
26 TOMBOL1, TOMBOL2, TOMBOL3,
27 TOMBOL4, TOMBOL5 };
28
29 // tombol saat ini dan tombol sebelumnya
30 byte tombol = 0;
31 byte tombol_last = 0;
32
33 // data saat ini dan data sebelumnya
34 int data = 0;
35 int data_last = 0;
36
37 // delay untuk penekanan tombol
38 unsigned long delay_press = 400; // dalam ms
39 unsigned long delay_press_last = 0;
40
41 void setup() {
42 // buka koneksi ke serial
43 Serial.begin(19200);
44 while(!Serial);
45
46 // tombol sebagai input
47 pinMode(PIN_TOMBOL,INPUT);
48 }
49
50 void loop() {
51
52 // panggil fungsi utk membaca tombol
53 TombolListener();
54 }
55
56 void TombolListener(){
57
58 // jika selisih waktu penekanan tombol
59 // lebih besar dari waktu delay tombol
60 // baca tombol lagi, jika tidak tombol tdk dibaca
61 if( millis() - delay_press_last > delay_press ){
62
63 // baca data analog tombol
64 data = analogRead(PIN_TOMBOL);
65 // reset tombol sebelumnya
66 tombol = TOMBOL_NONE;
67 // cocokkan data dengan ke-5 data tombol
116
68 for(byte i=0; i<sizeof(TOMBOL); i++){
69 // hitung koreksi data tombol
70 // jika ada yang cocok,
71 // catat tombol yang sesuai, lalu
72 // hentikan looping.
73 if( abs(data - TOMBOL_VAL[i]) < KOREKSI ){
74 tombol = TOMBOL[i];
75 break;
76 }
77 }
78
79 // jika ada tombol yang cocok
80 // cetak tombol, panggil aksi tombol
81 // lalu catat waktu pembacaan tombol
82 if(tombol != TOMBOL_NONE){
83 Serial.println(tombol);
84
85 AksiTombol(tombol);
86
87 tombol_last = tombol;
88 delay_press_last = millis();
89 }
90 }
91 }
92
93 // fungsi AksiTombol
94 // INPUT : byte tombol
95 void AksiTombol(byte tombol){
96 switch(tombol){
97 case TOMBOL1:
98 // proses sesuatu
99 Serial.println("Menu 1");
100 break;
101
102 case TOMBOL2:
103 // proses sesuatu
104 Serial.println("Menu 2");
105 break;
106
107 case TOMBOL3:
108 // proses sesuatu
109 Serial.println("Menu 3");
110 break;

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 }

Cara kerja program 9.9 yaitu:

1. Referensi data untuk 5 buah tombol ada di baris 19.


Sedangkan nilai toleransi yang dipilih adalah angka
15 (lihat baris 22).
2. Ketika tombol ditekan, maka data dari tombol
diterima dengan analogRead() pada baris 64.
3. Sebelum mendeteksi tombol, tombol direset untuk
menghindari salah baca (lihat baris 66).
4. Berikutnya data yang terbaca akan dicocokkan
dengan SEMUA referensi nilai tombol (lihat fungsi
loop di baris 68).
5. Data akan dicocokkan dengan setiap referensi data.
Jika selisihnya lebih kecil dari nilai toleransi (lihat
baris 73), maka pilih tombol, lalu stop looping
dengan perintah break pada baris 75.
6. Setelah tombol terpilih, pilih AksiTombol() yang
sesuai denga tombol yang terpilih (lihat baris 85).

118
Gambar 9.8 Output program Menu 5 Tombol

Setelah program 5 tombol dengan satu pin ini bekerja


dengan baik, mari kita lanjut dengan aksi untuk
menghidupkan led untuk setiap tombol. Program tombol
dan LED ini adalah kombinasi dari program membaca
banyak tombol dan program tombol dengan lock status.

Program tombol dan LED ini akan kita gunakan sebagai


dasar untuk mempelajari EEPROM pada bab berikutnya.
Jadi, pastikan Anda mencoba program terakhir pada Bab ini.

9.4.4 Rangkain 5 Tombol 5 LED


Part yang harus disiapkan dan rangkaiannya adalah:

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

Sambungan pin Arduino, LED, dan push button :

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

Gambar 9.9 Rangkaian untuk program 5 tombol 5 LED

Nilai resistor di gambar adalah 220 ohm, tapi Anda bisa


menggunakan nilai lainnya.

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

Setelah Anda memahami cara kerja Program 9.10, mari


lanjut mempelajari EEPROM. EEPROM bisa kita gunakan
untuk menyimpan data-data aplikasi yang sifatnya tidak
boleh berubah ketika Arduino mati atau restart.

125
Bagian #10

EEPROM SEBAGAI BLACKBOX

Hidupmu ada batasnya,jadi jangan sia-siakan hidupmu


untuk terus hidup dari orang lain. (Steve Jobs)

___

Secara singkat EEPROM bisa diibaratkan sebagai hardisk


internal pada Arduino. Data yang disimpan dalam EEPROM
tidak akan hilang meski Arduino dimatikan.

Mungkin Anda pernah menghadapi masalah tentang


konfigurasi atau settingan Arduino yang hilang setelah
Arduino restart atau mati. Kita ambil contoh Program 5
Tombol 5 Led pada bab sebelumnya.

Pada program 5 Tombol 5 Led, ketika beberapa LED kita


hidupkan, lalu Arduino kita reset, maka led yang tadinya
hidup akan kembali ke kondisi awal, yaitu semua LED tidak
menyala. Untuk menyimpan LED status LED nyala atau tidak,
kita bisa menyimpan informasi tersebut pada EEPROM.
Apabila terjadi kegagalan sistem, maka Arduino tidak akan
kehilangan data meskipun Arduino restart berulang-ulang.
Itulah kenapa judul pada bab ini kita namakan BlackBox.
126
Beberapa hal yang harus dipahami tentang EEPROM:

1. Ketahui kapasitas EEPROM, beda Arduino bisa jadi


beda kapasitasnya. Anda boleh cek di pengenalan
jenis-jenis Arduino.
2. Jika data pada alamat EEPROM belum pernah
digunakan untuk menyimpan data, data defaultnya
adalah 255.
3. Setiap alamat EEPROM hanya bisa menyimpan tipe
data byte, yaitu dari 0 255. Jika ingin menyimpan
data lebih dari 255, Anda harus memecahnya ke
dalam beberapa alamat.
4. Library yang harus di-include adalah EEPROM.h yang
sudah ada di Arduino IDE
5. Cara menyimpan ke EEPROM menggunakan perintah
EEPROM.write(alamat,data);
6. Cata membaca data dari EEPROM menggunakan
perintah EEPROM.read(alamat);

Mari kita membuat program counter sederhana. Jika


arduino baru start atau restart, maka counter tidak
mengulang dari depan lagi, tapi melanjutkan counter
sebelumnya. Membuat sistem yang seperti ini dapat
dilakukan dengan bantuan EEPROM. Mari kita praktek

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.

Program 10.1 Program Simulasi EEPROM


1 /*
2 * MONSTER ARDUINO V2
3 * Program Simulasi EEPROM
4 * www.ElangSakti.com
5 */
6
7 // import library EEPROM
8 #include <EEPROM.h>
9
10 // pilih adrress 0 untuk menyimpan data
11 const byte ADDR_COUNTER = 0;
12
13 // nilai maksimum counter
14 const byte counter_max = 100;
15
16 void setup() {
17 // buka koneksi ke serial
18 Serial.begin(19200);
19 while(!Serial);
20
21 // print tulisan Starting saat mulai start
22 Serial.println("Starting...");
23 }
24
25 void loop() {
26
27 // gunakan nonblocking_delay
28 // untuk delay responsive
29 if ( nonblocking_delay(1000) ){
30
128
31 // eksekusi fungsi untuk membaca
32 // dan menyimpan data dalam EEPROM
33 byte data = ReadSaveCounter();
34
35 // cetak counter di serial monitor
36 Serial.print("Counter : ");
37 Serial.println(data);
38 }
39
40 }
41
42 // fungsi untuk baca-tulis data ke EEPROM
43 // INPUT : -
44 // OUTPUT : byte data counter
45 byte ReadSaveCounter(){
46
47 // baca alamat 0 pada EEPROM
48 byte counter = EEPROM.read( ADDR_COUNTER );
49
50 // data yang diperoleh dari EEPROM tambah 1
51 // jika hasil counter > nilai maksimum counter
52 // reset counter ke 0
53 counter++;
54 if (counter > counter_max) counter = 0;
55
56 // simpan lagi data yang telah dimodifikasi
57 EEPROM.write(ADDR_COUNTER, counter);
58
59 // return data
60 return counter;
61 }
62
63 // tambahan untuk membuat delay non blocking
64 unsigned long nonblocking_time = millis();
65 unsigned long nonblocking_last = millis();
66 boolean nonblocking_delay(long milidetik){
67 nonblocking_time = millis();
68 if(nonblocking_time - nonblocking_last >= milidetik){
69 nonblocking_last = nonblocking_time;
70 return true;
71 }
72 return false;
73 }

129
Gambar 10.1 Ouput program simulasi EEPROM

Cara kerja program Simulasi EEPROM adalah:

1. Untuk menggunaan EEPROM, kita harus import


library EEPROM.h pada baris 8.
2. Alamat EEPROM untuk menyimpan data counter
adalah di alamat 0 (lihat baris 11).
3. Setiap arduino mulai start atau restart, kan muncul
tulisan Starting di serial monitor (lihat baris 22).
4. Proses baca tulis EEPROM dilakukan setiap 1 detik
(1000 ms), nilai ini dimasukkan ke fungsi
nonblockin_delay() (lihat baris 29).
5. Setiap 1 detik, arduino akan menjalankan fungsi
ReadSaveCounter() (lihat baris 33).

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.

Ouput program menunjukkan bahwa setiap program


restart, data counter langsung dilanjut berdasarkan data
yang disimpan pada EEPROM. Selanjutnya mari kita
membuat program 5 Tombol 5 LED dapat menyimpan
status LED. Sehingga ketika Arduino aktif, status LED akan
disesuaikan dengan kondisi status LED sebelumnya.

10.2 Program EEPROM 5 Tombol 5 LED


Rangkaian untuk program ini sesuai dengan rangkaian
Rangkaian 5 Tombol 5 LED pada bab sebelumnya.

Program 10.2 Program EEPROM 5 Tombol 5 LED


1 /*
2 * MONSTER ARDUINO V2
3 * Program EEPROM 5 Tombol 5 LED
4 * www.ElangSakti.com
5 */
6
7 // import library EEPROM
8 # <EEPROM.h>
9
10 // led diset active high
11 #define LED_ON HIGH
12 #define LED_OFF !LED_ON
13
131
14 // definisikan 5 tombol
15 #define TOMBOL_NONE 0
16 #define TOMBOL1 1
17 #define TOMBOL2 2
18 #define TOMBOL3 3
19 #define TOMBOL4 4
20 #define TOMBOL5 5
21
22 // output tombol di pin A0
23 // pin led di pin 2 - 6
24 const byte PIN_TOMBOL = A0;
25 const byte PIN_LED[] = {2,3,4,5,6};
26
27 // alamat EEPROM untuk data LED
28 const byte ADDR_LED[] = {0,1,2,3,4};
29
30 // nilai data tombol sesuai tabel
31 // dan nilai toleransi 15
32 const int TOMBOL_VAL[] = {200,250,338,507,1014};
33 const byte TOLERANSI = 15;
34
35 // status led untuk lock status
36 byte STATUS_LED[] = {LED_OFF,LED_OFF,LED_OFF,LED_OFF,LED_OFF};
37
38 // tombol dalam array
39 const byte TOMBOL[] = {
40 TOMBOL1, TOMBOL2, TOMBOL3,
41 TOMBOL4, TOMBOL5 };
42
43 // tombol saat ini dan tombol sebelumnya
44 byte tombol = 0;
45 byte tombol_last = 0;
46
47 // data saat ini dan data sebelumnya
48 int data = 0;
49 int data_last = 0;
50
51 // delay untuk penekanan tombol
52 unsigned long delay_press = 400; // dalam ms
53 unsigned long delay_press_last = 0;
54
55 void setup() {
56 // buka koneksi ke serial
57 Serial.begin(19200);
132
58 while(!Serial);
59
60 // tombol sebagai input
61 pinMode(PIN_TOMBOL,INPUT);
62
63 // pin sebagai output, defaultnya OFF
64 for(byte i=0; i<sizeof(PIN_LED); i++){
65 pinMode(PIN_LED[i],OUTPUT);
66 digitalWrite(PIN_LED[i],LED_OFF);
67 }
68
69 // panggil fungsi PrepareLED
70 // untuk mengetahui status led sebelumnya
71 PrepareLED();
72
73 }
74
75 void loop() {
76
77 // panggil fungsi utk membaca tombol
78 TombolListener();
79 }
80
81 void TombolListener(){
82
83 // jika selisih waktu penekanan tombol
84 // lebih besar dari waktu delay tombol
85 // baca tombol lagi, jika tidak tombol tdk dibaca
86 if( millis() - delay_press_last > delay_press ){
87
88 // baca data analog tombol
89 data = analogRead(PIN_TOMBOL);
90 // reset tombol sebelumnya
91 tombol = TOMBOL_NONE;
92 // cocokkan data dengan ke-5 data tombol
93 for(byte i=0; i<sizeof(TOMBOL); i++){
94 // hitung koreksi data tombol
95 // jika ada yang cocok,
96 // catat tombol yang sesuai, lalu
97 // hentikan looping.
98 if( abs(data - TOMBOL_VAL[i]) < TOLERANSI ){
99 tombol = TOMBOL[i];
100 break;

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 }

Cara kerja program ini seperti Program 5 Tombol 5 LED,


yang membedakannya adalah proses penyimpanan status
LED di EEPROM (lihat baris 180). Selain itu, ketika program
mulai start, maka program akan membaca status LED
sebelumnya di memori dengan fungsi PrepareLED (lihat
baris 71). Fungsi PrepareLED() ada di baris 185 195,
sedangkan baris untuk membaca data di EEPROM ada di
baris 188.

Pada bab sebelumnya, kita telah belajar bagaimana


caranya memperbanyak jumlah tombol (INPUT) dengan pin
Analog dan konsep pembagi tegangan. Selanjutnya, kita
akan memperbanyak jumlah ouput Arduino dengan Shift
Register. Bagiamana caranya? Mari lanjut ke bab
berikutnya

136
Bagian #11

PIN OUTPUT YANG MELIMPAH

Jangan takut gagal, karena yang tidak pernah gagal hanyalah


orang-orang yang tidak pernah melangkah. (Buya Hamka)

___

Pernahkah Anda merasa kalau pin Arduino kurang


ketika membuat sebuah project? Misal ketika
menghubungkan Arduino dengan LCD 1602, atau ketika
Arduino harus mengontrol banyak relay? Nah, solusi untuk
masalah tersebut akan kita bahas pada bab ini.

Untuk memperbanyak pin ouput Arduino, kita bisa


menggunan shift register. Shift register yang akan kita pakai
berupa IC yang berkode 74HC595. Kita tidak akan berteori
terlalu banyak tentang Shift Register ini. Namun kita
usahakan tetap ada informasi tentang Shift Register agar
Anda dapat memahami dengan mudah bagaimana cara
kerjanya. Tentu pengetahuan ini sebagai bekal untuk
berbagai project yang mungkin akan Anda kerjakan nanti.

137
Shift Register (register geser) adalah teknik pergeseran
bit data yang berfungsi untuk mengonversi data serial ke
paralel atau dari paralel ke serial.

Pengertian di atas adalah pendapat pribadi yang


didasarkan pada cara kerja shift register, khususnya untuk
konversi data. Semoga pengertian tersebut bisa dipahami.
Jadi, pengertian tersebut bukanlah pengertian secara
tekstual seperti yang dimuat di buku-buku pada umumnya.

Pada dasarnya ada 4 jenis shift register:

1. Serial In Serial Out (SISO), shift register ini untuk


mengolah atau memodifikasi data serial.
2. Paralel In Paralel Out (PIPO), shift register jenis ini
juga mungkin akan jarang ditemui, gunanya adalah
untuk mengubah data paralel.
3. Serial In Paralel Out (SIPO), shift register ini
digunakan untuk mengonversi data serial ke data
paralel. Jadi input data bisa hanya satu atau dua
jalur, tapi outputnya bisa banyak jalur. Pada bab ini,
kita akan membahas salah satu IC untuk shift
register jenis ini, yaitu menggunakan IC 74HC595.
4. Paralel In Serial Out (PISO), shift register ini untuk
konversi data paralel menjadi data serial.

Bingung dengan istilah data serial dan data paralel?


Perhatikan gambar di bawah ini.
138
Gambar 11.1 Perbedaan transmisi data dengan serial dan paralel

Data serial hanya membutuhkan satu jalur data. Bit data


akan dikirim satu-satu sehingga data harus antri pada jalur
yang sama. Sedangkan data yang ditransfer secara paralel
menggunakan banyak jalur data sehingga data yang dikirim
sesuai jumlah jalur yang tersedia.

Proses konversi dari serial ke paralel atau dari paralel ke


serial diilustrasikan dengan gambar berikut:

Gambar 11.2 Konversi data serial ke paralel (kiri)


dan dari paralel ke serial (kanan)

Pada gambar 11.2 kiri adalah konversi dari serial ke


paralel, input data satu jalur, sedangkan ouputnya menjadi 4
jalur. Pada konversi serial ke paralel, output bisa tak terbatas
tergantung kemampuan IC yang digunakan. Sedangkan

139
konversi dari paralel ke serial (lihat gambar 11.2 kanan),
input data dari 4 jalur, sedangkan outputnya jadi satu jalur.

Seperti itulah penjelasan sangat singkat terkait shift


register. Konsep ini diterapkan pada IC shift register
74HC595 yang akan kita gunakan untuk memperbanyak
kaki Arduino pada bab ini.

11.1 Rangkaian Dasar IC 74HC595

Gambar 11.3 Gambar dan Skema kaki IC 74HC595

IC 74HC595 memiliki jumlah kaki 16. Sebuah IC


74HC595 dapat mengkonversi dari serial data menjadi 8 bit
output. Jika membutuhkan lebih banyak output, kita bisa
menggunakan beberapa IC sekaligus yang dihubungkan
secara seri. Jika butuh 20 output, Anda bisa menggunakan 3
buah IC 74HC595.

Informasi kegunaan pin IC bisa dilihat pada Tabel 11.1.


Setelah Anda memahami cara kerja dan fungsi pin-pinnya,

140
mari kita membuat program lampu berjalan, maksudnya
lampu LED yang nyala satu-satu bergantian.

Tabel 11.1 Fungsi Pin IC 74HC595

Pin Simbol Keterangan


1 Q1 Output bit ke 2
2 Q2 Output bit ke 3
3 Q3 Output bit ke 4
4 Q4 Output bit ke 5
5 Q5 Output bit ke 6
6 Q6 Output bit ke 7
7 Q7 Output bit ke 8
8 GND Ground
9 Q7 Output data serial ke pin input (DS) IC berikutnya
10 MR Master Reset (active low)
11 SH_CP Clock untuk Shift Register
12 ST_CP Latch, Clock untuk Storage Register
13 OE Output Enable (active low)
14 DS Data Serial (DS) input
15 Q0 Ouput bit ke 1
16 VCC VCC

11.2 Project LED Berjalan

11.2.1 Rangkaian LED Berjalan

Peralatan yang disiapkan dan rangkaiannya adalah:

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

Sambungan pin Arduino, IC 74HC595, dan lainnya yaitu :

Arduino IC 74HC595 Komponen Lain


Pin 2 Pin 14, Data -
Pin 3 Pin 12, Latch -
Pin 4 Pin 11, Clock -
VCC Pin 10 dan 16 -
GND Pin 8 dan 13 Resistor ke kaki negatif LED
- Pin 15,1,2,3,4,5,6,7 (Q0-Q) Kaki positif LED 1,2,3,4,5,6,7,8
- Pin 9 -

Gambar 11.4 Rangkain LED berjalan dengan shift register

11.2.2 Program LED Berjalan


Program 11.1 Program LED Berjalan dengan Shift Register
1 /*
2 * MONSTER ARDUINO V2
3 * Program LED Berjalan dengan Shift Register
4 * www.ElangSakti.com
5 */
6
7 // konfigurasi pin Arduino

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 }

Cara kerja program di atas adalah :

1. Untuk mengontrol IC 74HC595, kita membutuhkan 3


buah pin Arduino yang akan digunakan sebagai jalur
data, latch, dan clock (lihat baris 8 - 10).
2. Karena jumlah LED hanya 8 buah, maka kita minimal
harus menggunakan data dengan lebar 8 bit. Data
yang memiliki lebar 8 bit adalah tipe data byte. Jadi
penggunaan tipe data byte sudah cukup untuk
membuat LED berjalan ini.
3. Untuk LED berjalan, kita bisa menggunakan perintah
untuk menggeser bit dari kiri ke kanan atau dari
kanan ke kiri. Pada contoh kali ini kita akan
menggeser bit dari kanan ke kiri. Ilustrasi
pergeserannya adalah seperti berikut:

Gambar 11.5 Ilustrasi pergeseran bit data

Dari angka 1 digeser ke kiri sebanyak 1 bit (lihat


baris 29). Jika sudah sampai pada bit 7, ketika
144
digeser ke kiri satu kali lagi, maka angka akan
berubah jadi 0. Sebab tipe data byte maksimal
hanya hingga bit ke 7. Jika digeser ke bit 8, maka bit
0 7 akan menjadi 0 semua.

4. Untuk mengirim data, maka antara Arduino dan IC


74HC595 harus diaktifkan dan disinkronisasi dahulu
dengan mengaktifkan pin Latch (lihat baris 35).
5. Data dikirim dengan perintah ShiftOut() dan
disesuaikan berdasarkan clock yang disinkronisasi
(lihat baris 37).
6. Setelah pengiriman data selesai, akhiri transfer data
dengan menonaktifkan pin latch (lihat baris 39).

Selain menggunakan perintah ShiftOut, komunikasi ke


IC 74HC595 bisa dilakukan dengan SPI. Apa bedanya? Jika
menggunakan ShiftOut, kita bisa menggunakan kaki mana
saja untuk dijadikan pin Clock dan Data. Jika menggunakan
SPI, maka pin Clock dan Data harus dihubungkan ke pin
digital 13 dan 11.

11.2.3 Rangkaian Shift Register dengan SPI


Peralatan pada rangkaian ini sama dengan rangkain
pada Program 11.1. Yang berbeda adalah kaki untuk pin

145
latch, data, dan clock yang menghubungkan antara Arduino
dan IC 74HC595.

Gambar 11.6 Rangkain LED berjalan dengan shift register SPI

Perbedaan dengan rangkaian sebelumnya adalah jalur


data dan clocknya. Seperti yang telah disebutkan
sebelumnya, jalur data pada pin 11 dan clock pada pin 13.
Jalur untuk pin Latch penulis ganti ke pin 12 supaya
gambarnya cukup rapi.

11.2.4 Program Shift Register dengan SPI


Program 11.2 Program Shift Register dengan SPI
1 /*
2 * MONSTER ARDUINO V2
3 * Program Shift Register dengan SPI
4 * www.ElangSakti.com
5 */
6
7 // include libary komunikasi SPI
8 #include <SPI.h>
146
9
10 // konfigurasi pin Arduino
11 // SH_CP | default SPI di pin 13
12 // data | defatul SPI di pin 11
13 const byte LatchPin = 12; // ST_CP
14
15 // menampung data
16 byte data = 0;
17
18 void setup() {
19
20 // konfigurasi pin sebagai ouput
21 pinMode(LatchPin, OUTPUT);
22
23 // konfigurasi SPI
24 SPI.setBitOrder(MSBFIRST);
25 SPI.setDataMode(SPI_MODE0);
26 SPI.setClockDivider(SPI_CLOCK_DIV2);
27 SPI.begin();
28
29 }
30
31 void loop() {
32
33 // delay 200ms
34 if ( nonblocking_delay(200) ){
35 // geser kiri
36 data <<= 1;
37 // jika data == 0 (gesernya sudah habis)
38 // ulangi dari awal
39 if( data == 0 ) data = 1;
40
41 // mulai transfer
42 digitalWrite(LatchPin, LOW);
43 // kirim data
44 SPI.transfer(data);
45 // stop transfer
46 digitalWrite(LatchPin, HIGH);
47 }
48 }
49
50 // tambahan untuk membuat delay non blocking
51 unsigned long nonblocking_time = millis();

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 }

Cara kerja program ini sama dengan program


sebelumnya, yang berbeda hanya mengirim data (lihat baris
44) dan inisialisasi komunikasinya (lihat baris 24-27). Oiya,
untuk komunikasi SPI, juga harus include library SPI.h (lihat
baris 8) dan hanya butuh konfigurasi pin latch (lihat baris
13). Library SPI.h sudah ada di aplikasi Arduino IDE.

Selain kedua cara di atas, kita juga bisa menggunakan


library Shift Register yang telah dibuat oleh para
pengembang. Ada beberapa library yang bisa Anda
gunakan, ada Shifter, ShiftRegister74HC595, atau library
lainnya. Library tersebut akan kita bahas pada edisi revisi.

Oiya satu lagi, IC Shift Register ini bisa Anda gunakan


untuk mengontrol banyak relay, display 7 segment, bahkan
LCD. Pada buku edisi ini hanya akan membahas tengan cara
mengontrol display 7 segment.

148
Bagian #12

SERBA-SERBI DISPLAY 7 SEGMENT

Tuhan sering mengunjungi kita,


tetapi kebanyakan kita sedang tidak ada di rumah. (Joseph Roux)

___

Anda pasti pernah lihat display seven segment, entah di


pom bensin, kalkulator generasi lama, atau perangkat
elektronika yang menampilkan angka dalam bentuk kotak.

Gambar 12.1 Display seven segment menampilkan harga BBM

Display seven segment terdiri dari 7 buah lampu LED


yang bisa menampilkan angka, dan kadang ada tambahan 1
LED sebagai titik di pojok bawah. Ah, sepertinya basa-
basinya gak penting-penting amat, hehe. Sebab seven
segmen bisa kita ketahui dengan mudah. Mungkin yang
149
tidak begitu mudah adalah memahami skema dan posisi
kaki tiap segmentnya, iya kan?

Sebelum kita lanjut membuat rangkaian dan program,


ada baiknya kita pahami dulu tentang tipe seven segmen
yang biasa kita temui. Jangan sampai salah pilih.

Tipe seven segment yang penulis maksud adalah tipe


Common Cathode dan Common Anode. Cathode atau
Katoda, adalah istilah lain dari GND (ground). Sedangkan
Anode atau Anoda, adalah istilah lain dari VCC (positif). Jika
Anda belum menghafalnya, Anda bisa mengingatnya
dengan sebutan : Aples Kamin.

Apa Aples Kamin?

Aples = Anoda Ples (Plus, kutub + )


Kamin = Katoda Min (minus, kutub - )

Jika Anda lupa Anoda atau Katoda itu apa,


ingatlah baik-baik mantra Aples Kamin.

Secara umum, LED pada seven segment diberi label A, B,


C, D, E, F, G, dan DP. Semua segment LED terhubung
menjadi satu pada salah satu sisinya. Jika yang terhubung
jadi satu adalah kaki positif, maka disebut dengan Common
Anode (CA). Jika yang terhubung jadi satu adalah kaki

150
negatifnya, maka disebut dengan Common Cathode (CC).
Anda boleh memperhatikan dengan seksama gabar di
bawah ini.

Gambar 12.2 Skema seven segment CC dan CA

Di pasaran ada yang jual seven segment, ada yang 1


digit, ada yang 3 digit, ada juga yang 4 digit. Prinsip kerja
semua seven segment tersebut sama saja, hanya saja cara
menampilkan angka dan rangkaiannya sudah pasti beda.

12.1 Seven Segment 1 Digit

Gambar 12.3 Seven segment tunggal tampak depan dan belakang

Kita langsung rangkai dan buat programnya!

151
12.1.1 Rangkaian Seven Segment 1 Digit

Peralatan dan rangkaian yang harus disiapkan adalah:

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

Sambungan pin Arduino dan display 7 segment yaitu :

Arduino Display 7 Segment 1 Digit


Pin 2 Kaki LED A
Pin 3 Kaki LED B
Pin 4 Kaki LED C
Pin 5 Kaki LED D
Pin 6 Kaki LED E
Pin 7 Kaki LED F
Pin 8 Kaki LED G
Pin 9 Kaki LED DP
GND Resistor di kaki common CC

Gambar 12.4 Rangkaian seven segment tunggal


152
Rangkaian di atas menunjukkan bahwa seven segment
yang penulis pakai adalah Common Cathode (CC), sebab
kaki tengah dihubungkan ke GND. Masihkah Anda ingat
Cathode itu istilah lain dari apa? Ingat, Aples Kamin!

Pada rangkaian di atas, penulis menggunakan resistor di


pin common-nya. Sebenarnya penggunaan resistor yang
seperti itu akan berpengaruh pada tingkat kecerahan LED-
nya. Pengaruhnya adalah ketika menampilkan angka 1 akan
lebih cerah daripada ketika menampilkan angka 8. Kenapa?
Sebab arus pada masing-masing LED dipakai bersama. Akan
berbeda hasilnya apabila kita menggunakan resistornya di
masing-masing segment A, B, C, D, E, F, G, dan DP.

Tujuan penulis menggunakan satu buah resistor supaya


lebih simpel dan menghemat penggunaan resistor saja.
Untuk performa terbaik, gunakan resistor di masing-masing
segment, ya.

12.1.2 Program Seven Segment 1 Digit


Program 12.1 Program Seven Segment 1 Digit
1 /*
2 * MONSTER ARDUINO V2
3 * Program Seven Segment 1 Digit
4 * www.ElangSakti.com
5 */
6
7 // definisikan CC, CA, ON, dan Brightness
8 #define COMMON_ANODE HIGH

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 }

Cara kerja program di atas adalah :

1. Pilih jenis seven segment, apakah CC atau CA (lihat


baris 15 16). Beda tipe beda cara mengaktifkan
seven segment (lihat baris 44 49).
2. Set semua segment sebagai output (lihat baris 53)
3. Data pada variabel counter akan berubah setiap
detik dengan delay responsive (lihat baris 61)
158
4. Angka yang akan ditampilkan dari 0 9, jika data
counter > 9, maka reset ke 0 lagi (lihat baris 63).
5. Menampilkan angka dengan fungsi
Digit(angka,dp,kecerahan). Angka adalah angka
yang ditampilkan, dp adalah logika untuk titik
(segment DP), dan kecerahan adalah angka untuk
tingkat kecerahan LED (lihat baris 67).
6. Dalam fungsi Digit(), masing-masing angka punya
cara tersendiri untuk menampilkannya. Contohnya
begini, jika kita ingin menampilkan angka 1, maka
segmen yang harus nyala adalah segment B dan C.

Gambar 12.5 Angka 1 ditampilkan dengan menyalakan


segment B dan C

Dengan demikian, hanya segmen B dan C yang


dinyalakan (lihat baris 95 102). Untuk menampilkan
angka yang lain, maka segment yang harus
dinyalakan juga berbeda.

7. Brightness terkait dengan berapa lama waktu LED


segment nyala dan mati. Anda bisa mengamati baris
80 untuk pengecekan lama segment nyala dan baris

159
195 197 untuk segment OFF seluruhnya. Silakan
coba ubah-ubah angkanya supaya Anda bisa bisa
memahaminya lebih baik

12.2 Seven Segment 4 Digit


Seven segment 4 digit memiliki 12 kaki. 8 kaki untuk
segment, dan 4 untuk digit D1, D2, D3, dan D4. Cara
kerjanya sama dengan seven segment 1 digit. Hanya saja,
untuk menampilkan angka di semua digit, kita harus
melakukan scanning untuk setiap digit. Jadi ke-4 digit harus
gantian nyala.

Gambar 12.6 Seven segment 4 digit tampak depan dan belakang dan skemanya

12.2.1 Rangkaian Seven Segment 4 Digit

Peralatan dan rangkaian yang perlu disiapkan :


160
1. Arduino x 1
2. Display 7 Segment 4 Digit CC x 1
3. Project board x 1
4. Resistor dengan nilai yang seragam x 4
5. Kabel jumper secukupnya

Rangkaian pin Arduino dan 7 segment 4 digit :

Arduino Display 7 Segment 4 Digit


Pin 2 Kaki LED A
Pin 3 Kaki LED B
Pin 4 Kaki LED C
Pin 5 Kaki LED D
Pin 6 Kaki LED E
Pin 7 Kaki LED F
Pin 8 Kaki LED G
Pin 9 Kaki LED DP
Pin A0, A1, A2, dan A3 Resistor pada kaki digit D1, D2, D2, dan D4

Gambar 12.7 Rangkaian segment 4 Digit

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 }

Program ini masih menggunakan contoh counter,


namun counternya dari -50 hingga 200. Cara kerja program
di atas mirip dengan program seven segment 1 Digit. Yang
berbeda adalah :

1. Ada pin digit yang harus diinisialisasi (lihat baris 32


35, 39, dan 76 78)
2. Untuk menampilkan angka, proses menampilkan
angka harus satu-persatu untuk setiap digit yang
terpilih pada variabel DIGIT_SELECT.
3. Karena angka yang ditampilkan lebih dari 1 digit,
maka angka akan dikonversi menjadi string (lihat
baris 103), lalu pilih satu-persatu berdasarkan posisi
indeksnya dengan cara memecah string angka
168
tersebut (lihat baris 117). Angka yang terpilih akan
dikonversi menjadi angka dan ditampilkan sesuai
angka yang cocok (lihat baris 125 245).
4. Untuk menampilkan angka minus, maka data harus
dicek apakah < 0 atau tidak (lihat baris 113).
5. Proses pergeseran digit dipilih saat semua segment
dimatikan (lihat baris 259).

Tampilan counter pada program ini muncul rata kiri


(muncul di sebela kiri seven segment). Untuk memunculkan
di sebelah kanan, Anda bisa coba program Seven Segment
Rata Kanan.

12.2.3 Program Seven Segment Rata Kanan


Rangkaian untuk program ini sama dengan rangkai
program 12.2. Untuk menampilkan angka rata kanan, kita
hanya perlu mengganti baris 121 menjadi :

Program 12.3 Program Seven Segment 4 Digit Rata Kanan


120 // nyalakan digit yang terpilih, geser ke kanan
121 digitalWrite(DIGIT[ sizeof(DIGIT) - (len_data-DIGIT_SELECT) ],DIGIT_ON);

Udah, gitu aja.

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!

12.3.1 Program Seven Segment dengan Sevseg


Program 12.4 Program Seven Segment dengan SevSeg
1 /*
2 * MONSTER ARDUINO V2
3 * Program Seven Segment dengan SevSeg
4 * www.ElangSakti.com
5 */
6
7 // include library sevseg
8 #include <SevSeg.h>
9
10 // buat object dari class sevseg
11 SevSeg SevSegment;
12
13 // pin digit 1-4
14 const byte Digit[] = {A0, A1, A2, A3};
15 // pin segment A,B,C - DP
16 const byte Segments[] = {2,3,4,5,6,7,8,9};
17 // penggunaan R internal
18 const bool R_Segments = false;
19 // tipe seven segment
20 const byte HW_Config = COMMON_CATHODE; // atau COMMON_ANODE
21
22 // counter dari -50
23 int counter = -50;
24
25 void setup() {
26

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;
}

Dengan menggunakan library, kita bisa menghemat


banyak waktu dan tentu baris source codenya jadi lebih
sedikit. Tapi, belum tentu ukuran programnya lebih sedikit
juga.

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!

12.4.1 Rangkaian 7 Segment 1 Digit dengan Shift Register


Peralatan dan rangkaian yang perlu disiapkan adalah:

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

Sambungan pin Arduino, 74HC595, dan 4 segment :

Arduino IC 74HC595 Display 7 Segment 1D


Pin 2 Pin 14, Data -
Pin 3 Pin 12, Latch -
Pin 4 Pin 11, Clock -
VCC Pin 10 dan 16 -
GND Pin 8 dan 13 Resistor di kaki Common
Pin 13,1,2,3,4,5,6,7 (Q0Q7) Pin Segment A,B,C,D,E,F,G,DP

172
Gambar 12.8 Rangkain seven segment dengan shift register

12.4.2 Program 7 Segment 1 Digit dengan Shift Register


Program 12.5 Program Seven Segment dengan Shift Register
1 /*
2 * MONSTER ARDUINO V2
3 * Program Seven Segmen 1D dg Shift Register
4 * www.ElangSakti.com
5 */
6
7 // untuk common cathode
8 #define OFF ~255
9
10 // konversi angka
11 // 8 bit data : A B C D E F G DP
12 const byte angka[] = {
13 B11111100, // 0
14 B01100000, // 1
15 B11011010, // 2
16 B11110010, // 3
17 B01100110, // 4
18 B10110110, // 5
19 B10111110, // 6
173
20 B11100000, // 7
21 B11111110, // 8
22 B11110110, // 9
23 B00000010 // -
24 };
25
26
27 // konfigurasi pin Arduino
28 const byte DataPin = 2; // data
29 const byte LatchPin = 3; // ST_CP
30 const byte ClockPin = 4; // SH_CP
31
32 // data counter
33 byte counter = 0;
34
35 void setup() {
36 // konfigurasi pin sebagai ouput
37 pinMode(LatchPin, OUTPUT);
38 pinMode(ClockPin, OUTPUT);
39 pinMode(DataPin, OUTPUT);
40
41 // pastikan seven segment mati
42 // mulai transfer
43 digitalWrite(LatchPin, LOW);
44 // kirim data
45 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
46 // stop transfer
47 digitalWrite(LatchPin, HIGH);
48 }
49
50 void loop() {
51 // delay 1 detik
52 if ( nonblocking_delay(1000) ){
53 counter++;
54 if(counter >= sizeof(angka)) counter = 0;
55
56 // mulai transfer
57 digitalWrite(LatchPin, LOW);
58 // kirim data
59 shiftOut(DataPin, ClockPin, LSBFIRST, angka[counter]);
60 // stop transfer
61 digitalWrite(LatchPin, HIGH);
62 }
63 }
174
64
65 // tambahan untuk membuat delay non blocking
66 unsigned long nonblocking_time = millis();
67 unsigned long nonblocking_last = millis();
68 boolean nonblocking_delay(long milidetik){
69 nonblocking_time = millis();
70 if(nonblocking_time - nonblocking_last >= milidetik){
71 nonblocking_last = nonblocking_time;
72 return true;
73 }
74 return false;
75 }

Pada rangkaian seven segment biasa, mode komunikasi


antara Arduino dan Seven segment bisa disebut komunikasi
serial. Sebab, ada 8 jalur data untuk mengirim data secara
bersamaan. Dengan shift register, kita hanya butuh 1 jalur
data. Sehingga 8 bit data yang awalnya dikirim secara
paralel, harus kita kumpulkan jadi satu dulu. Ke-8 bit data
tersebut kita urutkan seri, lalu kita kirim berurutan.

Proses pengurutan data menjadi seri (serial), dapat


dilihat pada baris 13 23. Baris 13, data 0B11111100 adalah
data serial untuk angka 0 di seven segment. Begitu juga
dengan angka 1, 2, dan seterusnya. Data-data angka kita
konversi menjadi data yang berurutan (serial).

Proses counter dilakukan seperti biasa, selebihnya


keterangan bisa dibaca pada bagian-bagian programnya.
Penulis percaya Anda sedang bersemangat belajar. Jadi,
silakan coba pahami setiap baris code yang ada di program.

175
Jika sudah paham, mari lanjut dengan 2 digit seven
segment.

12.4.3 Rangkaian Seven Segment 2 Digit dengan Shift Register

Peralatan dan rangkaian yang harus disiapkan adalah:

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

Sambungan pin Arduino, 74HC595, dan 7 Segment :

Arduino IC 74HC595 1 IC 74HC595 2


Pin 2 Pin 14, Data -
Pin 3 Pin 12, Latch Pin 12, Latch
Pin 4 Pin 11, Clock Pin 11, Clock
VCC Pin 10 dan 16 Pin 10 dan 16
GND Pin 8 dan 13 Pin 8 dan 13
- Pin 9 (Q7) Pin 14, Data

IC 74HC595 1 atau 2 Display 7 Segment 1 atau 2


Pin 15,1,2,3,4,5,6,7 (Q0-Q7) Pin Segment A,B,C,D,E,F,G,DP
GND Pin Common

176
Gambar 12.9 Rangkain seven segment 2 digit dengan shift register

Jika menggunakan shift register, berapun output yang


kita inginkan, cukup dikontrol dengan 3 buah pin Arduino.
Yang perlu diperhatikan dalam merangkan 2 buah IC Shift
register adalah:

1. Kaki Clock IC pertam diparalel dengan IC kedua


2. Kaki Latch IC pertama diparalel dengan IC kedua
3. Input DS IC kedua dari Output Q7 IC pertama

Jadi, silakan perhatikan sambungannya baik-baik.

12.4.4 Program Seven Segment 2 Digit dengan Shift Register


Program 12.6 Program Seven Segment 2D dengan Shift Register
1 /*
2 * MONSTER ARDUINO V2
177
3 * Program Seven Segmen 2D dg Shift Register
4 * www.ElangSakti.com
5 */
6
7 // common cathode
8 #define OFF ~255
9
10 // konversi angka
11 // 8 bit data : A B C D E F G DP
12 const byte Angka[] = {
13 B11111100, // 0
14 B01100000, // 1
15 B11011010, // 2
16 B11110010, // 3
17 B01100110, // 4
18 B10110110, // 5
19 B10111110, // 6
20 B11100000, // 7
21 B11111110, // 8
22 B11110110, // 9
23 B00000010 // -
24 };
25
26 // konfigurasi pin Arduino
27 const byte DataPin = 2; // data
28 const byte LatchPin = 3; // ST_CP
29 const byte ClockPin = 4; // SH_CP
30
31 // jumlah digit single seven segment
32 const byte jumlah_digit = 2;
33
34 // data counter
35 int counter = 0;
36
37 void setup() {
38 // konfigurasi pin sebagai ouput
39 pinMode(LatchPin, OUTPUT);
40 pinMode(ClockPin, OUTPUT);
41 pinMode(DataPin, OUTPUT);
42
43 // pastikan seven segment mati
44 // mulai transfer
45 digitalWrite(LatchPin, LOW);
46 // kirim data
178
47 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
48 // stop transfer
49 digitalWrite(LatchPin, HIGH);
50 }
51
52 void loop() {
53
54 // delay 200ms
55 if ( nonblocking_delay(200) ){
56 counter++;
57 if( counter >= 100 ) counter = 0;
58 // cetak angka
59 PrintDigit(counter, jumlah_digit);
60 }
61 }
62
63 // fungsi untuk mencetak angka
64 // INPUT : angka dan jumlah_digit
65 void PrintDigit(int angka, byte jumlah_digit){
66 // konversi angka jadi string
67 String numstr = String(angka);
68 byte lenstr = numstr.length();
69
70 // mulai transfer
71 digitalWrite(LatchPin, LOW);
72 // kirim data sesuai index angka
73 for(byte i=0; i<jumlah_digit; i++){
74 if( i < lenstr ){
75 // jika jumlah digit < jumlah angka
76 // cetak angka pada digit tersebut
77 byte posisi = (lenstr-i-1);
78 byte angka = (numstr.substring(posisi,posisi+1)).toInt();
79 shiftOut(DataPin, ClockPin, LSBFIRST, Angka[ angka ]);
80 } else {
81 // jika tidak, matikan digit seven segment
82 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
83 }
84 }
85 // stop transfer
86 digitalWrite(LatchPin, HIGH);
87 }
88
89 // tambahan untuk membuat delay non blocking

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 }

Untuk mempermudah cetak digit yang lebih dari satu,


blok program yang berfungsi untuk menampilkan angka
pada seven segment dipisah ke dalam fungsi tersendiri,
yaitu fungsi PrintDigit(). Fungsi tersebut tidak hanya untuk
menampilkan 1 digit saja, tapi bisa banyak digit, sesuai
dengan jumlah digit yang telah ditentukan (lihat baris 32).

Bagian yang cukup rumit mikirnya adalah pada baris 73


83. Tapi karena programnya sudah jadi, maka Anda tinggal
mencoba dan mempelajarinya, enak kan? Selanjutnya kita
akan kembali menggunakan seven segment 4 digit, tapi
tetap menggunakan shift register.

12.4.5 Rangkaian Seven Segment 4 Digit dengan Shift Register

Peralatan dan rangkaian yang harus disiapkan adalah


sebagai berikut :

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

Sambungan pin Arduino, 74HC595, dan 7 Segment :

Arduino IC 74HC595 Display 7 Segment 1D


Pin 2 Pin 14, Data -
Pin 3 Pin 12, Latch -
Pin 4 Pin 11, Clock -
Pin A0 - D1
Pin A1 - D2
Pin A2 - D3
Pin A3 - D4
VCC Pin 10 dan 16 -
GND Pin 8 dan 13 Resistor di kaki Common
Pin 13,1,2,3,4,5,6,7 (Q0Q7) Pin Segment A,B,C,D,E,F,G,DP

Gambar 12.10 Rangkain seven segment 4 digit dengan shift register

Lagi-lagi, Anda harus lebih teliti merangkainya.


181
12.4.6 Program Seven Segment 4 Digit dengan Shift Register
Program 12.7 Program Seven Segment 4D dengan Shift Register
1 /*
2 * MONSTER ARDUINO V2
3 * Program Seven Segmen 4D dg Shift Register
4 * www.ElangSakti.com
5 */
6
7 // common cathode
8 #define OFF ~255
9
10 // untuk brightness
11 #define BRIGHTNESS 100
12
13 // konversi angka
14 // 8 bit data : A B C D E F G DP
15 const byte Angka[] = {
16 B11111100, // 0
17 B01100000, // 1
18 B11011010, // 2
19 B11110010, // 3
20 B01100110, // 4
21 B10110110, // 5
22 B10111110, // 6
23 B11100000, // 7
24 B11111110, // 8
25 B11110110, // 9
26 B00000010 // -
27 };
28
29 // konfigurasi pin Arduino
30 const byte DataPin = 2; // data
31 const byte LatchPin = 3; // ST_CP
32 const byte ClockPin = 4; // SH_CP
33
34 // untuk mengontrol digit,
35 // kita masih pakai pin arduino
36 // untuk lebih menghemat, bisa tambah
37 // IC shift register lagi
38 const byte Digit1 = A0;
39 const byte Digit2 = A1;
40 const byte Digit3 = A2;
182
41 const byte Digit4 = A3;
42 const byte DIGIT[] = {Digit1, Digit2, Digit3, Digit4};
43
44 // jumlah digit seven segment
45 const byte jumlah_digit = sizeof(DIGIT);
46
47 // digit terpilih untuk diaktifkan
48 byte DIGIT_SELECT = 0;
49
50 // pengaturan untuk brightness
51 unsigned long brightness_now = 0;
52 unsigned long brightness_last = 0;
53 unsigned long brightness_limit = 0;
54
55 int counter = 0;
56
57 void setup() {
58 // konfigurasi pin sebagai ouput
59 pinMode(LatchPin, OUTPUT);
60 pinMode(ClockPin, OUTPUT);
61 pinMode(DataPin, OUTPUT);
62
63 // pastikan bahwa display mati
64 for(byte i=0; i<sizeof(DIGIT); i++){
65 pinMode(DIGIT[i],OUTPUT);
66 digitalWrite(DIGIT[i],HIGH);
67 }
68
69 // pastikan semua segment mati
70 // mulai transfer
71 digitalWrite(LatchPin, LOW);
72 // kirim data
73 shiftOut(DataPin, ClockPin, LSBFIRST, OFF);
74 // stop transfer
75 digitalWrite(LatchPin, HIGH);
76
77 }
78
79 void loop() {
80
81 // delay 1 detik
82 if ( nonblocking_delay(1000) ){
83

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 }

Secara prinsip, antara seven segment yang single digit


dan multi digit memiliki cara yang berbeda saat akan
menampilkan data. Untuk seven segment yang single digit,
kita tidak perlu melakukan scan digit, sebab kan memang
hanya 1 digit. Sedangkan untuk seven segment yan multiple
digit dalam satu modul, proses untuk menampilkan data
harus bergantian dengan cara scan satu-satu.

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.

1. Pada Program 12.4, PrintDigit() ada di baris 59.


Posisinya bisa diletakkan di dalam fungsi
nonblocking_delay().
2. Sedangkan pada Program 12.6, PrintDigit() di baris
90. Posisinya harus diluar fungsi
nonblocking_delay(). Kenapa demikian? Sebab,
pada seven segment 4 digit harus ada proses
scanning. Itulah yang mempengaruhi peletakannya.

Baik, pembahasan seven segment bisa kita akhiri di sini.


Selanjutkan, akan ada project yang displaynya juga
membutuhkan seven segment. Anda boleh ingat-ingat cara
kerja seven segment 1 digit dan 4 digit. Bab selanjutnya
yaitu tentang memaksimalkan tampilan pada LCD1602.
Semoga pembahasan berikutnya lebih menarik.

186
Bagian #13

LEBIH CANTIK DENGAN LCD1602

Jika seseorang belum menemukan sesuatu


untuk diperjuangkan hingga akhir hayatnya, maka kehidupannya
tidak berharga. (Anonim)
___

Pembahasan tentang LCD sudah pernah kita uraikan di


buku yang pertama. Pada buku kali ini, kita akan
mengoptimalkan fungsi LCD, baik dari sisi rangkaian dan
coding. Jika Anda butuh pengetahuan dasar tentang LCD,
Anda boleh download buku panduan yang pertama dengan
mengklik link ini https://goo.gl/JCEDmh.

13.1 Sekilas Modul I2C LCD


Jika menggunakan rangkaian standar, kita butuh 6 8
pin untuk mendapatkan fungsi maksimal seperti
menghidupmatikan backlight dan membaca data dari LCD.

Kali ini kita merekomendasikan penggunaan modul I2C


LCD untuk menghemat penggunaan pin tersebut. Dengan

187
modul ini, kita hanya butuh 2 pin untuk menampilkan data
di LCD. Lebih hemat kan? :D

Gambar 13.1 Modul I2C LCD tampak depan dan belakang

Gambar 13.2 Modul belum dipasang pada LCD dan belum disolder

Ada beberapa bagian penting yang perlu diperhatikan


untuk menggunakan modul ini:

1. Bagian Power Supply, adalah pin VCC dan GND,


penulis pikir Anda sudah paham ya.. :D
2. Bagian Komunikasi, Modul ini berkomunikasi
dengan protokol komunikasi I2C (Inter-Integrated
Circuit). Komunikasi ini membutuhkan 2 jalur data,
satu untuk mengirim data, satunya lagi clock untuk
sinkronisasi. Pada modul, ditandai dengan nama SDA
(Synchronous Data) dan SCL (Synchronous Clock).
Komunikasi I2C juga dikenal dengan komunikasi

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.

Modul I2C LCD sebenarnya adalah I2C IO extender /


expansion yang menggunakan IC PCF8574x dengan huruf x
yang bisa berbeda. Jika Anda penasaran dengan IC ini, Anda
boleh mencari skemanya di internet.

Mari kita langsung praktek!

13.2 Rangkaian Dasar Modul I2C LCD

Semua program akan menggunakan rangkaian seperti


ini. Jadi, selama mencoba program-program pada bab ini,
Anda bisa menggunakan rangkaian seperti Gambar 13.3 dan
peralatan yang dibutuhkan adalah:

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 :

Arduino LCD 1602


Pin A4 SDA
Pin A5 SCL
VCC VCC
GND GND

Gambar 13.3 Rangkaian dasar I2C LCD

Kelebihan dari komunikasi I2C adalah: banyak device,


modul, atau sensor yang bisa dipasang secara paralel dan
tetap dapat berkomunikasi. Anda bisa perhatikan gambar di
bawah ini.

Gambar 13.4 Arduino dengan sensor dan modul I2C


190
Mungkin yang akan jadi pertanyaan, apakah data dari
semua modul tersebut tidak akan tertukar atau saling
bertabrakan, sementara jalur komunikasi hanya satu? Tidak,
sebab setiap modul I2C punya alamat sendiri-sendiri,
termasuk modul I2C untuk LCD.

Darimana kita bisa tahu alamat modul I2C LCD? Ada


library I2C LCD yang sudah otomatis mencari alamat LCD,
ada juga yang tidak. Nah, sebelum kita lanjut untuk
membuat variasi pada tampilan LCD, kita berikan contoh
program untuk mencari alamat I2C.

13.3 Program Mencari Alamat Modul I2C


Program 13.1 Program Mencari Alamat I2C
1 /*
2 * MONSTER ARDUINO V2
3 * Program Mencari Alamat I2C
4 * www.ElangSakti.com
5 */
6
7 // include library wire
8 #include <Wire.h>
9
10 void setup() {
11 // komunikasi serial dg baud 19200
12 Serial.begin(19200);
13 while(!Serial);
14
15 Serial.println("#============o0o=============#");
16 Serial.println("# I2C Scanner #");
17 Serial.println("# Explored by Elangsakti.com #");
18 Serial.println("#============================#");
19
191
20 // panggil fungsi untuk mencari alamat I2C
21 Cari_Alamat();
22 }
23
24 void loop() { }
25
26 void Cari_Alamat() {
27
28 // buka komunikasi
29 Wire.begin();
30
31 byte respon, alamat, modul = 0;
32
33 Serial.println("Scanning...");
34 Serial.println();
35
36 // tes alamat dari 0 - 127
37 for(alamat=0; alamat<127; alamat++){
38 Wire.beginTransmission(alamat);
39 respon = Wire.endTransmission();
40 switch(respon){
41 case 0:
42 Serial.print(" ");
43 Serial.print(modul+1);
44 Serial.print(". Alamat = 0x");
45 if( alamat < 16 ) Serial.print("0");
46 Serial.println(alamat, HEX);
47 modul++;
48
49 break;
50
51 case 4:
52 Serial.print(" - Error ");
53 if( alamat < 16 ) Serial.print("0");
54 Serial.println(alamat, HEX);
55 }
56 }
57 Serial.println();
58
59 if(modul > 0){
60 Serial.print("Ditemukan ");
61 Serial.print(modul);
62 Serial.println(" modul I2C.");
63 }else{
192
64 Serial.println("Tidak ada modul I2C.");
65 }
66
67 delay(2000);
68 }

Cara kerja program diatas adalah mencoba satu-persatu


alamat yang mungkin dipakai oleh modul I2C. Rentang
alamat yang mungkin dipakai adalah dari 0 hingga 127 (lihat
baris 37). Teknik yang dilakukan oleh program di atas adalah
dengan mengetahui respon yang diterima. Jika responnya
adalah 0, berarti ada device I2C di alamat tersebut (lihat
baris 40). Jika tidak ada respon, berarti tidak terpakai.
Berikut contoh hasil alamat LCD yang kita jadikan ujicoba,
kita mendapatkan alamat 0x27.

Gambar 13.5 Output program mencari alamat I2C

Alamat tersebut nantinya kita masukkan ke konfigurasi


LCD. Jika alat I2C tidak ditemukan, kemungkinannya adalah
193
karena kabelnya kendor, alatnya rusak, atau kabel SDA dan
SCL-nya terbalik.

Setelah Anda menemukan alamat I2C yang benar, mari


lanjut ke program berikutnya.

13.4 Program Mengontrol Lampu Backlight LCD

Program ini akan membuat lampu backlight LCD hidup


mati. rangkaian pada program ini sama dengan program
13.1.

Program 13.2 Program Pengontrol Lampu Backlight LCD


1 /*
2 * MONSTER ARDUINO V2
3 * Program Mengontrol Lampu Backlight LCD
4 * www.ElangSakti.com
5 */
6
7 // library LCD dengan modul I2C
8 #include <LiquidCrystal_I2C.h>
9
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 // ===== 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

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 }

Program di atas akan membuat lampu backlight LCD


berkedip setiap detik. Jadi, pastikan jumper LCD dipasang.
Status backlight akan tertulis di LCD. Cara kerja program di
atas adalah :

1. Jika menggunakan modul I2C, maka kita harus import


dulu library LCD yang khusus I2C (lihat baris 8)
2. Jangan lupa jumlah baris dan kolom LCD juga
ditentukan (lihat baris 14 dan 15)
3. Alamat LCD yang sudah kita temukan tadi
dimasukkan ke konfigurasi pada baris 22. Ada
beberapa cara penulisan konfigurasi ini, namun yang
lebih simpel adalah seperti pada baris tersebut.
Semoga penjelasan lebih detail bisa disertakan saat
edisi revisi.

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.

13.5 Program Format Teks LCD

Program ini akan menampilkan tulisan rata kiri, rata


tengah, atau rata kanan.

Program 13.3 Program Format Teks LCD1602


1 /*
2 * MONSTER ARDUINO V2
3 * Program Format Teks LCD1602
4 * www.ElangSakti.com
5 */
6
7 // library LCD dengan modul I2C
8 #include <LiquidCrystal_I2C.h>
9
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
197
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 void setup() {
34
35 // Settingan LCD
36 lcd.begin(LCD_COL,LCD_ROW);
37
38 // Nyalakan Backlight
39 lcd.setBacklight(BACKLIGHT_ON);
40
41 }
42
43 void loop() {
44
45 if( nonblocking_delay(2000) ) {
46
47 SetDisplay("ELANGSAKTI.COM", 0, tipe_format[format], CLEAR);
48
49 switch( tipe_format[format] ){
50 case ALIGN_LEFT:
51 SetDisplay("LEFT", 1, ALIGN_LEFT, !CLEAR);
52 break;
53
54 case ALIGN_CENTER:
55 SetDisplay("CENTER", 1, ALIGN_CENTER, !CLEAR);
56 break;
57
58 case ALIGN_RIGHT:
59 SetDisplay("RIGHT", 1, ALIGN_RIGHT, !CLEAR);
60 break;
61 }
62
63 format++;
64 if( format >= sizeof(tipe_format) ){
65 format = 0;
66 }
67 }
68 }
69
70 // fungsi untuk menampilkan teks pada lcd sesuai format
198
71 void SetDisplay(String data, byte baris, byte format, boolean hapus){
72 if(hapus) lcd.clear();
73 int cols = data.length();
74 if( cols > LCD_COL) format = ALIGN_LEFT;
75 if(format == ALIGN_CENTER){
76 if(cols%2 == 1) cols++;
77 cols = (LCD_COL/2) - (cols/2);
78 }else if(format == ALIGN_RIGHT){
79 cols = LCD_COL - cols;
80 }else{
81 cols = 0;
82 }
83 lcd.setCursor(cols,baris);
84 lcd.print(data);
85 }
86
87 // tambahan untuk membuat delay non blocking
88 unsigned long nonblocking_time = millis();
89 unsigned long nonblocking_last = millis();
90 boolean nonblocking_delay(long milidetik){
91 nonblocking_time = millis();
92 if(nonblocking_time - nonblocking_last >= milidetik){
93 nonblocking_last = nonblocking_time;
94 return true;
95 }
96 return false;
97 }

Program ini akan menampilkan teks rata kiri, rata


tengah, atau rata kanan. Bagian penting dari program ini
yaitu fungsi SetDisplay(). Fungsi SetDisplay() terdiri dari 4
parameter:

1. data, String data yang akan dicetak ke LCD


2. baris, baris LCD. Untuk LCD 1602, pilihannya 0 atau 1
3. format, pilihannya ALIGN_LEFT, ALIGN_CENTER, dan
ALIGN_RIGHT

199
4. hapus, jika bernilai true, maka tampilan LCD akan
dibersihkan (clear) sebelum menulis teks.

Silakan analisa bagaimana cara kerja program ini,


khususnya yang ada dalam fungsi SetDisplay().

13.6 Program Efek Teks NgeBlink

Program ini merupakan salah satu teknik untuk


menampilkan teks ngeblink di LCD.

Program 13.4 Program Efek Teks NgeBlink


1 /*
2 * MONSTER ARDUINO V2
3 * Program Efek Teks NgeBlink
4 * www.ElangSakti.com
5 */
6
7 // library LCD dengan modul I2C
8 #include <LiquidCrystal_I2C.h>
9
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 // ===== 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 boolean blink_state = true;
25 unsigned long blink_timer = 0;

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 }

Program ini akan membuat efek ngeblink pada teks.


Kunci dari efek ini ada pada baris 55. Jika status blink_state
adalah true, maka teks akan digantikan dengan spasi. Jika
tidak, tampilkan teks aslinya. Silakan coba-coba dengan
delay yang berbeda-beda.

13.7 Program Format Teks dan NgeBlink

Program ini menampilan format teks rata kiri, rata


tengah, dan rata kanan dengan efek ngeblink.

Program 13.5 Program Kombinasi Format Teks dan Ngeblink


1 /*
2 * MONSTER ARDUINO V2
3 * Program Kombinasi Format Teks dan NgeBlink
4 * www.ElangSakti.com
5 */
6
7 // library LCD dengan modul I2C
8 #include <LiquidCrystal_I2C.h>
9

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

Pengganbungan kedua efek teks cukup simpel, kita


hanya perlu memodifikasi teks yang akan dicetak dengan
fungsi SetDisplay (lihat baris 48). Pada baris tersebut, setelah
teks diberi efek ngeblink, teks diberi format rata kiri, rata
tengah, atau rata kanan.

13.8 Program Teks Bergerak

Program ini menampilkan cara membuat teks bergerak


dari kiri ke kanan, dari kanan ke kiri, dari atas ke bawah, atau
dari bawah ke atas.

Program 13.6 Program Teks Bergerak


1 /*
2 * MONSTER ARDUINO V2
3 * Program Teks Bergerak
4 * www.ElangSakti.com
5 */
6
7 // library LCD dengan modul I2C
8 #include <LiquidCrystal_I2C.h>
9
10 #define BACKLIGHT_ON HIGH
205
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 #define MOVE_NONE 0
23 #define MOVE_UP 1 // teks rata kiri
24 #define MOVE_DOWN 2 // teks center
25 #define MOVE_LEFT 3 // teks rata kanan
26 #define MOVE_RIGHT 4
27 #define CLEAR true // clear screen
28
29 // ===== Konfigurasi LCD ===========
30
31 // LCD1602 dengan Modul I2C
32 // Alamat I2C di 0x27
33 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
34 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
35
36 // pilihat format penulisan teks
37 byte pilihan_move[] = {MOVE_UP, MOVE_DOWN, MOVE_LEFT,
MOVE_RIGHT};
38 byte moving = MOVE_NONE;
39
40 boolean moving_state = true;
41 unsigned long moving_timer = 0;
42
43 // temporary untuk move_up dan move_down
44 String tmp_teks = "";
45
46 // temporarty untuk move_left dan move_right
47 int posisi_kolom = 0;
48
49 int counter = 0;
50
51 void setup() {
52 // Settingan LCD
53 lcd.begin(LCD_COL,LCD_ROW);
206
54
55 // Nyalakan Backlight
56 lcd.setBacklight(BACKLIGHT_ON);
57 }
58
59 void loop() {
60 String tulisan = "Counter : ";
61 tulisan.concat( counter );
62 MoveText(tulisan, 1, MOVE_UP, 0);
63 delay(1000);
64 counter++;
65 }
66
67
68 void MoveText(String data, byte baris, byte pilih_moving, unsigned long
moving_delay){
69
70 if( millis() - moving_timer < moving_delay ) return;
71
72 int cols = 0;
73 int real_cols = 0;
74
75 switch(pilih_moving){
76 case MOVE_UP:
77
78 SetDisplay(tmp_teks, 0, ALIGN_LEFT, CLEAR);
79 SetDisplay(data, 1, ALIGN_LEFT, !CLEAR);
80 tmp_teks = data;
81
82 break;
83
84 case MOVE_DOWN:
85
86 SetDisplay(tmp_teks, 1, ALIGN_LEFT, CLEAR);
87 SetDisplay(data, 0, ALIGN_LEFT, !CLEAR);
88 tmp_teks = data;
89
90 break;
91
92 case MOVE_LEFT:
93
94 lcd.setCursor(0,baris);
95 for(byte i=0; i<LCD_COL; i++) lcd.print(' ');

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 }

Program teks bergerak ini juga dikombinasikan dengan


format teks rata kiri, rata tengah, atau rata kanan. Fungsi
utama dari program ini adalah MoveText. Ada pilihan
MOVE_UP, MOVE_DOWN, MODE_LEFT, dan MOVE_RIGHT.
Anda bisa mencobanya dengan mengedit baris 62.

13.9 Program Membuat Custom Karakter LCD

Contoh program ini menampilkan cara membuat


karakter sendiri pada LCD sesuai kenginan.

Program 13.7 Program Membuat Custom Karakter LCD


1 /*
2 * MONSTER ARDUINO V2
3 * Program Membuat Custom Karakter LCD
4 * www.ElangSakti.com
5 */
6
7 // library LCD dengan modul I2C
8 #include <LiquidCrystal_I2C.h>
9
10 #define BACKLIGHT_ON HIGH
11 #define BACKLIGHT_OFF !BACKLIGHT_ON
12
13 // jumlah kolom dan baris LCD (16x2)
14 #define LCD_COL 16

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 :

1. Anda harus mendefinisikan bit-bit pixel untuk setiap


karakter pada LCD. Setiap karakter LCD memiliki 5x8
pixel (lihat baris 24 44).
2. Untuk mempermudah pembuatan bit-bit pixelnya,
anda bisa gunakan aplikasi eksternal seperti
https://goo.gl/dYVzAx atau yang lainnya.
3. Setelah memiliki bit karakternya, selanjutnya proses
pembuatan karakter seperti pada baris 60 dan 61.
4. Jika karakter sudah dibuat, selanjutnya tinggal cetak
ke LCD (lihat baris 73 dan 75).

Sepertinya sudah cukup banyak contoh dan tips


memaksimalkan tampilan LCD. Semoga setelah ini
kemampuan kita makin meningkat. Selanjutnya, mari kita
membuat progra muntuk sensor PIR.

213
Bagian #14

ALARM SENSOR PIR

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)

___

Sensor PIR (Passive Infra Red) adalah sensor inframerah


yang didesain hanya untuk mendeteksi sinar inframerah
yang terpancar dari tubuh manusia. Sensor PIR tidak
didesain untuk mendeteksi semua benda yang bergerak.
Kenapa? Anda bisa menemukan alasannya pada penjelasan
selanjutnya.

Sensor PIR disebut pasif sebab sensor tersebut tidak


memancarkan sinar inframerah untuk dideteksi pantulannya.
Sensor PIR hanya menerima sinar inframerah dari
lingkungan sekitar, baik dari lampu, tubuh manusia, dan
semua benda yang memancarkan sinar inframerah.

Bagaimana Sensor PIR dapat mendeteksi manusia?

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.

Gambar 14.1 Blok diagram sensor PIR

Untuk memahami lebih dalam tentang tentang cara


kerja sensor PIR, Anda boleh memperhatikan gambar
bagian-bagian sensor PIR pada Gambar 14.1. Berikut
penjelasan dari gambar tersebut:

1. Energi (sinar infrared) dari lingkungan sekitar akan


melewati lensa Fresnel yang berfungsi memfokuskan
sinar infrared menuju sensor Pyroelectric.
2. Lensa Fresnel adalah pengembangan dari lensa
cembung. Kelebihan dari lensa Fresnel yaitu bentuk
yang jauh lebih tipis dari pada lensa cembung biasa.

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.

14.1 Sensor PIR HC-SR501

Setelah mengetahui bagian-bagian penting dari sensor


PIR, silakan perhatikan modul sensor PIR yang akan kita
pakai untuk belajar, yaitu modul HC-SR501. Simak gambar
14.2 dan 14.3 berikut penjelasannya.

Gambar 14.2 Sensor PIR HC-SR501 tampak luar dan dalam

216
Gambar 14.3 Sensor HC-SR501 tampak belakang

Bagian-bagian yang perlu kita ketahui tentang sensor


PIR HC-SR501:

1. Lensa Fresnel, dapat memfokuskan sinar inframerah


dengan jangkauan sudut 120 o
2. Sensor Pyroelectric mendeteksi sinar inframerah
3. Pengatur delay sensor aktif setelah mendeteksi
gerakan. Jika sensor mendeteksi gerakan, maka lama
sensor akan aktif sesuai dengan kondisi VR. Putar kiri
untuk mengurangi, putar kanan untuk menambah
delay (makin lama). Delay dari 3 300 detik.
4. Pengatur sensitifitas sensor. Semakin sensitif
semakin jauh jangkauan (3 7 meter). Putar kiri
untuk mengurangi sensitifitas, putar kanan untuk
meningkatkan sensitifitas.
5. Pengaturan Trigger. Jumper terpasang pada L, No
Repeat. Jumper terpasang pada H, Repeat. Status
jumper pada gambar, kondisi trigger adalah Repeat.
217
Pengaturan Trigger sangat terkait dengan lama delay.
Jika kondisi Repeat, setiap ada gerakan, maka delay
akan reset ke awal. Jika kondisi No Repeat, maka
sensor tidak akan mendeteksi gerakan lagi sebelum
delay habis.

Contohnya seperti ini, misal delay adalah 5 detik :


- Ketika kondisi No Repeat, misal sensor
mendeteksi gerakan lagi pada detik ke 3, sensor
tidak akan merespon sebelum hitungan 5 detik
berakhir.
- Ketika kondisi Repeat, misal sensor mendeteksi
gerakan lagi pada detik ke 3, maka hitungan detik
akan kembali ke 0 lagi, lalu delay akan
menghitung dari awal hingga 5 detik berakhir.

6. IC pengolah data sensor


7. VCC, GND, dan OUTPUT dalam bentuk sinyal digital.
VCC dapat diberi tegangan 5v 20v. Untuk OUTPUT,
HIGH berarti ada gerakan, LOW berarti tidak ada
gerakan.

Penting!!!
Kelemahan sensor HC-SR501 adalah ada jeda sekitar
5 detik sebelum sensor bisa mendeteksi gerakan
berikutnya.

218
14.2 Rangkaian Sensor HC-SR501

Pada rangkaian ini, kita akan mengaktifkan buzzer


sesuai dengan logika pada Output. Apabila ada gerakan,
maka buzzer akan berbunyi sesuai konfigurasi delay pada
sensor PIR. Perhatikan rangkaian pada Gambar Pin 2
dijadikan output ke buzzer, kaki positif buzzer. Sedangkan
pin 3 dijadikan sebagai input dari sensor PIR.

Silakan atur supaya sensitifitas sensor maksimal dengan


memutar VR di nomer 4 full ke kanan. Kemudian atur
supaya time delay sangat cepat dengan cara mengatur VR
di nomer 3 full ke kiri. Setelah itu, upload program berikut
untuk memberikan nyawa pada arduino sesuai fungsinya.

Alat dan rangkaian yang perlu disiapkan adalah:

1. Arduino x 1
2. Sensor PIR x 1
3. Buzzer x 1
4. Project board x 1
5. Kabel jumper secukupnya

Sambungan pin Arduino, sensor PIR, dan buzzer :

Arduino Sensor PIR Buzzer


Pin 2 - Kaki positif
Pin 3 Ouput -
VCC VCC -
GND GND Kani GND
219
Gambar 14.4 Rangkaian Sensor PIR dan Buzzer

14.3 Program Alarm Sensor PIR


Program 14.1 Program Alarm Sensor PIR
1 /*
2 * MONSTER ARDUINO V2
3 * Program Alarm Sensor PIR
4 * www.ElangSakti.com
5 */
6
7 // pin buzzer di pin 2 dan sensor pir di pin 3
8 const byte PIN_BUZZER = 2;
9 const byte PIN_PIR = 3;
10
11 void setup() {
12 // buzzer sebagai output
13 // sensor pir sebagai input
14 pinMode(PIN_BUZZER,OUTPUT);
15 pinMode(PIN_PIR,INPUT);
16 }
17
18 void loop() {
19 // logika buzzer == logika sensor pir
20 digitalWrite( PIN_BUZZER, digitalRead(PIN_PIR) );
21 }

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.

14.4 Program Identifikasi Delay Sensor PIR


Program 14.2 Program Identifikasi Delay Sensor PIR
1 /*
2 * MONSTER ARDUINO V2
3 * Program Identifikasi Delay Sensor PIR
4 * www.ElangSakti.com
5 */
6
7 // pin + buzzer di pin 2
8 // output sensor pir di pin 3
9 const byte PIN_BUZZER = 2;
10 const byte PIN_PIR = 3;
11
12 // variabel untuk history logika sensor pir
13 boolean logika_pir = LOW;
14 boolean logika_pir_last = logika_pir;
15
16 // variabel untuk mencatat timer
17 unsigned long timer_pir = 0;
18
19 void setup() {
20
21 // aktifkan komunikasi serial di baud 19200
22 Serial.begin(19200);
23
24 // buzzer sebagai output
25 // sensor pir sebagai input
26 pinMode(PIN_BUZZER,OUTPUT);
27 pinMode(PIN_PIR,INPUT);
28

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 }

Rangkaian untuk program ini akan tetap menggunakan


rangkaian sebelumnya. Kita hanya menambahkan program
untuk mengetahui lama delay pada pengaturan VR di no. 3.

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:

1. Putar VR (no. 3) full ke kiri


2. Upload program
3. Buka Serial Monitor, ubah baud rate menjadi 19200
4. Cek dengan menggerakkan bagian tubuh di depan
sensor PIR

Jika ingin mengetahui delay terlama, putar VR (no. 3) full


ke kanan. Silakan coba-coba sendiri.

223
Gambar 14.5 Output program identifikasi delay sensor PIR

Berdasarkan hasil percobaan, delay tercepat adalah


sekitar 2.5 detik (2587 ms). Sedangkan delay terlama adalah
sekitar 8 menit (530345 ms) sebagaimana tampak pada
gambar di bawah. Jika Anda mencoba dan hasilnya jauh
berbeda, itu wajar-wajar saja. Sebab setiap komponen tidak
sama persis yang mempengaruhi pada nilai delay.

14.5 Program Custom Delay Alarm Sensor PIR

Pada kondisi real, delay yang ditentukan oleh VR


kadang tidak sesuai dengan yang kita butuhkan. Contoh,
misal kita ingin mengaktifkan buzzer selama 5 detik setelah
mendeteksi gerakan. Maka akan merepotkan kalau kita
harus memutar-mutar VR hanya untuk mendapatkan delay 5
224
detik. Akan sangat merepotkan juga apabila delaynya ingin
kita ubah-ubah.

Solusinya, kita tidak tidak mengaktifkan buzzer sesuai


dengan delay sensor. Kita akan mengaktifkan buzzer sesuai
delay yang kita tentukan sendiri, kita buat variabel sendiri,
kita buat delay sendiri.

Program di bawah ini akan mengaktifka buzzer selama 5


detik ketika sensor mendeteksi gerakan. Silakan asah logika
Anda dengan membaca dan menganalisa program ini.

Program 14.3 Program Custom Delay Alarm Sensor PIR


1 /*
2 * MONSTER ARDUINO V2
3 * Program Custom Delay Alarm Sensor PIR
4 * www.ElangSakti.com
5 */
6
7 // pin + buzzer di pin 2
8 // output sensor pir di pin 3
9 const byte PIN_BUZZER = 2;
10 const byte PIN_PIR = 3;
11
12 // variabel untuk history logika sensor pir
13 boolean logika_pir = LOW;
14 boolean logika_pir_last = logika_pir;
15
16 // variabel untuk mencatat timer
17 unsigned long timer_pir = 0;
18
19
20 // output buzzer
21 boolean output_buzzer = LOW;
22 boolean buzzer_aktif = false;
23

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 }

Hasil dari program di atas tampak pada Gambar 14.6.


Boleh Anda perhatikan, delay untuk nyala alarm bisa kita
tentukan sesuai kebutuhan. Teknik ini bisa Anda terapkan
untuk sensor lainnya.

Gambar 14.6 Output program custom delay 5 detik

227
Bagian #15

SENSOR DHT11 & KUMBUNG JAMUR

Jangan ragu dan jangan malu,


tunjukkan pada dunia bahwa sebenarnya kita mampu. (Iwan Fals)

___

Pada ebook pertama, kita menggunakan sensor LM35


untuk mengetahui suhu sekitar. Kali ini kita tidak hanya
mengeksplorasi project yang berkaitan dengan suhu saja,
tetapi juga yang berkaitan dengan kelembaban udara.

Kira-kira, ide apa saja yang terbersit di benak Anda


ketika diminta untuk membuat project yang terkait dengan
suhu dan kelembaban? Kita abaikan dulu apa yang Anda
pikirkan. Kita mulai kenalan dulu dengan sensor DHT11.

15.1 Sensor DHT11

Sensor DHT11 adalah modul yang berisi sensor suhu


dan sensor kelembaban dalam satu device. Sensor DHT11
relative simpel, terjangkau, dan mudah digunakan untuk
pemula. Akurasinya cukup baik dan tidak kalah dengan
sensor suhu LM35.
228
DHT11 dibundel dengan NTC (Negative Temperature
Coefficient) sebagai sensor suhu yang mampu mengukur
o
suhu dari 0 50 C. Sedangkan sensor kelembabannya
menggunakan tipe resistif yang mampu mengukur
kelembaban dari 20 90 %.

Gambar 15.1 Sensor DHT11

Sensor ini memiliki respon perubahan suhu sekitar 6 -


30 detik. Jadi jika perubahan suhu yang dideteksi masih di
dalam rentang angka tersebut, masih wajar. Jika Anda butuh
sensor yang memiliki responsifitas yang lebih cepat, bisa
gunakan tipe yang lain.

229
15.2 Akuisi Data Sensor DHT11

Sensor DHT11 terdiri dari dua buah sensor, yaitu sensor


suhu dan sensor kelembaban. Namun, pin data hanya satu
(lihat Gambar 15.1), bagaimana cara Arduino memperoleh
data dari sensor tersebut?

Begini, data suhu dan kelembaban diolah oleh IC,


kemudian dikirim dengan komunikasi one-wire protocol.
One-wire protocol adalah protokol komunikasi yang hanya
membutuhkan satu jalur data untuk mengirim dan
menerima data.

Saat ini kita tidak akan membahas terlalu detail tentang


one-wire, sebab protokol tersebut sudah ada dalam library
DHT yang akan kita pakai. Selanjutnya, mari kita langsung
ke praktek!

15.2.1 Rangkaian Dasar Sensor DHT11

Perhatikan rangkaian sensor DHT11, kaki dari kiri adalah


VCC, DATA, NC, dan GND. NC artinya Not Connected.
Rangkaian simpel seperti di gambar. Peralatan yang
dibutuhkan adalah:

1. Arduino x 1
2. Sensor DHT11 x 1
3. Resistor 10k x 1
230
4. Project board x 1
5. Kabel Jumper secukupnya

Sambungan pin Arduino dan DHT11 yaitu :

Arduino Sensor DHT11


Pin 2 Ke Pin Output dengan pullup resistor
VCC VCC
GND GND

Gambar 15.2 Skema dasar rangkaian DHT11

15.2.2 Program Akuisisi Data Sensor DHT11

Program ini akan menampilkan suhu dan kelembaban di


serial monitor. Komunikasi antara komputer dan Arduino
menggunakan baud rate 19200.

Program 15.1 Program Akuisisi Data Sensor DHT11


1 /*
2 * MONSTER ARDUINO V2
3 * Program Akuisisi Data Sensor DHT11
4 * www.ElangSakti.com
231
5 */
6
7 // include library dht
8 #include <dht.h>
9
10 // buat instan dari class DHT
11 dht DHT;
12
13 // pin output DHT11
14 const byte DHT_PIN = 2;
15
16 // variabel untuk sensor suhu dan kelembaban
17 int suhu = 0;
18 int kelembaban = 0;
19
20 void setup() {
21
22 // Aktifkan komunikasi serial di baud 19200
23 Serial.begin(19200);
24
25 }
26
27 void loop() {
28
29 // jika sensor normal
30 if( DHT.read11(DHT_PIN) == DHTLIB_OK ){
31
32 // print suhu dan kelembaban
33 // setiap delay 2000 ms (2 detik)
34 if( nonblocking_delay(2000) ){
35
36 // akses data suhu dan kelembaban
37 suhu = DHT.temperature;
38 kelembaban = DHT.humidity;
39
40 // cetak di serial terminal
41 Serial.print("Suhu:");
42 Serial.print(suhu);
43 Serial.print(" Kelembaban:");
44 Serial.print(kelembaban);
45 Serial.println();
46 }
47 }
48 }
232
49
50 // tambahan untuk membuat delay non blocking
51 unsigned long nonblocking_time = millis();
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 }

Gambar 15.3 Output program akuisisi data sensor DHT11

Untuk bisa mengakses data dari sensor DHT11, maka


library yan harus diinclude adalah dht.h. Anda bisa
download librarynya di internet. Proses pengambilan data
suhu dan kelembaban relatif mudah. Jika proses pembacaan
sensor berhasil (lihat baris 30), maka data dapat dicetak ke
serial monitor.

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.

15.3 Menampilkan Data pada LCD

Kita sudah bisa menampilkan suhu dan kelembaban di


Serial Terminal. Selanjutnya, kita akan menampilkan suhu
dan kelembaban di LCD 1602. Silakan rangkai alat-alat
seperti gambar di bawah. Posisi kaki sensor tetap seperti
pada program sebelumnya. Yang ditambah adalah
rangkaian LCD dan modul LCD I2C.

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

Sambungan pin Arduino, LCD, dan sensor DHT11 :

Arduino LCD 1602 dg I2C Sensor DHT11


Pin 2 - Ke pin Ouput dengan pullup resistor
Pin A4 Pin SDA -
Pin A5 Pin SCL -
VCC VCC VCC
GND GND GND

234
Gambar 15.4 Rangkaian untuk menampilkan data sensor di LCD1602

15.3.1 Program Sensor Suhu dan Kelembaban Digital


Program 15.2 Program Sensor Suhu dan Kelembaban Digital
1 /*
2 * MONSTER ARDUINO V2
3 * Program Sensor Suhu dan Kelembaban Digital
4 * www.ElangSakti.com
5 */
6
7 // include library dht
8 #include <dht.h>
9 // library LCD dengan modul I2C
10 #include <LiquidCrystal_I2C.h>
11
12 // jika true, maka munculkan data di serial terminal
13 #define DEBUG true
14
15
16 // ===== Sensor DHT11 ===========
17
18 // buat instan dari class DHT
235
19 dht DHT;
20
21 // pin output DHT11
22 const byte DHT_PIN = 2;
23
24 // variabel untuk sensor suhu dan kelembaban
25 int suhu = 0;
26 int kelembaban = 0;
27
28
29 // ===== Konfigurasi LCD ===========
30
31 // LCD1602 dengan Modul I2C
32 // Alamat I2C di 0x27 : lcd_Addr, EN, RW, RS, D4, D5, D6, D7,
33 PIN_BACKLIGHT, Pol
34 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
35
36 // jumlah kolom dan baris LCD (16x2)
37 const byte LCD_COL = 16;
38 const byte LCD_ROW = 2;
39
40 void setup() {
41
42 // jika DEBUG = true
43 // Aktifkan komunikasi serial di baud 19200
44 if( DEBUG ) Serial.begin(19200);
45
46 // Settingan LCD
47 lcd.begin(LCD_COL,LCD_ROW);
48
49 // Nyalakan Backlight
50 lcd.setBacklight(BACKLIGHT_ON);
51
52 // letakkan kursor pada baris 0 kolom 0
53 lcd.setCursor(0,0);
54 lcd.print("SENSOR SUHU");
55
56 // letakkan kursor pada baris 1 kolom 0
57 lcd.setCursor(0,1);
58 lcd.print("& KELEMBABAN");
59 delay(3000);
60
61 }
62
236
63 void loop() {
64
65 // jika sensor normal
66 if( DHT.read11(DHT_PIN) == DHTLIB_OK ){
67
68 // ambil data suhu dan kelembaban
69 // setiap delay 2000 ms (2 detik)
70 if( nonblocking_delay(2000) ){
71
72 // akses data suhu dan kelembaban
73 suhu = DHT.temperature;
74 kelembaban = DHT.humidity;
75
76 // hapus tulisan di LCD
77 lcd.clear();
78
79 // pindah kursor ke baris 0, kolom 0
80 // tulis suhu
81 lcd.setCursor(0,0);
82 lcd.print("Suhu: ");
83 lcd.print(suhu);
84
85 // pindah kursor ke baris 1, kolom 0
86 // tulis kelembaban
87 lcd.setCursor(0,1);
88 lcd.print("Kelembaban: ");
89 lcd.print(kelembaban);
90
91 // jika DEBUG = true
92 if ( DEBUG ) {
93 // cetak di serial terminal
94 Serial.print("Suhu:");
95 Serial.print(suhu);
96 Serial.print(" Kelembaban:");
97 Serial.print(kelembaban);
98 Serial.println();
99 }
100 }
101 }
102 }
103
104 // tambahan untuk membuat delay non blocking
105 unsigned long nonblocking_time = millis();

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;
}

Penjelasan untuk program ini bisa dibaca di tiap-tiap


baris kode, sebab untuk program yang menampilkan data
ke LCD penulis sudah pada paham dan simpel.

15.4 Project Kumbung Jamur Sederhana

Project kali ini adalah membuat alat untuk mengontrol


suhu dan kelembaban di kumbung jamur. Alat yang akan
kita buat memiliki karakteristik kerja seperti berikut.

1. Informasi suhu dan kelembaban ditampilkan di LCD


2. Jika suhu atau kelembaban melebihi batas tertentu,
maka alat akan mengaktifkan pompa selama 5 menit.
3. Pompa dimatikan setelah akttif 5 menit, lalu sistem
harus istirahat (menunggu) 10 menit sebelum
pengecekan ulang suhu dan kelembaban.
4. Selama istirahat, lampu LCD dimatikan.
5. Setelah waktu istirahat selesai, aktifkan pompa
apabila suhu dan kelembaban masih belum sesuai
dengan batas yang ditentukan.

238
6. Selama pompa aktif, alarm atau buzzer akan berbunyi
dengan nada putus-putus.

15.4.1 Rangkaian Project Kumbung Jamur

Rangkaian alat sama persis seperti pada rangkaian


sebelumnya, namun ada penambahan buzzer di pin 3
seperti di Gambar 15.5. peralatan dan rangkaian yang harus
disiapkan adlah:

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

Sambungan antara Arduino, LCD, DHT11, Buzzer, dan


relay adalah sebagai berikut :

Arduino LCD 1602 DHT11 Buzzer Relay


Pin 2 - Pin Ouput - -
Pin 3 - - Pin Positif -
Pin 4 - - - Pin Input
Pin A4 Pin SDA - - -
Pin A5 Pin SCL - - -
VCC VCC VCC - VCC
GND GND GND Pin GND GND

239
Gambar 15.5 Rangkain project kumbung jamur sederhana

15.4.2 Program Kumbung Jamur Sederhana


Program 15.3 Program Kumbung Jamur Sederhana
1 /*
2 * MONSTER ARDUINO V2
3 * Program Kumbung Jamur Sederhana
4 * www.ElangSakti.com
5 */
6
7 // include library dht
8 #include <dht.h>
9 // library LCD dengan modul I2C
10 #include <LiquidCrystal_I2C.h>
11
12 // jika true, maka munculkan data di serial terminal
13 #define DEBUG true
14
15 #define RELAY_ON LOW
16 #define RELAY_OFF !RELAY_ON

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 }

Program untuk kumbung jamur sederhana akan


dijelaskan secara detail pada edisi revisi. Untuk sementara
Anda boleh baca keterangan yang ada pada source code.

246
Bagian #16

APLKASI REALTIME DENGAN RTC

Keberhasilan adalah kemampuan untuk melewati dan mengatasi


satu kegagalan ke kegagalan berikutnya
tanpa kehilangan semangat. (Winston Chuchill)

___

Jika komputer atau laptop tidak menggunakan RTC,


maka setiap menyalakan komputer, kita akan diminta untuk
memasukkan tanggal dan jam. Namun tidak demikian,
setiap kita menyalakan komputer, tanggal dan jam selalu
sama dengan tanggal dan jam sebenarnya. Itulah kegunaan
dari Real Time Clock (RTC).

Mungkin juga kita pernah menemukan jam digital di


rumah-rumah ibadah, pom bensin, atau fasilitas umum
lainnya. Komponen yang dipakai agar tanggal dan jamnya
selalu update pada peralatan tersebut adalah RTC.

Ada banyak jenis RTC, dari yang biasa hingga yang


akurasinya tinggi. Mungkin Anda sudah pernah dengar atau
lihat RTC DS1302, DS1307, DS3231, PCF8563, atau yang
247
lainnya. IC-IC tersebut memiliki fungsi utama yang sama,
yaitu mencacah dan mencatat waktu. Namun setiap IC
punya kelebihan dan kekurangan masing-masing. Sebagai
dasar pengenalan dan pembelajaran, kita menggunakan
yang Tiny RTC 1307 karena akurasinya cukup memadai dan
harganya pun relatif terjangkau.

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:

1. VCC, sumber tegangan +5V


2. GND, sumber tegangan Ground
3. SDA, serial data. Pin ini menjadi jalur komunikasi
data antara Arduino dan Modul RTC
4. SCL, serial clock untuk melakukan sinkronisasi
komunikasi data antara Arduino dan RTC
5. Selain ke-4 pin tersebut, pin yang lain mungkin akan
jarang dipakai. Jika Anda penasaran dengan fungsi-
fungsinya, silakan googling.

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.

Baterai berfungsi untuk memastikan RTC terus


mencacah. Jika baterai mati atau dilepas, maka RTC tidak
dapat mencacah. Hal ini menyebabkan informasi waktu
yang tersimpan di memori menjadi tidak valid, alias tanggal
atau jamnya kadaluarsa. Jika Anda pernah punya laptop
atau komputer yang tanggalnya selalu kadaluarsa ketika
dihidupkan, berarti baterai RTC-nya sudah kehabisan energi.

16.1 Rangkaian Dasar RTC DS1307

Peralatan dan rangkaian yang perlu disiapkan adalah :

1. Arduino x 1
2. TinyRTC D1307 x 1
3. Kabel jumper secukupnya

Sambungan Arduino dan RTC yaitu:

Arduino TinyRTC DS1307


VCC 5V VCC
GND GND
A4 SDA
A5 SCL

249
Gambar 16.2 Rangkaian dasar RTC DS1307 dan Arduino

16.2 Menampilkan Waktu di Serial Monitor


Program 16.1 Program Menampilkan Waktu di Serial Monitor
1 /*
2 * MONSTER ARDUINO V2
3 * Program Menampilkan Waktu di Serial Monitor
4 * www.ElangSakti.com
5 */
6
7 // include library Wire dan RTCLib
8 #include <Wire.h>
9 #include <RTClib.h>
10
11 // buat object RTC
12 RTC_DS1307 RTC;
13
14 void setup() {
15 // buka koneksi ke serial monitor
16 Serial.begin(19200);
17 while(!Serial);
18
19 // buka koneksi ke RTC
20 Wire.begin();
21 RTC.begin();
22 delay(1000);
23
24 // jika RTC belum disetting & running
250
25 if (! RTC.isrunning()) {
26 // set waktu RTC sesuai waktu di komputer
27 RTC.adjust(DateTime(__DATE__, __TIME__));
28 Serial.println("RTC is NOT Running");
29 } else {
30 // RTC normal
31 Serial.println("RTC OK!");
32 }
33 }
34
35 void loop() {
36
37 // cetak waktu setiap detik
38 if( nonblocking_delay(1000) ){
39 PrintTime();
40 }
41
42 }
43
44 // fungsi untuk mencetak waktu
45 // di serial monitor
46 void PrintTime(){
47 // ambil data jam dan tanggal
48 DateTime now = RTC.now();
49
50 // jika tanggal < 9, tambahkan
51 // angka 0 didepan angka.
52 if( now.day() < 10 ) Serial.print(0);
53 Serial.print(now.day(), DEC);
54 Serial.print('/');
55 // tampilkan bulan
56 if( now.month() < 10 ) Serial.print(0);
57 Serial.print(now.month(), DEC);
58 Serial.print('/');
59 // tampilkan tahun
60 Serial.print(now.year(), DEC);
61
62 Serial.print(' ');
63
64 // tampilkan jam
65 if( now.hour() < 10 ) Serial.print(0);
66 Serial.print(now.hour(), DEC);
67 Serial.print(':');

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 }

Cara kerja program di atas yaitu :

1. Import library yang dibutuhkan modul RTC, yaitu


Wire.h dan RTCLib.h (lihat baris 8 dan 9)
2. Setelah membuat koneksi ke modul RTC, cek apakah
RTC sudah running atau belum (lihat baris 25). Jika
belum running, waktu yang tersimpan di RTC tidak
update. Oleh sebab itu, update waktu RTC sesuai
dengan waktu compile komputer (lihat baris 27).
3. Untuk mencetak waktu, ambil data dari RTC seperti
pada baris 48. Setelah itu ambil data tanggal, tahun,
bulan, jam, menit, dan detik. Pastikan format yang
dicetak pada serial monitor adalah desimal (DEC).

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.

Yang perlu diperhatikan adalah jangan menempatkan


perintah update waktu seperti baris ke 27 di sembarang
tempat. Sebab, jika salah penempatan, waktu yang ada di
RTC akan diupdate seperti waktu saat program dicompile
dan waktu akan reset ke awal ketika Arduino direset.

16.3 Menampilkan Jam di Seven Segment

Dengan program ini, kita akan membuat jam digital


seperti yang dipakai oleh instansi atau rumah-rumah
ibadah. Oleh sebab itu, silakan pelajari dengan baik.

16.3.1 Rangkaian Menampilkan Jam di Seven Segment

Peralatan dan rangkaian yang harus disiapkan adalah:

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 :

Arduino TinyRTC 74HC595 7 Segment


Pin 2 - Pin 14, Data -
Pin 3 - Pin 12, Latch -
Pin 4 - Pin 11, Clock -
Pin A0 - - D1
Pin A1 - - D2
Pin A2 - - D3
Pin A3 - - D4
Pin A4 SDA - -
Pin A5 SCL - -
VCC VCC Pin 10 dan 16
GND GND Pin 8 dan 13

Gambar 16.3 Rangkaian untuk menampilkan jam di seven segment

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 }

Cara kerja program di atas yaitu :

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

16.4.1 Rangkan Menampilkan Waktu di LCD

Peralatan dan rangkaian yang harus disiapkan adalah:

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

Sambungan pin Arduino, TinyRTC, dan LCD 1602 :

Arduino TinyRTC LCD1602


Pin A4 SDA SDA
Pin A5 SCL SCL
VCC VCC VCC
GND GND GND

Gambar 16.4 Rangkaian untuk menampilkan waktu di LCD

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.

16.4.2 Program Menampilkan Waktu di LCD


Program 16.3 Program Menampilkan Waktu di LCD
1 /*
2 * MONSTER ARDUINO V2
3 * Program Menampilkan Waktu di LCD
4 * www.ElangSakti.com
5 */
6
7 // include library Wire dan RTCLib
8 #include <Wire.h>
9 #include <RTClib.h>
10
11 // library LCD dengan modul I2C
12 #include <LiquidCrystal_I2C.h>
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 // ===== Konfigurasi LCD ===========
27
28 // LCD1602 dengan Modul I2C
29 // Alamat I2C di 0x27
30 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
31 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
262
32
33 // pilihat format penulisan teks
34 byte tipe_format[] = {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
35 byte format = ALIGN_LEFT;
36
37 // instance objek RTC
38 RTC_DS1307 RTC;
39
40 // jam dalam format teks
41 String teks_jam = "";
42
43 void setup() {
44 // buka koneksi ke serial monitor
45 Serial.begin(19200);
46 while(!Serial);
47
48 // buka koneksi ke RTC
49 Wire.begin();
50 RTC.begin();
51 delay(1000);
52
53 // jika RTC belum disetting & running
54 if (! RTC.isrunning()) {
55 // set waktu RTC sesuai waktu di komputer
56 RTC.adjust(DateTime(__DATE__, __TIME__));
57 Serial.println("RTC is NOT Running");
58 } else {
59 // RTC normal
60 Serial.println("RTC OK!");
61 }
62
63 // Settingan LCD
64 lcd.begin(LCD_COL,LCD_ROW);
65
66 // Nyalakan Backlight
67 lcd.setBacklight(BACKLIGHT_ON);
68
69 }
70
71 void loop() {
72 // tampilkan data setiap detik
73 if( nonblocking_delay(1000) ){
74 // Clear sebelum menampilkan tanggal di baris 1

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 }

Program ini cukup simpel karena hanya


mengombinasikan antara dasar-dasar untuk mengambil
data tanggal dan jam serta dasar-dasar membuat format
teks di tampilan LCD. Jika Anda bingung, boleh cek di bab-
bab sebelumnya. Atau, silakan tanya di group sesuai materi
yang dibahas.

16.5 Menampilkan Nama Hari dan Bulan

Program ini akan menampilkan nama hari dan nama


bulan di LCD. Rangkaian untuk program ini sama dengan
rangkaian untuk menampilkan waktu di LCD.
265
16.5.1 Program Menampilkan Nama Hari dan Bulan
Program 16.4 Program Menampilkan Nama Hari dan Bulan
1 /*
2 * MONSTER ARDUINO V2
3 * Program Menampilkan Nama Hari dan Bulan
4 * www.ElangSakti.com
5 */
6
7 // include library Wire dan RTCLib
8 #include <Wire.h>
9 #include <RTClib.h>
10
11 // library LCD dengan modul I2C
12 #include <LiquidCrystal_I2C.h>
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 // ===== Konfigurasi LCD ===========
27
28 // LCD1602 dengan Modul I2C
29 // Alamat I2C di 0x27
30 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
31 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
32
33 // pilihat format penulisan teks
34 byte tipe_format[] = {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
35 byte format = ALIGN_LEFT;
36
37 // membuat instance class RTC
38 RTC_DS1307 RTC;
39
40 // nama-nama hari
266
41 const String NAMA_HARI[] = {
42 "Min",
43 "Sen",
44 "Sel",
45 "Rab",
46 "Kam",
47 "Jum",
48 "Sab"
49 };
50
51 // nama-nama bulan
52 // indeks 0 kita anggap tidak ada
53 // sebab bulan dimulai dari 1, bukan 0
54 const String NAMA_BULAN[] = {
55 "",
56 "Jan",
57 "Feb",
58 "Mar",
59 "Apr",
60 "Mei",
61 "Jun",
62 "Jul",
63 "Agu",
64 "Sep",
65 "Okt",
66 "Nop",
67 "Des"
68 };
69
70 // variabel waktu
71 DateTime WAKTU;
72 // detik
73 byte DETIK = 0;
74
75 String teks_jam = "";
76
77
78 void setup() {
79 // buka koneksi ke serial monitor
80 Serial.begin(19200);
81 while(!Serial);
82
83 // buka koneksi ke RTC

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 }

Cara kerja program ini yaitu:

1. Buat daftar nama hari dan bulan. Karena jumlah


karakter lcd hanya 16, maka penamaannya dibatasi 3
huruf saja (lihat baris 41 68). Untuk menampilkan
nama hari dan bulan secara lengkap dalam satu
baris, maka teks tanggal harus bergerak. Untuk teks
bergerak akan dicontohkan di program selanjutnya.
2. Teknik mengubah tampilan pada program ini
berbeda dengan program sebelumnya. Pada
program sebelumnya, tampilan LCD akan diubah
setiap 1 detik. Sedangkan pada program ini,
tampilan akan diubah setiap angka detik berubah
(lihat baris 111). Beda logikanya kan ya? Perubahan
teknik ini mungkin tidak akan berefek secara
signifikan pada sistem. Tapi, perubahan teknik ini
akan berpengaruh pada variasi logika berpikir kita
sebagai programmer. Tujuannya satu, tapi bisa
dilakukan dengan cara yang berbeda.

270
3. Untuk menampilkan nama hari dan nama bulan
dilakukan saat mengon versi tanggal ke string, yaitu
pada baris 140 dan 145.

16.6 Menampilkan Tanggal Bergerak


Sebelumnya kita telah membuat program untuk
menampilkan nama hari dan nama bulan di LCD, akan tetapi
namanya harus kita singkat karena jumlah karakter di LCD
tidak mencukupi. Salah satu solusinya adalah membuat teks
tanggal bergerak ke kiri atau ke kanan. Dengan demikian
informasi nama hari dan bulan dapat ditulis secara lengkap.

Rangkaian untuk program ini sama dengan rangkaian


untuk program sebelumnya.

16.6.1 Program Menampilkan Tanggal Bergerak


Program 16.5 Program Menampilkan Tanggal Bergerak
1 /*
2 * MONSTER ARDUINO V2
3 * Program Menampilkan Tanggal Bergerak
4 * www.ElangSakti.com
5 */
6
7 // include library Wire dan RTCLib
8 #include <Wire.h>
9 #include <RTClib.h>
10
11 // library LCD dengan modul I2C
12 #include <LiquidCrystal_I2C.h>

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 }

Program ini merupakan kombinasi dari program-


program sebelumnya. Oleh sebab itu, kita tidak akan
menjelaskan satu persatu. Akan tetapi, inti dari program ini
ada di baris 127. Setelah mengkonversi tanggal menjadi
string, langsung diberi efek bergerak ke kiri dengan fungsi
MoveText(). Selanjutnya, mari kita membuat project
sederhana dengan timer RTC. Kita buat timer pagi sore
untuk mengontrol nyala lampu.

16.7 Project Timer Pagi Sore

Project ini bertujuan untuk membuat timer pagi sore.


Timer akan digunakan untuk menghidupkan lampu saat

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 :

1. Lampu akan menyala mulai jam 5 sore


2. Lampu akan mati ketika sudah jam 5 pagi
3. Jika ada kegagalan sistem seperti arduino error atau
ada yang rusak, listrik akan otomatis menyala.
4. Muncul informasi tanggal dan jam di LCD
5. Muncul kondisi relay saat ON atau OFF di LCD
6. Saat dinyalakan, muncul nama pembuat program
7. Proses konfigurasi dimunculkan saat sistem startup

Yang menjadi catatan penting adalah requirement


nomer 3. Untuk mendapatkan respon sistem yang seperti
itu, maka kita harus menyambung kabel lampu di posisi NC
(Normally Close). Jika Anda belum memahami karakteristik
ini, mungkin akan bingung. Sebab, status relay dan status
lampu akan berkebalikan.

Jika RELAY OFF, maka LAMPU ON


Jika RELAY ON, maka LAMPU OFF

Boleh Anda ingat-ingat, jika kepala Anda mulai pusing.


Berarti otak Anda mulai bertumbuh dan koneksi sel-sel
sarafnya sedang membentuk struktur logika dan keilmuan
baru. Percayalah.

279
16.7.1 Rangkaian Timer Pagi Sore

Peralatan dan rangkaian yang perlu kita siapkan yaitu:

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

Sambungan pin Arduino, TinyRTC, LCD, dan relay :

Arduino TinyRTC LCD1602 Modul Relay


Pin A0 - - Input1
Pin A4 SDA SDA -
Pin A5 SCL SCL -
VCC VCC VCC VCC
GND GND GND GND

Gambar 16.5 Rangkaian timer pagi sore

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 }

Penjelasan requirement yang diinginkan dalam program


adalah sebagai berikut:

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.

Jika siang (jam 5 pagi hingga jam 5 sore) lampu


MATI, maka siang RELAY HARUS ON, pengecekan
kondisi ini pada baris 187 189. Sedangkan kondisi
malam (jam 5 sore hingga jam 5 pagi) lampu HIDUP,
maka RELAY HARUS OFF (lihat baris 191 192).

4. Untuk menampilkan informasi tanggal dan jam ada


di baris 126 dan 128.
5. Informasi ON/OFF lampu ada di dalam fungsi
RelayAction(), khususnya pada baris 196.
6. Untuk menampilkan informasi awal, harus
dimasukkan dalam fungsi void setup(). Dalam hal ini
dilakukan dengan mengeksekusi fungsi StartUp()
pada baris 116. Fungsi StartUp() sendiri ada pada
baris 218. Data-data yang muncul di LCD saat
startup adalah data dummy. Hal ini termasuk
requirement nomer 7.

289
Ada yang menarik degan project ini? Mari kita
diskusikan di grup.

290
Bagian #17

KENDALI DENGAN REMOTE


INFRARED

Manusia tidak memiliki talenta yang sama,


tapi kita memiliki kesempatan yang sama untuk mengembangkan
talenta kita. (John Fitzgerald Kennedy)

___

Remote infrared yang akan dipakai bukanlah remote


bekas sebagaimana pernah kita posting di
https://goo.gl/uEc5Ys. Remote yang ini adalah remote yang
memang ditujukan untuk edukasi. Remote ini kompatibel
dengan library IRremote yang biasa dipakai pengembang.

Gambar 17.1 Modul IR remotedan IR receiver


291
Gambar 17.2 Modul receiver infrared KY-022

Modul infrared terdiri dari 3 pin. Pin yang ditandai


dengan S adalah output Signal. Pin yang ditandai dengan (
) adalah pin GND. Pin yang tengah adalah VCC +5V.
Pastikan masangnya tidak terbalik. Kalau terbalik, mungkin
bisa hangus.

Untuk memprogram remote, hal yang pertama harus


kita lakukan adalah memetakan setiap tombol. Dengan
adanya library IRremote, kita bisa langsung memetakan
tombol dengan mudah. Mari langsung praktek!

17.1 Mengidentifikasi Tombol Remote

17.1.1 Rangkaian Modul Receiver Infrared

Peralatan dan rangkaian yang perlu disiapkan adalah:

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

Gambar 17.3 Rangkaian Arduino dan IR Receiver

17.1.2 Program Identifikasi Tombol Remote


Program 17.1 Program Identifikasi Tombol Remote
1 /*
2 * MONSTER ARDUINO V2
3 * Program Identifikasi Tombol Remote
4 * www.ElangSakti.com
5 */
6
7 // include library IRremote
8 #include <IRremote.h>
9
10 // pin Signal ke pin 2
11 const byte PIN_RECV = 2;
12
13 // konfigurasi class irremote
14 IRrecv irrecv(PIN_RECV);
293
15 // penampung hasil identifikasi remote
16 decode_results results;
17
18 void setup() {
19 // buka koneksi ke serial monitor
20 Serial.begin(19200);
21 // aktifkan IR penerima
22 irrecv.enableIRIn();
23 }
24
25 void loop() {
26 // jika menerima data dan berhasil mendecode data
27 if (irrecv.decode(&results)) {
28 // cetak ke serial monitor dg format Hex
29 Serial.println(results.value, HEX);
30 // hapus history hasil sebelumnya
31 irrecv.resume();
32 }
33 }

Cara kerja program di atas adalah:

1. Include libraray IRremote


2. Konfiugurasi pin dan variabel penampung data hasil
identifikasi (lihat baris 14 dan 16)
3. Aktifkan modul untuk menerima sinyal infrared
dengan enableIRIn() di baris 22.
4. Terima sinyal infrared, jika hasil decode berhasil
(lihat baris 27), maka cetak hasilnya ke serial monitor.
5. Setelah mendeteksi tombol, reset data tombol (lihat
baris 31). Jika tidak direset, maka proses decode akan
mendeteksi tombol data lama sebagai data baru dan
mencetak tombol yang sama pada serial monitor.

294
Gambar 17.4 Output tombol 0 9

Gambar 17.4 adalah output dari penekanan tombol 0


9. Data FFFFFFFF berarti data yang diterima sama dengan
data sebelumnya karena penekanan tombol terlalu lama.
Selengkapnya, hasil dari proses identifikasi tombol ini
tampak seperti Tabel 17.1.

Tabel 17.1 Kode tombol remote yang teridentifikasi

Tombol Kode Hex Tombol Kode Hex


1 0xFFA25D 0 0xFF9867
2 0xFF629D * 0xFF6897
3 0xFFE21D # 0xFFB04F
4 0xFF22DD Panah Atas 0xFF18E7
5 0xFF02FD Panah Bawah 0xFF4AB5
6 0xFFC23D OK 0xFF38C7
7 0xFFE01F Panah Kiri 0xFF10EF
8 0xFFA857 Panah Kanan 0xFF5AA5
9 0xFF906F

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.

Mari kita eksekusi project tersebut

17.2 Project Remote Kontrol Karakter LCD

Project ini bertujuan untuk membuat remote kontrol


untuk sebuah karakter yang ada di LCD. Karakter akan
bergerak ke atas, bawah, kiri, kanan, atau diam di tempat.

Jika tombol kiri ditekan, karakter akan bergerak ke kiri.


Jika tombol kanan ditekan, karakter akan bergerak ke kanan.
Begitu juga jika tombol ke atas dan ke bawah ditekan.
Apabila tombol OK ditekan, maka karakter akan diam.

Selain untuk mengontrol gerakan karakter, nyala


backlight LCD juga dapat dikontrol dengan sebuah tombol
di remote. Jika tombol bintang * ditekan, maka kondisi
backlight LCD akan berubah. Jika backlight menyala,
backligh akan mati, dan sebaliknya.

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!

17.2.1 Rangkaian Remote Kontrol Karakter LCD

Peralatan dan rangkaian yang perlu disiapkan adalah:


1. Arduino x 1
2. Modul IR Receiver (model KY-022) x 1
3. Remote IR x 1
4. LCD 1602 dengan modul I2C LCd x 1
5. Project board
6. Kabel jumper secukupnya

Sambungan pin Arduino, IR Receiver, dan LCD yaitu :

Arduino IR Receiver LCD1602 I2C


Pin 2 Pin S (signal) -
Pin A4 - SDA
Pin A5 - SCL
VCC VCC VCC
GND GND GND

297
Gambar 17.5 Rangkain pengontrol karakter LCD

17.2.2 Program Remote Kontrol Karakter LCD


Program 17.2 Program Remote Kontrol Karakter LCD
1 /*
2 * MONSTER ARDUINO V2
3 * Program Remote Kontrol Karakter LCD
4 * www.ElangSakti.com
5 */
6
7 // include library IRremote
8 #include <IRremote.h>
9 #include <EEPROM.h>
10
11 // pin Signal ke pin 2
12 const byte PIN_RECV = 2;
13
14 // konfigurasi class irremote
15 IRrecv irrecv(PIN_RECV);
16 // penampung hasil identifikasi remote
17 decode_results results;
18
19 // data tombol
20 #define TOMBOL_1 0xFFA25D
21 #define TOMBOL_2 0xFF629D

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 :

1. Aksi untuk penekanan tombol atas, bawah, kanan,


kiri, OK, dan tombol bintang ada di fungsi IRAction,
khususnya pada baris 149 182. Fungsi IRAction
dieksekusi ketika arduino mendeteksi penekanan
tombol di baris 134.
2. Penekanan tombol bintang akan mengatur nyala
backlight LCD pada baris 153 dan 154, proses
penyimpanan data di EEPROM ada pada baris 155.
3. Penekanan tombol juga berpengaruh pada arah
gerakan karakter melalui variabel arah dalam fungsi
IRAction(), termasuk fungsi pilihArah() pada baris
214.
4. Untuk pemilihan arah kiri atau kanan, maka proses
pemindahan karakter ditentukan berdasarkan
variabel posisi_kolom (lihat baris 230 dan 240).
Sedangkan untuk pemilihan arah atas atau bawah,
maka perpindahan karakter ditentukan berdasarkan
posisi_baris (lihat baris 251 dan 261).

305
Bagian #18

PENGENALAN SERVO

M impi adalah kunci untuk kita menaklukkan dunia,


berlarilah tanpa lelah sampai engkau meraihnya. (Nijdi)

___

Bab ini adalah bab bonus. Pembahasan lebih banyak


tentang servo akan diulas pada buku berikutnya. Oleh sebab
itu, kita akan membahas servo secukupnya saja. Secara
prinsip, semua servo memiliki kaki dan fungsi yang sama.
Namun ada dua jenis servo yang umum di pasaran, ada
yang putarannya terbatas, ada yang berputar hingga 360o.

Gambar 18.1 Motor servo SG90

Kali ini kita hanya akan membahas motor servo yang


dapat diputar 180o, salah satau contohnya adalah motor
servo SG90. Ketika Anda bisa menggunakan servo ini, dapat

306
dipastikan Anda akan bisa menggunakan tipe servo sejenis
lainnya. Yang penting Anda paham batasan sudut servo
yang dipakai.

Motor servo terdiri dari tiga buah kabel, kabel VCC


(merah), GND (coklat), dan PWM (jingga). Fungsi kabel VCC
dan GND sudah jelas sebagai jalur power supply. Sedangkan
kabel PWM untuk mengatur arah putaran servo. Untuk
memahami cara kerja PWM, silakan download buku Arduino
Versi 1 di https://goo.gl/JCEDmh. Mari langsung praktek!

18.1 Motor Servo Dasar

Pada praktek ini, servo akan dikendalikan berdasarkan


sudut servo. Untuk mempermuda pemrograman, kita
menggunakan library Servo.h, library ini sudah ada di
aplikasi Arduino IDE. Karakteristik program pertama ini
sederhana, Arduino bertugas untuk memutar servo dari
sudut 0 180o dan sebaliknya.

18.1.1 Rangkain Servo dan Arduino

Peralatan dan rangkaian yang perlu disiapkan adalah:

1. Arduino x 1
2. Servo SG90 x 1
3. Kabel jumper secukupnya
307
Sambungan pin Arduino dan Servo adalah :

Arduino Servo SG90


Pin 3 PWM (orange)
VCC VCC
GND GND

Gambar 18.2 Rangkaian servo dan Arduino

18.1.2 Program Servo Sederhana


Program 18.1 Program Motor Server Sederhana
1 /*
2 * MONSTER ARDUINO V2
3 * Program Motor Servo Sederhana
4 * www.ElangSakti.com
5 */
6
7 // include library servo
8 #include <Servo.h>
9
10 // control PWM servo di pin 3
11 const byte PIN_SERVO = 3;
12
13 // objeck untuk class servo
14 Servo myservo;
15
308
16 // sudut servo dan sudut maksimum
17 int posisi = 0;
18 int SERVO_MAX = 180;
19
20 void setup() {
21 // siapkan servo
22 myservo.attach(PIN_SERVO);
23 }
24
25 void loop() {
26 // putar servo dari sudut 0 - 180
27 for(int i=0; i<=SERVO_MAX; i++){
28 myservo.write(i);
29 delay(10);
30 }
31
32 delay(2000);
33
34 // putar balik ke sudut 0
35 for(int i=SERVO_MAX; i>=0; i--){
36 myservo.write(i);
37 delay(10);
38 }
39
40 delay(2000);
41 }

Cara kerja program ini adalah:

1. Pin kontrol servo dihubungkan ke pin 3 Arduino


2. Tentukan sudut minimal / awal dan sudut maksimal
(lihat baris 17 dan 18)
3. Setelah servo disiapkan (baris 22), putar servo dari
sudut 0 180 (baris 27 30). Jeda 2 detik, lalu lanjut
putar servo dari sudut 180 0 (baris 35 - 38).

309
4. Program ini simpel, selanjutkan kita akan
mengendalikan servo dengan potensiomenter. Jadi
gerakan servo bisa kita ubah dengan cepat.

18.2 Kendali Servo dengan Potensiometer

Pada aplikasi ini, jika nilai potensio diputar ke arah


maksimal, maka servo akan berpura ke sudut yang lebih
tinggi. Begitu juga sebaliknya.

18.2.1 Rangkaian Kendali Servo

Peralatan dan rangkain yang perlu kita siapkan adalah :

1. Arduino x 1
2. Servo SG90 x 1
3. Potensiometer x 1
4. Project board x 1
5. Kabel jumper secukupnya

Sambungan pin Arduino, Servo SG90, dan


Potensiometer adalah :

Arduino Servo SG90 Potensiometer


Pin 3 PWM (orange) -
Pin A0 - Kaki tengah
VCC VCC Kaki kanan
GND GND Kaki kiri

310
Gambar 18.3 Rangkain kendali servo dengan potensiometer

18.2.2 Program Kendali Servo


Program 18.2 Program Kendali Servo dengan Potensiomenter
1 /*
2 * MONSTER ARDUINO V2
3 * Program Kendali Servo dengan Potensiometer
4 * www.ElangSakti.com
5 */
6
7 // include library servo
8 #include <Servo.h>
9
10 // pwm servo di pin 3
11 // output potensi di pin A0
12 const byte PIN_SERVO = 3;
13 const byte PIN_POTENSIO = A0;
14
15 // objeck untuk class servo
16 Servo myservo;
17
18 // sudut servo dan sudut maksimum
19 int posisi = 0;
20 int SERVO_MAX = 180;
21
22 void setup() {
23 // siapkan servo

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 }

Cara kerja program ini seperti program yang


sebelumnya. Yang berbeda adalah, kita bisa mengatur sudut
servo menggunakan potensiomenter. Data dari
potensiometer diambil (lihat baris 29), lalu dinormalisasi
sehingga nilainya sesuai dengan range 0 180 (lihat baris
31). Setelah data dinormalisasi menyerupai sudut dari 0
180, gerakkan servo sesuai data tersebut. Selanjutnya, kita
akan mengendalikan servo dengan remote infrared.

18.3 Kendali Servo dengan Remote

Aplikasi ini adalah implementasi dari program remote


infrared, LCD, dan servo. Gerakan servo akan dikendalikan
dengan tombol panah kanan dan panah kiri. Sedangkan jika
kita menekan tombol panah ke atas, maka servo langsung
bergerak ke sudut 180o, jika tombol panah ke bawah
ditekan maka servo akan bergerak ke sudut 0 o .

312
18.3.1 Rangkaian Kendali Servo dan IR Receiver

Peralatan dan rangkaian yang perlu kita siapkan adalah:

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

Sambungan pin Arduino, Servo, LCD, dan IR Receiver :

Arduino Servo SG90 LCD1602 I2C Receiver IR


Pin 2 - - Pin S (signal)
Pin 3 PWM (orange) - -
Pin A4 - SDA -
Pin A5 - SCL -
VCC VCC VCC VCC
GND GND GND GND

Gambar 18.4 Rangkaian kendali servo dengan remote IR dan LCD


313
18.3.2 Program Kendali Servo dengan Remote IR
Program 18.3 Program Kendali Servo dengan Remote IR
1 /*
2 * MONSTER ARDUINO V2
3 * Program Kendali Servo dengan Remote IR
4 * www.ElangSakti.com
5 */
6
7 // include library IRremote
8 // dan servo
9 #include <IRremote.h>
10 #include <Servo.h>
11
12 // pin Signal IR receiver ke pin 2
13 // dan pin pwm servo di pin 3
14 const byte PIN_RECV = 2;
15 const byte PIN_SERVO = 3;
16
17 // konfigurasi class irremote
18 IRrecv irrecv(PIN_RECV);
19 // penampung hasil identifikasi remote
20 decode_results results;
21
22 // data tombol
23 #define TOMBOL_1 0xFFA25D
24 #define TOMBOL_2 0xFF629D
25 #define TOMBOL_3 0xFFE21D
26 #define TOMBOL_4 0xFF22DD
27 #define TOMBOL_5 0xFF02FD
28 #define TOMBOL_6 0xFFC23D
29 #define TOMBOL_7 0xFFE01F
30 #define TOMBOL_8 0xFFA857
31 #define TOMBOL_9 0xFF906F
32 #define TOMBOL_0 0xFF9867
33 #define TOMBOL_STAR 0xFF6897 // *
34 #define TOMBOL_HASH 0xFFB04F // #
35 #define TOMBOL_ATAS 0xFF18E7 // panah ke atas
36 #define TOMBOL_BAWAH 0xFF4AB5 // panah ke bawah
37 #define TOMBOL_OK 0xFF38C7 // ok
38 #define TOMBOL_KIRI 0xFF10EF // panah ke kiri
39 #define TOMBOL_KANAN 0xFF5AA5 // panah ke kanan
40 #define TOMBOL_REPEAT 0xFFFFFFFF // sama seperti sebelumnya
314
41
42 unsigned long tombol = TOMBOL_REPEAT;
43
44 // instance class servo
45 Servo myservo;
46
47 int posisi = 0;
48 int SERVO_MAX = 180;
49
50 int posisi_last = -1;
51
52 // library LCD dengan modul I2C
53 #include <LiquidCrystal_I2C.h>
54
55 #define BACKLIGHT_ON HIGH
56 #define BACKLIGHT_OFF !BACKLIGHT_ON
57
58 // jumlah kolom dan baris LCD (16x2)
59 #define LCD_COL 16
60 #define LCD_ROW 2
61
62 #define ALIGN_LEFT 1 // teks rata kiri
63 #define ALIGN_CENTER 2 // teks center
64 #define ALIGN_RIGHT 3 // teks rata kanan
65 #define CLEAR true // clear screen
66
67 // ===== Konfigurasi LCD ===========
68
69 // LCD1602 dengan Modul I2C
70 // Alamat I2C di 0x27
71 // lcd_Addr, EN, RW, RS, D4, D5, D6, D7, PIN_BACKLIGHT, Pol
72 LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
73
74 // pilihat format penulisan teks
75 byte tipe_format[] = {ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT};
76 byte format = ALIGN_LEFT;
77
78 String teks_servo = "";
79
80 void setup() {
81 Serial.begin(19200);
82
83 // Settingan LCD

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 }

Cara kerja program ini adalah :

1. Aksi tombol ketika dipencet panah ke kanan, kiri,


atas, dan bawah ada di baris 141 157. Sedangkan
proses identifikasi tombol ada di baris 99 109.

2. Jika tombol ditahan lama, maka kode tombol akan


menjadi 0xFFFFFFFF, oleh sebab itu ada penyesuaian
proses identifikasi tombol di baris 109 dan 108.
Setiap ada tombol yang valid dan bukan 0xFFFFFFFF,
maka informasi tombol tersebut dicatat pada
variabel tombol. Apabila tombol yang teridentifikasi
adalah 0xFFFFFFFF, maka tombol yang telah dicatan
sebelumnya yang akan dikirim ke aksi tombol.

3. Untuk gerakan servo, jika terjadi perubahan sudut


maka tampilan sudut di LCD diubah dan servo juga
digerakkan sesuai sudut tersebut (lihat 120 131).

Cukup demikian dengan penjelasan dan contoh motor


servo. Teknik dan contoh yang lain akan dimuat dalam buku
seri selanjutnya.

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.

Sekali lagi, kami ucapkan terima kasih pada member


MONSTER ARDUINO karena telah meramaikan grup. Terima
kasih juga karena telah tetap menjaga sopan santun dalam
berdiskusi sesuai isi postingan.

319
Tentang Penulis

Hari Santoso, Owner ElangSakti.com dan


Penggagas ebook MONSTER ARDUINO.
Ebook berseri tentang Arduino untuk
pemula dari tingkat dasar hingga
menengah. Penulis adalah lulusan Teknik
Informatika yang secara mandiri belajar
mikrokontroller dan Arduino.

Minat utama penulis dalam keilmuan komputer yaitu semua


hal yang terkait Programming, Artificial Intelligence,
Network Security, dan Internet of Things (IoT).

320