You are on page 1of 13

PHẦN I

THIẾT KẾ PHẦN CỨNG


Sơ đồ khối của mạch

Khối xử lý Khối Khối xử lý Khối hiển


Nhiệt độ nhiệt độ ADC vào ra thị và cảnh
môi trường báo

Khối xử lý chung

♣ Khối xử lý nhiệt độ và khối ADC : Là một sensor nhiệt LM335 và một bộ


ADC 10 bit
Sơ đồ của sensor nhiệt LM335

LM335 cố đầu vào là nhiệt độ môi trường và đầu ra là diện áp


Chân 1 là chân mang dấu “-”, thường được nối đất khi phân
cực
Chân 2 là chân mang dấu “+”, được nối với V+ thông qua một
điện trở và chân 2 cũng là đầu ra của LM335
Chân 3 là chân mang ch ữ “ADJ”, thường được nối với một
biến trở để điều chỉnh nhiệt độ ban đầu cho phù hợp

Người ta thường phân cực cho nó như sau:


Tài liệu này được upload & download miễn phí tại website: http://hutonline.net

Còn bộ biến đổi ADC , ta dùng ADC của PIC là ADC 10 bít

Nguyên lý làm việc và các công thức tính toán:


Đo nhiệt độ môi trường tại một điểm thông qua sensor nhiệt LM335 (Chi
tiết về LM335 xem thêm trong datasheet). LM335 là sensor đo nhiệt, đo được
nhiệt độ trong khoảng từ -400C đến 1000C, đầu ra là 10mV/K. Đầu ra này được
đưa vao chân Analog của bộ ADC (Cụ thể ở đây là đưa vào Chân AN0 ).Vì ở đây là
tính theo độ K nên để đo độ C ta cần có công thức chuyển đổi giá trị từ độ K
sang độ C. Ở đây ta dùng ADC của PIC là 10 bit => max=1023, Vref=Vcc, giả thiết là
Vcc = 5V nên tại 0 độ C hay 273K thì đầu ra của LM335 có giá tr ị là 2.73V. Như
vậy khi muốn tính toán ra độ C ta cần phải trừ đi mức điện áp là 2.73V. Lấy ví dụ:
nhiệt độ là 30 độ C = 303K -> out = 303 x 10mV/K =3.03V. Ta tính toán giá trị
đọc được từ ADC 10 bit (ADC_Vin là điện áp đưa vào chân ADC của PIC,
ADC_value là giá trị đầu ra của ADC dưới dạng thập phân):
ADC_Vin = 5V => ADC_value = 1023
ADC_Vin = 2.73V => ADC_value = (1023/5)x2.73=558.558
(tương ứng 0 độ C)
ADC_Vin = 3.03V => ADC_value = (1023/5)x3.03=619.938
(tương ứng 30 độ C)
Mặt khác do V_ref = V cc =5V nên ADC_value=1 t ương ứng 5/1023 =
4.887mV
(~ 5mV). Trong khi đó LM335 cho ra điện áp là 10mV/1K nên để giá trị ADC
thay đổi 1 đơn vị thì nhiệt độ phải thay đổi là 0.5K (hay gần 5mV) Từ đó ta có
công thức đầy đủ sau để tính giá trị độ C:
C=(ADC_value -
558.558)x(4.887mV/10mV) =>
C=(ADC_value - 558.6)/ 2.046

♣Khối hiển thị và cảnh báo

Ta dùng LED 7 thanh để hiển thị nhiệt độ của môi trường và dùng loa để
phát ra cảnh báo khi nhiệt độ môi trường ở trong khoảng nguy hiểm. Cụ thể
trong mạch này ta dùng Hai LED 7 thanh Anot chung (chúng ta c ũng có thể
dùng LCD thay thế)

Sau đây là sơ đồ mạch nguyên lý:


Sơ đồ nguyên lý

