Sunday, April 03, 2011

Kemudahan Memprogram LCD

Kemudahan Memprogram LCD

Sebagai mahasiswa jurusan Sistem Komputer tentunya tidak asing bagi saya melakukan interfacing dengan perangkat seperti LCD. Saya pun menggunakan LCD 2×16 (2 baris, 16 kolom) dalam PI, pengganti PKL, saya untuk diaplikasikan menjadi sistem kunci pintu digital. Sebelumnya saya pun tidak begitu mengerti bagaimana LCD bekerja dan bagaimana cara memprogramnya, tapi dengan bantuan search engine saya mendapat begitu banyak referensi. Yang saya sayangkan adalah kemalasan teman-teman sejurusan saya yang enggan mempelajari hal ini, padahal mereka menggunakan LCD dalam alat yang mereka buat. Untuk mengetahui bagaimana LCD itu bekerja dapat di cek pada alamat-alamat berikut :

Saya pun banyak menyadur dari artikel dari link di atas untuk dijadikan pembahasan pada landasan teori (bab II). Tapi intinya adalah bagaimana memprogram LCD agar bekerja sesuai dengan aplikasi yang kita rancang. Pada alat PI saya, komunikasi perangkat terjadi antara mikrokontroler (turunan 8051) dengan LCD dengan menggunakan 8 bit jalur data dan 2 jalur kontrol. Pada saat itu, saya tidak mengetahui jenis-jenis LCD, yang saya tahu adalah size nya (1×16, 2×16, 2×20 dsb). Namun ada standarisasi yang cukup populer digunakan banyak vendor LCD, yaitu HD44780U, yang memiliki chip kontroler Hitachi 44780. LCD bertipe ini memungkinkan pemrogram untuk mengoperasikan komunikasi data secara 8 bit atau 4 bit. Jika menggunakan jalur data 4 bit akan ada 7 jalur data (3 untuk jalur kontrol & 4 untuk jalur data). Jika menggunakan jalur data 8 bit maka akan ada 11 jalur data (3 untuk jalur kontrol & 8 untuk jalur data). Tiga jalur kontrol ke LCD ini adalah EN (Enable), RS (Register Select) dan R/W (Read/Write). Berikut adalah susunan umum pin LCD bertipe 44780 :




































PinDeskripsi
1Ground
2Vcc
3Pengatur kontras
4“RS” Instruction/Register Select
5“R/W” Read/Write LCD Registers
6“EN” Enable clock
7-14Data I/O Pins


Urutan pin (1), umumnya, dimulai dari sebelah kiri (terletak di pojok kiri atas) dan untuk LCD yang memiliki 16 pin, 2 pin terakhir (15 & 16) adalah anoda dan katoda untuk back-lighting. Berikut adalah contoh LCD (2×16) yang umum digunakan :



Sebagaimana terlihat pada kolom deskripsi, interface LCD merupakan sebuah parallel bus, dimana hal ini sangat memudahkan dan sangat cepat dalam pembacaan dan penulisan data dari atau ke LCD. Kode ASCII yang ditampilkan sepanjang 8 bit dikirim ke LCD secara 4 atau 8 bit pada satu waktu. Jika mode 4 bit yang digunakan, maka 2 nibble data dikirim untuk membuat sepenuhnya 8 bit (pertama dikirim 4 bit MSB lalu 4 bit LSB dengan pulsa clock EN setiap nibblenya). Jalur kontrol EN digunakan untuk memberitahu LCD bahwa mikrokontroller mengirimkan data ke LCD. Untuk mengirim data ke LCD program harus menset EN ke kondisi high (1) dan kemudian menset dua jalur kontrol lainnya (RS dan R/W) atau juga mengirimkan data ke jalur data bus. Saat jalur lainnya sudah siap, EN harus diset ke 0 dan tunggu beberapa saat (tergantung pada datasheet LCD), dan set EN kembali ke high (1). Ketika jalur RS berada dalam kondisi low (0), data yang dikirimkan ke LCD dianggap sebagai sebuah perintah atau instruksi khusus (seperti bersihkan layar, posisi kursor dll). Ketika RS dalam kondisi high atau 1, data yang dikirimkan adalah data ASCII yang akan ditampilkan dilayar. Misal, untuk menampilkan huruf “A” pada layar maka RS harus diset ke 1. Jalur kontrol R/W harus berada dalam kondisi low (0) saat informasi pada data bus akan dituliskan ke LCD. Apabila R/W berada dalam kondisi high (1), maka program akan melakukan query (pembacaan) data dari LCD. Instruksi pembacaan hanya satu, yaitu Get LCD status (membaca status LCD), lainnya merupakan instruksi penulisan. Jadi hampir setiap aplikasi yang menggunakan LCD, R/W selalu diset ke 0. Jalur data dapat terdiri 4 atau 8 jalur (tergantung mode yang dipilih pengguna), mereka dinamakan DB0, DB1, DB2, DB3, DB4, DB5, DB6 dan DB7. Mengirim data secara parallel baik 4 atau 8 bit merupakan 2 mode operasi primer. Untuk membuat sebuah aplikasi interface LCD, menentukan mode operasi merupakan hal yang paling penting. Mode 8 bit sangat baik digunakan ketika kecepatan menjadi keutamaan dalam sebuah aplikasi dan setidaknya minimal tersedia 11 pin I/O (3 pin untuk kontrol, 8 pin untuk data). Sedangkan mode 4 bit minimal hanya membutuhkan 7 bit (3 pin untuk kontrol, 4 untuk data). Bit “RS” digunakan untuk memilih apakah data atau instruksi yang akan ditransfer antara mikrokontroller dan LCD. Jika bit ini di set (RS = 1), maka byte pada posisi kursor LCD saat itu dapat dibaca atau ditulis. Jika bit ini di reset (RS = 0), bisa merupakan instruksi yang dikirim ke LCD atau status eksekusi dari instruksi terakhir yang dibaca. Macam-macam instruksi yang tersedia untuk standar LCD 44780 dapat dirujuk pada link berikut :

