Simple cpp wrapper of a ds18b20, onewire 'c' library. Supports multiple sensors.

Dependencies:   mbed

Dependents:   LPC11U68_DS18B20Sensor

Fork of DS18B20Sensor by Steve Spence

Committer:
Bongjun
Date:
Fri Jul 04 00:08:44 2014 +0000
Revision:
5:0bcc4e42fec0
Parent:
0:1449f126b241
added comments

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jsteve 0:1449f126b241 1 /**
jsteve 0:1449f126b241 2 * @file DS18x20.c
jsteve 0:1449f126b241 3 * @brief library of DS18X20 1-Wire digital thermometer (http://www.maxim-ic.com/datasheet/index.mvp/id/2812)
jsteve 0:1449f126b241 4 * @author Maciej Rajtar (Published 10 May 2010 www.mbed.org)
jsteve 0:1449f126b241 5 * @author Frederic BLANC
jsteve 0:1449f126b241 6 */
jsteve 0:1449f126b241 7 #include "mbed.h"
jsteve 0:1449f126b241 8 #include "onewire.h"
jsteve 0:1449f126b241 9 #include "DS18X20.h"
jsteve 0:1449f126b241 10 #include "crc8.h"
jsteve 0:1449f126b241 11 /**
jsteve 0:1449f126b241 12 * @brief get power status of DS18x20
jsteve 0:1449f126b241 13 * @param [in] uint8_t id[] = rom_code
jsteve 0:1449f126b241 14 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE
jsteve 0:1449f126b241 15 * @date 20/06/2011
jsteve 0:1449f126b241 16 */
jsteve 0:1449f126b241 17 uint8_t DS18X20_get_power_status(uint8_t id[]) {
jsteve 0:1449f126b241 18 uint8_t pstat;
jsteve 0:1449f126b241 19 ow_reset();
jsteve 0:1449f126b241 20 ow_command(DS18X20_READ_POWER_SUPPLY, id);
jsteve 0:1449f126b241 21 pstat=ow_bit_io(1); // pstat 0=is parasite/ !=0 ext. powered
jsteve 0:1449f126b241 22 ow_reset();
jsteve 0:1449f126b241 23 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE;
jsteve 0:1449f126b241 24 }
jsteve 0:1449f126b241 25
jsteve 0:1449f126b241 26
jsteve 0:1449f126b241 27
jsteve 0:1449f126b241 28 /**
jsteve 0:1449f126b241 29 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL
jsteve 0:1449f126b241 30 or for single sensor. then id is the rom-code
jsteve 0:1449f126b241 31 * @param [in] uint8_t with_power_extern
jsteve 0:1449f126b241 32 * @param [in] uint8_t id[] = rom_code
jsteve 0:1449f126b241 33 * @return DS18X20_OK or DS18X20_START_FAIL
jsteve 0:1449f126b241 34 * @date 20/06/2011
jsteve 0:1449f126b241 35 */
jsteve 0:1449f126b241 36 uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[]) {
jsteve 0:1449f126b241 37 ow_reset(); //**
jsteve 0:1449f126b241 38 if ( ow_test_pin() ) { // only send if bus is "idle" = high
jsteve 0:1449f126b241 39 ow_command( DS18X20_CONVERT_T, id );
jsteve 0:1449f126b241 40 if (with_power_extern != DS18X20_POWER_EXTERN)
jsteve 0:1449f126b241 41 ow_parasite_enable();
jsteve 0:1449f126b241 42 return DS18X20_OK;
jsteve 0:1449f126b241 43 }
jsteve 0:1449f126b241 44 return DS18X20_START_FAIL;
jsteve 0:1449f126b241 45
jsteve 0:1449f126b241 46 }
jsteve 0:1449f126b241 47
jsteve 0:1449f126b241 48 /**
jsteve 0:1449f126b241 49 * @brief reads temperature (scratchpad) of sensor with rom-code id
jsteve 0:1449f126b241 50 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac
jsteve 0:1449f126b241 51 in millicelsius*0.1
jsteve 0:1449f126b241 52 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000&#65533;C
jsteve 0:1449f126b241 53 * @param [in] id[] = rom_code
jsteve 0:1449f126b241 54 * @param [out] subzero
jsteve 0:1449f126b241 55 * @param [out] cel
jsteve 0:1449f126b241 56 * @param [out] cel_frac_bits
jsteve 0:1449f126b241 57 * @return DS18X20_OK or DS18X20_ERROR_CRC
jsteve 0:1449f126b241 58 * @date 20/06/2011
jsteve 0:1449f126b241 59 */
jsteve 0:1449f126b241 60 uint8_t DS18X20_read_meas(uint8_t id[], uint8_t *subzero,
jsteve 0:1449f126b241 61 uint8_t *cel, uint8_t *cel_frac_bits) {
jsteve 0:1449f126b241 62 uint8_t i;
jsteve 0:1449f126b241 63 uint8_t sp[DS18X20_SP_SIZE];
jsteve 0:1449f126b241 64
jsteve 0:1449f126b241 65 ow_reset();
jsteve 0:1449f126b241 66 ow_command(DS18X20_READ, id);
jsteve 0:1449f126b241 67 for ( i=0 ; i< DS18X20_SP_SIZE; i++ )
jsteve 0:1449f126b241 68 sp[i]=ow_byte_rd();
jsteve 0:1449f126b241 69 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){
jsteve 0:1449f126b241 70 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF))
jsteve 0:1449f126b241 71 return OW_ERROR; // bus error
jsteve 0:1449f126b241 72 return DS18X20_ERROR_CRC; // data error
jsteve 0:1449f126b241 73 }
jsteve 0:1449f126b241 74
jsteve 0:1449f126b241 75 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits);
jsteve 0:1449f126b241 76 return DS18X20_OK;
jsteve 0:1449f126b241 77 }
jsteve 0:1449f126b241 78
jsteve 0:1449f126b241 79 /**
jsteve 0:1449f126b241 80 * @brief convert raw value from DS18x20 to Celsius
jsteve 0:1449f126b241 81 input is:
jsteve 0:1449f126b241 82 - familycode fc (0x10/0x28 see header)
jsteve 0:1449f126b241 83 - scratchpad-buffer
jsteve 0:1449f126b241 84 output is:
jsteve 0:1449f126b241 85 - cel full celsius
jsteve 0:1449f126b241 86 - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits)
jsteve 0:1449f126b241 87 - subzero =0 positiv / 1 negativ
jsteve 0:1449f126b241 88 always returns DS18X20_OK
jsteve 0:1449f126b241 89 TODO invalid-values detection (but should be covered by CRC)
jsteve 0:1449f126b241 90 * @param [in] fc
jsteve 0:1449f126b241 91 * @param [in] sp
jsteve 0:1449f126b241 92 * @param [out] subzero
jsteve 0:1449f126b241 93 * @param [out] cel
jsteve 0:1449f126b241 94 * @param [out] cel_frac_bits
jsteve 0:1449f126b241 95 * @return DS18X20_OK
jsteve 0:1449f126b241 96 * @date 20/06/2011
jsteve 0:1449f126b241 97 */
jsteve 0:1449f126b241 98 uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp,
jsteve 0:1449f126b241 99 uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits) {
jsteve 0:1449f126b241 100 uint16_t meas;
jsteve 0:1449f126b241 101 uint8_t i;
jsteve 0:1449f126b241 102
jsteve 0:1449f126b241 103 meas = sp[0]; // LSB
jsteve 0:1449f126b241 104 meas |= ((uint16_t)sp[1])<<8; // MSB
jsteve 0:1449f126b241 105 //meas = 0xff5e; meas = 0xfe6f;
jsteve 0:1449f126b241 106
jsteve 0:1449f126b241 107 // only work on 12bit-base
jsteve 0:1449f126b241 108 if ( fc == DS18S20_ID ) { // 9 -> 12 bit if 18S20
jsteve 0:1449f126b241 109 /* Extended measurements for DS18S20 contributed by Carsten Foss */
jsteve 0:1449f126b241 110 meas &= (uint16_t) 0xfffe; // Discard LSB , needed for later extended precicion calc
jsteve 0:1449f126b241 111 meas <<= 3; // Convert to 12-bit , now degrees are in 1/16 degrees units
jsteve 0:1449f126b241 112 meas += (16 - sp[6]) - 4; // Add the compensation , and remember to subtract 0.25 degree (4/16)
jsteve 0:1449f126b241 113 }
jsteve 0:1449f126b241 114
jsteve 0:1449f126b241 115 // check for negative
jsteve 0:1449f126b241 116 if ( meas & 0x8000 ) {
jsteve 0:1449f126b241 117 *subzero=1; // mark negative
jsteve 0:1449f126b241 118 meas ^= 0xffff; // convert to positive => (twos complement)++
jsteve 0:1449f126b241 119 meas++;
jsteve 0:1449f126b241 120 } else *subzero=0;
jsteve 0:1449f126b241 121
jsteve 0:1449f126b241 122 // clear undefined bits for B != 12bit
jsteve 0:1449f126b241 123 if ( fc == DS18B20_ID ) { // check resolution 18B20
jsteve 0:1449f126b241 124 i = sp[DS18B20_CONF_REG];
jsteve 0:1449f126b241 125 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) ;
jsteve 0:1449f126b241 126 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT )
jsteve 0:1449f126b241 127 meas &= ~(DS18B20_11_BIT_UNDF);
jsteve 0:1449f126b241 128 else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT )
jsteve 0:1449f126b241 129 meas &= ~(DS18B20_10_BIT_UNDF);
jsteve 0:1449f126b241 130 else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) {
jsteve 0:1449f126b241 131 meas &= ~(DS18B20_9_BIT_UNDF);
jsteve 0:1449f126b241 132 }
jsteve 0:1449f126b241 133 }
jsteve 0:1449f126b241 134
jsteve 0:1449f126b241 135 *cel = (uint8_t)(meas >> 4);
jsteve 0:1449f126b241 136 *cel_frac_bits = (uint8_t)(meas & 0x000F);
jsteve 0:1449f126b241 137
jsteve 0:1449f126b241 138 return DS18X20_OK;
jsteve 0:1449f126b241 139 }
jsteve 0:1449f126b241 140
jsteve 0:1449f126b241 141 /**
jsteve 0:1449f126b241 142 * @brief converts to decicelsius
jsteve 0:1449f126b241 143 input is ouput from meas_to_cel
jsteve 0:1449f126b241 144 i.e.: sz=0, c=28, frac=15 returns 289 (=28.9&#65533;C)
jsteve 0:1449f126b241 145 0 0 0
jsteve 0:1449f126b241 146 1 625 625 1
jsteve 0:1449f126b241 147 2 1250 250
jsteve 0:1449f126b241 148 3 1875 875 3
jsteve 0:1449f126b241 149 4 2500 500 4
jsteve 0:1449f126b241 150 5 3125 125
jsteve 0:1449f126b241 151 6 3750 750 6
jsteve 0:1449f126b241 152 7 4375 375
jsteve 0:1449f126b241 153 8 5000 0
jsteve 0:1449f126b241 154 9 5625 625 9
jsteve 0:1449f126b241 155 10 6250 250
jsteve 0:1449f126b241 156 11 6875 875 11
jsteve 0:1449f126b241 157 12 7500 500 12
jsteve 0:1449f126b241 158 13 8125 125
jsteve 0:1449f126b241 159 14 8750 750 14
jsteve 0:1449f126b241 160 15 9375 375
jsteve 0:1449f126b241 161 * @param [in] subzero
jsteve 0:1449f126b241 162 * @param [in] cel
jsteve 0:1449f126b241 163 * @param [in] cel_frac_bits
jsteve 0:1449f126b241 164 * @return absolute value of temperatur in decicelsius
jsteve 0:1449f126b241 165 * @date 20/06/2011
jsteve 0:1449f126b241 166 */
jsteve 0:1449f126b241 167 uint16_t DS18X20_temp_to_decicel(uint8_t subzero, uint8_t cel,
jsteve 0:1449f126b241 168 uint8_t cel_frac_bits) {
jsteve 0:1449f126b241 169 uint16_t h;
jsteve 0:1449f126b241 170 uint8_t i;
jsteve 0:1449f126b241 171 uint8_t need_rounding[] = { 1, 3, 4, 6, 9, 11, 12, 14 };
jsteve 0:1449f126b241 172
jsteve 0:1449f126b241 173 h = cel_frac_bits*DS18X20_FRACCONV/1000;
jsteve 0:1449f126b241 174 h += cel*10;
jsteve 0:1449f126b241 175 if (!subzero) {
jsteve 0:1449f126b241 176 for (i=0; i<sizeof(need_rounding); i++) {
jsteve 0:1449f126b241 177 if ( cel_frac_bits == need_rounding[i] ) {
jsteve 0:1449f126b241 178 h++;
jsteve 0:1449f126b241 179 break;
jsteve 0:1449f126b241 180 }
jsteve 0:1449f126b241 181 }
jsteve 0:1449f126b241 182 }
jsteve 0:1449f126b241 183 return h;
jsteve 0:1449f126b241 184 }
jsteve 0:1449f126b241 185 /**
jsteve 0:1449f126b241 186 * @brief compare temperature values (full celsius only)
jsteve 0:1449f126b241 187 * @param [in] subzero1
jsteve 0:1449f126b241 188 * @param [in] cel1
jsteve 0:1449f126b241 189 * @param [in] subzero2
jsteve 0:1449f126b241 190 * @param [in] cel2
jsteve 0:1449f126b241 191 * @return -1 if param-pair1 < param-pair2
jsteve 0:1449f126b241 192 0 if ==
jsteve 0:1449f126b241 193 1 if >
jsteve 0:1449f126b241 194 * @date 20/06/2011
jsteve 0:1449f126b241 195 */
jsteve 0:1449f126b241 196 int8_t DS18X20_temp_cmp(uint8_t subzero1, uint16_t cel1,
jsteve 0:1449f126b241 197 uint8_t subzero2, uint16_t cel2) {
jsteve 0:1449f126b241 198 int16_t t1 = (subzero1) ? (cel1*(-1)) : (cel1);
jsteve 0:1449f126b241 199 int16_t t2 = (subzero2) ? (cel2*(-1)) : (cel2);
jsteve 0:1449f126b241 200
jsteve 0:1449f126b241 201 if (t1<t2) return -1;
jsteve 0:1449f126b241 202 if (t1>t2) return 1;
jsteve 0:1449f126b241 203 return 0;
jsteve 0:1449f126b241 204 }