SELAMAT TAHUN BARU 2013 kepada para pembaca setia blog tercinta. Dengan semangat baru di tahun yang baru ini kita mulai dengan pembahasan script-script yang terdapat di blog ini karena ada beberapa teman yang merasa "terintimidasi" dengan bahasa pemrograman yang dianggap terlalu susah.
Kali ini kita akan membahas script dari percobaan led matriks
"love hurt" yang ditulis agustus 2011. Project love hurt ini juga terdapat dalam
paket belajar dasar microcontroller yang dapat anda pesan dengan harga yang cukup terjangkau oleh kantong anak SMA sekalipun.
Seperti pada posting led matrix love hurt rangkaian yang digunakan seperti skematik berikut ini :
Rangkaian nya sangat simple, sesimple scriptnya juga dan marilah kita break down scriptnya
HEADER
#define F_CPU 1000000UL
#include < avr/io.h >
#include < util/delay.h >
#include < avr/pgmspace.h >
#include < string.h >
#include < avr/eeprom.h >
Pada penjelasan terdahulu mengenai dasar-dasar bahasa GCC maka dapat dilihat pada header terdapat inisialisai dari beberapa parameter. Yang pertama adalah #define F_CPU yang menjelaskan clock microcontroller yang digunakan. Berdasarkan skematik rangkaian dapat dilihat jika microcontroller attiny2313 yang dipakai tanpa menggunakan xtal sehingga dapat dikatakan memakai internal clock (Calibrated RC Oscillator). Secara default ketika ic attiny2313 keluar dari pabrik memiliki clock internal 8MHz dengan pembagian CLKDIV8=ON yang berarti clock dibagi 8 sehingga menghasilkan angka 1MHz. Untuk melihat clock yang dipakai dapat dilihat pada pembacaan fusebit, dapat dilakukan melalui menu programming pada AVRSTUDIO.
Selanjutnya didalam header dituliskan beberapa include yang berguna dalam script love hurt seperti definisi kaki micro (io.h) ,delay.h sebagai pengatur delay waktu, pgmspace.h sebagai trick memanfaatkan flash memory sebagai static ram, string.h sebagai pengolah data berupa string dan eeprom.h yang memudahkan penulisan script untuk akses eeprom (memory non-volatile / tidak hilang saat micro tanpa power) .
DEFINISI VARIABEL , RAM & EEPROM
//Progmem simpannya di FLASH memory
const char love1[] PROGMEM =
{
0b0011110,
0b0100001,
0b1000010,
0b0100001,
0b0011110
};
const char love2[] PROGMEM =
{
0b0001100,
0b0010010,
0b0100100,
0b0010010,
0b0001100
};
const char L[] PROGMEM ={0x7f, 0x7f, 0x40, 0x40, 0x20};
const char O[] PROGMEM ={0x3e, 0x7f, 0x41, 0x41, 0x3e};
const char V[] PROGMEM ={0x3f, 0x7e, 0x40, 0x20, 0x1f};
const char E[] PROGMEM ={0x7f, 0x7f, 0x49, 0x49, 0x41};
const char H[] PROGMEM ={0x7f, 0x7f, 0x08, 0x08, 0x7f};
const char U[] PROGMEM ={0x3f, 0x7f, 0x40, 0x40, 0x3f};
const char R[] PROGMEM ={0x7f, 0x7f, 0x11, 0x29, 0x46};
const char T[] PROGMEM ={0x03, 0x03, 0x7f, 0x03, 0x02};
const char creature[]={0x4e, 0x31, 0x35, 0x31, 0x4e}; //simpan di memory/RAM aja
uint8_t EEMEM tengkorak[5]= {0x1e, 0x75, 0x61, 0x75, 0x1e}; //simpan di EEPROM
uint8_t EEMEM pacman[5]= {0x26, 0x67, 0x67, 0x7f, 0x3e}; //simpan di EEPROM
char dotnya[5],scrolnya[7];
Untuk mengetahui angka hexa yang terdapat dalam array ada lebih baiknya terlebih dahulu membuka software generator dot matrix yang dapat dilihat
disini.
Pada penulisan array diatas ada 3 type yang dipergunakan yaitu RAM, PROGMEM dan EEMEM. Kenapa mesti seperti ini ya karena dikarenakan attiny2313 yang memiliki kapasitas RAM yang super irit yaitu 128byte saja, sehingga untuk menambah memory maka kita manfaatkan memory flash (program) yang cukup lumayan 2048byte atau 2Kbyte (ini aja masih kecil banget). Untuk memanfaatkan flash diperlukan inisialisasi tambahan berupa PROGMEM dan tidak bisa dipakai langsung seperti halnya jika ditempatkan pada RAM umum, harus ada proses memindahkan flash PROGMEM menuju memory RAM. Tentunya tidak semuanya tapi yang akan diolah saja yang dipindahkan. Pada inisialisasi variabel array diatas terdapat 2 buah array RAM yaitu dotnya[5] dan scrolnya[7] yang akan ditimpa dengan isi PROGMEM jika dibutuhkan.
Pada project lovehurt diperlihatkan juga cara mengakses memory EEPROM dengan inisialisai berupa EEMEM. Tujuan menggunakan memory EEPROM adalah sifatnya yang tidak terhapus jika baterai atau power dimatikan (non-volatile memory)
BAGIAN MENULIS KE LED MATRIX
void tulis(uint8_t lama)
{
uint8_t a,b;
for(a=0 ; a<lama ; a++)
{
for(b=0 ; b<5 ; b++)
{
PORTB = ~(1<<b) ;
PORTD = dotnya[b];
_delay_ms(2);
}
}
}
void geser(uint8_t lama)
{
uint8_t a,b;
for(a=0 ; a<11 ; a++)
{
if( a<6)
{
for(b=0 ; b<(5-a) ; b++) dotnya[b]=0x80;
for(b=(5-a); b<5 ;b++) dotnya[b]=scrolnya[b-5+a];
tulis(10);
}
else if (a==6) tulis(lama);
else
{ for(b=0 ; b<11-a ; b++) dotnya[b]=scrolnya[a-5+b];
for(b=(11-a); b<11 ;b++) dotnya[b]=0x80;
tulis(10);
}
}
}
void naik (uint8_t lama)
{ uint8_t q,step=0;
while(step!=16)
{
if( step <8)
{
for(q=0 ; q < 5 ; q++) dotnya[q] = scrolnya[q] << (7 - step) ;
tulis(10);
}
else if (step == 8)
{
tulis(lama);
}
else
{
for(q=0 ; q < 5 ; q++) dotnya[q] = scrolnya[q] >> (step - 7) ;
tulis(10);
}
step++;
}
}
}
Nah inilah bagian utama dari penggerak tulisan geser kiri atau naik. Perhatikan pertama bagian function tulis dimana terdapat isian variabel lama yang berarti lama looping dieksekusi yang akan menentukan lama tulisan ditampilkan. Begitu pula jika ingin menggeser maka variabel lama perlu dimasukkan untuk menentukan lama nya teks diam setelah digeser.
Bagaimana sih cara menghidupkan dotmatrix ? sebaiknya baca penjelasannya
disini . Jadi pada intinya nilai hexa yang diinisialisaikan pada array diawal berjumlah 5 buah array. Sedangkan bit yang digunakan adalah 7 bit karena memang dot matrix yang dgunakan bertype 5x7 (5 kolom x 7 baris) . Perhatikan loop berikut :
for(b=0 ; b<5 ; b++)
{
PORTB = ~(1<<b) ;
PORTD = dotnya[b];
_delay_ms(2);
}
Skematik menunjukkan bahwa kolom di kontrol oleh port B0 - B4 dan baris dikontrol oleh port D0 - D6. Loop diatas menunjukkan proses geser kolom (scanning) dengan perintah PORTB = ~(1<<b) yang artinya angka 1(biner) digeser ke sebelah kiri sebanyak dari nilai b kemudian dinegasi . Variabel b mengontrol pergeseran berdasarkan loop. Jika kolom dot matrix '0' akan menyebabkan LED pada baris yang mendapat bit '1' menyala. Hal ini dapat dikatakan kolom aktif LOW dan baris aktif HIGH. Urutan loop dari scanning pada PORTB seperti berikut (11110) , (11101) ,(11011) ,(10111) ,(01111).
Ingat penjelasan terdahulu bahwa array yang ada pada flash (PROGMEM) atau EEPROM harus dipindahkan kedalam array memori RAM dotnya[b]. Sekali lagi variabel b berperan dalam menentukan array baris yang sesuai dengan kolom yang sedang aktif atau mendapat scanning "LOW" (0).
Untuk proses geser ke kiri dan geser keatas ada sebuah variabel yaitu step yang berfungsi sebagai penanda posisi pergeseran yang sedang tampil sehingga text yang tampil pada dot matrix memiliki efek bergeser. Selebihnya yang diperlukan hanya proses kreatif mengeser-geser bit dari baris berdasarkan loop yang sedang berjalan dan dipindahkan ke array scrolnya[ ].
MAIN PROGRAM
int main(void)
{
DDRD = 0b1111111; // untuk baris
DDRB = 0b11111; // untuk kolom
PORTD =0; // Set all pins low
PORTB =0b11111; //matikan layar
while(1)
{
// yang ini nulis langsung
strncpy_P(dotnya,love2,5);
tulis(20);
strncpy_P(dotnya,love1,5);
tulis(40);
strncpy_P(dotnya,love2,5);
tulis(20);
strncpy_P(dotnya,love1,5);
tulis(40);
strncpy_P(dotnya,love2,5);
tulis(20);
strncpy_P(dotnya,love1,5);
tulis(40);
//yang ini pake function geser
strncpy_P(scrolnya,L,5);
geser(50);
strncpy_P(scrolnya,O,5);
geser(50);
strncpy_P(scrolnya,V,5);
geser(50);
strncpy_P(scrolnya,E,5);
geser(50);
strncpy_P(scrolnya,H,5);
geser(50);
strncpy_P(scrolnya,U,5);
geser(50);
strncpy_P(scrolnya,R,5);
geser(50);
strncpy_P(scrolnya,T,5);
geser(50);
//geser ambil dari RAM
strncpy(scrolnya,creature,5); //tanpa _P karena ambil di RAM
naik(50);
//ambil dari eeprom ..mengirit..
eeprom_read_block((void*)&scrolnya,(const void*)&tengkorak, 5);
naik(50);
eeprom_read_block((void*)&scrolnya,(const void*)&pacman, 5);
geser(50);
}
return 0;
}
Pada bagian awal dari function main( ) terdapat inisialisai port dari attiny yang digunakan yaitu PORTB dan PORTD yang kesemuanya diberi bit 1 yang artinya port tersebut dipakai sebagai port output.
Script yang digunakan untuk memindahkan memory flash (PROGMEM) menuju RAM adalah operasi string strncpy_P, ingat array dari char (8byte) dapat dianggap sebagai string, seperti contoh strncpy_P(dotnya,love2,5) yang artinya isi dari array dotnya[ ] diisi dengan array dari array PROGMEM love2. Jika diambil dari RAM langsung maka operasi copy ini menggunakan strncpy( ) tanpa _P.
Untuk pemindahan isi dari EEPROM menuju RAM menggunakan syntax eeprom_read_block ( *pointer_ram_tujuan, *posisi_memori_eeprom, jumlah blok ), seperti contoh eeprom_read_block((void*)&scrolnya,(const void*)&tengkorak, 5). Jangan dipusingkan dengan void dan * (pointer) karena itu hanya atribut yang menyatakan type data diabaikan.
MUDAH BUKAN ? jika ada pertanyaan atau request script break down yang lain akan saya bahas dengan senang hati.
SELAMAT TAHUN BARU 2013 KAWAN