/* ds18B20_test<br /><br /> Test utility to configure resolution and read temp from the Dallas Semi 18B20 <br /> one-wire digital temp sensor.<br /> <br /> datasheet: http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf<br /><br /> Derived from sample code at http://www.arduino.cc/playground/Learning/OneWire<br /><br />*/<br /><br />#include <OneWire.h><br /><br />#define BAUDRATE 9600<br />#define TEMPSENSOR 3 // arduino i/o port connected to the ds18B20<br />//#define DEBUG // uncomment for verbose output<br /><br />/* some defines to make more legible checks into data read from the device <br /> * (see the DS18B20 datasheet for more detail)<br /> */ <br />#define TEMP_LSB 0<br />#define TEMP_MSB 1<br />#define TH_REG 2<br />#define USERBYTE_1 2<br />#define TL_REG 3<br />#define USERBYTE_2 3<br />#define CONFIG_REG 4<br />#define CRC 8<br /><br />OneWire ds(TEMPSENSOR); <br /><br />void setup() {<br /> Serial.begin(BAUDRATE);<br />}<br /><br />/* convert celsius to fahrenheit<br /> *<br /> * takes: float<br /> * returns: float<br /> */<br />float c2f(float cel) {<br /> return (cel * (9.0/5.0)) + (float)32;<br />}<br /><br />/* read temp from DS18B20 sensor using one-wire protocol */<br />void loop() {<br /><br /> byte i;<br /> byte present = 0;<br /> byte data[12];<br /> byte addr[8];<br /><br /> int temp_c_int;<br /> float temp_c_frac;<br /> float temp_c;<br /> float temp_f;<br /> int test_bit;<br /> int set_bit;<br /> int resolution_floor;<br /> float expon;<br /> <br /> if ( !ds.search(addr)) {<br /> ds.reset_search();<br /> return;<br /> }<br /><br /> /* print the address - might be useful for non-debug mode if you have<br /> * >1 devices on the bus<br /> */<br />#ifdef DEBUG<br /> Serial.print("R=");<br /> for( i = 0; i < 8; i++) {<br /> Serial.print(addr[i], HEX);<br /> Serial.print(" ");<br /> }<br />#endif<br /><br /> if ( OneWire::crc8( addr, 7) != addr[7]) {<br /> Serial.print("CRC is not valid!\n");<br /> return;<br /> }<br /><br /> if ( addr[0] != 0x28) {<br /> Serial.print("Device is not a DS18B20 family device.\n");<br /> return;<br /> }<br /><br /> /* modify scratchpad register to set temp sampling resolution */<br /> ds.reset();<br /> ds.select(addr); <br /> ds.write(0x4E); // write scratchpad (starts at byte 2)<br /> // note: set high/low temp alarms by changing the next two values <br /> ds.write(0x4B); // default value of TH reg (user byte 1)<br /> ds.write(0x46); // default value of TL reg (user byte 2)<br /> // uncomment one of the following<br /> //ds.write(0x7F); // 12-bit sampling resolution (default)<br /> //ds.write(0x5F); // 11-bit<br /> //ds.write(0x3F); // 10-bit<br /> ds.write(0x1F); // 9-bit<br /><br /> ds.reset();<br /> ds.select(addr);<br /> ds.write(0x44,1); // start conversion, with parasite power on at the end<br /><br /> delay(1000); // maybe 750ms is enough, maybe not<br /> // we might do a ds.depower() here, but the reset will take care of it.<br /><br /> present = ds.reset();<br /> ds.select(addr); <br /> ds.write(0xBE); // Read Scratchpad<br /><br /> if (!present) {<br /> Serial.print("ERROR: selected device not present\n");<br /> return;<br /> }<br /> <br /> for ( i = 0; i < 9; i++) { // we need 9 bytes<br /> data[i] = ds.read();<br />#ifdef DEBUG<br /> Serial.print(data[i], HEX);<br /> Serial.print(" ");<br />#endif<br /> }<br /><br /> if (data[8] != OneWire::crc8(data,8)) {<br /> Serial.print("ERROR: CRC didn't match\n");<br /> return;<br /> }<br /> <br /> /* print raw bytes from which we'll extract temp data */<br />#ifdef DEBUG <br /> Serial.print("[MSB:");<br /> Serial.print(data[TEMP_MSB],BIN);<br /> Serial.print(" LSB:");<br /> Serial.print(data[TEMP_LSB],BIN);<br /> Serial.print("] ");<br />#endif<br /> <br /> /* compute the degrees in celcius / integer part */<br /> temp_c_int = 0;<br /> <br /> /* The measured temp is spread across two bytes of the returned data.<br /> * The integer part of the temp value is spread across the least 3 significant<br /> * bits of the most significant byte (MSB) and the most significant 4 of <br /> * the LSB. Here we shift those 7 bits into their proper place in our<br /> * result byte. <br /> *<br /> * note: could do this with 2 bit-shift / mask operations, alternatively<br /> */<br /> set_bit = 6;<br /> for (test_bit = 2; test_bit >= 0; test_bit--) {<br /> temp_c_int |= ( ((data[TEMP_MSB] & (1 << test_bit)) >> test_bit) << set_bit );<br /> set_bit--;<br /> }<br /> for (test_bit = 7; test_bit >= 4; test_bit--) {<br /> temp_c_int |= ( ((data[TEMP_LSB] & (1 << test_bit)) >> test_bit) << set_bit );<br /> set_bit--;<br /> }<br /><br />#ifdef DEBUG<br /> Serial.print(temp_c_int,DEC);<br />#endif<br /><br /> /* compute the fractional part */<br /><br /> /* first figure out what resolution we're measuring in - varies between 1 and 4 bits<br /> * after the decimal (based on the contents of the CONFIG_REG byte):<br /> * bit 6 == 0 && bit 5 == 0 --> 9-bit resolution (ignore 3 least sig bits)<br /> * bit 6 == 0 && bit 5 == 1 --> 10-bit resolution (ignore 2 least sig bits)<br /> * bit 6 == 1 && bit 5 == 0 --> 11-bit resolution (ignore 1 least sig bits)<br /> * bit 6 == 1 && bit 5 == 1 --> 12-bit resolution <br /> */<br /> if ((data[CONFIG_REG] & (1 << 5)) > 0) { <br /> if ((data[CONFIG_REG] & (1 << 4)) > 0) { // bits 6 and 5 are set<br /> resolution_floor = 0;<br /> } else { // bit 6 is set, 5 is clear<br /> resolution_floor = 1;<br /> }<br /> } else {<br /> if ((data[CONFIG_REG] & (1 << 4)) > 0) { // bits 6 is clear, 5 is set<br /> resolution_floor = 2;<br /> } else { // bit 6 and 5 are clear<br /> resolution_floor = 3;<br /> }<br /> } <br /><br /> temp_c_frac = 0;<br /> for (test_bit = 3; test_bit >= resolution_floor; test_bit--) {<br /> if ((data[TEMP_LSB] & (1 << test_bit)) > 0) {<br /> expon = test_bit - 4; // will be negative<br /> temp_c_frac += pow(2,expon);<br /> }<br /> }<br />#ifdef DEBUG<br /> Serial.print(" ");<br /> Serial.print(temp_c_frac * 10000,DEC);<br />#endif<br /><br /> /* put it all together */<br /> temp_c = (float)temp_c_int + temp_c_frac; <br /><br /> if ((data[TEMP_MSB] & (1 << 7)) > 0) { // the temp is negative<br /> temp_c *= -1;<br /> }<br /><br /> temp_f = c2f(temp_c);<br /> <br /> Serial.print(" Cx10k=");<br /> Serial.print(temp_c * 10000,DEC); // Serial.print truncates after the decimal pt<br /> Serial.print(" Fx10k=");<br /> Serial.print(temp_f * 10000,DEC);<br /> <br /> Serial.print("\n"); <br />}<br />
2008年11月12日 星期三
DS18B20
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言