21 40
A1015 A1015 22 RD2/PSP2 RB7/PGD 39
T1 T2
23
24
RD3/PSP3
RC4/SDI/SDA
RB6/PGC
RB5
38
37
25 RC5/SDO RB4 36
HI
26 RC6/TX/CK RB3/PGM 35
27 RC7/RX/DT RB2 34
28 RD4/PSP4 RB1 33
29 RD5/PSP5 RB0/INT
30 RD6/PSP6
RD7/PSP7
22pF 4
RA2/AN2 5
RA3/AN3
10MHz 6
RA4 7 Q3
RA5/AN4
13 8 4K7
OSC1/CLKI RE0/AN5
14 9
15 OSC2/CLKO RE1/AN6
RC0/T1CKI RE2/AN7
10 T3 SPEAKER
22pF 16
RC1/CCP2
17
RC2/CCP1
18
RC3/SCK/SCL
4K7 19
RD0/PSP0
20 32
RD1/PSP1 VDD1
4K7 31
VSS1

3 3
RA1/AN1
11 2 VR10K
VDD RA0/AN0
1 10K LM335Z
VPP
12
VSS 1K

PIC16F877A

SW2

Giải thích sơ đồ nguyên lý:


Các Transistor A1015 (chúng ta gọi là các đèn T1, T2, T3) được cấp nguồn 5V ở
chân E , chân C của T1 và T2 được nối với 2 chân Vcc của LED 7 thanh, các
chân B của T1, T2 được nối lần lượt với các chân 20 và 19 của VĐK
PIC16F877A (cụ thể là nối với các chân RD0 và RD1 là các chân output của
PORTB). Khi RD1 ở mức thấp thì đầu C của đèn T1 sẽ ở mức cao lúc đó LED 1
được phân cực đúng và có thể sáng, ngược lại thì LED 1 bị phân cực sai lúc đó nó
sẽ không sáng. Tương tự cho chân RD0 và LED còn lại. Đèn T3 cũng như vậy
nhưng thay LED bằng một cái Loa (và chân output là chân RE0 của PORTE)
dùng để cảnh báo .
Đầu ra của sensor nhiệt LM335 sẽ được đưa vào chân 2 của VĐK (là chân Analog
AN0 của ADC 10 bít tích hợp sẵn trong VĐK PIC, chân AN0 này sẽ được thiết lập
là chân vào Analog của ADC) .
Cuối cùng là VĐK PIC16F877A, ở đây ta chỉ nói đến những tính năng mà ta dùng
cho đề tài này, nó là một con VĐK tích hợp rất nhiều chức năng mà chúng ta có
thể tham khảo thêm trong Datasheet của nó. Nhìn vào sơ đồ nguyên lý ta có thể
thấy ngay rằng các chân 19, 20 là các chân output (đã được nói ở trên) ,ngoài ra
còn có các chân 33 đến 39 cũng là các chân output (chính là các bít RB0 đến
RB6 được thiết lập là các chân output của PORTB), các chân này được nối với
LED 7 thanh để hiển thị nhiệt độ, khi LED được phân cực đúng thì nếu các chân
này ở mưc cao thì LED sẽ sáng. Chân 2 là chân Input, là chân vào Analog của
ADC
Các chân 11,12,31,32 là các chân cấp nguồn cho VĐK, riêng chân Vpp (chân 1)
chính là chân RESET. Chân 13, 14 là các chân dùng cho việc thiêt lập xung Clock
cho VĐK
PHẦN II

THIẾT KẾ PHẦN MỀM


Trong bài này chúng ta sẽ dùng chương trình CCS (ngôn ngữ C cho PIC của
Microchip) để viết phần lập trình cho VĐK, ưu điểm của nó là khá nhỏ gọn so với
khi ta viết bằng MASM nhờ được hỗ trợ khá nhiều hàm, ngoài ra ta còn có thể
chèn một đoạn chương trình viết bằng ASM giũa hai chỉ thị tiền xử lý là #ASM và
#ENDASM . Tài liệu tham khảo: “Tài liệu hướng dẫn CCS Tiếng việt” của tác giả
Trần Xuân Trường, SV K2001, ĐHBK HCM hoặc đầy đủ hơn là phần Hepl
trong trình cài đặt PIC C Compiler

Code đầy đủ cho chương trình

#include <16F877A.h> //Khai báo con PIC ta sử dụng và file khai báo các
bít,các
// thanh ghi quan trọng trong con PIC này
#include <def_877a.h> //Khai báo sự định ngiã các thanh ghi và các bít quan
trọng
#device *=16 adc=10 // Khai báo dùng poiter 16 bít và ADC 10 bít
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT,
NOLVP, NOCPD, NOWRT //Khai báo các config
#use delay(clock=20000000) //Khai báo sử dụng hàm Delay và tần số dao động
sử dụng

