Tested and working library for the DS1621 temperature sensor with I2C

Dependents:   condato_Coldchainlogger condato_Coldchainlogger 039847382-S3_DS1621_and_LCD_V1

Committer:
Bas
Date:
Fri Jul 06 20:51:31 2012 +0000
Revision:
0:20bfb7df0470
fixed compiler warning LastTemp

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bas 0:20bfb7df0470 1 #include "ds1621.h"
Bas 0:20bfb7df0470 2
Bas 0:20bfb7df0470 3 DS1621::DS1621(I2C* _interface, unsigned char _address): i2c(_interface), address(_address) {
Bas 0:20bfb7df0470 4 conversion_busy=false;
Bas 0:20bfb7df0470 5 LastTemp=0.0;
Bas 0:20bfb7df0470 6 StartConversion(false);
Bas 0:20bfb7df0470 7
Bas 0:20bfb7df0470 8 printf("Searching for I2C devices...\n");
Bas 0:20bfb7df0470 9
Bas 0:20bfb7df0470 10 int count = 0;
Bas 0:20bfb7df0470 11 for (int address=4; address<256; address+=2) {
Bas 0:20bfb7df0470 12 if (!i2c->write(address, NULL, 0)) { // 0 returned is ok
Bas 0:20bfb7df0470 13 printf(" - I2C device found at address 0x%02X\r\n", address);
Bas 0:20bfb7df0470 14 count++;
Bas 0:20bfb7df0470 15 }
Bas 0:20bfb7df0470 16 }
Bas 0:20bfb7df0470 17 printf("%d devices found\r\n", count);
Bas 0:20bfb7df0470 18 }
Bas 0:20bfb7df0470 19
Bas 0:20bfb7df0470 20 // Set configuration register
Bas 0:20bfb7df0470 21 void DS1621::SetConfig(unsigned char cfg) {
Bas 0:20bfb7df0470 22 char data[2];
Bas 0:20bfb7df0470 23 data[0]=ACCESS_CONFIG;
Bas 0:20bfb7df0470 24 data[1]=cfg;
Bas 0:20bfb7df0470 25 i2c->write(address,data,2);
Bas 0:20bfb7df0470 26 }
Bas 0:20bfb7df0470 27
Bas 0:20bfb7df0470 28 // Read a DS1621 register
Bas 0:20bfb7df0470 29 unsigned char DS1621::ReadReg(unsigned char reg) {
Bas 0:20bfb7df0470 30 char data[1];
Bas 0:20bfb7df0470 31 data[0]=reg;
Bas 0:20bfb7df0470 32 i2c->write(address,data,1,true);
Bas 0:20bfb7df0470 33 i2c->read(address,data,1);
Bas 0:20bfb7df0470 34 return (data[0]);
Bas 0:20bfb7df0470 35 }
Bas 0:20bfb7df0470 36
Bas 0:20bfb7df0470 37 // Sets temperature limit
Bas 0:20bfb7df0470 38 // -- works only with ACCESS_TL and ACCESS_TH
Bas 0:20bfb7df0470 39 void DS1621::SetLimit(unsigned char reg, float temp) {
Bas 0:20bfb7df0470 40 if (reg == ACCESS_TL || reg == ACCESS_TH) {
Bas 0:20bfb7df0470 41 char data[3];
Bas 0:20bfb7df0470 42 data[0]=reg;
Bas 0:20bfb7df0470 43 if (temp <0.0) {
Bas 0:20bfb7df0470 44 temp = ceil(temp * 2.0 - 0.5) / 2.0; //round to 1/2 degree
Bas 0:20bfb7df0470 45 if (floor(temp) < temp ) { // check for extra half
Bas 0:20bfb7df0470 46 data[1]=(~char(temp * -1.0)); //one's complement
Bas 0:20bfb7df0470 47 data[2]=0x80; // -25.5 = -26 + 0.5
Bas 0:20bfb7df0470 48 } else {
Bas 0:20bfb7df0470 49 data[1]=(~char(temp * -1.0)) + 1; //two's complement
Bas 0:20bfb7df0470 50 data[2]=0; // -25 = -25
Bas 0:20bfb7df0470 51 }
Bas 0:20bfb7df0470 52 } else {
Bas 0:20bfb7df0470 53 temp = floor(temp * 2.0 + 0.5) / 2.0; //round to 1/2 degree
Bas 0:20bfb7df0470 54 data[1]=char(temp); //whole degrees
Bas 0:20bfb7df0470 55 if (ceil(temp) > temp) { // check for extra half
Bas 0:20bfb7df0470 56 data[2]=0x80;
Bas 0:20bfb7df0470 57 } else {
Bas 0:20bfb7df0470 58 data[2]=0x00;
Bas 0:20bfb7df0470 59 }
Bas 0:20bfb7df0470 60 }
Bas 0:20bfb7df0470 61 i2c->write(address,data,3);
Bas 0:20bfb7df0470 62 wait_ms(10);
Bas 0:20bfb7df0470 63 }
Bas 0:20bfb7df0470 64 }
Bas 0:20bfb7df0470 65
Bas 0:20bfb7df0470 66 // Start/Stop DS1621 temperature conversion
Bas 0:20bfb7df0470 67 void DS1621::StartConversion(bool start) {
Bas 0:20bfb7df0470 68 char data[1];
Bas 0:20bfb7df0470 69 if (start == true) {
Bas 0:20bfb7df0470 70 data[0]=START_CONVERT_T;
Bas 0:20bfb7df0470 71 i2c->write(address,data,1);
Bas 0:20bfb7df0470 72 } else {
Bas 0:20bfb7df0470 73 data[0]=STOP_CONVERT_T;
Bas 0:20bfb7df0470 74 i2c->write(address,data,1);
Bas 0:20bfb7df0470 75 }
Bas 0:20bfb7df0470 76 }
Bas 0:20bfb7df0470 77
Bas 0:20bfb7df0470 78 // Reads temperature or threshold
Bas 0:20bfb7df0470 79 // -- works only with READ_TEMPERATURE, ACCESS_TL, and ACCESS_TH
Bas 0:20bfb7df0470 80 // -- DS1621 must be in continouis mode and started for the actual temperature
Bas 0:20bfb7df0470 81 bool DS1621::GetTemp(unsigned char reg, float *Temp) {
Bas 0:20bfb7df0470 82 unsigned char data[2];
Bas 0:20bfb7df0470 83 float Tc;
Bas 0:20bfb7df0470 84
Bas 0:20bfb7df0470 85 if (reg == READ_TEMPERATURE || reg == ACCESS_TL || reg == ACCESS_TH) {
Bas 0:20bfb7df0470 86 ReadChipTemp(reg,data);
Bas 0:20bfb7df0470 87
Bas 0:20bfb7df0470 88 Tc=float(data[1]>>7) * 0.5; // decimal part = +0.5 if bit7=1
Bas 0:20bfb7df0470 89
Bas 0:20bfb7df0470 90 if (data[0] >= 0x80) { // negative? -> make two's complement
Bas 0:20bfb7df0470 91 *Temp = float((char (~data[0])+1)*-1) + Tc;
Bas 0:20bfb7df0470 92 } else {
Bas 0:20bfb7df0470 93 *Temp = float(data[0])+ Tc;
Bas 0:20bfb7df0470 94 }
Bas 0:20bfb7df0470 95 return (true);
Bas 0:20bfb7df0470 96 }
Bas 0:20bfb7df0470 97 return (false);
Bas 0:20bfb7df0470 98 }
Bas 0:20bfb7df0470 99
Bas 0:20bfb7df0470 100 // Read high resolution temperature
Bas 0:20bfb7df0470 101 // -- returns temperature in 1/100ths degrees
Bas 0:20bfb7df0470 102 // -- DS1620 must be in 1-shot mode
Bas 0:20bfb7df0470 103 bool DS1621::GetHResTemp(float *Temp) {
Bas 0:20bfb7df0470 104
Bas 0:20bfb7df0470 105 if (conversion_busy==false) {
Bas 0:20bfb7df0470 106 SetConfig(ONESHOT);
Bas 0:20bfb7df0470 107 StartConversion(true); // initiate conversion
Bas 0:20bfb7df0470 108 conversion_busy=true;
Bas 0:20bfb7df0470 109 *Temp = LastTemp;
Bas 0:20bfb7df0470 110 return (false);
Bas 0:20bfb7df0470 111 }
Bas 0:20bfb7df0470 112
Bas 0:20bfb7df0470 113 if (!(ReadReg(ACCESS_CONFIG) & DONE)) {
Bas 0:20bfb7df0470 114 *Temp = LastTemp;
Bas 0:20bfb7df0470 115 return (false);
Bas 0:20bfb7df0470 116 } else {
Bas 0:20bfb7df0470 117 unsigned char data[2];
Bas 0:20bfb7df0470 118 // get the results
Bas 0:20bfb7df0470 119 ReadChipTemp(READ_TEMPERATURE,data); // get whole degrees reading
Bas 0:20bfb7df0470 120 float cRem = (float)ReadReg(READ_COUNTER); // get counts remaining
Bas 0:20bfb7df0470 121 float cSlope = (float)ReadReg(READ_SLOPE); // get counts per degree
Bas 0:20bfb7df0470 122 if (data[0] >= 0x80) { // negative? -> make two's complement
Bas 0:20bfb7df0470 123 LastTemp = float((char (~data[0])+1)*-1);
Bas 0:20bfb7df0470 124 } else {
Bas 0:20bfb7df0470 125 LastTemp = float(data[0]);
Bas 0:20bfb7df0470 126 }
Bas 0:20bfb7df0470 127 LastTemp = LastTemp - 0.25 + (cSlope - cRem)/cSlope;
Bas 0:20bfb7df0470 128 conversion_busy=false;
Bas 0:20bfb7df0470 129 *Temp = LastTemp;
Bas 0:20bfb7df0470 130 return (true);
Bas 0:20bfb7df0470 131 }
Bas 0:20bfb7df0470 132
Bas 0:20bfb7df0470 133 }
Bas 0:20bfb7df0470 134
Bas 0:20bfb7df0470 135 void DS1621::ReadChipTemp(unsigned char reg, unsigned char *data) {
Bas 0:20bfb7df0470 136 if (reg == READ_TEMPERATURE || reg == ACCESS_TL || reg == ACCESS_TH) {
Bas 0:20bfb7df0470 137 char cmd[1];
Bas 0:20bfb7df0470 138 cmd[0]=reg;
Bas 0:20bfb7df0470 139 i2c->write(address,cmd,1,true);
Bas 0:20bfb7df0470 140 i2c->read(address, (char *)data, 2);
Bas 0:20bfb7df0470 141 }
Bas 0:20bfb7df0470 142 }