Anda di halaman 1dari 6

LAPORAN TUGAS # 1 JAM DIGITAL SEDERHANA

Achmad Fathoni 13215061

Najmi Kertasafari 13216017

1. Spesifikasi
a. Display 6 digit 7-segment yang menampilkan waktu HHMMSS sejak pertama kali
mikrokontroller menyala
b. Tidak ada tombol
c. Menggunakan daya dari kabel USB
d. Prosesor ATMEGA328P dari Arduino Nano
e. Rangkaian menggunakan breadboard
f. Diprogram di tingkat register
g. Menampilkan waktu selama 24 Jam
2. Skema hardware
a. Diagram

b. IC7447 adalah IC decoder dari BCD 4 bit ke bit kode 7-segment. Pasokan daya IC ini dari
Arduino.
c. Karena masukan IC7447 hanya merupakan kumpulan gerbang logika yang menarik
arus kecil maka tidak ada resistor yang dipakai antara IC7447 dan Arduino.
d. Tampilan angka dari tiap 7-segment diatur secara paraller oleh satu IC7447 namun
hanya ada satu 7-segment yang menyala tiap saat(multiplexing) dengan pergantian
setiap 1ms atau refresh rate 1kHz.
e. Tiap common anode dari 7-segment dijadikan pin enable yang disambungkan ke
Arduino dengan perlindungan arus berupa resistor 1kOhm.
f. Jika Arduino memberikan sinyal HIGH(3.3V) ke common anode maka 7-segment akan
aktif.
g. Segment dari 7-segment aktif akan menyala ketika IC7447 memberikan sinyal LOW
dengan tegangan 0.3V. Anggap tiap LED segment mempunya drop 0.7V sehingga arus
maksimal(ketika 7-segment menampilkan angka 8) adalah 7*(3.3-0.7-0,3)/1k = 16.1
mA. Arus ini lebih rendah dari arus maksimal pin Arduino yaitu 40mA.
3. Skema software
a. Diagram alir
b. Dua timer interrupt
i. TIMER0 dijadikan interrupt dengan compare trigger untuk multiplexing 7-segment.
Menggunakan prescaler 1024 dengan frekuensi 16MHz ATMEGA328P maka tiap
kenaikan tick dari TIMER0 di register TCNT0 setara 64 mikrodetik sehingga agar
interval interrupt TIMER0 menjadi 1milidetik maka diperlukan 1mili/64micro ≈ 156
tick, muat di register compare TIMER0 (OCR0A) yang kapasitasnya 255 tick. Agar
TCNT0 bernilai 0 kembali ketika nilainya sama dengan OCR0A maka TIMER0 dipilih
mode CTC(Clear Time on Compare).
ii. TIMER1 dijadikan interrupt compare trigger untuk timekeeping dengan unit tiap
detik. Jika interrupt terjadi maka variable sec akan bertambah satu yang
menandakan satu detik sudah berlalu. Untuk menunggu satu detik itu ,register
compare OCR1A diisi 15624 tick, muat dari kapasitasnya yaitu 65535 tick. TIMER1
juga diset mode CTC.
c. Konversi desimal ke BCD dalam 8 bit/ 2 desimal dengan membagi digit desimal dengan
10 lalu agar menjadi satuan menggeser bitnya sebanyak 4 bit. Hal ini akan membuat
bit 7-4 berisi BCD digit puluhan. Lalu bit 3-0 BCD cukup menyalin bit 3-0 desimal.
d. Dalam multiplexing 6 7-segment, kami memakaia dua pin dari PORTD dan 4 pin dari
PORTB. Agar menyala bergantian PORTB dilakukan bitshift 1 digit tiap interrupt saat
giliran digit MMSS, sayangnya karena PORTD juga berisI data untuk masukan IC7447
maka tidak bisa dilakukan bitshitf saat giliran digit HH. Oleh karena itu digunakan
hardcode seperti yang ada di switchcase dalam fungsi ISR untuk TIMER0.
4. Pengujian

Pengujian dilakukan dengan menggunakan stopwatch dari smartphone karena jadwal


