JAM DIGITAL Freddy Isman (13213501) Fuad Ismail (13214121) EL3014- Sistem Mikroprosesor
Sekolah Teknik Elektro dan Informatika ITB Abstrak Kali ini, kami membuat sebuah sistem jam digital menggunakan mikrokontroler AVR ATMega328 dengan platform Arduino. Beberapa fitur dari yang tersedia pada jam digital yang telah kami buat adalah mampu menampilkan jam hingga nilai menitnya, mampu melakukan pengesetan nilai jam hingga nilai menitnya, serta adanya mode timer yang bisa di set untuk mulai dari waktu berapapun. Tugas ini dibuat untuk mengaplikasikan pengetahuan timer dan counter. Kata kunci: Jam Digital, Timer/Counter, Interrupt, Arduino. 1.
PENDAHULUAN
Untuk membuat jam digital, pengetahuan akan timer, counter, dan interrupt sangatlah penting. Nantinya, kualitas dari ketiga hal tersebut lah yang akan menentukan kualitas (akurasi) dari jam dan timer yang dibuat.
2. 2.1
STUDI PUSTAKA CLOCK DAN PRESCALER
Tentunya, dengan mengetahui frekuensi clock suatu sistem, timer dengan rentang waktu yang spesifik dapat dibuat dengan counter yang menghitung jumlah clock sistemnya hingga,
dispesifikasikan oleh pengguna, misalnya 8, 64 256, dan 1024. Berikut adalah penggambaran output keluaran prescaler 8 dengan terhadap clock masukan.
2.2
REGISTER TCNT, TIMSK, OCR, DAN TIFR
Register TCNT adalah register yang menampung nilai counter setiap saat. Pada ATMega328 terdapat 3 register TCNT, satu diantaranya TCNT1 adalah counter 16 bit, sedangkan sisanya, TCNT0 dan TCNT2 adalah counter 8 bit. Panjang bit dari TCNT inilah yang membatasi waktu maksimal yang dapat di record. Register TIFR adalah register yang menyimpan nilai flag apabila counter overflow atau counter mencapai nilai register OCR, yaitu register yang menyimpan nilai yang akan di compare dengan register TCNT untuk mengeset flag pada TIFR. Register TIMSK adalah register yang menentukan counter mana mana saja yang di enable. Berikut adalah peta register TIMSK.
πππ’ππ‘ = π‘πππ Γ πππππ’ππππ¦ Namun, untuk nilai waktu yang besar, hasil perkalian diatas bisa sangat besar sehingga perhitungan waktu yang lama menjadi tidak masuk akal. Tentunya, untuk memperkecil hasil perkalian tersebut bisa dengan mengecilkan frekuensi kerja sistem, namun itu bukan solusi yang efektif, solusi yang lebih baik adalah menggunakan prescaler. Prescaler pada dasarnya membagi clock sistem dengan bilangan bulat tertentu, dan memasukkan hasil pembagian clock tersebut sebagai clock untuk timer/counter. Dengan demikian, perhitungan waktu yang panjang menjadi lebih mungkin untuk dilakukan. Cara kerja prescaler relatif simple, yaitu keluaran baru mengeluarkan pulsa setelah clock mengeluarkan pulsa sebanyak yang
3.
METODOLOGI
3.1
PERALATAN 1.
Arduino UNO (1)
2.
4-Digit 7 Segment 5643BH (1)
3.
Resistor 220 Ohm (8)
4.
Push button (4)
5.
Kapasitor 100nF (3)
6.
Perfboard potong (2)
7.
Beberapa kabel jumper
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
1
3.2
LANGKAH PENGERJAAN
Langkah pengerjaan dimulai dari pertama-tama merangkai/menyolder rangkaian pada perfboard. Dilanjutkan dengan pembuatan kode dengan beberapa kali debugging hingga diperoleh hasil yang relatif memuaskan. Kemudian, pengetesan dilakukan beberapa kali untuk mengamati kualitas perangkat dibuat. Selanjutnya dilakukan lagi sedikit pengesetan untuk mengamati pengaruhnya terhadap kualitas perangkat. Terakhir, pengetesan terakhir dilakukan untuk mengecek perbaikan kuaitas perangkat yang telah dibuat.
4. 4.1
HASIL DAN ANALISIS HARDWARE JAM DIGITAL
Untuk tugas kali ini, kami memilih untuk menggunakan Arduino UNO dengan mikrokontroler ATMega328 sebagai platform jam digital kami. Berikut adalah penampakan Arduino UNO yang kami gunakan.
Kemudian, agar jam terlihat rapih, kami menggunakan Perfboard / DOT PCB sebagai media peletakan komponen. Kami merangkai rangkaian jam serta rangkaian push button pada lokasi yang berbeda untuk mempermudah interkoneksi antar prefboard dengan Arduino UNO yang kami gunakan. Berikut adalah penampakan kedua Perfboard kami yang telah dipasangi dengan komponen-komponen yang digunakan, serta penampakan hasil akhir tugas kami.
Beberapa hal yang perlu diperhatikan disini adalah jenis 7 segment LED kami, serta penggunaan kapasitor pada push button. Tipe 4-digit segment yang kami gunakan disini adalah 5643BH. 4-digit 7 segment 5643BH adalah 4 digit 7 segment tipe common anode yang hanya memerlukan 12 pin untuk interkoneksinya. Berikut adalah rangkain dalam dari 4-digit 7 segment 5643BH.
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
2
Cara menampilkan digit yang berbeda untuk keempat digit nya akan dijelaskan pada bagian penjelasan kode. Kemudian, untuk membatasi agar arusnya tetap pada kisaran 20mA, digunakan resistor-resistor 220 Ohm. Selanjutnya, rangkaian push button. Berikut adalah rangkaian push button yang kami gunakan. Terlihat bahwa tidak digunakan pull-up eksternal, hal ini dikarenakan pada software telah di set untuk menggunakan pull up internal. Kemudian, kapasitor yang diletakkan parallel dengan tombol tersebut berguna sebagai debouncer secara hardware. Kapasitor dapat digunakan untuk men-debounce tombol dkarenakan kapasitor memiliki sifat low pass terhadap tegangan, dengan demikian, tegangantegangan yang berubah berkali-kali dengan cepat dapat dihilangkan.
4.2
HASIL PENGETESAN 12 JAM DAN 24 JAM
Berikut adalah hasil pengetesan jam digital kami untuk selang waktu yang berbeda-beda. Ketiga pengetesan awal menggunakan prescaler 1024. UTC/GMT+7
Jam kami
Range
01.56-15.12
00.00-13.16
Duration
13.16
13.16
Keterangan
Kira-kira terpisah sekitar 5 detik
Tabel 1 β Hasil pengetesan pertama UTC/GMT+7
Jam kami
Range
12.06-00.06
12.06-00.06
Duration
12.00
12.00
Keterangan
Kira-kira terpisah sekitar 4 detik
Tabel 2 β Hasil pengetesan kedua UTC/GMT+7
Jam kami
Range
12.06-12.26
12.06-12.26
Duration
24.20
24.20
Keterangan
Kira-kira terpisah sekitar 9 detik
Tabel 3 β Hasil pengetesan ketiga Pengetesan berikut menggunakan prescaler 256. UTC/GMT+7
Jam kami
Range
20.15-13.18
20.15-13.18
Duration
17.03
17.03
Keterangan
Kira-kira terpisah sekitar 7 detik
Jika dihitung, kira kira ada error sekitar kurang dari 100us setiap detiknya untuk kedua jenis prescaler.
4.3
ANALISIS KODE
Kode keseluruhan dari tugas kali ini dapat dilihat pada bagian lampiran. Berikut akan dianalisa kode yang telah dibuat bagian per bagian. Bagian pertama yang akan dianalisa adalah fungsi show_time dan show_digit, yaitu fungsi yang dipakai untuk menampilkan nilai waktu (4 digit), serta fungsi yang digunakan untuk menampilkan digit tertentu. Berikut adalah fungsi show_digit. void show_digit(char dig){ switch (dig){ case 0: PORTD = 0b10000011; PORTB = 0b11000000 | sec; break; case 1: PORTD = 0b10000011; PORTB = 0b11111100 | sec; break; case 2: PORTD = 0b00000011; PORTB = 0b11010001 | sec; break; case 3: PORTD = 0b00000011; PORTB = 0b11011000 | sec; break; case 4: PORTD = 0b00000011; PORTB = 0b11101100 | sec; break; case 5: PORTD = 0b01000011; PORTB = 0b11001000 | sec; break; case 6: PORTD = 0b01000011; PORTB = 0b11000000 | sec; break; case 7: PORTD = 0b10000011; PORTB = 0b11011100 | sec; break; case 8:
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
3
PORTD = PORTB = break; case 9: PORTD = PORTB = break;
0b00000011; 0b11000000 | sec;
mengaktifkan keempat 7 segment adalah pin 2-5 Arduino, atau pin D2-D5 ATMega328.
0b00000011; 0b11001000 | sec;
Selanjutnya, akan dijelaskan bagian kode pengesetan timer, init_tim serta ISR dari timer overflow. Berikut adalah fungsi init_tim yang dibuat.
} } Pada dasarnya, bagian ini berfungsi untuk mengatur nilai keluaran dari tiap pin yang berhubungan dengan pin yang digunakan untuk menampilkan angka pada 4-digit 7 segment. Yang dalam kasus kami adalah pin 6-13 Arduino, atau kalau di map ke pin AVR adalah pin D7 dan D6 serta pin B0-B5. Pola bit yang dikeluarkan bergantung pada angka yang ingin ditampilkan. Kemudian, LED DP ditampilkan sekali tiap 2 detik dengan menggunakan |sec yang mana nilainya ditoggle setiap detik. Berikut adalah bagian show_time. void show_time(char digs[]){ for(int i = 0; i < 4; i++){ show_digit(digs[i]); PORTD ^= (1<<(i+2)); PORTD ^= (1<<(i+2)); }
void init_int(){ TIMSK1 = 0b00000001; TCCR1B = 0b00000100; TCNT1H = 0x0B; TCNT1L = 0xDC; sei(); } Pada dasarnya, bagian kode ini melakukan pengesetan terhadap nilai prescaler yang digunakan, interrupt timer yang di-enable serta nilai TCNT awal. Pengesetan nilai TIMSK1 = 1 berfungsi untuk meenable interrupt timer overflow dari TCNT1. TCCR1B = 0b00000100 mengeset nilai prescaler nya menjadi 256. Sedangkan nilai TCNT1H dan TCNT1L dipilih agar diperoleh interrupt overflow setiap 1 detik. Nilai TCNT diperoleh dari perhitungan berikut. ππΆππ1 = 216 β
} Pada dasarnya, bagian ini akan menampilkan nilai digit yang berbeda-beda pada posisi digit 7 segment yang berbeda bergantung pada nilai dari digs[i]. Sebagai contoh, apabila nilai digs adalah {1,2,3,4}, maka 7 segment pertama akan menampilkan angka 1, 7 segment kedua akan menampilkan angka 2, 7 segment ketiga akan menampilkan angka 3, serta 7 segment keempat akan menampilkan angka 4.
Berikut adalah fungsi ISR yang dipanggil setiap detik. void init_int(void); ISR(TIMER1_OVF_vect){ TIFR1 = (1<
0){ mytimer--; }
Cara kerja dari fungsi ini adalah dengan mengaktifkan posisi digit yang sesuai pada 4-digit 7 segment secara berganti-gantian dengan sangat cepat. Setiap kali posisi digit tertentu diaktifkan, ditampilkan nilai digit yang sesuai untuk posisi tersebut dengan menggunakan fungsi show_digit. Meskipun akhirnya untuk setiap digit akan ditampilkan dengan sangat singkat, namun dikarenakan dalam waktu yang sangat singkat pula digit ditampilkan kembali, mata manusia akan mengangapnya menyala secara terus menerus. Satu hal lagi yang perlu diperhatikan disini adalah, dikarenakan 7 segment yang digunakan adalah common anode, maka untuk mengakitfkan 7 segment tertentu justru diberikan tegangan low. Untuk kasus kami, pin-pin yang digunakan untuk
16 ππ»π§ Γ 1π = 3036 = 0π₯0π΅πΆπ· 256
minute = (mytime/60)%60; hour = (mytime/3600)%24; mytime_arr[0] = minute%10; mytime_arr[1] = minute/10; mytime_arr[2] = hour%10; mytime_arr[3] = hour/10; minute = (mytimer)%60; hour = (mytimer/60)%60; mytimer_arr[0] = minute%10; mytimer_arr[1] = minute/10; mytimer_arr[2] = hour%10; mytimer_arr[3] = hour/10; } Bagian pertama, yaitu TIFR1 = (1<
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
4
TCNT1L = 0xDC; Berfungsi untuk me-reset timer sehingga dapat kembali digunakan untuk menghitung 1 detik. Bagian kedua, yaitu
if(!digitalRead(A0)){ while(!digitalRead(A0)); mode = (mode+1)%3; } Terlihat bahwa pada dasarnya ketka tombol mode ditekan, nilai mode ditambah sehingga mode pun berubah.
mytime++; if(mytimer > 0){ mytimer--; } Berfungsi untuk menaikkan nilai mytime yang digunakan untuk mode jam serta menurunkan nilai mytimer yang digunakan untuk mode timer. Bagian terakhir, yaitu minute = (mytime/60)%60; hour = (mytime/3600)%24; mytime_arr[0] = minute%10; mytime_arr[1] = minute/10; mytime_arr[2] = hour%10; mytime_arr[3] = hour/10;
Berikut adalah penanganan penekanan tombol untuk melakukan pengesetan. else if(!digitalRead(A3)){ while(!digitalRead(A3)); if(mode == 1 || mode == 2){ pos = (pos+1)%4; } }else if(!digitalRead(A2)){ while(!digitalRead(A2)); if(mode == 1 || mode == 2){ tempTime[pos] = (tempTime[pos]+1)%10; }
minute = (mytimer)%60; hour = (mytimer/60)%24; mytimer_arr[0] = minute%10; mytimer_arr[1] = minute/10; mytimer_arr[2] = hour%10; mytimer_arr[3] = hour/10; Berfungsi untuk mengkonversi nilai detik pada variabel mytime dan mytimer menjadi digit-digit pada 7 segment LED 4 digit. Selanjutnya, akan dijelaskan kode yang ada di dalam loop while(1). Berikut adalah bagian pertama dari kode dalam loop while(1). if(mode == 0){ show_time(mytime_arr); }else if(mode == 1){ show_time(tempTime); }else if(mode == 2){ show_time(tempTime); }else if(mode == 3){ show_time(mytimer_arr); } Pada dasarnya bagian kode ini akan menampilkan angka yang sesuai bergantung pada sedang pada mode apa. Mode 0 adalah mode jam, dengan demikian yang akan ditampilkan adalah mytime. mode 1 dan mode 2 adalah mode pengesetan, dengan demikian nilai yang akan ditampilkan adalah temptime, yaitu nilai yang sedang di set. Mode 3 adalah mode timer, dengan demikian yang akan ditampilkan adalah mytimer, yaitu nilai timer. Selanjutnya, adalah penanganan penekanan tombol. Berikut adalah penanganan penekanan tombol merubah mode.
Dalam mode pengesetan, pengguna dapat mengeset nilai tiap digit dari keempat digit pada 7 segment LED 4 digit. Untuk itu, disediakan dua tombol untuk melakukan pengesetan, yaitu tombol yang digunakan untuk memilih digit mana yang akan diubah nilainya, serta tombol yang digunakan untuk menaikkan nilai nya. Terlihat bahwa nilai yang diset dalam mode ini adalah nilai tempTime, dengan demikian, selama pengesetan, nilai jam tidak terpengaruh, hingga tombol konfirmasi ditekan. Berikut adalah bagian penganganan penekanan tombol konfirmasi. else if(!digitalRead(A1)){ while(!digitalRead(A1)); if(mode == 1){ mode = 0; mytime_arr[3] = tempTime[3];mytime_arr[2] = tempTime[2];mytime_arr[1] = tempTime[1];mytime_arr[0] = tempTime[0]; mytime = tempTime[0]*60+tempTime[1]*600+tempTi me[2]*3600+tempTime[3]*36000; }else if(mode == 2){ mode = 3; mytimer_arr[3] = tempTime[3];mytimer_arr[2] = tempTime[2];mytimer_arr[1] = tempTime[1];mytimer_arr[0] = tempTime[0]; mytimer = tempTime[0]+tempTime[1]*10+tempTime[2 ]*60+tempTime[3]*600; } }
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
5
Pada dasarnya, ketika tombol konfirmasi ditekan, nilai pengesetan akan dijadikan nilai yang dipakai pada mode jam atau mode timer, bergantung pada mode apakah pengesetan dilakukan. Apabila pengesetan dilakukan pada mode 1, yaitu pengesetan jam, maka nilai yang akan diubah adalah nilai mytime, sedangkan apabila pengesetan dilakukan pada mode 2, yaitu pengesetan timer, maka nilai yang akan diubah adalah nili mytimer.
5.
KESIMPULAN
Jam digital telah berhasil dibuat dengan kualitas yang cukup memuaskan, yaitu akurasi hingga kurang dari 100us untuk setiap detiknya.
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
6
LAMPIRAN int mode = 0; long long char char
unsigned int mytime = 0; unsigned int mytimer = 0; minute; hour;
char mytime_arr[4] = {0,0,0,0}; char mytimer_arr[4] = {0,0,0,0}; char tempTime[4] = {0,0,0,0}; char pos = 0; void init_int(void); ISR(TIMER1_OVF_vect){ TIFR1 = (1< 0){ mytimer--; } minute = (mytime/60)%60; hour = (mytime/3600)%24; mytime_arr[0] = minute%10; mytime_arr[1] = minute/10; mytime_arr[2] = hour%10; mytime_arr[3] = hour/10; minute = (mytimer/60)%60; hour = (mytimer/3600)%24; mytimer_arr[0] = minute%10; mytimer_arr[1] = minute/10; mytimer_arr[2] = hour%10; mytimer_arr[3] = hour/10; } void show_digit(char dig){ switch (dig){ case 0: PORTD = 0b10000011; PORTB = 0b11000010; break; case 1: PORTD = 0b10000011; PORTB = 0b11111110; break; case 2: PORTD = 0b00000011; PORTB = 0b11010011; break; case 3: PORTD = 0b00000011; PORTB = 0b11011010; break; case 4: PORTD = 0b00000011; PORTB = 0b11101110; Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
7
break; case 5: PORTD = PORTB = break; case 6: PORTD = PORTB = break; case 7: PORTD = PORTB = break; case 8: PORTD = PORTB = break; case 9: PORTD = PORTB = break;
0b01000011; 0b11001010; 0b01000011; 0b11000010; 0b10000011; 0b11011110; 0b00000011; 0b11000010; 0b00000011; 0b11001010;
} } void show_time(char digs[]){ for(int i = 0; i < 4; i++){ show_digit(digs[i]); PORTD ^= (1<<(i+2)); PORTD ^= (1<<(i+2)); } } int main(void){ DDRD = 0xFF; DDRB = 0xFF; DDRC = 0x00; PORTC = 0xFF; PORTD = 0x00; init_int(); while(1){ if(mode == 0){ show_time(mytime_arr); }else if(mode == 1){ show_time(tempTime); }else if(mode == 2){ show_time(tempTime); }else if(mode == 3){ show_time(mytimer_arr); } if(!digitalRead(A0)){ while(!digitalRead(A0)); mode = (mode+1)%3; } else if(!digitalRead(A3)){ while(!digitalRead(A3)); if(mode == 1 || mode == 2){ pos = (pos+1)%4; } }else if(!digitalRead(A2)){ while(!digitalRead(A2)); if(mode == 1 || mode == 2){ tempTime[pos] = (tempTime[pos]+1)%10; } Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
8
}else if(!digitalRead(A1)){ while(!digitalRead(A1)); if(mode == 1){ mode = 0; mytime_arr[3] = tempTime[3];mytime_arr[2] = tempTime[2];mytime_arr[1] = tempTime[1];mytime_arr[0] = tempTime[0]; mytime = tempTime[0]*60+tempTime[1]*600+tempTime[2]*3600+tempTime[3]*36000; }else if(mode == 2){ mode = 3; mytimer_arr[3] = tempTime[3];mytimer_arr[2] = tempTime[2];mytimer_arr[1] = tempTime[1];mytimer_arr[0] = tempTime[0]; mytimer = tempTime[0]*60+tempTime[1]*600+tempTime[2]*3600+tempTime[3]*36000; } } } } void init_int(){ TIMSK1 = 0b00000001; TCCR1B = 0b00000100; TCNT1H = 0x0B; TCNT1L = 0xDC; sei(); }
Laporan Praktikum - Laboratorium Dasar Teknik Elektro β STEI ITB
9