การทดลองที่ 6 อ่านค่าอุณหภูมิ DS1820

ในการทดลองนี้เราจะมาเรียนรู้การอ่านค่าอุณหภูมิจากไอซี DS1820 ซึ่งเป็นตัวแปลงอุณหภูมิ ให้เป็นค่าดิจิตอล สำหรับการอ่านค่าอุณหภูมิ ใช้สายสัญญาณเพียง 1 เส้น (1-Wire?) เท่านั้น ถ้ารวม VCC, GND เข้าไปด้วยก็จะมีขาใช้งานเพียง 3 ขาเท่านั้น รูปร่างหน้าตาก็จะคล้ายกับทรานซิสเตอร์ตัวถัง TO-92 จริงๆแล้วมันไม่ใช่แค่เซนเซอร์อุณหภูมิเท่านั้น แต่ยังมี LASERED ROM ขนาด 64 บิตโดย DS1820 ในแต่ละตัวจะมีค่า LASERED ROM ไม่ซ้ำกัน ทำให้สามารถต่อ DS1820 (1-Wire?) หลายๆตัวในสายสัญญาณเส้นเดียวกันได้

ย่านการวัดอุณหภูมิจะอยู่ในช่วง -55 C ถึง +125 C

ยังไม่หมดแค่นั้นครับ ยังมี Alarm Triger TH, TL ไว้คอยเตือนเราด้วยว่าอุณหภูิมิเกิด เกิด range ที่เราต้องการควบคุม

รูปที่ 1 ไอซี DS1820

ในการต่อใช้งานจะมีอยู่ 2 วิธีด้วยกัน

1. ใช้ไฟเลี้ยงจาก R Pull-up (PARASITE POWER) วิธีนี้ขา VDD จะต้องต่อลง GND ทำให้ต่อสายเพียง 2 เส้นเท่านั้น

รูปที่ 2 การต่อแบบใช้ไฟเลี้ยง R Pull-up

2. ต่อไฟเลี้ยงให้กับขา VDD (External power supply) วิธีนี้จะเป็นที่นิยมใช้กันมากกว่า

รูปที่ 3 การต่อแบบจ่ายไฟเลี้ยงให้กับขา VDD

ค่าอุณหภูมิที่อ่านได้จาก DS1820 จะมีความละเอียดสเตปละ 0.5 C ขนาด 9 บิต

ตารางที่ 1 ความสัมพันธ์ระหว่างอุณหภูมิกับค่าที่อ่านได้

การทำงานของ Alarm TH, TL

หลังจากที่ DS1820 ได้ทำการแปลงอุณหภูิมิออกมาเป็นตัวเลขแล้ว ค่าอุณหภูมิก็จะถูกนำไปเปรียบเทียบกับ TH, TL ค่าอุณหภูมิมีขนาด 9 บิต ส่วนค่า TH, TL มีขนาด 8 บิต แล้วจะเปรียบเทียบกันยังไงละ? เฉลยครับ มันก็จะตัดบิต LSB ของ DS1820 ทิ้งไปนั่นเอง หลังจากเปรียบเทียบแล้วค่าอุณหภูมิมากกว่า TH หรือน้อยกว่า TL ค่า Alarm Flag ก็จะถูกเซต เมื่อใดก็ตามที่ Alarm Flag ถูกเซตอยู่ มันก็จะแสดงตัวออกมาให้รู้ในช่วงของคำสั่ง Search command เราจึงเข้าไปอ่าน DS1820 ตัวนั้นได้ทันที โดยไม่ต้องไล่อ่าน DS1820 ทีละตัว

ขั้นตอนการสื่อสารกับ DS1820

Initialization (เริ่มต้นสื่อสาร)

เริ่มแรกการสื่อสารด้วย reset pulse โดยตัวมาสเตอร์(ไมโครคอนโทรลเลอร์)จะส่งสัญญาณไปรีเซต DS1820 จากนั้น DS1820 ก็ตอบกลับด้วย present pulse เสมือนเป็นก่อนบอกว่ามัน “พร้อมแล้ว” ถ้าขั้นตอนนี้ DS1820 ไม่ส่ง present pulse กลับมาก็ให้ยกเลิกการสื่อสารได้เลยครับ

ROM FUNCTION COMMANDS (คำสั่งต่างๆ)

หลังจากที่มาสเตอร์ได้รับสัญญาณตอบกลับ (present pulse) เราก็สามารถส่ง command ต่อไปนี้ไปยัง DS1820 ได้