pengumpulan laporan yang dekat kami hanya mampu menguji alat hingga tiga jam. Walaupun
terlihat detik jam kami lebih cepat berganti daripada smartphone tapi belum sampai dikondisi
menunjukan waktu berbeda tiap saat..
5. Foto alat
6. Source code
tv6f nm

#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif

//Multiplexer constant
#define SEVSEGDIGIT 6
#define PRESCALER 1024
#define DELAY 0.001 //second, max 0.01632
#define WAIT_TIME_MUX (DELAY * F_CPU / PRESCALER)

//Time keeper constant with 1 second resolution


#define WAIT_TIME_TK (1 * F_CPU / PRESCALER)

#define DAY2SEC 86399


#define HOUR2SEC 3600
#define MIN2SEC 60

#include <avr/io.h>
#include <avr/interrupt.h>

uint8_t sevSegMuxInc = 0;
uint32_t sec = 0;

uint8_t BCDTime[] = {
0, 0, 0
};

//Konversi dua digit desimal ke dua digit BCD


uint8_t DecTo2BCD(uint8_t dec){
return (((dec/10)<<4)+(dec%10));
}

//Display a BCD digit


void displayBCD(uint8_t val){
//Fill PORTD2 to PORTD5 with first 4 bit of val
for(uint8_t i = PORTD2; i <= PORTD5; ++i){
if(val & 0x01){
PORTD |= 1 << i;
}else{
PORTD &= ~(1 << i);
}
val = val >> 1;
}
}
int main(){
//Set 7-segment output pin
DDRB = (1 << PORTB0) | (1 << PORTB1) | (1 << PORTB2) | (1 << PORTB3);
DDRD = (1 << PORTD6) | (1 << PORTD7);

//Set BCD pin


DDRD |= (1 << PORTD2) | (1 << PORTD3) | (1 << PORTD4) | (1 << PORTD5);

// Set the Timer Mode to CTC


TCCR0A |= (1 << WGM01);
TCCR1B |= (1 << WGM12);

// Set timer target


OCR0A = WAIT_TIME_MUX;
OCR1A = WAIT_TIME_TK;

//Set the ISR COMPA vect


TIMSK0 |= (1 << OCIE0A);
TIMSK1 |= (1 << OCIE1A);

// set prescaler to 1024 and start the timer


TCCR0B |= (1 << CS00) | (1 << CS02);
TCCR1B |= (1 << CS10) | (1 << CS12);

//enable interrupts
sei();
while(1){
}
}
//7-segment multiplexer ISR
ISR (TIMER0_COMPA_vect) // timer0 overflow interrupt
{
//Processing Time BCD
uint8_t BCD = BCDTime[sevSegMuxInc/2];
if(sevSegMuxInc % 2 == 0){
BCD = BCD >> 4;
}
displayBCD(BCD);

//Multiplexing 7-segment
switch(sevSegMuxInc){
case 0:
PORTB = 0x00;
PORTD |= 1 << PORTD6;
break;
case 1:
PORTD &= ~(1 << PORTD6);
PORTD |= 1 << PORTD7;
break;
case 2:
PORTD &= ~(1 << PORTD7);
PORTB = 1 << PORTB0;
break;
case 3:
case 4:
case 5:
PORTB = PORTB << 1;
break;
}

//Increment 7-segment digit multiplexer counter


if(sevSegMuxInc < SEVSEGDIGIT-1){
++sevSegMuxInc;
}else{
sevSegMuxInc = 0;
}
}

ISR (TIMER1_COMPA_vect)
{
// action to be done every 1 sec
if(sec == DAY2SEC){
sec = 0;
}else{
++sec;
}

uint32_t sec_ = sec;

BCDTime[0] = DecTo2BCD(sec_ / HOUR2SEC);


sec_ %= HOUR2SEC;

BCDTime[1] = DecTo2BCD(sec_ / MIN2SEC);


sec_ %= MIN2SEC;

BCDTime[2] = DecTo2BCD(sec_);
}