2008年11月12日 星期三

DS18B20


/* 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 />

沒有留言: