III. Ví dụ minh họa.
Chương 3 THIẾT KẾ VÀ THỰC HÀNH 3.1 Thiết kế phần cứng
3.2.1 CÔNG THỨC CHUYỂN ĐỔI GIÁ TRỊ ANALOG THÀNH GIÁ TRỊ NỒNG ĐỘ CỒN
Phương trình : F(x)
Trong đó F1, X1 và F0, x0 là 2 điểm lấy từ đồ thị : F0 = 1, x0 = 0,4
F1 = 0,2, x1 = 4 F(x) F(x)
Bây giờ chúng ta có mối quan hệ giữa Rs và mgL: = mgL =
Vo = ADC*Vi/1024;
Trong đó : Rs : biến trở thay đổi theo nồng độ cồn .
R0 : giá trị của Rs trong không
khí( chưa có cồn ) RL : trở kháng tải phân áp ( Chọn RL=200K theo datasheet ) 3.2.2Code chương trình
#define F_CPU 8000000UL /* Define CPU Frequency e.g. here 8MHz */ #include <avr/io.h> /* Include AVR std. library file */
#include <util/delay.h> /* Include Delay header file */ #include <stdio.h>
#define LCD_Dir DDRD /* Define LCD data port direction */ #define LCD_Port PORTD /* Define LCD data port */
#define RS PD0 /* Define Register Select pin */ #define EN PD2 /* Define Enable signal pin */ void LCD_Command(unsigned char);
void LCD_Char(unsigned char); void LCD_Init(void);
void LCD_String(char*);
void LCD_String_xy(char, char, char*); void LCD_Clear();
uint16_t Read_ADC(unsigned char); int main() { LCD_Init(); DDRA = 0x00; ADMUX |= (1<<REFS0); ADCSRA = (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1); char mq3[20]; float mgl, Vo, rs; float R0 = 1800, rl=200000, Vi=5;
while(1) { Vo = Read_ADC(0)*Vi/1024; rs = (Vi*rl)/Vo - rl; float x= 0.4* rs/R0; mgl = pow(x, -1.431);
sprintf(mq3,"%d.%02d mg/l",(int)mgl, (int)(mgl*100)%100); LCD_String_xy(0, 0, mq3);
if((0.00 <= mgl) && (mgl < 0.1)) LCD_String_xy(1, 0, " ");
else if((0.1 <= mgl) && (mgl <= 0.25)) LCD_String_xy(1, 0, "Phat muc 1"); else if((0.25 < mgl) && (mgl <= 0.4)) LCD_String_xy(1, 0, "Phat muc 2"); else
LCD_String_xy(1, 0, "Phat muc 3"); }
return 0; }
void LCD_Command( unsigned char cmnd ) {
LCD_Port = (LCD_Port & 0x0F) | (cmnd & 0xF0); /* sending upper nibble */ LCD_Port &= ~ (1<<RS); /* RS=0, command reg. */
LCD_Port |= (1<<EN); /* Enable pulse */ _delay_us(1);
LCD_Port &= ~ (1<<EN);
_delay_us(200);
LCD_Port = (LCD_Port & 0x0F) | (cmnd << 4); /* sending lower nibble */ LCD_Port |= (1<<EN);
_delay_us(1);
LCD_Port &= ~ (1<<EN); _delay_ms(2);
}
void LCD_Char( unsigned char data ) {
LCD_Port = (LCD_Port & 0x0F) | (data & 0xF0); /* sending upper nibble */ LCD_Port |= (1<<RS); /* RS=1, data reg. */
LCD_Port|= (1<<EN); _delay_us(1);
LCD_Port &= ~ (1<<EN);
_delay_us(200);
LCD_Port = (LCD_Port & 0x0F) | (data << 4); /* sending lower nibble */ LCD_Port |= (1<<EN);
_delay_us(1);
LCD_Port &= ~ (1<<EN); _delay_ms(2);
void LCD_Init (void) /* LCD Initialize function */ {
LCD_Dir = 0xFF; /* Make LCD port direction as o/p */ _delay_ms(20); /* LCD Power ON delay always >15ms */
LCD_Command(0x02); /* send for 4 bit initialization of LCD */ LCD_Command(0x28); /* 2 line, 5*7 matrix in 4-bit mode */
LCD_Command(0x0c); /* Display on cursor off*/
LCD_Command(0x06); /* Increment cursor (shift cursor to right)*/ LCD_Command(0x01); /* Clear display screen*/
_delay_ms(2); }
void LCD_String (char *str) /* Send string to LCD function */ {
int i;
for(i=0;str[i]!=0;i++) /* Send each char of string till the NULL */ {
LCD_Char (str[i]); }
}
void LCD_String_xy (char row, char pos, char *str) /* Send string to LCD with xy position */
{
LCD_Command((pos & 0x0F)|0x80); /* Command of first row and required position<16 */
else if (row == 1 && pos<16)
LCD_Command((pos & 0x0F)|0xC0); /* Command of first row and required position<16 */
LCD_String(str); /* Call LCD string function */ }
void LCD_Clear() {
LCD_Command (0x01); /* Clear display */ _delay_ms(2);
LCD_Command (0x80); /* Cursor at home position */ }
uint16_t Read_ADC(unsigned char channel) {
ADMUX = channel | (1<<REFS0); ADCSRA |= (1<<ADSC);
while((ADCSRA & (1<<ADIF))==0); ADCSRA &= ~(1<<ADIF);
_delay_ms(1); return ADCW; }