* http://home.iae.nl/users/pouweha/lcd/lcd0.shtml
* http://www.myke.com/lcd.htm

Saya tidak akan membahas panjang lebar bagaima memprogram kontroller (baik dari mikrokontroller ataupun PC), karena sudah banyak situs yang memberikan contoh program beserta penjelasannya (akan saya cantumkan beberapa link di baris akhir posting ini). Saya sendiri menggunakan rutin LCD siap pakai untuk berkomunikasi dengan mikrokontroller 8051. Aplikasi dengan LCD dapat dibuat dengan mudah dan waktu yang singkat, mengingat koneksi parallel yang cukup mudah antara kontroller dan LCD. Untuk hobi elektronik yang enggan melakukan coding, terdapat banyak aplikasi siap pakai untuk berkomunikasi dengan LCD melalui parallel port PC, seperti : LCDCenter & LCD Smartie. Entah kenapa saya jadi ingin menulis tentang LCD setelah beberapa teman meminta saya untuk membantu pembuatan PI nya yang berhubungan dengan LCD. Saya juga tidak menyalahkan mereka yang terdesak oleh waktu atau terjerat kemalasan untuk belajar yang notabene untuk kebaikan mereka sendiri.

Referensi :

* http://8052.com/tutlcd.phtml
* http://www.howstuffworks.com/lcd.htm
* http://en.wikipedia.org/wiki/LCD
* http://www.teac.com.au/pages/howdoesanlcdwork
* http://www.doc.ic.ac.uk/%7Eih/doc/lcd/pc_example/conn1.html
* http://ee.cleversoul.com/lcd_project.html
* http://www.overclockers.com.au/techstuff/a_diy_lcd/index.shtml
* http://gedex.web.id/archives/2006/12/21/kemudahan-memprogram-lcd/

Kemudahan Memprogram LCD (Bagian II)

Kemudahan Memprogram LCD (Bagian II)

pada tulisan kali ini saya akan memberikan contoh program (berdasarkan rutin siap pakai dari beberapa situs serta rutin yang built in
dari compiler tertentu) utk interfacing dengan lcd dengan berbagai macam compiler disesuaikan dengan mikrokontroller yang digunakan (MCS51 atau AVR RISC 8 bit).

Seperti yang saya paparkan pada postingan terdahulu, bahwa ada 2 cara utk berkomunikasi dengan LCD, yaitu 8 bit dan 4 bit jalur data. Selain 8 atau 4 jalur yang terhubung dengan kontroler, dibutuhkan 3 jalur lagi untuk kontrol, yaitu RS, RW dan EN.

Untuk MCS51 :

1. Dalam Assembler Ada banyak rutin siap pakai di http://8052.com/codelib.phtml Yang sudah saya coba : http://8052.com/codelib/lcd_kepad.asm, rutin ini untuk komunikasi 8 bit. Jika menggunakan LCD 2 x 16, tidak perlu ada modifikasi pada rutin INITIALIZE. Contoh penggunaannya :

