Apa gak bosen kali ya saya menulis tentang jam digital ? Kalu dipikir memang saya maniak per-jam-an digital, dari yg paling sederhana pake delay sampai yg murni tanpa microcontroller, FULL CMOS. Saya rangkum dulu deh isi blog ini yg membahas jam mana saja...
- Jam tanpa Mikro Full CMOS
- Praktek Jam attiny2313
- Jam Attiny2313 - Request orang prancis 2021
- Jam 6 digit dengan Attiny2313
- Menampilkan Jam di TV
- Jam di Led Matrix
Wah masih banyak lagi yang tidak saya sebutkan karena panjang, cek aja sendiri pasti banyak ketemu pembahasan tentang jam yang keseluruhannya memanfaatkan register timer pada microcontroller sekelas AVR. Kali ini saya akan melanjutkan praktek I/O pada microcontroller Attiny2313 dengan melengkapi 7 segmen agar lebih bermanfaat yaitu ketika digabung beberapa buah menjadi jam yg dapat digunakan. Rangkaiannya seperti berikut ini.
Metode yang sangat terkenal saat pin I/O terbatas adalah metode scanning cepat, dimana tiap display 7 segmen ditampilkan secara bergantian. Jadi ke 7 kaki segmen dari masing-masing display 7 segmen terhubung semuanya. Sedangkan untuk melakukan penyalaannya diberikan tegangan pada common anoda secara satu-persatu dengan kecepatan tinggi sehingga menipu mata kalau nyalanya bareng. Jadi logikanya sesuai flowchart berikut :
Proses scanning penjelasannya seperti berikut :
- Bagi nilai jam dengan 10 untuk mendapatkan puluhan jam, kemudian aktifkan PB#0, sedangkan PB#1,2,3 OFF. Nilai 7 segmen adalah segmen[puluhan_jam]
- Ambil sisa pembagian jam dengan 10, kemudian aktifkan PB#1, sedangkan PB#0,2,3 OFF. Nilai 7 segmen adalah segmen[satuan_jam]
- Bagi nilai menit dengan 10 untuk mendapatkan puluhan menit, kemudian aktifkan PB#2, sedangkan PB#0,1,3 OFF. Nilai 7 segmen adalah segmen[puluhan_menit]
- Ambil sisa pembagian menit dengan 10, kemudian aktifkan PB#3, sedangkan PB#0,1,2 OFF. Nilai 7 segmen adalah segmen[satuan_menit]
#define F_CPU 1000000UL // frekuensi clock internal 1Mhz
#include <avr/io.h> // definisi library standar IO port
#include <util/delay.h> // definisi include untuk delay
#include <avr/interrupt.h>
#include <stdlib.h>
int jam=23, menit=59, detik=50; //variable global untuk menyimpan data2 waktu
//susunan segmen dari portD = GFEDCBA
//7 segmen common ANODA
uint8_t segmen[11]=
{0b1000000, // 0
0b1111001, // 1
0b0100100, // 2
0b0110000, // 3
0b0011001, // 4
0b0010010, // 5
0b0000010, // 6
0b1111000, // 7
0b0000000, // 8
0b0010000, //9
0b1111111}; // 10 / blank
ISR(TIMER1_COMPA_vect) // 1 detik
{
detik ++;
if ( detik == 60)
{ detik=0;
menit++;
}
if ( menit == 60)
{ menit = 0;
jam++ ;
}
if (jam >23) jam=0;
}
int main(void)
{
DDRD |= (1<<PD6) |(1<<PD5) |(1<<PD4) |(1<<PD3) |(1<<PD2) |(1<<PD1) | (1<<PD0) ; //segmen
DDRB |= (1<<PB0) | (1<<PB1) |(1<<PB2) |(1<<PB3) | (1<<PB6) ; //Scan 7 segmen
DDRB &= ~(1<<PB4) & ~(1<<PB5); // tombol tambah menit dan jam
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
OCR1A = 15625; //compare the CTC A for 1 second
TCCR1B |= (1 << CS11)|(1 << CS10); // Start timer at Fcpu/64
//untuk tombol anti blocking
uint16_t waktu =0;
bool pencet = false;
sei(); //start interrupt
while (1)
{
PORTD = segmen[10]; //blanking biar tidak membayang
PORTB |=(1<<PB0); //nyalakan 7 segmen no 1 (puluhan jam)
PORTB &= ~(1<<PB1) & ~(1<<PB2) & ~(1<<PB3) ;
PORTD = segmen[jam / 10]; //ambil nilai puluhan jam
_delay_ms(1); //delay disesuaikan terang tampilan 7 seg
PORTD = segmen[10];
PORTB |=(1<<PB1); //nyalakan 7 segmen no 2 (satuan jam)
PORTB &= ~(1<<PB0) & ~(1<<PB2) & ~(1<<PB3) ;
PORTD = segmen[jam % 10]; //modulus atau sisa untuk satuan jam
_delay_ms(1);
PORTD = segmen[10];
PORTB |=(1<<PB2); //nyalakan 7 segmen no 3 (puluhan menit)
PORTB &= ~(1<<PB0) & ~(1<<PB1) & ~(1<<PB3) ;
PORTD = segmen[menit / 10]; //ambil nilai puluham menit
_delay_ms(1);
PORTD = segmen[10];
PORTB |=(1<<PB3); //nyalakan 7 segmen no 4 (satuan menit)
PORTB &= ~(1<<PB0) & ~(1<<PB1) & ~(1<<PB2) ;
PORTD = segmen[menit% 10]; //modulus atau sisa untuk satuan jam
_delay_ms(1);
//Tombol
if (bit_is_set(PINB, PINB5))
{
if(pencet == false) {
jam++;
if(jam==24) jam =0;
}
pencet=true;
waktu=TCNT1;
}
if (bit_is_set(PINB, PINB4))
{
if(pencet == false) {
menit++;
if(menit==60) menit=0;
}
pencet=true;
waktu=TCNT1;
}
if(abs(waktu - TCNT1) > 4000) { //non blocking delay tombol
waktu=0;
pencet = false;
}
//blink Led Pemisah Jam : menit
if(TCNT1 <7500) PORTB |=(1<<PB6);
else PORTB &= ~(1<<PB6);
}
}
- clock yg digunakan adalah RC oscillator internal pada attiny2313 yg sangat tidak akurat, untuk itu jika menggunakan nilai yg akurat bisa menggunakan xtal oscillator seperti praktek jam lainnya dan jangan lupa merubah fusebit seperti penjelsan disini dan jika menggunakan USBASP maka butuh batuan fusebit calculator disini .
- Jika menggunakan clock 4 MHZ maka nilai fusebitnya :
- Sedangkan perubahan untuk menyesuaikan clock dilakukan pada script dibagian ini :
#define F_CPU 4000000UL
==========================================
TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
OCR1A = 62499; //compare the CTC A (clock 4 Mhz)
TCCR1B |= (1 << CS11)|(1 << CS10); // Start timer at Fcpu/64
- Non blocking delay pada tombol akan berpengaruh pada tampilan yang tidak terlihat kedip saat tombol dipencet, seperti animasi paling atas dimana saya menggunakan _delay_ms(300); setelah penekanan tombol.