Tested and working library for the DS1621 temperature sensor with I2C
Dependents: condato_Coldchainlogger condato_Coldchainlogger 039847382-S3_DS1621_and_LCD_V1
ds1621.cpp
- Committer:
- Bas
- Date:
- 2012-07-06
- Revision:
- 0:20bfb7df0470
File content as of revision 0:20bfb7df0470:
#include "ds1621.h" DS1621::DS1621(I2C* _interface, unsigned char _address): i2c(_interface), address(_address) { conversion_busy=false; LastTemp=0.0; StartConversion(false); printf("Searching for I2C devices...\n"); int count = 0; for (int address=4; address<256; address+=2) { if (!i2c->write(address, NULL, 0)) { // 0 returned is ok printf(" - I2C device found at address 0x%02X\r\n", address); count++; } } printf("%d devices found\r\n", count); } // Set configuration register void DS1621::SetConfig(unsigned char cfg) { char data[2]; data[0]=ACCESS_CONFIG; data[1]=cfg; i2c->write(address,data,2); } // Read a DS1621 register unsigned char DS1621::ReadReg(unsigned char reg) { char data[1]; data[0]=reg; i2c->write(address,data,1,true); i2c->read(address,data,1); return (data[0]); } // Sets temperature limit // -- works only with ACCESS_TL and ACCESS_TH void DS1621::SetLimit(unsigned char reg, float temp) { if (reg == ACCESS_TL || reg == ACCESS_TH) { char data[3]; data[0]=reg; if (temp <0.0) { temp = ceil(temp * 2.0 - 0.5) / 2.0; //round to 1/2 degree if (floor(temp) < temp ) { // check for extra half data[1]=(~char(temp * -1.0)); //one's complement data[2]=0x80; // -25.5 = -26 + 0.5 } else { data[1]=(~char(temp * -1.0)) + 1; //two's complement data[2]=0; // -25 = -25 } } else { temp = floor(temp * 2.0 + 0.5) / 2.0; //round to 1/2 degree data[1]=char(temp); //whole degrees if (ceil(temp) > temp) { // check for extra half data[2]=0x80; } else { data[2]=0x00; } } i2c->write(address,data,3); wait_ms(10); } } // Start/Stop DS1621 temperature conversion void DS1621::StartConversion(bool start) { char data[1]; if (start == true) { data[0]=START_CONVERT_T; i2c->write(address,data,1); } else { data[0]=STOP_CONVERT_T; i2c->write(address,data,1); } } // Reads temperature or threshold // -- works only with READ_TEMPERATURE, ACCESS_TL, and ACCESS_TH // -- DS1621 must be in continouis mode and started for the actual temperature bool DS1621::GetTemp(unsigned char reg, float *Temp) { unsigned char data[2]; float Tc; if (reg == READ_TEMPERATURE || reg == ACCESS_TL || reg == ACCESS_TH) { ReadChipTemp(reg,data); Tc=float(data[1]>>7) * 0.5; // decimal part = +0.5 if bit7=1 if (data[0] >= 0x80) { // negative? -> make two's complement *Temp = float((char (~data[0])+1)*-1) + Tc; } else { *Temp = float(data[0])+ Tc; } return (true); } return (false); } // Read high resolution temperature // -- returns temperature in 1/100ths degrees // -- DS1620 must be in 1-shot mode bool DS1621::GetHResTemp(float *Temp) { if (conversion_busy==false) { SetConfig(ONESHOT); StartConversion(true); // initiate conversion conversion_busy=true; *Temp = LastTemp; return (false); } if (!(ReadReg(ACCESS_CONFIG) & DONE)) { *Temp = LastTemp; return (false); } else { unsigned char data[2]; // get the results ReadChipTemp(READ_TEMPERATURE,data); // get whole degrees reading float cRem = (float)ReadReg(READ_COUNTER); // get counts remaining float cSlope = (float)ReadReg(READ_SLOPE); // get counts per degree if (data[0] >= 0x80) { // negative? -> make two's complement LastTemp = float((char (~data[0])+1)*-1); } else { LastTemp = float(data[0]); } LastTemp = LastTemp - 0.25 + (cSlope - cRem)/cSlope; conversion_busy=false; *Temp = LastTemp; return (true); } } void DS1621::ReadChipTemp(unsigned char reg, unsigned char *data) { if (reg == READ_TEMPERATURE || reg == ACCESS_TL || reg == ACCESS_TH) { char cmd[1]; cmd[0]=reg; i2c->write(address,cmd,1,true); i2c->read(address, (char *)data, 2); } }