int8 high,low; //Khai báo các biến số nguyên 1byte (8bít)


//Khai báo mảng hằng số là số nguyen 1 byte
int8 const a[10] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
// Chương trình con tách số hàng chục và hàng đơn vị thành hai số chứa trong hai
biến
//đã khai báo ở trên là high và low
void convert_bcd(int8 x)
{
low=x%10; //chia lấy phần dư, low=hàng đơn vị
high=x/10;
high=high%10; //high=số hàng chục
}
// Chương trình con giải mã và hiển thị nhiệt độ
void display()
{
PORTB=a[low]; // Gửi dữ liệu đến LED 1
RD0=0; // Bật LED1, LED1 sẽ hiển thị đúng giá trị của low

delay_ms(2); // Cho trễ 2ms


RD0=1; // tắt LED 1
PORTB=a[high]; // LED 2
RD1=0;
delay_ms(2);
RD1=1;
}
//Chương trình con thục hiện việc báo động
void bao_dong(){
int8 i;
for(i=0;i<200;i++)
{
RE0=0;delay_us(100);
RE0=1;delay_us(100);
} //Kêu 200 tiếng
}
// Chương trình chính
void main() {
float value;
int16 i;

trisb = 0x00; //thiết lập các chân của PORTB là các chân Output
trisc = 0x00; // thiết lập các chân của PORTC là các chân Output
trisd = 0x00; // thiết lập các chân của PORTD là các chân Output
trise = 0x00; // thiết lập các chân của PORTE là các chân Output
trisa = 0xff; // thiết lập các chân của PORTa là các chân Intput
portC = 0xff; // thiết lập các chân của PORTC xuất ra điện áp ở mức cao
portD = 0xff; // thiết lập các chân của PORTd xuất ra điện áp ở mức cao

//Thiết lập cho ADC


setup_adc(ADC_CLOCK_INTERNAL); //Chỉ ra cách thức hoạt động của
ADC là thời
// gian lấy mẫu bằng xung clock
//Thiết lâp.chân lấy tín hiệu Analog là chân AN0
setup_adc_ports(AN0);
setup_ADC_channel(0)

delay_us(10); //Trễ 10 us

value=(float)read_adc();
value = (value - 558.5)/2.048;
convert_bcd((int8)value);
i=0;
//Vòng lặp vô tận
while(1)
{
i++;
value = (float)read_adc();
value = (value - 558.5)/2.048; //for 5V supply
if (i==150) { convert_bcd((int8)value);i=0;}
if(((int8)value > 40) || ((int8)value < 15)) bao_dong();
display();
}
}

Lưu ý:
●Tại sao khi gắn a[low] =PORTB thì LED 1 lại hiển thị giá trị của low?
Bởi vì mảng hằng số:
a[10] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
sẽ tương đương với mảng giá trị các số nhị phân như sau:
a[10] =
{11000000,11111001,10100100,10110000,10011001,10010010,10000010,
11111000,10000000,10010000};
Kể từ phải qua trái (bỏ qua số nhị phân cuối cùng bởi vì ta không sử dụng chan
RB7 của PORTB) các số nhị phân này chỉ ra mức điện áp ở các thanh
a,b,c,d,e,f,g,h của LED
Tức là mảng này tương ứng với các giá trị hiển thị trên LED là các số:
0,1,2,3,4,5,6,7,8,9
●Một số các hàm trong CCS đã được sử dụng là:
Hàm
delay_us(time)
delay_ms(time)
ví dụ: delay_us(2) ; //tạo trễ 2us
delay_ms(2); //tạo trễ 2ms
Hàm:
setup_adc(ADC_CLOCK_INTERNAL);

hàm này dùng để xác định cách thức hoạt động của bộ biến đổi
ADC, cụ thể là xác định thời gian lấy mẫu bằng một xung clock
Hàm:
setup_adc_ports(AN0);
setup_ADC_channel(0)
các hàm này dùng để xác định chân lấy tín hiệu Analog là chân AN0

Còn đây là file định ngĩa “def_877a.h” mà ta đã khai báo ở trên:

// register definitions

#define W 0
#define F 1

