AVR Digital Voltmeter (LCD Display & CodeVisionAVR)Posted by
Herlambang on May 16, 2011 Leave a comment (7) Go to comments
Mengukur tegangan dan menampilkan hasil pengukuran pada LCD nama
kerennya (DIGITAL VOLT METER) adalah hal yang mudah, apalagi dengan
CodeVisionAVR , semuanya jadi lebih mudah. Sebagai contoh, kita
akan membuat program yang bisa mengukur tegangan antara 0 5V dengan
ketelitian tegangan yang dapat diukur sebesar 0.00488V atau 4.88mV.
Dalam aplikasi ini kita akan menggunakan ADC internal AVR dengan
resolusi maksimal 10bit dengan data mulai dari 0 1023 atau 2n-1 dan
jumlah total data 1024. Untuk menentukan ketelitian yang akan
diperoleh sangat mudah, yaitu dengan membagi nilai tegangan
referensi dengan resolusi ADC. Misal tegangan referensi yang kita
pakai adalah AVCC yang bernilai 5V maka akan didapatkan resolusi
sebesar 0.00488V yang didapat dari 5/1024 = 0.00488V atau 4.88mV.
Contoh disini diasumsikan bahwa tegangan AVCC adalah bernilai pas
5V.
Untuk aplikasi riil dengan kepresisian tinggi disarankan untuk
melakukan trim tegangan dengan pembagi tegangan yang menggunakan
multiturn VR dan buffer DC dan gunakan referensi pada Vref bukan
AVCC . Akan tetapi kalau hanya sekedar ingin mengetahui nilai
tegangan tanpa kepresisian tinggi, referensi pada AVCC sudah cukup.
Dan bila diinginkan mengukur tegangan dengan level yang lebih
tinggi, bisa digunakan pembagi tegangan seperti pada voltmeter
digital
dan tentu saja jangan lupa saklar bwt select range dan lagi..
jangan lupa modifikasi programnya hehe . Wokey lets check it
out#include #include #include // Alphanumeric LCD Module functions
#asm .equ __lcd_port=0x18 ;PORTB #endasm #include
Seperti code diatas, tentukan dulu library yang mo dipake..
berhugung kita akan menggunakan LCD, delay dan fungsi sprintf jadi
kita include librarinya masing2. Jangan lupa sesuaikan port yang
akan digunakan untuk LCD.#define ADC_VREF_TYPE 0x40 //AVCC
Yang tak kalah pentingnya adalah menentukan referensi untuk ADC.
Dalam program ini ane gunakan referensi AVCC.unsigned char
buffer[16]; //Untuk buffer sprintf float tegangan; //Untuk data
perhitungan tegangan (float) unsigned int temporary; //Untuk
temporary data ADC (komparasi)
code diatas berfungsi untuk menentukan variable global yang akan
digunakan.. buffer berfungsi untuk buffer sprintf. Berhubung
sprintf disini akan digunakan dalam formating LCD jadi cukup dah
arraynya cuman 16 char. Sedangkan untuk variabel tegangan berfungsi
untuk menampung perhitungan hasil bagi dari (data
ADC*(referensi/1024)/1000) tipe datanya adalah float biar presisi
hasil pembacaanya . nah kalo variabel temporary berfungsi cuman
untuk pembanding data ADC yang sebelumnya tersimpan dan data ADC
terbaca (bwt update aja biar gk terus kerja LCDnya).void
sett_regs(void); //Fungsi untuk setting register di awal proses
unsigned int read_adc(unsigned char adc_input);//Fungsi baca
ADC
code yang tertulis persis diatas tulisan ini adalah cuman untuk
function prototype dan digunakan bila fungsi main mau diletakkan
dimana saja termasuk diatas fungsi tersebut.// Routine baca ADC
unsigned int read_adc(unsigned char adc_input){ ADMUX=adc_input |
(ADC_VREF_TYPE & 0xff); // Delay needed for the stabilization
of the ADC input voltage delay_us(10); // Start the AD conversion
ADCSRA|=0x40; // Wait for the AD conversion to complete while
((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCW;
}
Fungsi diatas digunakan untuk pengambilan data ADC. Bila
dipanggil akan mengembalikan nilai berupa data ADC terbaru dengan
tipe unsigned int.// Function for setting register void
sett_regs(void){ // Port a initialization PORTA=0x00;DDRA=0x00; //
Port b initialization PORTB=0x00;DDRB=0x00; // Port c
initialization PORTC=0x00;DDRC=0x00; // Port D initialization
PORTD=0x00;DDRD=0x00; // ADC initialization // ADC Clock frequency:
1000.000 kHz // ADC Voltage Reference: AVCC pin // ADC Auto Trigger
Source: Free Running ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0xA2;
SFIOR&=0x1F; // LCD module initialization lcd_init(16); //
Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
ACSR=0x80; SFIOR=0x00; // Watchdog Timer initialization // Watchdog
Timer Prescaler: OSC/2048k #pragma optsizeWDTCR=0x1F; WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif }
Fungsi diatas untuk inisialisasi register port maupun SFR.
Silahkan baca sendiri ada keterangannya disamping atau diatas baris
code.// Main function void main(void){ //--------------- Setting IO
and peripheral at startup! sett_regs(); _lcd_ready();
//--------------- Time for going CRAZY (looping forever).. for(;;){
//mainloop looping forever until ERROR/POWER SHUTDOWN/RST/WDT
ACTIVE #asm("wdr") //kick your DOG before timeout! hwahwa... :D if
(temporary != read_adc(0)){ tegangan =
(read_adc(0)*4.8828125)/1000; lcd_gotoxy(0,0);
lcd_putsf("WWW.NUBIELAB.COM");//Don't forget to visit :)
lcd_gotoxy(0,1); sprintf(buffer,"TEGANGAN: %0.2fV",tegangan);
lcd_puts(buffer); temporary = read_adc(0); delay_ms(100); }
#asm("nop") }; }
Fungsi yang paling penting dalam C yaitu main() dalam fungsi ini
terdapat kode yang berfungsi untuk pengolahan data ADC sampai
dengan formatting character untuk ditampilkan di LCD. Pengambilan
dan penulisan data tegangan tidak dilakukan secara terus menerus..
tapi menunggu perubahan nilai dulu. Kasihan kalo LCDnya dipenetrasi
terus menerus haha.. OK, berikut adalah listing program
komplitnya:/*__ ___ __ __ ___ ___ ___ ___ _ _ |_ _| ___ | / |_ _|/
__| _ / _ | | - eMBEDDED Design & | || |) ||___|| |/| || | (__|
/ (_)| .` | - System Development |___|___/ |_|
|_|___|___|_|_\___/_|_|______________________+ ;Homepage :
http://www.nubielab.com ;Email : [email protected] ;Code by :
Herlambang Aribowo. -----------input tegangan dihubungkan ke PINA.0
atau ADC 0 dalam aplikasi real, mungkin diperlukan buffer dan bisa
dibuat dari opamp single supply misal LM358. Jangan lupa kalo mo
dibuat beneran, PIN AVCC dan VREF ADC dihubungkan ke tegangan 5V yg
stabil. Atmega16 X-tall 4Mhz ;*/ #include #include #include //
Alphanumeric LCD Module functions #asm .equ __lcd_port=0x18 ;PORTB
#endasm #include //#define ADC_VREF_TYPE 0xC0 //Internal //#define
ADC_VREF_TYPE 0x00 //AREF #define ADC_VREF_TYPE 0x40 //AVCC
unsigned char buffer[16]; //Untuk buffer sprintf float tegangan;
//Untuk data perhitungan tegangan (float) unsigned int temporary;
//Untuk temporary data ADC (komparasi) void sett_regs(void);
//Fungsi untuk setting register di awal proses unsigned int
read_adc(unsigned char adc_input);//Fungsi baca ADC // Main
function void main(void){
//--------------- Setting IO and peripheral at startup!
sett_regs(); _lcd_ready(); //--------------- Time for going CRAZY
(looping forever).. for(;;){ //mainloop looping forever until
ERROR/POWER SHUTDOWN/RST/WDT ACTIVE #asm("wdr") //kick your DOG
before timeout! hwahwa... :D if (temporary != read_adc(0)){
tegangan = (read_adc(0)*4.8828125)/1000; lcd_gotoxy(0,0);
lcd_putsf("WWW.NUBIELAB.COM");//Don't forget to visit :)
lcd_gotoxy(0,1); sprintf(buffer,"TEGANGAN: %0.2fV",tegangan);
lcd_puts(buffer); temporary = read_adc(0); delay_ms(100); }
#asm("nop") }; } // Function for setting register void
sett_regs(void){ // Port a initialization PORTA=0x00;DDRA=0x00; //
Port b initialization PORTB=0x00;DDRB=0x00; // Port c
initialization PORTC=0x00;DDRC=0x00; // Port D initialization
PORTD=0x00;DDRD=0x00; // ADC initialization // ADC Clock frequency:
1000.000 kHz // ADC Voltage Reference: AVCC pin // ADC Auto Trigger
Source: Free Running ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0xA2;
SFIOR&=0x1F; // LCD module initialization lcd_init(16); //
Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
ACSR=0x80; SFIOR=0x00; // Watchdog Timer initialization // Watchdog
Timer Prescaler: OSC/2048k #pragma optsizeWDTCR=0x1F; WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif } // Routine baca
ADC
unsigned int read_adc(unsigned char adc_input){ ADMUX=adc_input
| (ADC_VREF_TYPE & 0xff); // Delay needed for the stabilization
of the ADC input voltage delay_us(10); // Start the AD conversion
ADCSRA|=0x40; // Wait for the AD conversion to complete while
((ADCSRA & 0x10)==0); ADCSRA|=0x10; return ADCW; }