...
DATA EQU PORTx ;misal x adalah PORT1
LCD_RS EQU PORTy.0 ;misal y adalah PORT2
LCD_RW EQU PORTy.1
LCD_EN EQU PORTy.2
CALL INITIALIZE ;inisialisasi LCD
CALL CLEAR_SCREEN ;bersihkan layar
MOV A,#80h ;mengisi 0x80 ke accumulator untuk menset
CALL ADDRESS ;alamat DDRAM LCD. Ini akan menset posisi
;LCD pada baris 1 kolom 1.
MOV A,#'g' ;Menulis karakter 'g'
CALL WRITE_ON ;pada baris 1 kolom 1
MOV DPTR,#str1 ;menset data pointer ke alamat dgn label str1
CALL TRANSFER ;mencetak string 'gedex
...
str1:
DB 'gedex',offh ;rutin TRANSFER akan mencetak karakter per karakter
;dan memerlukan byte 0xff utk menandakan akhir dari
;string.
...

Jika saat kompilasi timbul error yang berhubungan dengan baris yang terdapat kata DATA, maka penamaan DATA perlu di rubah. Di beberapa compiler,DATA merupakan reserved word.
Catatan : Saya mengcompilenya dengan Pinnacle v52 (Evaluation) dan ASM51.
Pada Pinnacle tidak ada masalah terhadap penamaan DATA. Pada ASM51 timbul error, sehingga penamaan DATA perlu di rubah.
2. Menggunakan BASCOM 8051 IDE.
Komunikasi yang digunakan bisa 8 bit atau 4 bit. Jika menggunakan komunikasi 4 bit, maka pin LCD untuk data yang digunakan adalah DB4-DB7. Konfigurasi pin LCD ke port kontroller di inisialisasi dengan statement Config Lcdpin, misal :

Config Lcdpin = Pin ,Db4 = P3.4,Db5 = P3.5,Db6 = P3.6,Db7 = P3.7,E = P2.4,Rs = P2.0

Dengan pin RW terhubung ground. Tipe LCD yang digunakan diinisialisasi dengan statement Config LCD, misal :

Config Lcd = 16 * 2

Setelah pemanggilan statement di atas, LCD siap dikirimi data atau instruksi. BASCOM juga telah menyediakan syntax yang berhubungan dengan LCD seperti :
CLS : untuk membersihkan layar
CURSOR : dengan parameter ON/OFF, BLINK/NOBLINK
LOCATE y,x : untuk memindahkan kursor ke posisi tertentu.
LCD : mencetak konstanta atau variabel ke tampilan LCD.
dsb.. Contoh penggunaannya :

...
Config Lcdpin = Pin , Db4 = P3.4 , Db5 = P3.5 , Db6 = P3.6 , Db7 = P3.7 , E = P2.4 , Rs = P2.0
Config Lcd = 16 * 2
Cursor Off
Cls
Locate 1 , 1 : Lcd "gedex"
Locate 2 , 1 : Lcd "C"; "o"; "o"; "L"
...

Komunikasi secara 8 bit pada BASCOM direkomendasikan untuk berkomunikasi dengan mikroprosesor, dimana DB0-DB7 harus terhubung dengan D0-D7 dan RS / EN dengan jalur A0. Saya sendiri belum pernah mencobanya.
Catatan : Saya menggunakan BASCOM 8051 v2.0.11.0 Serial Demo.

Untuk AVR RISC Microcontroller 8 bit :

1. Menggunakan AVR Studio
Rutin dari OMIDKOMPANI, dapat di download di http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=904&item_type=project
2. Menggunakan WinAVR
Rutin dari by iamgotzaa. Contoh pada program main nya akan menampilkan hasil sampling ADC ke LCD. dapat di download di http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=440&item_type=project
Rutin dari nasi, dapat didownload di : http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=293&item_type=project
3. BASCOM utk AVR
Penggunaannya hampir sama dengan BASCOM 8051 IDE
4. Menggunakan CodeVisionAVR
CodeVision menyediakan wizard, CodeWizardAVR, untuk menggenerate baris kode untuk mendefiniskan LCD. Interfacing ke LCD ini membutuhkan 7 pin pada port yang sama. Misal digunakan PORTB untuk LCD port, maka konfigurasi pin antara LCD dan chip AVR adalah :
PORTB.0 : RS
PORTB.1 : RW
PORTB.2 : EN
PORTB.4 : DB4
PORTB.5 : DB5
PORTB.6 : DB6
PORTB.7 : DB7
Langkah-langkah menggunakan CodeWizardAVR untuk LCD :
1. Pilih Create new file

2. Pilih File type project

