1. แนะนำไอซีเบอร์
DS1820
ไอซีดิจิตอลเบอร์
DS1820
เป็นเซนเซอร์วัดอุณหภูมิที่มีข้อมูลขนาด 9
บิตเพื่อแสดงค่าอุณหภูมิของไอซี
สามารถเชื่อมต่อกับไมโครคอนโทรลเลอร์ผ่านมาตรฐานการเชื่อมต่อแบบ 1-wireTM
ซึ่งใช้สายในการเชื่อมต่อข้อมูลเพียงเส้นเดียวร่วมกับกราวด์และไฟเลี้ยง
สามารถอ่าน เขียน
และแปลงค่าอุณหภูมิโดยใช้คำสั่งผ่านสายเส้นเดียวกันกับข้อมูลได้โดยไม่จำเป็นต้องใช้ไฟเลี้ยงจากภายนอก
เนื่องจากไอซี
DS1820 ที่ผลิตออกแต่ละตัวมีเลขประจำตัวเฉพาะ ทำให้สามารถเชื่อมต่อบนสายข้อมูลเส้นเดียวกันได้หลายตัว
ทำให้สามารถนำไปประยุกต์ใช้ในงานด้านการตรวจวัดในบริเวณต่างๆ ได้อย่างหลากหลาย
อาทิเช่น ในงานด้านการควบคุมความร้อน การระบายอากาศ ระบบปรับอากาศ
เซนเซอร์วัดอุณหภูมิภายในอาคาร ติดตั้งกับเครื่องจักรกล และในกระบวนการที่มีการตรวจสอบอุณหภูมิตลอดเวลา
เป็นต้น
รูปที่ 1
การจัดเรียงขาของไอซีตรวจวัดอุณหภูมิเบอร์ DS1820
2. วงจรการเชื่อมต่อกับไมโครคอนโทรลเลอร์
การเชื่อมต่อจะใช้สายข้อมูลเพียงเส้นเดียวต่อเข้ากับ
พอร์ตอินพุตเอาท์พุทของไมโครคอนโทรลเลอร์ดังแสดงในรูปที่ 2
รูปที่ 2
การเชื่อมต่อไอซีตรวจวัดอุณหภูมิเบอร์ DS1820 กับไมโครคอนโทรลเลอร์ตระกูล
AVR เบอร์ATtiny2313
3. การพัฒนาโปรแกรม
ในส่วนนี้เป็นการอธิบายขั้นตอนการพัฒนาโปรแกรมเพื่ออ่านและเขียนค่า
สำหรับเชื่อมต่อไมโครคอนโทรลเลอร์ตระกูล AVR
กับเซนเซอร์ตรวจวัดอุณหภูมิ โดยไม่กล่าวถึงขั้นตอนการพัฒนาโปรแกรมที่เป็นพื้นฐาน
สำหรับการแสดงผลของอุณหภูมิที่วัดได้นั้น จะแสดงผ่านหน้าจอเทอร์มินอลมอนิเตอร์
ซึ่งเป็น ส่วนเพิ่มขยายของ Atmel Studio 6.0 เบื้องต้นจะกล่าวถึงการเชื่อมต่อในกรณีที่มีเซนเซอร์ต่ออยู่กับสายข้อมูลเพียงเส้นเดียวก่อนเท่านั้น
3.1 การจัดการเรื่องเวลา
เนื่องจากการเชื่อมต่อกับเซนเซอร์ใช้เพียงสายเส้นเดียว
จึงจำเป็นอย่างยิ่งที่ต้องทำให้ช่วงจังหวะเวลาในการอ่านหรือเขียนค่านั้นมีความแม่นยำ
โดยในแต่ละช่วงเวลาอ่านเขียนนั้น
จะมีการอธิบายอย่างชัดเจนในเอกสารอธิบายข้อมูลของไอซี และพบว่าต้องมีความแม่นยำในระดับไมโครวินาทีเลยทีเดียว
ซึ่งมีค่าน้อยมากเลยทีเดียว
ดังนั้นจึงจำเป็นต้องเข้าใจในระดับหนึ่งเรื่องฐานเวลาเพื่อนำมาจัดการให้ได้ช่วงเวลาที่ต้องการอย่างแม่นยำ
สำหรับ Atmel Studio 6.0 มีการเตรียมไลบรารีเรื่องหน่วงเวลา ซึ่งสามารถนำมาใช้ได้เลยคือ delay.h
โดยภายในจะมีฟังก์ชันการหน่วงเวลาที่มีความแม่นยำในระดับ
ไมโครวินาที (_delay_us()) และ มิลลิวินาที (_delay_ms()) ไว้ให้ใช้งาน แต่ต้องมีการเพิ่มเข้ามาในส่วนเริ่มต้นของโปรแกรม
และกำหนดความถี่เริ่มต้นของระบบที่นำมาใช้ ก่อนที่จะเรียกใช้งาน ดังนี้
#define F_CPU 12000000UL //define CPU clock
#include <util/delay.h> //include
delay library
ทั้งนี้
ต้องกำหนดตัวแปร F_CPU
ก่อนเป็นอันดับแรกเพื่อให้ได้ฐานเวลาที่ตรงกับผู้ใช้งานจริง
โดยในที่นี้กำหนดความถี่ที่ใช้เป็น 12MHz
แต่ถ้าผู้เขียนโปรแกรมไม่มีการกำหนดค่าดังกล่าวนี้
ไลบรารีจะกำหนดเองซึ่งจะมีค่าปกติเท่ากับ 1MHz และสามารถเรียกใช้งานได้ดังนี้
เมื่อต้องการหน่วงเวลา 480 ไมโครวินาที
_delay_us(480); // if we want to make 480 us delay
3.2
การเริ่มต้นเชื่อมต่อข้อมูล
สิ่งแรกที่ต้องทำก่อนการรับส่งข้อมูลจำเป็นต้องมีการขั้นตอนการในการเริ่มต้นหรือรีเซตค่าอุปกรณ์เพื่อให้พร้อมสำหรับการรับส่ง
ในขั้นตอนนี้ประกอบไปด้วยรีเซตพัลส์ที่ถูกส่งมาจากตัวไมโครคอนโทรลเลอร์ซึ่งเป็นมาสเตอร์
และตามด้วยพัลส์ตอบสนองจากอุปกรณ์ซึ่งเป็นไอซีตรวจวัดอุณหภูมิ
ดังแสดงตามแผนผังเวลาในรูปที่ 3
รูปที่ 3
แผนผังเวลาสำหรับกระบวนการเริ่มต้นรับส่งข้อมูล
จากรูปที่ 3 พบว่ามาสเตอร์ส่งค่าเพื่อทำให้สายข้อมูลมีค่าเป็นศูนย์เป็นระยะเวลาอย่างน้อย
480 ไมโครวินาที และตามด้วยการคืนค่าสายข้อมูล ถัดจากนั้น 15-60 ไมโครวินาที
ตัวอุปกรณ์ที่เป็นไอซีตรวจวัดอุณหภูมิก็จะทำให้สายข้อมูลมีค่าเป็นศูนย์เป็นเวลา 60-240 ไมโครวินาที ซึ่งเรียกว่าพัลส์ตอบสนอง โดยในส่วนหลังนี้ก็ใช้เวลา 480 ไมโครวินาที เช่นกัน เมื่อใช้ PORTD PIND6 จะสามารถนำมาเขียนเป็นโปรแกรมได้ดังนี้
uint8_t reset()
{
uint8_t i;
PORTD &= ~(1 << PIND6); //Pull line low and
wait for 480 us
DDRD |= (1<<PIND6);
_delay_us(480);
DDRD &= ~(1 << PIND6); //Release line and wait for 60us
_delay_us(60);
i = (PORTD &(1<<PIND6)); //Store line value and wait until the
//completion of 480us period
_delay_us(420);
return i; //Return the value
read from the //presence pulse (0 is OK & 1 is WRONG)
}
3.3 การเขียนและอ่านค่าข้อมูล
ในส่วนนี้เป็นการเขียนฟังก์ชันเพื่อเขียนและอ่านค่าข้อมูลลงบนสายข้อมูลทีละบิตก่อน
จากนั้นจึงเขียนฟังก์ชันเพื่อเขียนและอ่านค่าข้อมูลเป็นไบต์โดยเรียกใช้ฟังก์ชันก่อนหน้า
3.3.1 การอ่านและเขียนค่าทีละบิต
พิจารณาจากแผนผังเวลาในเอกสารอธิบายรายละเอียดอุปกรณ์ดังในรูปที่
4
รูปที่ 4
แผนผังเวลาการอ่านและเขียนข้อมูลแต่ละบิต
ในการเขียนค่า
เริ่มต้นด้วยการเขียนค่าให้สายข้อมูลเป็นลอจิกต่ำและถ้าต้องเขียนค่าเป็นศูนย์ก็ให้คงสถานะลอจิกต่ำไว้นาน
60 ไมโครวินาที แต่ถ้าต้องการเขียนค่าหนึ่ง
ให้คืนสถานะของสายข้อมูลหลังจากเป็นลอจิกต่ำอยู่ 1 ไมโครวินาที
ซึ่งจะได้ฟังก์ชันการเขียนค่าข้อมูลทีละบิตดังนี้
void write_bitdata(uint8_t bitData)
{
PORTD &= ~(1 << PIND6); //Pull
line low for 1 us
DDRD |= (1 << PIND6);
_delay_us(1);
if(bitData) DDRD &= ~(1 << PIND6);
//release the
line if Bit = 0 and //write 1 if Bit = 1
_delay_us(60); //wait for 60 uS and release line
DDRD &= ~(1 << PIND6);
}
ในทางตรงกันข้าม
สำหรับการอ่านค่าข้อมูลจะดูเหมือนคล้ายกันแต่ต่างกันเล็กน้อย
โดยจะเริ่มด้วยการทำให้สายข้อมูลเป็นลอจิกต่ำ 1 ไมโครวินาที
จากนั้นคืนค่าสายข้อมูลและรอเป็นเวลา 14 ไมโครวินาที
ดังแสดงตามแผนผังเวลาในรูปที่ 4
หลังจากนั้นก็สามารถอ่านค่าข้อมูลบนสายข้อมูลได้
โดยจะมีค่าเป็นลอจิกสูงถ้าอุปกรณ์ส่งค่า 1 ออกมา
และจะมีค่าเป็นลอจิกต่ำถ้าอุปกรณ์ส่งค่า 0 ออกมา
ซึ่งจะต้องหน่วงเวลารอ 45 ไมโครวินาที เพื่อให้ครบ 60
ไมโครวินาที ซึ่งจะได้ฟังก์ชันการอ่านค่าข้อมูลทีละบิตดังนี้
uint8_t read_bitdata(void)
{
uint8_t bit = 0;
PORTD &= ~(1 << PIND6); //Pull line
low for 1 us
DDRD |= (1 << PIND6);
_delay_us(1);
DDRD &= ~(1 << PIND6); //release line and wait for 1 us
_delay_us(14);
if (PIND&(1<<PIND6)) bit =1; //read line
value
_delay_us(45); //wait for 45 us and return read value
return bit;
}
3.3.2
การอ่านและเขียนค่าทีละไบต์
เนื่องจากได้สร้างฟังก์ชันเขียนและอ่านค่าทีละบิตไว้แล้ว
การที่จะอ่านค่าเป็นไบต์ก็ทำได้โดยง่ายเพียงวนลูป 8
ครั้งแล้วเขียนค่าออกไป หรืออ่านค่าเข้ามาเก็บไว้ในตัวแปร
ดังแสดงในฟังก์ชันต่อไปนี้
void write_bytedata(uint8_t byte)
{
uint8_t i = 8;
while (i--)
{
write_bitdata(byte &1); //write bit
and shift one position //for next write
byte >>=1;
}
}
uint8_t read_bytedata()
{
uint8_t i = 8, n = 0;
while(i--)
{
n>>=1; //shift one position right and store read
value
n|=(read_bitdata()<<7);
}
return n;
}
3.5 ชุดคำสั่ง
เมื่อสามารถเขียนอ่านข้อมูลได้แล้ว
สิ่งต่อไปที่ควรทราบก็คือ ชุดคำสั่ง
ซึ่งเป็นตัวบ่งชี้ว่าเราต้องการให้อุปกรณ์ตรวจวัดอุณหภูมิของเราทำอะไร
ซึ่งแสดงได้โดยสรุปดังตารางที่ 1
ตารางที่ 1 สรุปรายละเอียดของชุดคำสั่งสำหรับ DS1820
ชุดคำสั่ง
|
รหัสคำสั่ง
|
คำอธิบาย
|
ชุดคำสั่งสำหรับรอม
|
||
Search ROM
|
0xF0
|
สำหรับระบุตัวตนหรือรหัสรอมของ
DS1820 แต่ละตัว เพื่อตรวจสอบจำนวนอุปกรณ์ทั้งหมดที่เชื่อมต่ออยู่กับสายข้อมูล
|
Read ROM
|
0x33
|
มีผลเช่นเดียวกันกับ Search ROM
เพียงแต่สามารถใช้ได้ในกรณีมีอุปกรณ์เพียงตัวเดียวเท่านั้น
ถ้าใช้ในอุปกรณ์เชื่อมต่ออุปกรณ์หลายต่อจะให้ข้อมูลซ้อนทับกัน
|
Match ROM
|
0x55
|
ใช้ร่วมกับรหัสรอม
64 บิต เพื่อระบุว่ามาสเตอร์จะติดต่อกับอุปกรณ์ลูกตัวไหน
โดยที่ตัวรหัสรอมตรงกันเพียงตัวเดียวเท่านั้นในสายข้อมูลที่จะตอบสนองกลับ
ตัวอื่นจะรอกระบวนรีเซต
|
Skip ROM
|
0xCC
|
ใช้ระบุอุปกรณ์ทุกตัวที่เชื่อมต่ออยู่กับสายข้อมูล
ซึ่งใช้ในกรณีต้องการส่งคำสั่งแปลงค่า ในระบบที่มีอุปกรณ์เชื่อมต่อเพียงตัวเดียว
|
Alarm
Search
|
0xEC
|
คล้ายกับ Search ROM เพียงแต่อุปกรณ์จะตอบสนองโดยการเซตค่าแจ้งเตือน
|
ชุดคำสั่งกำหนดหน้าที่
|
||
Convert T
|
0x44
|
คำสั่งแปลงเริ่มแปลงค่าอุณหภูมิ
ซึ่งจะเก็บค่าไว้ที่สองไบต์แรกของ หน่วยความจำ Scratchpad ถ้ามีการอ่านค่าขณะทำการแปลงค่าไม่เสร็จจะทำให้สายข้อมูลมีสถานะเป็นลอจิกต่ำ
และแสดงสถานะเป็นลอจิกสูงถ้ากระบวนการแปลงค่าเสร็จสิ้นแล้ว
|
Write
Scratchpad
|
0x4E
|
มาสเตอร์เขียนค่าไปที่
หน่วยความจำ 3 ตัว คือ TH TL และ หน่วยความจำสำหรับปรับตั้งค่า (Configuration
register)
|
Read
Scratchpad
|
0xBE
|
ทำการอ่านค่าจาก
Scratchpad ซึ่งมีทั้งหมด 9
ไบต์โดยจะให้ค่าบิตนัยสำคัญต่ำสุดออกมาก่อน ซึ่งสามารถรีเซตได้ตลอดเวลา
ถ้าไม่ต้องการอ่านค่าทุกไบต์
|
Copy
Scratchpad
|
0x48
|
คัดลอกหน่วยความจำ
3 ตัว คือ TH TL และ หน่วยความจำสำหรับปรับตั้งค่า (Configuration
register) ไปที่ EEPROM
|
Recall E2
|
0xB8
|
เรียกคืนค่าหน่วยความจำ
3 ตัว คือ TH TL และ หน่วยความจำสำหรับปรับตั้งค่า (Configuration
register) จาก EEPROM
|
Read Power
Supply
|
0xB4
|
สำหรับเป็นตัวบ่งชี้ว่าอุปกรณ์เชื่อมต่อใช้แหล่งจากไฟจากภายนอกหรือใช้แบบพาราสิทเพาเวอร์
ถ้าเป็นแบบพาราสิทเพาเวอร์อุปกรณ์เชื่อมต่อจะทำให้สายข้อมูลมีสถานะเป็นลอจิกต่ำหลังจากใช้คำสั่งแต่ถ้าไม่จะให้สถานะเป็นลอจิกสูง
|
3.6 การอ่านค่าอุณหภูมิ
ข้อมูลแสดงค่าอุณหภูมิของ DS1820 ถูกเก็บอยู่ใน 2 ไบต์แรกของหน่วยความจำ Scratchpad
ซึ่งมีทั้งหมด 9 ไบต์ ประกอบด้วยส่วนต่างๆ
ดังแสดงในรูปที่ 5
รูปที่ 5
แผนที่หน่วยความจำ
Scratchpad ของ DS1820
ข้อมูลอุณหภูมิมีขนาด 16
บิต 2 คอมพลีเมนต์แบบมีเครื่องหมาย ในตารางที่ 1 แสดงความสัมพันธ์ของค่าข้อมูลทั้งสองไบต์กับค่าอุณหภูมิที่วัดได้
โดยข้อมูลจะส่งผ่านสายข้อมูล ซึ่งสามารถวัดอุณหภูมิได้ในช่วง -55 ถึง 125 องศาเซลเซียส ความละเอียด 0.5 องศาเซลเซียส ต่อหนึ่งบิตดิจิตอล (สามารถเพิ่มความละเอียดเป็น
0.25 องศาเซลเซียสได้ รายละเอียดในเอกสารแสดงรายละเอียดของ DS1820)
ตารางที่ 2
ความสัมพันธ์ระหว่างค่าข้อมูลกับค่าอุณหภูมิ
Temperature (oC)
|
Digital Output (Binary)
|
Digital Output (Hex)
|
+125
|
00000000 11111010
|
00FA
|
+25
|
00000000 00110010
|
0032
|
+0.5
|
00000000 00000001
|
0001
|
+0
|
00000000 00000000
|
0000
|
-0.5
|
11111111 11111111
|
FFFF
|
-25
|
11111111 11001110
|
FFCE
|
-50
|
11111111 10010010
|
FF92
|
ดังนั้นในการอ่านค่าอุณหภูมิ สามารถทำได้โดยการตรวจสอบข้อมูลในไบต์สูงว่ามีค่าเป็น
0 หรือ 1 ถ้าเป็น 0
อุณหภูมิที่ได้จะมีค่าเป็นบวกและมีค่าอุณหภูมิเท่ากับค่าของข้อมูลในไบต์ต่ำ (LSB)
คูณด้วย 0.5 แต่ถ้ามีค่าเป็น 1 อุณหภูมิที่ได้จะมีค่าเป็นลบและมีค่าอุณหภูมิเท่ากับ การทำ 2 คอมพลีเมนต์ของข้อมูลในไบต์ต่ำ
4. โปรแกรมอ่านค่าข้อมูลและแสดงผล
ในที่นี้จะกล่าวถึงการอ่านค่าข้อมูลสำหรับการเชื่อมต่อ
DS1820 ในสายข้อมูลเพียง 1 ตัว
โดยมีลำดับการเขียนและอ่านข้อมูล ดังแสดงในตารางที่ 3
ตารางที่ 3
ลำดับการแปลงค่าข้อมูลและการอ่านค่าอุณหภูมิ
Master mode
|
Data (LSB first)
|
รายละเอียด
|
ส่ง
|
รีเซต
|
พัลส์รีเซต
|
รับ
|
ตอบสนอง
|
พัลส์ตอบสนอง
|
ส่ง
|
CCh
|
คำสั่ง Skip ROM
|
ส่ง
|
44h
|
คำสั่งแปลงค่าอุณหภูมิ
|
รับ
|
ข้อมูล 1 ไบต์
|
อ่านค่าข้อมูลเพื่อตรวจสอบว่าการแปลงค่าเรียบร้อยหรือไม่
โดย 0 ยังไม่เสร็จ 1 เสร็จสมบูรณ์
|
ส่ง
|
รีเซต
|
พัลส์รีเซต
|
รับ
|
ตอบสนอง
|
พัลส์ตอบสนอง
|
ส่ง
|
CCh
|
คำสั่ง Skip ROM
|
ส่ง
|
BEh
|
คำสั่งอ่านค่าข้อมูลใน Scratchpad
|
รับ
|
ข้อมูล 9 ไบต์
|
ข้อมูลทั้งหมด
9 ไบต์ ถูกส่งออกมาบนสายข้อมูล
|
ส่ง
|
รีเซต
|
พัลส์รีเซต
|
รับ
|
ตอบสนอง
|
พัลส์ตอบสนอง
เสร็จสิ้นการแปลงและอ่านค่าข้อมูลอุณหภูมิ 1 รอบ
|
-
|
-
|
ไมโครคอนโทรลเลอร์ทำความคำนวณค่าและแสดงผล
|
ซึ่งสามารถเขียนเป็นโปรแกรม
ได้ดังนี้
int main(void)
{
uint8_t buffTemp[2]; //Temperature
buffer for read MSB and LSB
uint16_t buffInt;
USART_Init(12); //Initial
serial port with 57600 baud rate
while(1)
{
reset(); //Reset,
Skip ROM and Start conversion
write_bytedata(0xCC);
write_bytedata(0x44);
while(!read_bitdata()); //Wait until conversion complete
reset(); // Reset, Skip ROM and read Scratchpad
write_bytedata(0xCC);
write_bytedata(0xBE);
buffTemp[0] = read_bytedata(); //Read only 2 first Bytes
buffTemp[1] = read_bytedata();
reset();
buffInt = buffTemp[0] * 5; //Convert
to degree celcius
int2terminal(buffInt); //Display on Terminal window
}
}
โดยเพิ่มส่วนแสดงผลให้สามารถแสดงค่าอุณหภูมิผ่านหน้าจอเทอร์มินอลของส่วนเพิ่มขยายของ Atmel Studio
ดังแสดงในรูปที่ 6
รูปที่ 6 การแสดงค่าอุณหภูมิห้องที่วัดได้ผ่านหน้าจอเทอร์มินอล
5. เอกสารอ้างอิง
[1]
DALLAS, DS1820 1WireTM Digital Thermometer Datasheet,
[2]
Gerard Marull Paretas, Using DS18B20 digital temperature sensor on AVR
microcontrollers,
0 comments:
Post a Comment