การวัดอุณหภูมิด้วยไอซี DS18B20 Digital Thermometer
ไอซีวัดอุณหภูมิในตระกูล DS18xx มีอยู่หลายรุ่น เช่น DS1820, DS18S20 และ DS18B20
เป็นไอซีที่วัดอุณหภูมิและให้ค่าแบบดิจิทัล เชื่อมต่อในรูปแบบของบัสที่เรียกว่า 1-Wire
ไอซีเหล่านี้มีความแตกต่างกันเล็กน้อย แต่ในบทความนี้จะกล่าวถึงเฉพาะ DS18B20
ในปัจจุบัน มีไอซีสำหรับวัดอุณหภูมิให้เลือกใช้อยู่หลายแบบ แบ่งตามรูปแบบของเอาต์พุตได้
เป็นสองประเภทคือ ไอซีที่ให้เอาต์พุตแบบแอนะล็อก และแบบดิจิทัล โดยทั่วไปไอซีแบบดิจิทัล จะมีวงจรประเภท ADC (Analog to Digital Converter) รวมอยู่ภายใน บางตระกูลหรือบางรุ่น สามารถโปรแกรมหรืออ่านค่ารีจิสเตอร์ภายในได้ เช่น เพื่อกำหนดค่าที่เกี่ยวข้องกับการทำงาน ของไอซี ในส่วนการเชื่อมต่อกับไมโครคอนโทรลเลอร์ มักจะเป็นการสื่อสารข้อมูลแบบ SPI หรือ I2C เพื่อประหยัดขา I/O ในการเชื่อมต่อ บทความนี้กล่าวถึง การใช้งานไอซี DS18B20 Digital Thermometer ของบริษัท Maxim และเขียนโปรแกรมติดต่อสื่อสารด้วย Arduino จุดเด่นของไอซีในตระกูลนี้คือ การสื่อสารข้อมูลด้วย สัญญาณเพียงเส้นเดียว นำอุปกรณ์หรือไอซีมาต่อกันหลายตัวเป็นบัส (Bus) ได้โดยใช้โปรโตคอลสื่อสาร ที่เรียกว่า 1-Wire (OneWire) | ||
ข้อมูลเชิงเทคนิคเกี่ยวกับไอซี DS18B20:
ภายในไอซี DS18B20 มีหน่วยความจำแบบ SRAM ขนาดความจุ 9 ไบต์ (Byte 0 ถึง Byte 9)
และเรียกว่า Scratchpadส่วนหนึ่งของหน่วยความจำนี้ จะใช้สำหรับเก็บค่าอุณหภูมิ ที่ได้จากการอ่านและแปลงเป็นข้อมูลดิจิทัลในแต่ละครั้ง (ใช้ 2 ไบต์ และเก็บไว้ใน Byte 0 และ Byte 1) และยังมีการคำนวณค่า CRC (checksum) ขนาดหนึ่งไบต์ด้วย (เก็บไว้ใน Byte 8)
รูปแสดงอุปกรณ์สำหรับวัดอุณหภูมิ DS18B20 ที่ใช้ในการทดลอง (Waterproof / encapsulated DS18B20 temperature sensor) 3-Wire connector: Black=GND, Yellow=DQ, Red=Vdd | ||
Arduino Sketch
ในการเขียนโปรแกรมสำหรับ Arduino เพื่อเชื่อมต่อกับไอซี DS18B20 สามารถใช้ไลบรารี่ "OneWire.h" ของ Arduino ซึ่งทำให้สะดวกในการเขียนโปรแกรม เช่น เพื่อการค้นหาหลายเลข (64-bit code) ของอุปกรณ์ที่ต่ออยู่กับบัส 1-Wire การสั่งให้ไอซีตามหมายเลขอุปกรณ์อ่านและแปลงค่าอุณหภูมิ จากนั้นเว้นระยะเวลาอย่างน้อย 750msec แล้วจึงอ่านค่าจากหน่วยความจำ Scratchpad ของไอซี
โค้ดตัวอย่างต่อไปนี้ ทำหน้าที่ค้นหาไอซี DS18B20 ที่ต่ออยู่กับบัส 1-Wire ซึ่งในตัวอย่างนี้ ได้ใช้อุปกรณ์ 2 ชุด ขา DQ ของไอซีแต่ละตัว จะนำไปต่อกับขา D2 ของ Arduino และที่ขานี้จะต้องต่อ 4.7kΩ แบบ pull-up กับ +5V อยู่ด้วย ข้อมูลที่ได้จากอุปกรณ์วัดอุณหภูมิทั้งสองชุด จะปรากฏเป็นข้อความที่ถูกส่งผ่านทาง Serial (Baudrate 115200)
Sourcecode: ds18b20_demo.ino ///////////////////////////////////////////////////////////////////////////////
// Author: RSP @ Embedded System Lab (ESL), KMUTNB, Thailand
// Date: 2014-May-12
// Board: Arduino with ATmega168/328P (5V/16MHz)
// Arduino IDE: version 1.0.5
// Description:
// This Arduino Sketch shows how to read temperature values from
// two DS18B20 digital thermometers connected to the same bus (1-wire).
///////////////////////////////////////////////////////////////////////////////
#include <OneWire.h> // Use the Arduino "OneWire" library.
#define DS18S20_ID (0x10) // The byte code for the DS18S20 device family.
#define DS18B20_ID (0x28) // The byte code for the DS18B20 device family.
#define DQ_PIN (2) // Use Arduino D2 pin for I/O (connected to the DQ pin).
OneWire ds( DQ_PIN ); // Create a OneWire object.
#define NUM_DEVICES (2) // Specify the number of DS18B20 devices to be used.
byte ds_addr[NUM_DEVICES][8]; // used to stored 8-byte device addresses (for two devices)
char sbuf[20]; // used for sprintf()
// 'buf' must be an array of at least 8 bytes.
boolean ds_addr_search( byte *buf ) { // Perform a DS18xx device search
if ( ds.search(buf) == 1 ) { // ok
if ( OneWire::crc8( buf, 7 ) == buf[7] ) { // check the CRC byte
return true; // CRC is valid
}
} else {
ds.reset_search();
}
return false;
}
void ds_devices_scan() { // Scan devices on the 1-Wire bus
for ( uint8_t dev=0; dev < NUM_DEVICES; dev++ ) {
uint8_t *addr = ds_addr[dev];
memset( addr, 0x00, 8 );
if ( ds_addr_search( addr ) ) {
for (uint8_t i=0; i < 8; i++) {
sprintf( sbuf+3*i, "%02X ", addr[i] );
}
Serial.print( "Address found: " );
Serial.print( sbuf );
sprintf( sbuf, "(Device %d)", dev );
Serial.println( sbuf );
if ( addr[0] == DS18B20_ID ) {
Serial.println( "This device is DS18B20." );
}
else if ( addr[0] == DS18S20_ID ) {
Serial.println( "This device is DS18S20." );
}
else {
Serial.println( "Unrecognized device family!" );
}
}
}
}
void setup(void) {
Serial.begin(115200);
ds_devices_scan();
}
boolean ds_read_temp( byte *addr, int16_t *temp ) {
static byte data[9];
ds.reset();
ds.select( addr );
ds.write( 0x44, 1 ); // initiates a temperature conversion, enable pull-up on the 1-Wire bus
delay( 800 ); // wait for at least 750ms for 12-bit ADC conversion time
ds.reset();
ds.select( addr );
ds.write( 0xBE ); // read Scratchpad
for ( byte i=0; i < 9; i++ ) { // read 9 bytes in total
data[i] = ds.read();
}
if ( OneWire::crc8( data, 8) == data[8] ) { // CRC is ok.
int16_t t = data[1];
t = (t << 8) + data[0];
*temp = (t*10)/16; // for DS18B20, use 0.0625 = 1/16 deg per bit
return true;
}
return false;
}
void loop(void) {
static int16_t temp;
for ( uint8_t dev=0; dev < NUM_DEVICES; dev++ ) {
if ( ds_addr[dev][0] != DS18B20_ID ) continue;
if ( ds_read_temp( ds_addr[dev], &temp ) ) {
char pm = (temp < 0) ? '-' : '+';
temp = abs(temp);
sprintf( sbuf, "Device %d: %c%d.%d C", dev, pm, (temp/10), (temp%10) );
Serial.println( sbuf );
} else {
Serial.println( "Read operation failed!" );
}
}
}
/////////////////////////////////////////////////////////////////////////////////
รูปแสดงการวางแผนต่อวงจรบนเบรดบอร์ดด้วย Fritzing วงจรนี้ใช้ไอซี DS18B20 จำนวน 2 ตัว และตัวต้านทาน 4.7kΩ 1 ตัว การต่อไอซีแบบ 3-wire (normal power mode) รูปแสดงการวางแผนต่อวงจรบนเบรดบอร์ดด้วย Fritzing การต่อไอซีแบบ 2-wire (parasite power mode) รูปแสดงฮาร์ดแวร์และการต่อวงจรทดลอง รูปแสดงตัวอย่างข้อความใน Serial Monitor ที่ได้จากการทำงานของ Arduino ตามโค้ดตัวอย่าง เริ่มต้นแสดงอุณหภูมิที่วัดได้จากอุปกรณ์ 2 ชุด วางอยู่ในตำแหน่งเดียวกัน และได้อุณหภูมิที่เท่ากัน รูปแสดงข้อความในการวัดค่าอุณหภูมิจากอุปกรณ์ 2 ชุด แต่วัดอุณหภูมิในที่แตกต่างกัน Device 1 นำไปไว้ใกล้แหล่งความร้อน (ช่องระบายความร้อนของคอมพิวเตอร์ Notebook) ในขณะที่ Device 0 ยังวัดอุณหภูมิที่จุดเดิม |
ไม่มีความคิดเห็น:
แสดงความคิดเห็น