Read ROM[33h]
Command นี้ใช้อ่านค่า 64 บิต (Lasers ROM) แต่ command นี้จะใช้ได้ก็ต่อเมื่อต่อ DS1820 ไว้ตัวเดียวในเท่านั้น ถ้าขืนต่อหลายๆตัวแล้วใช้ command นี้ DS1820 แต่ละตัวก็จะส่งข้อมูลออกมาชนกัน
Match ROM[55h]
Command นี้แล้วตามด้วย 64 บิต (Lasers ROM) เป็นการที่มาสเตอร์ระบุว่าจะให้ DS1820 ตัวไหนทำงาน จะใช้ก็ต่อเมื่อต่อ DS1820 หลายตัวในสายเส้นเดียวกัน
Skip ROM[CCh]
ถ้าเราต่อ DS1820 เพียงตัวเดียวใน BUS เราก็ไม่ต้องระบุ 64 บิต (Lasers ROM) เราสามารถใช้ command นี้เพื่อลดขั้นตอนในการสื่อสาร
Search ROM[F0h]
เมื่อเริ่มทำการ initial ไปแล้วตัวมาสเตอร์อาจจะยังไม่รู้ว่ามี DS1820 อยู่กี่ตัว command Search ROM ทำให้มาสเตอร์สามารถแยกแยะ DS1820 แต่ละตัวได้้
Write Scratchpad[4Eh]
command นี้ใช้ในการเขียนข้อมูลลง DS1820 เริ่มต้นที่ตำแหน่งของ TH register การเขียนจะสิ้นสุดลงเมื่อไหร่ก็ได้ด้วยการส่งสัญญาณรีเซต
Read Scratchpad[48h]
command นี้ใช้ในการ copy ข้อมูล scratchpad ไปยัง EE memory
Convert T[44h]
เป็น command ที่ใช้ในการเริ่มต้นแปลงค่าอุณหภูมิ
Recall E2[B8h]
command นี้จะอ่านค่า Temperature trigger ที่เก็บไว้ใน EE memory ขึ้นมา
Read Power Supply [B4h]
หลังจากส่ง command นี้ไปแล้ว DS1820 จะส่ง สัญญาณกลับมา ส่ง 0 = parasite power, ส่ง 1 = external power supply

คลิกที่ภาพเพื่อดูขนาดใหญ่

รูปที่ 4 Timming การรีเซต และการตอบกลับ(Presence Pulse) ของ DS1820

unsigned char tempresbit()
{
DQ = 0; ??????????//Bit = 0
delay_600us();

DQ = 1; ??????????//Input
delay_60us();

if (DQ)
return 0;

delay_600us(); ???//Delay 480 uSes minimum
return 1;
}

การเขียนโปรแกรมในส่วนของการรีเซต เริ่มจากให้ DQ = 0 (ดูสัญญาณเส้นสีเขียวประกอบ) แล้วหน่วงเวลาประมาณ 600 uS จึงดึงสัญญาณให้ DQ = 1 ถ้าเป็นไมโครคอนโทรลเลอร์ตระกูล PIC, AVR ต้องกำหนดให้ขาทำงานเป็นอินพุตด้วย ไม่งั้น DS1820 จะไม่สามารถึุงสัญญาณลง 0 ได้ ใน datasheet บอกว่า DS1820 จะปล่อย presence pulse ออกมาในช่วง 60-240 uS ก็เลยหน่วงเวลาไป 60 uS แล้วเช็ค DQ ว่าเป็น 0 หรือยัง(ดูสัญญาณเส้นสีแดงประกอบ) ถ้ายังเป็น 1 อยู่แสดงว่าไม่สามารถติดต่อ DS1820 ได้

* สิ่งสำคัญของการสื่อสารแบบ 1 Wire คือ Time slot ต้องมีค่าเปะๆ ตรงช่วง delay ต่างๆควรจะใช้ timer มาจับเวลา หรือใช้คำสั่ง _nop_() จะช่วยให้คำนวณ delay ได้แม่นยำ

คลิกที่ภาพเพื่อดูขนาดใหญ่

รูปที่ 5 Timming การเขียนข้อมูลจากมาสเตอร์ไปยัง DS1820

//————————————————————
//Write DS1820
//————————————————————

void tempwrbyte (unsigned char dat)
{
unsigned char i;

for (i = 0;i < 8;i++){
DQ = 0; //Bit = 0

_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); ?????????????????????????//Delay 15 uSec

if (dat & 0×01)
DQ = 1;
else
DQ = 0;

delay_60us(); ?????????????????????????????//Delay 60 uSEC
DQ = 1;
dat >>= 1;

_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); //Delay 10 uSEC
}

}

