Mục Lục
BÁO CÁO ĐỒ ÁN VI XỮ LÝ
THIẾT KẾ VÀ ĐIỀU KHIỂN MÔ HÌNH HỆ
THỐNG GIÁM SÁT VÀ CẢNH BÁO CHÁY NỔ
TRONG NHÀ
CBHD:
Ths. Trần Hữu Danh
1
•
NỘI DUNG BÁO CÁO
1. MỤC TIÊU VÀ GIỚI HẠN ĐỀ TÀI CẦN
ĐẠT ĐƯỢC
Mục tiêu : Thiết kế và điều khiển được mô hình đo nhiệt độ và
cảnh báo khi nhiệt độ quá cao. Cảnh báo khi có khói, khí gas,…
Giới hạn :
- Mạch hiển thị được nhiệt độ và nhiệt độ đặt trước trên lcd.
Khi nhiệt độ vượt quá nhiệt độ đặt trước thì mạch sẽ cảnh báo
led tắt mở.
- Mạch cảnh báo led tắt mở khi có khí gas, khói,…
- không hiển thị nồng độ chất khí lên LCD.
2
2.
MÔ HÌNH HỆ THỐNG THÔNG QUA
SƠ ĐỒ KHỐI
Cảm biến LM35 và
MQ-2
Bộ xữ lý trung tâm
MSP430
Hiển thị LCD
Khối nút nhấn
3.
•
•
•
•
PHÂN TÍCH VÀ LỰA CHỌN LINH KIỆN
Sử dụng ADC10 Để biến đổi ngã ra của LM 35 và hiển thị nhiệt độ đo
được lên LCD.
Sử dụng trực tiếp ngõ ra số của MQ-2 vào msp.
Thực hiện cảnh báo bằng cách tắt mở led đơn.
Dùng các nút nhấn để điều chỉnh nhiệt độ đặt trước.
Chọn linh kiện :
•
•
•
•
•
Vi điều khiển : msp430g2553.
Cảm biến nhiệt độ LM 35.
Cảm biến khí gas MQ-2.
LCD 16x2.
Các linh kiện cơ bản khác.
3
•
3.1.Giới Thiệu về MSP430G2553
MSP 430 là dòng vi điều khiển có kiến trúc RISC 16 bit siêu tiết kiệm
năng lượng, sử dụng nguồn điện áp từ 1.8 đến 3.6v.
•
Sơ đồ chân MSP430G2553
•
Sơ đồ khối các chức năng của MSP430G2553
4
•
3.2.Giới thiệu về cảm biến nhiệt độ LM 35
Cảm biến
cảm biến
tích hợp
mà điện áp
tỷ lệ tuyến
độ theo
Celsius Điện
4V đến 30V
LM35 là bộ
nhiệt mạch
chính xác cao
đầu ra của nó
tính với nhiệt
thang độ
áp đầu vào từ
Đặc điểm
cảm biến
chính của
LM35
•
Độ phân giải
ra là
điện áp đầu
10mV/oC
•
Độ chính xác cao ở 25 C là 0.5 C
•
Trở kháng đầu ra thấp 0.1 cho 1mA tải
•
Dải nhiệt độ đo được của LM35 là từ -55 C 150 C với
các mức điện áp ra khác nhau.
+ Nhiệt độ -55 C điện áp đầu ra -550mV
+ Nhiệt độ 25 C điện áp đầu ra 250mV
+ Nhiệt độ 150 C điện áp đầu ra 1500mV
5
3.3.Giới thiệu về LCD 16x2
Ký hiệu và chắc năng các chân lcd 16x2
4.
LƯU ĐỒ CHƯƠNG TRÌNH DIỀU KHIỂN
BẮT ĐẦU
KHỞI TẠO LCD
HIỂN THỊ THÔNG TIN ĐỀ TÀI
HIỂN THỊ NHIỆT ĐỘ ĐO ĐƯỢC VÀ
NHIỆT ĐỘ SET
6
NẾU NHIỆT ĐỘ >NHIỆT ĐỘ SET, HOẶC CÓ
KHÓI, KHÍ GAS,…
Đ
LED CẢNH BÁO TẮT
MỞ
S
HIỆN THI RA LCD NHIỆT ĐỘ VÀ ĐỘ ẨM DO
ĐƯƠC
7
5.
PHẦN CODE CỦA ĐỒ ÁN
5.1.THƯ VIỆN LCD
#include "msp430.h"
#define MCLK_F 16
typedef unsigned char uchar;
union reg
{
unsigned char _byte;
struct bit
{
unsigned char b0:1; //bit 0 trong byte
unsigned char b1:1; //bit 1 trong byte
unsigned char b2:1; //bit 2 trong byte
unsigned char b3:1; //bit 2 trong byte
unsigned char b4:1; //bit 2 trong byte
unsigned char b5:1; //bit 2 trong byte
unsigned char b6:1; //bit 2 trong byte
unsigned char b7:1; //bit 7 trong byte
} _bit;
};
union reg* P3_dir=(union reg*)0x1a;
union reg* P3_out=(union reg*)0x19;
union reg* P3_sel=(union reg*)0x1b;
union reg* P3_in=(union reg*)0x18;
union reg* P3_ren=(union reg*)0x10;
union reg* P2_dir=(union reg*)0x2a;
union reg* P2_out=(union reg*)0x29;
union reg* P2_sel=(union reg*)0x2e;
union reg* P2_in=(union reg*)0x28;
union reg* P2_ren=(union reg*)0x2f;
union reg* P1_sel=(union reg*)0x26;
union reg* P1_dir=(union reg*)0x22;
8
union reg* P1_out=(union reg*)0x21;
union reg* P1_in=(union reg*)0x20;
union reg* P1_ren=(union reg*)0x27;
/* Function Set definitions – LCD s? d?ng ch? d? 4 bit*/
#define FOUR_BIT
0x2C /* 4-bit Interface
*/
#define LINES_5X7 0x38 /* 5x7 characters, multiple line */
/*note:
EIGHT_BIT 0x3C == 8-bit Interface
LINE_5X7
0x30 == 5x7 characters, single line
LINE_5X10 0x34 == 5x10 characters */
/* Display ON/OFF Control definitions */
#define DON
0x0F /* Display on
*/
#define DOFF
0x0B /* Display off
*/
#define CURSOR_ON
0x0F /* Cursor on
#define CURSOR_OFF 0x0D /* Cursor off
*/
*/
#define BLINK_ON
0x0F /* Cursor Blink
*/
#define BLINK_OFF
0x0E /* Cursor No Blink */
/* Cursor or Display Shift definitions */
#define SHIFT_CUR_LEFT
0x04 /* Cursor shifts to the left */
/*note:
SHIFT_CUR_RIGHT
SHIFT_DISP_LEFT
0x05 == Cursor shifts to the right
0x06 == Display shifts to the left
SHIFT_DISP_RIGHT 0x07 == Display shifts to the right */
#define LCD_RS P2_out -> _bit.b1
#define LCD_RS_DIR P2_dir -> _bit.b1
#define LCD_EN P2_out -> _bit.b3
#define LCD_EN_DIR P2_dir -> _bit.b3
#define LCD_DATA_4 P2_out -> _bit.b4
#define LCD_DATA_4_DIR P2_dir -> _bit.b4
#define LCD_DATA_5 P2_out -> _bit.b5
#define LCD_DATA_5_DIR P2_dir -> _bit.b5
#define LCD_DATA_6 P2_out -> _bit.b6
9
#define LCD_DATA_6_DIR P2_dir -> _bit.b6
#define LCD_DATA_7 P2_out -> _bit.b7
#define LCD_DATA_7_DIR P2_dir -> _bit.b7
void lcd_delay_us (unsigned long t)
{int i;
for (i = t; i>0; i-- )
__delay_cycles(MCLK_F); }
void lcd_delay_ms (unsigned long t)
{int i;
for (i = t; i>0; i-- )
__delay_cycles(MCLK_F*50); }
// Send a byte of data (rs == 1) or command (rs == 0) to LCD
void lcd_put_byte(unsigned char rs, unsigned char data)
{ LCD_RS = 0;
if(rs) LCD_RS = 1;
lcd_delay_us(20);
LCD_EN = 0;
// send the high nibble
if (data&BIT4) LCD_DATA_4 = 1;
else LCD_DATA_4 = 0;
if (data&BIT5) LCD_DATA_5 = 1;
else LCD_DATA_5 = 0;
if (data&BIT6) LCD_DATA_6 = 1;
else LCD_DATA_6 = 0;
if (data&BIT7) LCD_DATA_7 = 1;
else LCD_DATA_7 = 0;
lcd_delay_us(20);
LCD_EN = 1;
lcd_delay_us(20);
LCD_EN = 0;
// send the low nibble
if (data&BIT0) LCD_DATA_4 = 1;
10
else LCD_DATA_4 = 0;
if (data&BIT1) LCD_DATA_5 = 1;
else LCD_DATA_5 = 0;
if (data&BIT2) LCD_DATA_6 = 1;
else LCD_DATA_6 = 0;
if (data&BIT3) LCD_DATA_7 = 1;
else LCD_DATA_7 = 0;
lcd_delay_us(20);
LCD_EN = 1;
lcd_delay_us(20);
LCD_EN = 0; }
void lcd_init(void)
{// Set all signal pins as output
LCD_RS_DIR = 1;
LCD_EN_DIR = 1;
LCD_DATA_4_DIR = 1;
LCD_DATA_5_DIR = 1;
LCD_DATA_6_DIR = 1;
LCD_DATA_7_DIR = 1;
LCD_RS = 0;
LCD_EN = 0;
lcd_delay_ms(200); // delay for power on
// reset LCD
lcd_put_byte(0,0x30);
lcd_delay_ms(50);
lcd_put_byte(0,0x30);
lcd_delay_ms(50);
lcd_put_byte(0,0x32);
lcd_delay_ms(200); // delay for LCD reset
lcd_delay_ms(2); // wait for LCD
lcd_put_byte(0,FOUR_BIT & LINES_5X7); // Set LCD type
lcd_delay_ms(2); // wait for LCD
11
lcd_put_byte(0,DOFF&CURSOR_OFF&BLINK_OFF); // display off
lcd_delay_ms(2); // wait for LCD
lcd_put_byte(0,DON&CURSOR_OFF&BLINK_OFF); // display on
lcd_delay_ms(2); // wait for LCD
lcd_put_byte(0,0x01); // clear display and move cursor to home
lcd_delay_ms(2); // wait for LCD
lcd_put_byte(0,SHIFT_CUR_LEFT); // cursor shift mode
lcd_delay_ms(2); // wait for LCD
lcd_put_byte(0,0x01); // clear display and move cursor to home
lcd_delay_ms(2); } // wait for LCD
void lcd_clear(void)
{ lcd_put_byte(0,0x01); // display off
lcd_delay_ms(2); } // wait for LCD
void lcd_gotoxy(unsigned char row, unsigned char col)
{ unsigned char address;
if(row!=0)
address=0x40;
else
address=0;
address += col;
lcd_put_byte(0,0x80|address);
lcd_delay_ms(2); } // wait for LCD
void lcd_putc(char c)
{ switch(c){
case '\f':
lcd_put_byte(0, 0x01);
lcd_delay_ms(2); // wait for LCD
break;
case '\n':
lcd_gotoxy(0, 0x01);
break;
default:
12
lcd_put_byte(1, c);
lcd_delay_ms(2); // wait for LCD
break; }}
void lcd_puts(const char* s)
{ while(*s){
lcd_putc(*s++); } }
void lcd_string(unsigned char *data)
{ char length=16;
while(length > 0) // Write data to LCD up to null
{ lcd_putc(*data); // Write character to LCD
data++; length--; }}// Increment buffer
void lcd_2l_puts (const char* s1 , const char* s2)
{ lcd_gotoxy (0,0);
lcd_puts (s1);
lcd_gotoxy (0,1);
lcd_puts (s2);}
void lcd_put_num (unsigned long val, char dec, unsigned char neg)
{ char i, j, digit,k;
long total;
long temp;
for (i = 0, total = val; total > 0;i++) // count number
total /= 10;
total = i;
if (neg !=0 )
lcd_putc ('-');
if ((total - dec) <=0) // if total < dec put 0.xxxx
lcd_putc('0');
else
{ for (i=0; i< (total-dec); i++)
{ temp = 1;
for (j=1;j<(total-i);j++)
temp *=10;
13
digit = (val/temp)%10;
lcd_putc(digit + 0x30); } }
if (dec > 0)
{ lcd_putc('.');
if ( (dec - total)> 0) // ex: val = 55; dec = 3 put 0.055
{ for ( i = 0; i < (dec-total);i++)
lcd_putc('0');
k = 0; }
else
k = total - dec;
for (i=k; i< total; i++)
{ temp = 1;
for (j=1;j<(total-i);j++)
temp *=10;
digit = (val/temp)%10;
lcd_putc(digit + 0x30);}}}
void lcd_2n(unsigned char x)
{ lcd_putc((x/10)+48);
lcd_putc((x%10)+48);}
void lcd_3n(unsigned char x)
{ lcd_putc((x/100)+48);
lcd_putc(((x/10) % 10)+48);
lcd_putc((x%10)+48);}
5.2.CODE CHƯƠNG TRÌNH CHÍNH :
#include "msp430g2553.h"
void lm35_read();
void canhbao1();
void canhbao2();
unsigned long nhietdo,nhietdoset=40;
14
void main(void)
{ WDTCTL = WDTPW + WDTHOLD;
// chon tan so dao dong noi
BCSCTL1 = CALBC1_1MHZ; /* Set DCO to 1MHz */
DCOCTL = CALDCO_1MHZ;
P1DIR |= BIT5+BIT7;// chon P1.5 va P1.7 la ngo ra dieu khien LED don.
P1DIR &=~ BIT2;
P1OUT|=0X00;
P2DIR =BIT1 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // d?nh nghia P2 là ngõ ra
P2SEL &= ~(BIT6 + BIT7); // su dung chuc nang tich hop
P2SEL2 &= ~(BIT6 + BIT7); // chon bit P2.6 và P2.7 là ngõ ra,
P2OUT &= ~(BIT6 + BIT7); //dat chuc nang mac dinh la ngo ra.
// Khoi tao ngat ngoai cho 2 phim don
P1IE |= 0x18; // cho phep ngat ngoai tai P1.3 va P1.4.
P1IES &= ~0x18; // P1.3 & P1.4 Hi/lo chon canh ngat.
P1IFG &= ~0x18; // xoa co ngat IFG.
// Khai báo ADC
// tham chieu noi 1,5V, cho phep ngat ADC, bat ADC10, Time lay
mau16*ADC10CLKs
ADC10CTL0 = SREF_1 + ADC10SHT_2 + REFON + ADC10ON + ADC10IE;
__delay_cycles (30);
ADC10CTL1 = INCH_0; // chon kênh ngõ vào A0
ADC10AE0 |= 0x01; // chon P1.1 là ngõ vào bien doi ADC
// khoi tao LCD
lcd_init();//--hàm khoi tao cho LCD
lcd_clear();//--xoa man hinh LCD
//dinh vi vi tri con tro tren LCD de in ky tu (y,x)
lcd_gotoxy(0,0);
// hien thi thong tin ve de tai
lcd_puts(" DO AN VI XU LY");
lcd_gotoxy(1,0);
lcd_puts("CANH BAO CHAY NO");
__delay_cycles(4000000);
15
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts("Giao vien");
lcd_gotoxy(1,0);
lcd_puts(" TRAN HUU DANH");
__delay_cycles(4000000);
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts("
HUU LUAN");
lcd_gotoxy(1,0);
lcd_puts("
B1509254 ");
__delay_cycles(4000000);
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts("NHIET DO:
C");//--HANG 1 HIEN THI NHIET DO
lcd_gotoxy(1,0);
lcd_puts("NHIETDOSET:
C "); //--HANG 2 HIEN THI NHIET DO SET.
_BIS_SR(GIE); // ngat toan cuc.
while(1)
{ lm35_read();
lcd_gotoxy(0,9);
lcd_3n(nhietdo);
lcd_putc(223);
lcd_gotoxy(1,11);
lcd_3n(nhietdoset);
lcd_putc(223);
canhbao1();
canhbao2();}}
void lm35_read()
{nhietdo = (unsigned long)(ADC10MEM*1.5*100)/1024;
ADC10CTL0 |= ENC + ADC10SC;// cho phep va bat dau bien doi ADC
}
16
LM35 VỚI ARDUINO:
Cảm biến nhiệt độ LM35 là một loại cảm biến tương tự rất hay được
ứng dụng trong các ứng dụng đo nhiệt độ thời gian thực. Vì nó hoạt
động khá chính xác với sai số nhỏ, đồng thời với kích thước nhỏ và
giá thành rẻ là một trong những ưu điểm của nó. Vì đây là cảm biến
tương tự (analog sensor) nên ta có thể dễ dàng đọc được giá trị của
nó bằng hàm analogRead(). Nào, cùng nhau tìm hiểu thôi!
LM35 là một cảm biến nhiệt độ analog
Nhiệt độ được xác định bằng cách đo hiệu điện thế ngõ ra của LM35.
→ Đơn vị nhiệt độ: °C.
→ Nhiệt độ thay đổi tuyến tính: 10mV/°C
Sơ đồ chân của LM35
LM35 không cần phải canh chỉnh nhiệt độ khi sử dụng.
Độ chính xác thực tế: 1/4°C ở nhiệt độ phòng và 3/4°C ngoài khoảng
2°C tới 150°C
LM35 có hiệu năng cao, công suất tiêu thụ là 60uA
Cảm biến LM35 hoạt động bằng cách cho ra một giá trị hiệu điện thế
nhất định tại chân Vout (chân giữa) ứng với mỗi mức nhiệt độ.
Như vậy, bằng cách đưa vào chân bên trái của cảm biến LM35 hiệu
điện thế 5V, chân phải nối đất, đo hiệu điện thế ở chân giữa bằng
các pin A0 trên arduino (giống y hệt cách đọc giá trị biến trở), bạn sẽ
có được nhiệt độ (0-100ºC) bằng công thức:
17
1. float temperature = (5.0*analogRead(A0)*100.0/1024.0);
Với LM35, bạn có thể tự tạo cho mình mạch cảm biến nhiệt độ sử
dụng LM35 và tự động ngắt điện khi nhiệt độ vượt ngưỡng tối đa,
đóng điện khi nhiệt độ thấp hơn ngưỡng tối thiểu thông qua module
rơ le...
LM35 thay đổi nhiệt độ nhanh và chính xác.
void canhbao1()// neu nhiet do lon hon nhiet do set thi LED chop tat.
{ if (nhietdo > nhietdoset)
P1OUT|=BIT5;
__delay_cycles(500000);
P1OUT &=~ BIT5;
__delay_cycles(500000);
}
void canhbao2()
{
if((P1IN & BIT2)==0) // neu có khi gas LED chop tat.
{
P1OUT |=BIT7;
__delay_cycles(500000);
P1OUT &=~BIT7;
__delay_cycles(500000);
}
else
{
P1OUT &=~ BIT7;
}
}
// chuong trinh ngat AD10
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
18
{ __bic_SR_register_on_exit(CPUOFF); }
// chuong trinh ngat cho port P1.3 va P1.4.
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
{if ( P1IFG & BIT3)
nhietdoset++;
P1IFG &= ~BIT3;} // tang nhiet do set
{if (P1IFG & BIT4)
{nhietdoset--;}
P1IFG &= ~BIT4;} // giam nhiet do set
}
Lắp mạch với ARDUINO:
19
Lập trình
1. int sensorPin = A0;// chân analog kết nối tới cảm biến LM35
2.
3. void setup() {
Serial.begin(9600);
4.
//Khởi động Serial ở mức baudrate 9600
// Bạn không cần phải pinMode cho các chân analog trước khi
dùng nó
5.
6. }
7.
8. void loop() {
//đọc giá trị từ cảm biến LM35
9.
int reading = analogRead(sensorPin);
10.
11.
//tính ra giá trị hiệu điện thế (đơn vị Volt) từ giá trị cảm
biến
12.
float voltage = reading * 5.0 / 1024.0;
13.
14.
// ở trên mình đã giới thiệu, cứ mỗi 10mV = 1 độ C.
15.
// Vì vậy nếu biến voltage là biến lưu hiệu điện thế (đơn vị
Volt)
16.
17.
// thì ta chỉ việc nhân voltage cho 100 là ra được nhiệt độ!
18.
19.
float temp = voltage * 100.0;
20.
21.
Serial.println(temp);
22.
/*Mẹo:
Các bạn phaỉ khai báo phần thực cho toàn bộ các số thực nhé!
23.
24.
*/
20
delay(1000);//đợi 1 giây cho lần đọc tiếp theo
25.
26. }
6.
SƠ ĐỒ NGUYÊN LÝ
7.
MẠCH IN
21
8.
TỔNG KẾT ĐỀ TÀI
Mạch chạy không đúng với yêu cầu.
Mạch chỉ chạy đúng phần cảm biến khí gas MQ-2
Mạch hiển thị không đúng nhiệt độ của LM 35.
9.
TÀI LIỆU THAM KHẢO
Giáo trình vi điều khiển msp430, tác giả TS. Lương Vinh
Quốc Danh và Ths. Trần Hữu Danh.
Nguồn internet : google, youtube, datasheet,…
22