Siapkan bahan-bahan seperti berikut:
Attiny 2313 + downloader isp
Bagian power supply
- Trafo AC atau Adaptor yang dapat diatur tegangannya
- Jika menggunakan Trafo AC, maka ubah-ubah terminal sekunder trafo untuk V Segmen
- 7805 untuk menurunkan tegangan ke 5V
- Baterai backup 3v - 4.5 v
Dioda 1N4002 (4 + 1 )atau Dioda Bridge sebagai penyearah jika memakai Trafo AC
Capasitor 1000uF/25v , 100nF, 22pF (2buah) atau Varco 0-50pF
Resistor 10K (3 buah), 1K 2Buah
Led 4 buah sebagai pembatas digit
ULN 2003
OptoIsolator PC817 atau 4N25 atau yang sejenis (6 buah)
Xtal 4MHz atau sesuai keinginan
Push Buton tactile (2 buah)
7 segment common Anoda ukuran terserah (6 buah)
SKEMATIK
- Gunakan power supply berbeda (yang dapat diubah-ubah) untuk V SEGMEN sehingga dapat mengatur kecerahan dari 7 segmen
- Untuk mengkompensasi ketidak akuratan xtal, maka salah satu load cap dari xtal dibuat variabel
- Nilai Xtal yang digunakan disesuaikan dengan xtal yg tersedia dipasaran, jika berbeda maka silahkan baca pembahasan mengenai counter/timer disini.
- Baterai backup akan mencatu attiny jika listrik mati (tanpa display) sehingga time keeping tetap jalan.
#define F_CPU 4000000UL //sesuaikan xtal yg dipakai
#include <avr/io.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <string.h>
uint8_t jam,menit,detik,bulan,tanggal,tahun,clock,menu,mode,blink;
uint8_t a = 0;
char bul_max[12]={31,28,31,30,31,30,31,31,30,31,30,31} ;
//tampilan 7 digit 7 segmen dan animasi
void segmen(uint8_t digit)
{
switch (digit)
{
case 0 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4)
& ~_BV(PB5) & ~_BV(PB6);
PORTB |= _BV(PB7);
break;
}
case 1 :
{
PORTB &= ~_BV(PB2) & ~_BV(PB3);
PORTB |= _BV(PB1)| _BV(PB4)| _BV(PB5)| _BV(PB6)| _BV(PB7);
break;
}
case 2 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB7) & ~_BV(PB5) & ~_BV(PB4);
PORTB |= _BV(PB3)| _BV(PB6) ;
break;
}
case 3 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB7);
PORTB |= _BV(PB5)| _BV(PB6) ;
break;
}
case 4 :
{
PORTB &= ~_BV(PB6) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB7) ;
PORTB |= _BV(PB4)| _BV(PB5) | _BV(PB1);
break;
}
case 5 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB7) & ~_BV(PB6);
PORTB |= _BV(PB2) | _BV(PB5);
break;
}
case 6 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB3) & ~_BV(PB4) & ~_BV(PB7) & ~_BV(PB6) & ~_BV(PB5);
PORTB |= _BV(PB2) ;
break;
}
case 7 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3);
PORTB |= _BV(PB4)| _BV(PB5)| _BV(PB6)| _BV(PB7);
break;
}
case 8 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4)
& ~_BV(PB5) & ~_BV(PB6) & ~_BV(PB7);
break;
}
case 9 :
{
PORTB &= ~_BV(PB1) & ~_BV(PB2) & ~_BV(PB3) & ~_BV(PB4)
& ~_BV(PB6) & ~_BV(PB7);
PORTB |= _BV(PB5);
break;
}
case 10 :
{
PORTB |= _BV(PB1) | _BV(PB2) | _BV(PB3) | _BV(PB4)|
_BV(PB5) | _BV(PB6) | _BV(PB7) ;
break;
}
case 11 :
{
PORTB &= ~_BV(PB1);
PORTB |= _BV(PB2) | _BV(PB3) | _BV(PB4)|
_BV(PB5) | _BV(PB6) | _BV(PB7) ;
break;
}
case 12 :
{
PORTB &= ~_BV(PB4);
PORTB |= _BV(PB2) | _BV(PB3) | _BV(PB1)|
_BV(PB5) | _BV(PB6) | _BV(PB7) ;
break;
}
case 13 :
{
PORTB &= ~_BV(PB2);
PORTB |= _BV(PB4) | _BV(PB3) | _BV(PB1)|
_BV(PB5) | _BV(PB6) | _BV(PB7) ;
break;
}
case 14 :
{
PORTB &= ~_BV(PB3);
PORTB |= _BV(PB2) | _BV(PB4) | _BV(PB1)|
_BV(PB5) | _BV(PB6) | _BV(PB7) ;
break;
}
case 15 :
{
PORTB &= ~_BV(PB5);
PORTB |= _BV(PB2) | _BV(PB3) | _BV(PB1)|
_BV(PB4) | _BV(PB6) | _BV(PB7) ;
break;
}
case 16 :
{
PORTB &= ~_BV(PB6);
PORTB |= _BV(PB2) | _BV(PB3) | _BV(PB1)|
_BV(PB5) | _BV(PB4) | _BV(PB7) ;
break;
}
}
PORTB = _BV(PB0) | ~PORTB; //khusus memakai uln2003
}
//posisi scan digit
void posisi(uint8_t pos)
{
switch (pos)
{
case 0 :
{
PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5) & ~_BV(PD6) ;
PORTB &= ~_BV(PB0);
break;
}
case 1 :
{
PORTD |= _BV(PD0);
PORTD &= ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5) & ~_BV(PD6) ;
PORTB &= ~_BV(PB0);
break;
}
case 2 :
{
PORTD |= _BV(PD1);
PORTD &= ~_BV(PD0) & ~_BV(PD6) & ~_BV(PD4) & ~_BV(PD5) ;
PORTB &= ~_BV(PB0);
break;
}
case 3 :
{
PORTD |= _BV(PD4);
PORTD &= ~_BV(PD1) & ~_BV(PD0) & ~_BV(PD5) & ~_BV(PD6) ;
PORTB &= ~_BV(PB0);
break;
}
case 4 :
{
PORTD |= _BV(PD5);
PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD6) ;
PORTB &= ~_BV(PB0);
break;
}
case 5 :
{
PORTD |= _BV(PD6);
PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5) ;
PORTB &= ~_BV(PB0);
break;
}
case 6 :
{
PORTB |= _BV(PB0);
PORTD &= ~_BV(PD0) & ~_BV(PD1) & ~_BV(PD4) & ~_BV(PD5) & ~_BV(PD6) ;
break;
}
}
}
void animasi(void) //animasi pindah jam-kalender
{
posisi(1);
segmen(11);
_delay_ms(50);
posisi(2);
segmen(11);
_delay_ms(50);
posisi(3);
segmen(11);
_delay_ms(50);
posisi(4);
segmen(11);
_delay_ms(50);
posisi(5);
segmen(11);
_delay_ms(50);
posisi(6);
segmen(11);
_delay_ms(50);
segmen(13);
_delay_ms(50);
segmen(14);
_delay_ms(50);
posisi(5);
segmen(12);
_delay_ms(50);
posisi(4);
segmen(12);
_delay_ms(50);
posisi(3);
segmen(12);
_delay_ms(50);
posisi(2);
segmen(12);
_delay_ms(50);
posisi(1);
segmen(15);
_delay_ms(50);
segmen(16);
_delay_ms(50);
}
void tulis(void) //tulis ke 7 segmen
{
posisi(1);
if(menu == 1 && TCNT1 < 20000) segmen(10); //edit jam
else segmen((jam/10));
_delay_ms(1);
segmen(10);
posisi(2);
if(menu == 1 && TCNT1 < 20000) segmen(10); //edit jam
else segmen((jam%10));
_delay_ms(1);
segmen(10);
posisi(3);
if(menu == 2 && TCNT1 < 20000) segmen(10); //edit menit
else segmen((menit/10));
_delay_ms(1);
segmen(10);
posisi(4);
if(menu == 2 && TCNT1 < 20000) segmen(10); //edit menit
else segmen((menit%10));
_delay_ms(1);
segmen(10);
posisi(5);
if(menu == 3 && TCNT1 < 20000) segmen(10); //edit detik
else segmen((detik/10));
_delay_ms(1);
segmen(10);
posisi(6);
if(menu == 3 && TCNT1 < 20000) segmen(10); //edit detik
else segmen((detik%10));
_delay_ms(1);
segmen(10);
}
void tanggalan(void)
{
posisi(1);
if(menu == 4 && TCNT1 < 20000) segmen(10); //edit tgl
else segmen((tanggal/10));
_delay_ms(1);
segmen(10);
posisi(2);
if(menu == 4 && TCNT1 < 20000) segmen(10); //edit tgl
else segmen((tanggal%10));
_delay_ms(1);
segmen(10);
posisi(3);
if(menu == 5 && TCNT1 < 20000) segmen(10); //edit bulan
else segmen((bulan/10));
_delay_ms(1);
segmen(10);
posisi(4);
if(menu == 5 && TCNT1 < 20000) segmen(10); //edit bulan
else segmen((bulan%10));
_delay_ms(1);
segmen(10);
posisi(5);
if(menu == 6 && TCNT1 < 20000) segmen(10); //edit tahun
else segmen((tahun/10));
_delay_ms(1);
segmen(10);
posisi(6);
if(menu == 6 && TCNT1 < 20000) segmen(10); //edit tahun
else segmen((tahun%10));
_delay_ms(1);
segmen(10);
}
//INTERUPT 1 DETIK
ISR(TIMER1_COMPA_vect)
{
detik++;
clock++;
if(detik == 60)
{
detik=0;
menit++;
if(menit == 60)
{ menit=0;
jam++;
}
if (jam == 24)
{ tanggal++; jam = 0 ; }
if(tahun%4 == 0) bul_max[1]=29;
else bul_max[1]=28;
if (tanggal > bul_max[bulan-1]) {bulan++; tanggal =1 ;}
if (bulan > 12) {tahun++; bulan=1; }
}
}
void tombol(void)
{
if(bit_is_clear(PIND, PIND2))
{
if(menu == 0) menu =1;
else if (menu == 1) menu=2;
else if (menu == 2) menu=3;
else if (menu == 3) menu=4;
else if (menu == 4) menu=5;
else if (menu == 5) menu=6;
else if (menu == 6) menu=0;
_delay_ms(200);
}
else if(bit_is_clear(PIND, PIND3))
{
if(mode==0 && menu == 0)
{ animasi();
mode=1;
clock=0; }
else if(mode ==1 && menu ==0)
{mode=0;
clock=0;
}
if(menu == 1)
{ jam ++;
if (jam == 24) jam =0;
}
else if(menu == 2)
{ menit ++;
if (menit == 60) menit =0;
}
else if(menu == 3) detik = 0;
else if(menu == 4)
{ tanggal++;
if (tanggal == 32) tanggal =1;
}
else if(menu == 5)
{ bulan++;
if (bulan == 13) bulan =1;
}
else if(menu == 6)
{ tahun++;
if (tahun == 100) tahun=0;
}
_delay_ms(200);
}
}
int main(void)
{
DDRD |= _BV(PD0) | _BV(PD1) | _BV(PD4) | _BV(PD5) | _BV(PD6) ; //scan digit
DDRB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) | _BV(PB7) ; //segment
DDRD &= ~_BV(PD2) & ~_BV(PD3); //tombol
// ------------ini untuk xtal 4Mhz----------------------
TCCR1B |= (1 << WGM12);
TIMSK |= (1 << OCIE1A);
OCR1A = 62499;
TCCR1B |= (1 << CS11)|(1 << CS10);
//------------------------------------------------------
jam = 0;
menit= 0;
detik=0;
tanggal=1;
bulan=1;
tahun=11;
clock=0; //perpindahan animasi jam dan kalender
mode=0;
menu=0;
sei();
while(1)
{
if(clock == 40 && mode == 1 && menu == 0)
{ animasi();}
else if(clock > 40 && clock <50 && mode == 1 && menu == 0)
{
tanggalan();
}
else if(clock == 50 && mode == 1 && menu == 0)
{ animasi(); clock =0; }
else if(menu == 0)
{ tulis(); }
else if(menu > 3)
{ tanggalan(); }
else
{ tulis(); }
tombol();
}
return 0;
}
ALTERNATIF UNTUK 7 SEGMEN LEBIH BESAR
Optoisolator PC817 mempunyai kekurangan yaitu dayanya kecil sehingga arus yg dapat dialirkan kecil saja. Hal ini akan menyebabkan 7 segmen besar menjadi redup sehingga perlu ditambahkan transistor yg memiliki daya lebih dan dengan rangkaian common Emiter menggunakan transistor PNP seperti BD140 dan PC817 sebagai control base nya (bisa juga transistor NPN 2N3906/2222) dengan contoh rangkaian pengganti sebagai berikut:
SELAMAT MENCOBA