// register files
#byte INDF =0x00
#byte TMR0 =0x01
#byte PCL =0x02
#byte STATUS =0x03
#byte FSR =0x04
#byte PORTA =0x05
#byte PORTB =0x06
#byte PORTC =0x07
#byte PORTD =0x08
#byte PORTE =0x09

#byte EEDATA =0x10C


#byte EEADR =0x10D
#byte EEDATH =0x10E
#byte EEADRH =0x10F
#byte ADCON0 =0x1F
#byte ADCON1 =0x9F
#byte ADRESH =0x9F
#byte ADSESL =0x9F

#byte PCLATH =0x0a


#byte INTCON =0x0b
#byte PIR1 =0x0c
#byte PIR2 =0x0d
#byte PIE1 =0x8c
#byte PIE2 =0x8d

#byte OPTION_REG =0x81


#byte TRISA =0x85
#byte TRISB =0x86
#byte TRISC =0x87
#byte TRISD =0x88
#byte TRISE =0x89

#byte EECON1 =0x18C


#byte EECON2 =0x18D

#byte SSPBUF =0x13


#byte SSPCON =0x14
#byte SSPCON2 =0x91
#byte SSPADD =0x93
#byte SSPSTAT =0x94
// SSPCON bit
#bit SSPWCOL = 0x14.7
#bit SSPOV = 0x14.6
#bit SSPEN = 0x14.5
#bit SSPCKP = 0x14.4
#bit SSPM3 = 0x14.3
#bit SSPM2 = 0x14.2
#bit SSPM1 = 0x14.1
#bit SSPM0 = 0x14.0
// SSPSTAT bit
#bit SSPSMP = 0x94.7
#bit SSPCKE = 0x94.6
#bit SSPDA = 0x94.5
#bit SSPP = 0x94.4
#bit SSPS = 0x94.3
#bit SSPRW = 0x94.2
#bit SSPUA = 0x94.1
#bit SSPBF = 0x94.0

//DINH NGHIA BIT


#bit ra5 =0x05.5
#bit ra4 =0x05.4
#bit ra3 =0x05.3
#bit ra2 =0x05.2
#bit ra1 =0x05.1
#bit ra0 =0x05.0

#bit rb7 =0x06.7


#bit rb6 =0x06.6
#bit rb5 =0x06.5
#bit rb4 =0x06.4
#bit rb3 =0x06.3
#bit rb2 =0x06.2
#bit rb1 =0x06.1
#bit rb0 =0x06.0

#bit rC7 =0x07.7


#bit rC6 =0x07.6
#bit rC5 =0x07.5
#bit rC4 =0x07.4
#bit rC3 =0x07.3
#bit rC2 =0x07.2
#bit rC1 =0x07.1
#bit rC0 =0x07.0

#bit rD7 =0x08.7


#bit rD6 =0x08.6
#bit rD5 =0x08.5
#bit rD4 =0x08.4
#bit rD3 =0x08.3
#bit rD2 =0x08.2
#bit rD1 =0x08.1
#bit rD0 =0x08.0
#bit rE2 =0x09.2
#bit rE1 =0x09.1
#bit rE0 =0x09.0

#bit trisa5 =0x85.5


#bit trisa4 =0x85.4
#bit trisa3 =0x85.3
#bit trisa2 =0x85.2
#bit trisa1 =0x85.1
#bit trisa0 =0x85.0

#bit trisb7 =0x86.7


#bit trisb6 =0x86.6
#bit trisb5 =0x86.5
#bit trisb4 =0x86.4
#bit trisb3 =0x86.3
#bit trisb2 =0x86.2
#bit trisb1 =0x86.1
#bit trisb0 =0x86.0

#bit trisc7 =0x87.7


#bit trisc6 =0x87.6
#bit trisc5 =0x87.5
#bit trisc4 =0x87.4
#bit trisc3 =0x87.3
#bit trisc2 =0x87.2
#bit trisc1 =0x87.1
#bit trisc0 =0x87.0

#bit trisd7 =0x88.7


#bit trisd6 =0x88.6
#bit trisd5 =0x88.5
#bit trisd4 =0x88.4
#bit trisd3 =0x88.3
#bit trisd2 =0x88.2
#bit trisd1 =0x88.1
#bit trisd0 =0x88.0

#bit trise2 =0x89.2