Lalu pilih yes untuk menggunakan CodeWizardAVR

3. Akan muncul jendela seperti gambar di bawah ini. Pilih chip yang digunakan serta clock yang dipakai. Misal menggunakan ATMega16 dengan frekuensi clock 4 MHz

4. Pindah ke tab LCD, pilih port yang akan di gunakan untuk LCD port. Misal pada PORTB, maka hubungan pin antara LCD dan PORTB akan ditampilkan.

Menggunakan rutin LCD yang sudah built in dari compiler tertentu dapat mempermudah pekerjaan dan menghemat waktu. Jika LCD yang digunakan hanya digunakan sesaat, misal nya hanya untuk debug data dari sensor atau bagian sistem yg tidak significant, maka saya menyarankan untuk menggunakan rutin bawaan dari compiler dengan komunikasi 4 bit. Gambar di bawah ini adalah LCD yang biasa saya pakai untuk memonitor nilai sensor atau debug sistem.


Referensi :
http://gedex.web.id/archives/2007/05/21/kemudahan-memprogram-lcd-bagian-ii/

PWM dengan Interrupt Timer

PWM dengan Interrupt Timer

Ada beberapa teman (especially me2t) yang masih bingung bagaimana sebenarnya Interrupt Timer dapat digunakan sebagai PWM (Pulse Width Modulation). Sebelum menjelaskan lebih dalam mengenai Timer, saya akan mengulas balik tentang sumber pencacah (clock source) pada uC AVR. Sumber pencacah untuk AVR itu seperti detak jantung yang diperlukan untuk mengeksekusi instruksi. Pengeksekusian instruksi umumnya membutuhkan satu sampai tiga siklus pencacah (clock cycles). Satu siklus adalah transisi low-hi-low _|¯|_. Jadi semakin cepat pencacah berjalan (menghitung), maka semakin cepat uC bekerja. Jadi jelas uC AVR 16 MHz akan lebih cepat dari uC AVR 1 MHz. Tapi perlu diperhatikan, kecepatan pencacah tidak begitu berarti banyak. Satu prosesor dapat membutuhkan 1 siklus pencacah untuk memindahkan data dari satu register ke register lainnya, tapi prosesor lain dapat saja membutuhkan 2 sikus pencacah untuk melakukan hal yang sama. Hal ini berarti bahwa prosesor ke-2 harus memiliki kecepatan 2x lipat prosesor ke-1 untuk melakukan instruksi yang sama dalam waktu yang sama. Kuncinya disini adalah sebuah penilaian kasar yang disebut MIPS (Milion of Instructions Per Second), yang dapat digunakan untuk menilai secara kasar berapa instruksi yang dapat dilakukan uC dalam satu detik pada frekuensi pencacah tertentu. Jika pada lembar data (datasheet) tertulis “Up to 16 MIPS Throughput at 16 MHz”, kita bisa mengasumsikan secara kasar bahwa dengan pencacah 4 MHz, kita bisa mencapai 4 MIPS (4 juta instruksi per detiknya atau sekitar 1/4 uS untuk eksekusi 1 instruksi, CMIIW). Sebenarnya penjelasan untuk pencacah dapat lebih panjang, tapi sisanya saya serahkan kepada pembaca untuk mengubeknya di google dan datasheet terkait :).

Kembali ke Timer. Secara prinsip, sebuah timer adalah sebuah counter (penghitung). Tugas Timer hanya menghitung, dia selalu menyimpan hitungannya saat menghitung “satu, dua, tiga, …” hingga 255 (8 bit) atau bahkan bisa sampai 65535 (16 bit). Naiknya hitungan Timer dan berapa lama jeda antar hitungan ini ditentukan dari siklus pencacah uC (seperti saya jelaskan di atas), mode Timer dan settingan Timer. Kita bisa menggunakan Timer sebagai pemicu event. Misal kita bisa menset Timer agar menghitung sampai 255. Dan jika sudah 255 Timer (overflow) akan memberikan sinyal, dan kita bisa mengerjakan sesuatu dalam program (disinilah PWM bekerja) dan menyuruh Timer untuk menghitung lagi dari 0. Demikian seterusnya terjadi jika nilai 255 tercapai, dan Timer hanya akan berhenti jika kita memprogramnya untuk berhenti. Sebagai kemudahan saya akan langsung memberikannya contohnya dengan CodeVisionAVR, menggunakan Timer 0 mode normal yang menghitung sampai 255. Besarnya frekuensi PWM itu bisa Anda hitung secara kasar (tidak akurat) dengan rating MIPS chip. Anda bisa menggunakan CodeWizardAVR untuk menghasilkan kode siap pakai, tanpa perlu mengecek datasheet berapa register terkait Timer harus kita berikan nilai. OK, ini langkahnya:

1. Tentukan mode normal untuk Timer 0 dan check overflow interrupt

1. Setting Timer 0
2. Generate, Save dan Exit. Maka kurang lebih kita mendapatkan deklarasi rutin Timer 0 overflow interrupt seperti berikut:

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
}

3. Nilai register terkait Timer 0 yang telah diset

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

4. Timer 0 diinisialisasi pada interrupt mask dan interrupt diaktifkan

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;...

// Global enable interrupts
#asm("sei")

Apakah Timer 0 sudah mulai menghitung? Ya belum lah. Kita harus menset register Timer Control 0 (TCCR0) agar Timer 0 mulai bekerja. Untuk menjalankan Timer 0 tanpa prescaler beri nilai 0×01 pada TCCR0.

TCCR0 = 0x01;

Nah loh?! Apalagi tuh prescaler? Lalu apa saja sih bit-bit pada TCCR0 dan TIMSK. Nah itu semua sudah sangat jelas di tulis dalam datasheet, silahkan buka datasheet chip terkait jika merasa bingung.

Kembali ke rutin overflow interrupt Timer 0 (pada langkah 2). Rutin tersebut akan dieksekusi jika Timer 0 sudah menghitung sampai TOP atau dalam hal ini 255 / 0xFF. Bagaimana kalau kita menginginkan Timer 0 memulai dari hmm.., katakanlah 100 / 0×64 dan bukan dari 0 ? Ingat bagaimana cara Timer 0 berhitung “satu, dua, tiga, …” ? Hitungan Timer 0 selalu disimpan dalam register TCNT0. Dengan mengakali jarak hitungan Timer, kita dapat memainkan frekuensi PWM. OK, contoh berikut akan mengubah bagaimana Timer 0 akan mulai menghitung dari 192 / 0xc0:

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0 = 0xC0;

}

...

TCNT0 = 0xC0;
OCR0 = 0x00;
TCCR0 = 0x01; //Timer 0 mulai bekerja tanpa prescaler
TIMSK = 0x01; //pantau Timer 0 overflow interrupt service routine

#asm("sei"); //aktifkan global interrupt

...

Nah sekarang bagaimana kita memanfaatkan mode 0 dari Timer 0 agar dapat bekerja sebagai PWM. Katakanlah kita mempunyai 2 pin enable ke motor kiri dan kanan. Kita buat sebuah penampung nilai PWM yang berperan sebagai duty cycle dari PWM. Anggaplah variabel duty cycle PWM ini mempunyai nilai 0 - 255 (unsigned char). Jika duty cycle-nya 100% maka nilai tersebut adalah 255. Dapatkan gambarannya? Full speed adalah 255, half-speed adalah 127 dan no-speed adalah 0. OK, kita tulis kodenya seperti berikut:

...

#define pwmKi PORTC.0
#define pwmKa PORTC.1
#define mKi_plus PORTC.2
#define mKi_min PORTC.3

#define mKa_plus PORTC.4
#define mKa_min PORTC.5

unsigned char pwmKi_val,pwmKa_val,x = 0;

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

TCNT0 = 0xC0;

x++;

if (x>=pwmKa_val) {
pwmKa=0;
} else {
pwmKa=1;
}
if (x>=pwmKi_val) {
pwmKi=0;
} else {
pwmKi=1;
}

}

...

Lalu untuk implementasi nya pada program utama bisa dilakukan dengan testing PWM motor.

...

pwmKi = 1;
pwmKa = 1;

mKi_plus = 1;
mKi_min = 0;
mKa_plus = 1;
mKa_min = 0;

while (1) {
pwmKa_val = 0xff;
pwmKi_val = 0x20;
delay_ms(1500);
pwmKa_val = 0x20;
pwmKi_val = 0xff;
delay_ms(1500);
};

...

Jika motor secara bergantian pelan dan cepat setiap 1.5 detik, maka tidak ada masalah dengan implementasi dengan Timer 0 mode 0 dengan overflow interrupt. Perlu diketahui, beberapa chip AVR menyediakan variasi Timer dan modenya. Akan sangat panjang jika ditulis di sini, untuk itu kawan-kawan bisa RTFD (Read The Fucking Datasheet) :p.

Referensi :

- Datasheet ATMega16 / ATmega8535
- http://www.avrfreaks.net/
- http://gedex.web.id/archives/2008/04/11/pwm-dengan-interrupt-timer/