หลังจากที่ได้รับ presence pulse จาก DS1820 ที่นี้เรามาดู Timing การเขียนข้อมูลไปยัง DS1820 กันนะครับ เริ่มแรกเลยเราดึงสัญญาณให้เป็น 0 ประมาณ 15 uS จากนั้นก็ส่ง logic ที่ต้องการออกมา ในช่วงหลังจากนี้ ภายใน 45 uS DS1820 จะเข้ามาอ่านสัญญาณ ผมเลย delay 60 uS (จริงๆจะ 45 uS เป๊ะๆก็ได้นะ) เพื่อไม่เห็นการทำงานเร็วเกินไปจึงมีการ delay ที่ช่วงเป็น logic มีการเปลี่ยนแปลง

คลิกที่ภาพเพื่อดูขนาดใหญ่

รูปที่ 6 Timming การอ่านข้อมูล

//————————————————————
//Read DS1820
//————————————————————
unsigned char temprdbyte (void){
unsigned char dat,i;

for (i = 0;i < 8;i++)
{
dat >>= 1;
DQ = 0; //Bit = 0

_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); //Delay 15 uSec

DQ = 1;
if (DQ)
dat |= 0×80; //Input = 1
else
dat &= 0x7f; //Input = 0;

delay_30us(); //Delay 60 uSEC
_nop_(); _nop_();

}
return dat;
}

สำหรับการอ่านข้อมูลก็ไม่ยากครับ เราก็ดึง DQ ลง 0 แล้วก็ปิดตานับเลขในใจไป 15 uS พอลืมตาขึ้นมามองเห็น DQ เป็น logic อะไรก็นำไปเก็บไว้ แล้วก็เอาข้อมูล 8 บิตมาเรียงกันก็จะได้ค่าออกมา

//————————————————————
//Read Temperature DS1820
//————————————————————

unsigned int rdtemp(void)
{
unsigned int dat;

if (tempresbit()){
tempwrbyte(0xcc); //Skip ROM
tempwrbyte(0×44); //Temperature Convert
dmsec(500);
tempresbit();
tempwrbyte(0xcc); //Skip ROM
tempwrbyte(0xbe); //Read scratchpad

dat = temprdbyte()*5;
return dat;
}

return 0;
}

มาถึงขั้นตอนสุดท้าย คือการอ่านค่าอุณหภูมิ จากตารางที่ 1 จะเห็นว่าข้อมูลจะมีขนาด 2 ไบต์โดยไบต์แรกจะเป็นอุณหภูมิที่อ่านได้ อีกไบต์นึงจะเป็นเครื่องหมาย เราจึงอ่านข้อมูลมาไบต์เดียวก็ได้ อุณหภูมิที่แท้จริงที่ได้จากฟังก์ชัน temprdbyte() จะต้องถูกหารด้วย 2 (เพราะ Step ละ 0.5 C) จึงจะเป็นอุณหภูมิที่แท้จริง เพื่อเป็นการเลี่ยงไม่ให้เกิดทศนิยมผมจึงเอาไปคูณด้วย 5 แทน จากนั้นจึงตัดเอาตัวเลขในแต่ละหลักไปแสดงผลที่ LCD

รูปที่ 7 วงจรที่ใช้ในการทดลอง

รูปที่ 8 การทดลอง

บทสรุป

สำหรับผมแล้วนะ DS1820 มีจุดเด่นตรงเรื่องขนาดเราสามารถ wire สายจากบอร์ดเพียง 2 หรือ 3 เส้นลากสายได้ยาวเกือบเมตร(จากการใช้งานจริง) แถมยังต่อขนานพ่วงกันได้หลายตัว ทำให้สามารถวัดอุณหภูมิได้หลายๆตำแหน่ง แต่ข้อเสียก็คือ 1-Wire เป็นการสื่อสารแบบ Time Stot คือเวลาต้องเปะๆ ระหว่างการอ่าน/เขียน ไม่สามารถกระโดดไปอินเตอร์รัพได้เลย ต่างจากพวก SPI, I2C ซึ่งระหว่างสื่อสารสามารถกระโดดไปอินเตอร์รัพและกลับมาอ่าน/เขียน บิตที่ยังค้างอยู่ได้ และไมโครคอนโทรลเลอร์บางตระกูลก็มีโมดูล SPI, I2C อยู่ในตัวเลยจึงทำให้การสื่อสารแบบ SPI, I2C ง่ายและยืดหยุ่นกว่า

Download Code การทดลองที่ 6