#bit trise1 =0x89.1
#bit trise0 =0x89.0

// INTCON Bits for C


#bit gie = 0x0b.7
#bit peie = 0x0b.6
#bit tmr0ie = 0x0b.5
Tài liệu này được upload & download miễn phí tại website: http://hutonline.net

#bit int0ie = 0x0b.4


#bit rbie = 0x0b.3
#bit tmr0if = 0x0b.2
#bit int0if = 0x0b.1
#bit rbif = 0x0b.0

// PIR1 for C
#bit pspif = 0x0c.7
#bit adif = 0x0c.6
#bit rcif = 0x0c.5
#bit txif = 0x0c.4
#bit sspif = 0x0c.3
#bit ccp1if = 0x0c.2
#bit tmr2if = 0x0c.1
#bit tmr1if = 0x0c.0

//PIR2 for C
#bit cmif = 0x0d.6
#bit eeif = 0x0d.4
#bit bclif = 0x0d.3
#bit ccp2if = 0x0d.0

// PIE1 for C
#bit adie = 0x8c.6
#bit rcie = 0x8c.5
#bit txie = 0x8c.4
#bit sspie = 0x8c.3
#bit ccp1ie = 0x8c.2
#bit tmr2ie = 0x8c.1
#bit tmr1ie = 0x8c.0

//PIE2 for C
#bit osfie = 0x8d.7
#bit cmie = 0x8d.6
#bit eeie = 0x8d.4

// OPTION Bits
#bit not_rbpu = 0x81.7
#bit intedg = 0x81.6
#bit t0cs = 0x81.5
#bit t0se = 0x81.4
#bit psa = 0x81.3
#bit ps2 = 0x81.2
#bit ps1 = 0x81.1
#bit ps0 = 0x81.0

// EECON1 Bits
Tài liệu này được upload & download miễn phí tại website: http://hutonline.net

#bit eepgd = 0x18c.7


#bit free = 0x18C.4
#bit wrerr = 0x18C.3
#bit wren = 0x18C.2
#bit wr = 0x18C.1
#bit rd = 0x18C.0

//ADCON0
#bit CHS0 =0x1F.3
#bit CHS1 =0x1F.4
#bit CHS2 =0x1F.5
Tài liệu này được upload & download miễn phí tại website: http://hutonline.net

PHẦN TỔNG KẾT

1. Nhận xét kết quả nhận được


Nhiệt độ đo dược khá chuẩn xác, tuy nhiên sai số vẫn còn khá
lớn (tới một độ C), điều này ta có thể khắc phục được bằng cách
dùng ba
LED để hiển thị, lúc đó sai số sẽ giảm xuống còn 0,1oC (bởi vì ADC
trong con PIC này là 10 bít => giá trị nó xuất ra tới 1023). Nếu
muốn
chuẩn xác hơn nữa ta có thể dùng ADC ngoài có số bít cao hơn,
hoặc
dùng LCD để hiển thị
Ứng dụng của đề tài rất rộng rãi trong cuộc sống, nhất là
trong
các nhà máy bia, các hệ thống làm lạnh trong việc kiểm soát
nhiệt độ

2.Hướng phát triển mở rộng đề tài:


- Nâng cao độ chính xác hiển thị bằng cách dùng ADC có độ phân
giải cao hơn (có thể dùng ADC ngoài)
- Thêm bàn phím giao tiếp để có thể thay đổi trực tiếp khoảng
nhiệt độ
theo dõi, cùng với đó ta thêm vào LED 7 để hiển thị hai giá trị
nhiệt độ
này
- Sử dụng EEPROM để lưu giá trị nhiệt độ mà người dùng thiết lập,
các lần thay đổi khác...
- Ghép nối máy tính để truyền giá trị nhiệt độ đến máy tính
- Ghép nối LCD và một mạch đếm thời gian thực (DS1307) để ứng
với mỗi thời điểm chương trình sẽ tự động chọn khoảng thiết lập
nhiệt độ thích hợp theo từng mùa, từng thời điểm định trước...
- Sử dụng PID trong điều khiển tự động kết hợp với các mạch
điều khiển tăng giảm nhiêt độ để đảm bảo nhiệt độ luôn bám
theo một giá trị cho trước, hệ ổn định nhiệt (giá trị thay đổi là rất
nhỏ)

You might also like