MAX31850, DS18B20, DS2450, thermocouple
Diff: DS18X20.cpp
- Revision:
- 0:5d39f2521173
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/DS18X20.cpp Mon Mar 09 11:55:54 2015 +0000
@@ -0,0 +1,350 @@
+/**
+* @file DS18x20.c
+* @brief library of DS18X20 1-Wire digital thermometer (http://www.maxim-ic.com/datasheet/index.mvp/id/2812)
+* @author Maciej Rajtar (Published 10 May 2010 www.mbed.org)
+* @author Frederic BLANC (Published 01/03/2012 www.mbed.org)
+*/
+#include "mbed.h"
+#include "onewire.h"
+#include "DS18X20.h"
+#include "crc8.h"
+#include "utils.h"
+//**********************************************************************************************************
+//* DS18X20_show_temp
+//**********************************************************************************************************
+
+/**
+* @brief DS18X20_show_temp
+* @param [in] id[] = rom_code
+* @param [in] n number of id[n]
+* @param [out] text temp in degre celsius
+
+* @date 20/06/2011
+*/
+void DS18X20_show_temp(uint8_t subzero, uint8_t cel, uint8_t cel_frac_bits,char *text) {
+ uint16_t decicelsius;
+ char s[10];
+ float temperature;
+ sprintf(text,"");
+ sprintf(s,"%s", (subzero)?"-":"");
+ strcat(text,s);
+ decicelsius = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits);
+ temperature = decicelsius;
+ temperature = temperature/10;
+ sprintf(s,"%4.1f", temperature);
+ strcat(text,s);
+
+}
+/**
+* @brief DS18X20_show_temp
+* @param [in] id[] = rom_code
+* @param [in] n number of id[n]
+* @return temp in degre celsius
+
+* @date 21/10/2011
+*/
+float DS18X20_temp(uint8_t subzero, uint8_t cel, uint8_t cel_frac_bits) {
+ return ((subzero)?-1:1)*DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits)/10;
+}
+//**********************************************************************************************************
+//* DS18X20_get_power_status
+//**********************************************************************************************************
+
+/**
+* @brief get power status of DS18x20
+* @param [in] id[] = rom_code
+* @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE
+* @date 20/06/2011
+*/
+uint8_t DS18X20_get_power_status(uint8_t id[]) {
+ uint8_t pstat;
+ ow_reset();
+ ow_command(DS18X20_READ_POWER_SUPPLY, id);
+ pstat=ow_bit_io(1); // pstat 0=is parasite/ !=0 ext. powered
+ ow_reset();
+ return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE;
+}
+
+/**
+* @brief get power status of DS18x20
+* @param [in] n num bus onewire
+* @param [in] id[] = rom_code
+* @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE
+* @date 6/09/2011
+*/
+uint8_t DS18X20_get_power_status(uint8_t n,uint8_t id[]) {
+ uint8_t pstat;
+ ow_reset(n);
+ ow_command(n,DS18X20_READ_POWER_SUPPLY, id);
+ pstat=ow_bit_io(n,1); // pstat 0=is parasite/ !=0 ext. powered
+ ow_reset(n);
+ return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE;
+}
+//**********************************************************************************************************
+//* DS18X20_start_meas
+//**********************************************************************************************************
+/**
+* @brief reads temperature (scratchpad) of sensor with rom-code id
+ output: subzero==1 if temp.<0, cel: full celsius, mcel: frac
+ in millicelsius*0.1
+ i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C
+* @param [in] n num bus onewire
+* @param [in] id[] = rom_code
+* @param [out] temperature
+* @return DS18X20_OK or DS18X20_ERROR_CRC
+* @date 07/12/2012
+*/
+uint8_t DS18X20_read_meas(uint8_t n,uint8_t id[], float* temperature) {
+ uint8_t i;
+ uint8_t sp[DS18X20_SP_SIZE];
+ uint8_t subzero;
+ uint8_t cel;
+ uint8_t cel_frac_bits;
+
+ ow_reset(n);
+ ow_command(n,DS18X20_READ, id);
+ for ( i=0 ; i< DS18X20_SP_SIZE; i++ )
+ sp[i]=ow_byte_rd(n);
+ if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){
+ if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF))
+ return OW_ERROR; // bus error
+ return DS18X20_ERROR_CRC; // data error
+ }
+
+ DS18X20_meas_to_cel(id[0], sp, &subzero, &cel, &cel_frac_bits);
+ *temperature = cel_frac_bits*.0625;
+ *temperature += cel;
+ if (subzero)
+ *temperature *= -1;
+ return DS18X20_OK;
+}
+/**
+* @brief start measurement (CONVERT_T) for all sensors if input id==NULL
+ or for single sensor. then id is the rom-code
+* @param [in] with_power_extern
+* @param [in] rom_code
+* @return DS18X20_OK or DS18X20_START_FAIL
+* @date 20/06/2011
+*/
+uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[]) {
+ ow_reset(); //**
+ if ( ow_test_pin() ) { // only send if bus is "idle" = high
+ ow_command( DS18X20_CONVERT_T, id );
+ if (with_power_extern != DS18X20_POWER_EXTERN)
+ ow_parasite_enable();
+ return DS18X20_OK;
+ }
+ return DS18X20_START_FAIL;
+
+}
+/**
+* @brief start measurement (CONVERT_T) for all sensors if input id==NULL
+ or for single sensor. then id is the rom-code
+* @param [in] n num bus onewire
+* @param [in] with_power_extern
+* @param [in] rom_code
+* @return DS18X20_OK or DS18X20_START_FAIL
+* @date 06/09/2011
+*/
+uint8_t DS18X20_start_meas(uint8_t n, uint8_t with_power_extern, uint8_t id[]) {
+ ow_reset(n); //**
+ if ( ow_test_pin(n) ) { // only send if bus is "idle" = high
+ ow_command(n, DS18X20_CONVERT_T, id );
+ if (with_power_extern != DS18X20_POWER_EXTERN)
+ ow_parasite_enable(n);
+ return DS18X20_OK;
+ }
+ return DS18X20_START_FAIL;
+
+}
+//**********************************************************************************************************
+//* DS18X20_read_meas
+//**********************************************************************************************************
+
+/**
+* @brief reads temperature (scratchpad) of sensor with rom-code id
+ output: subzero==1 if temp.<0, cel: full celsius, mcel: frac
+ in millicelsius*0.1
+ i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C
+* @param [in] id[] = rom_code
+* @param [out] subzero
+* @param [out] cel
+* @param [out] cel_frac_bits
+* @return DS18X20_OK or DS18X20_ERROR_CRC
+* @date 20/06/2011
+*/
+uint8_t DS18X20_read_meas(uint8_t id[], uint8_t *subzero,
+ uint8_t *cel, uint8_t *cel_frac_bits) {
+ uint8_t i;
+ uint8_t sp[DS18X20_SP_SIZE];
+
+ ow_reset();
+ ow_command(DS18X20_READ, id);
+ for ( i=0 ; i< DS18X20_SP_SIZE; i++ )
+ sp[i]=ow_byte_rd();
+ if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){
+ if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF))
+ return OW_ERROR; // bus error
+ return DS18X20_ERROR_CRC; // data error
+ }
+
+ DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits);
+ return DS18X20_OK;
+}
+/**
+* @brief reads temperature (scratchpad) of sensor with rom-code id
+ output: subzero==1 if temp.<0, cel: full celsius, mcel: frac
+ in millicelsius*0.1
+ i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C
+* @param [in] n num bus onewire
+* @param [in] id[] = rom_code
+* @param [out] subzero
+* @param [out] cel
+* @param [out] cel_frac_bits
+* @return DS18X20_OK or DS18X20_ERROR_CRC
+* @date 06/09/2011
+*/
+uint8_t DS18X20_read_meas(uint8_t n,uint8_t id[], uint8_t *subzero,
+ uint8_t *cel, uint8_t *cel_frac_bits) {
+ uint8_t i;
+ uint8_t sp[DS18X20_SP_SIZE];
+
+ ow_reset(n);
+ ow_command(n,DS18X20_READ, id);
+ for ( i=0 ; i< DS18X20_SP_SIZE; i++ )
+ sp[i]=ow_byte_rd(n);
+ if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){
+ if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF))
+ return OW_ERROR; // bus error
+ return DS18X20_ERROR_CRC; // data error
+ }
+
+ DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits);
+ return DS18X20_OK;
+}
+/**
+* @brief convert raw value from DS18x20 to Celsius
+ input is:
+ - familycode fc (0x10/0x28 see header)
+ - scratchpad-buffer
+ output is:
+ - cel full celsius
+ - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits)
+ - subzero =0 positiv / 1 negativ
+ always returns DS18X20_OK
+ TODO invalid-values detection (but should be covered by CRC)
+* @param [in] fc
+* @param [in] sp
+* @param [out] subzero
+* @param [out] cel
+* @param [out] cel_frac_bits
+* @return DS18X20_OK
+* @date 20/06/2011
+*/
+uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp,
+ uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits) {
+ uint16_t meas;
+ uint8_t i;
+
+ meas = sp[0]; // LSB
+ meas |= ((uint16_t)sp[1])<<8; // MSB
+ //meas = 0xff5e; meas = 0xfe6f;
+
+ // only work on 12bit-base
+ if ( fc == DS18S20_ID ) { // 9 -> 12 bit if 18S20
+ /* Extended measurements for DS18S20 contributed by Carsten Foss */
+ meas &= (uint16_t) 0xfffe; // Discard LSB , needed for later extended precicion calc
+ meas <<= 3; // Convert to 12-bit , now degrees are in 1/16 degrees units
+ meas += (16 - sp[6]) - 4; // Add the compensation , and remember to subtract 0.25 degree (4/16)
+ }
+
+ // check for negative
+ if ( meas & 0x8000 ) {
+ *subzero=1; // mark negative
+ meas ^= 0xffff; // convert to positive => (twos complement)++
+ meas++;
+ } else *subzero=0;
+
+ // clear undefined bits for B != 12bit
+ if ( fc == DS18B20_ID ) { // check resolution 18B20
+ i = sp[DS18B20_CONF_REG];
+ if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) ;
+ else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT )
+ meas &= ~(DS18B20_11_BIT_UNDF);
+ else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT )
+ meas &= ~(DS18B20_10_BIT_UNDF);
+ else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) {
+ meas &= ~(DS18B20_9_BIT_UNDF);
+ }
+ }
+
+ *cel = (uint8_t)(meas >> 4);
+ *cel_frac_bits = (uint8_t)(meas & 0x000F);
+
+ return DS18X20_OK;
+}
+
+/**
+* @brief converts to decicelsius
+ input is ouput from meas_to_cel
+ i.e.: sz=0, c=28, frac=15 returns 289 (=28.9�C)
+0 0 0
+1 625 625 1
+2 1250 250
+3 1875 875 3
+4 2500 500 4
+5 3125 125
+6 3750 750 6
+7 4375 375
+8 5000 0
+9 5625 625 9
+10 6250 250
+11 6875 875 11
+12 7500 500 12
+13 8125 125
+14 8750 750 14
+15 9375 375
+* @param [in] subzero
+* @param [in] cel
+* @param [in] cel_frac_bits
+* @return absolute value of temperatur in decicelsius
+* @date 20/06/2011
+*/
+uint16_t DS18X20_temp_to_decicel(uint8_t subzero, uint8_t cel,
+ uint8_t cel_frac_bits) {
+ uint16_t h;
+ uint8_t i;
+ uint8_t need_rounding[] = { 1, 3, 4, 6, 9, 11, 12, 14 };
+
+ h = cel_frac_bits*DS18X20_FRACCONV/1000;
+ h += cel*10;
+ if (!subzero) {
+ for (i=0; i<sizeof(need_rounding); i++) {
+ if ( cel_frac_bits == need_rounding[i] ) {
+ h++;
+ break;
+ }
+ }
+ }
+ return h;
+}
+/**
+* @brief compare temperature values (full celsius only)
+* @param [in] subzero1
+* @param [in] cel1
+* @param [in] subzero2
+* @param [in] cel2
+* @return -1 if param-pair1 < param-pair2
+ 0 if ==
+ 1 if >
+* @date 20/06/2011
+*/
+int8_t DS18X20_temp_cmp(uint8_t subzero1, uint16_t cel1,
+ uint8_t subzero2, uint16_t cel2) {
+ int16_t t1 = (subzero1) ? (cel1*(-1)) : (cel1);
+ int16_t t2 = (subzero2) ? (cel2*(-1)) : (cel2);
+
+ if (t1<t2) return -1;
+ if (t1>t2) return 1;
+ return 0;
+}
\ No newline at end of file
frederic blanc