DS1631

Hello,

Just to propose a sketch to control the DS1631 Temperature Sensor.
Here it is. Hope that will help somebody in the future :

#include <Wire.h>

// PIN adresses are set to GND
#define DS1631_ADDR 0x90 >> 1

// SETUP
void setup(){
    
  // Setup Serial connection
  Serial.begin(9600); 
  Serial.println("");
  Serial.println("-----------------------------------");
  Serial.println("DS1631 test: Temp. sensor"); 
  Serial.println("-----------------------------------");
  Serial.println("");
  
  Wire.begin();             // join I2C bus

  // Stop conversion to be able to modify "Access Config" Register
  Wire.beginTransmission(DS1631_ADDR);
  Wire.send((int)(0x22)); // Stop conversion
  Wire.endTransmission();  
    
  // Read "Access Config" regsiter
  Wire.beginTransmission(DS1631_ADDR);
  Wire.send((int)(0xAC)); // @AC : Acces Config
  Wire.endTransmission();
  Wire.requestFrom(DS1631_ADDR,1); //Reade 1 byte
  Wire.available();
  int AC = Wire.receive(); // receive a byte

  Serial.print("Acces Config (Before): "); Serial.print(AC);  Serial.println("");
    
  // WRITE into "Access Config" Register
  Wire.beginTransmission(DS1631_ADDR);
  Wire.send(0xAC); // @AC : Acces Config
  Wire.send(0x0C); // Continuous conversion & 12 bits resolution
  Wire.endTransmission();
    
  // READ "Access Config" register
  Wire.beginTransmission(DS1631_ADDR);
  Wire.send((int)(0xAC)); // @AC : Acces Config
  Wire.endTransmission();
  Wire.requestFrom(DS1631_ADDR,1);
  Wire.available();
  AC = Wire.receive();

  Serial.print("Acces Config (AFTER): "); Serial.print(AC);  Serial.println("");
  
  // START conversion to get T°
  Wire.beginTransmission(DS1631_ADDR);
  Wire.send((int)(0x51)); // Start Conversion
  Wire.endTransmission();
}

// Main Loop
void loop(){
  
  //READ T°
  Wire.beginTransmission(DS1631_ADDR);
  Wire.send((int)(0xAA)); // @AA : Temperature
  Wire.endTransmission();
  Wire.requestFrom(DS1631_ADDR,2); // READ 2 bytes
  Wire.available(); // 1st byte
  int Th = Wire.receive(); // receive a byte
  Wire.available(); // 2nd byte
  int Tl = Wire.receive(); // receive a byte


  // T° processing
  if(Th>=0x80) //if sign bit is set, then temp is negative
  Th = Th - 256;
  int T_dec=(10*(100*(Tl/16)))/16; // decimal part of the T°

  // Display T° on "Serial Monitor"
  Serial.print("Temperature : ");
  Serial.print(Th);   Serial.print(".");
  if (T_dec<10)   Serial.print("0");
  if (T_dec<100)   Serial.print("0");
  Serial.print(T_dec);   Serial.print(" degC / ");
  Serial.print("Th register: "); Serial.print(Th);  Serial.print(" / ");
  Serial.print("Tl register: "); Serial.print(Tl);  Serial.println("");
  
  // Wait 1s before restart
  delay(1000);
}

Have fun :wink:

Thanks.
I made my first tests with ds1631 as a Object

Is it for somebody usable???

iTom

ds1631.cpp

/*
  Ds1631.cpp - Library for High-Precision Digital Thermometer and Thermostat
  Created by ITom Ibach
  Version 20090915
  http://datasheets.maxim-ic.com/en/ds/DS1631-DS1731.pdf
  
*/
#include <Wire.h>
#include <Ds1631.h>

// Initialize Class Variables //////////////////////////////////////////////////
  int _Addr;
  uint8_t Th;
  uint8_t Tl;

// Constructors ////////////////////////////////////////////////////////////////
Ds1631::Ds1631(int Addr){
  _Addr=Addr + 72;  // Ground Addr 72 for Ds1631  
}

// Public Methods //////////////////////////////////////////////////////////////
void Ds1631::stopConversion(){
  Wire.beginTransmission(_Addr);
  Wire.send(0x22); // Stop conversion
  Wire.endTransmission();
}

void Ds1631::startConversion(){
  Wire.beginTransmission(_Addr);
  Wire.send(0x51); // Start conversion
  Wire.endTransmission();
  
}

void Ds1631::writeConfig(uint8_t _data){
  stopConversion(); 
  Wire.beginTransmission(_Addr);
  Wire.send(0xAC);        // @AC : Acces Config
  Wire.send(_data);
  Wire.endTransmission();
  startConversion();
}

uint8_t Ds1631::readConfig(){
  uint8_t _data;
  Wire.beginTransmission(_Addr);
  Wire.send(0xAC);        // @AC : Acces Config
  Wire.endTransmission();
  Wire.requestFrom(_Addr, 1);
  if(Wire.available()) {
    _data = Wire.receive();
  }
  return _data;
}

void Ds1631::readT(){
  Wire.beginTransmission(_Addr);
  Wire.send(0xAA); // @AA : Temperature
  Wire.endTransmission();
  Wire.requestFrom(_Addr,2); // READ 2 bytes
  Wire.available(); // 1st byte
  Th = Wire.receive(); // receive a byte
  Wire.available(); // 2nd byte
  Tl = Wire.receive(); // receive a byte
}

float Ds1631::readTempF(){
  int T_dec;
  double T;
  readT();
  // T° processing
  Tl = Tl>>4;
  if(Th>=0x80){ //if sign bit is set, then temp is negative
    Th = Th - 256;
  }
  T = (float) Th + (float) Tl*0.0625;
  return T;
}

int32_t Ds1631::readTempD(){ // 1/16°C = 1 Bit 0.0625°C
  int T_dec;
  int32_t T; 
  readT();
  
  T=((int32_t)Th << 8) + Tl ;
  // T° processing
  if(T >= 0x8000){   //if sign bit is set, then temp is negative
    T = T - 0xFFFF;
  }
  T = T >>4;
  return T;
}

bool Ds1631::conversionDone(){  // if Conversion Done = Boolean = True
  uint8_t _data = readConfig();
  if ((_data | 127)==255)
     return true;
  else 
     return false;
}

ds1631.h

/*
  Ds1631.h - Lirbray for Ds1631 Expander
  Created by ITom Ibach
  Version 20090915
*/
#ifndef Ds1631_h
#define Ds1631_h

//#include <WProgram.h>
#include <inttypes.h>

class Ds1631
{
  public:
    Ds1631(int);
    void stopConversion();
    void startConversion();
    void writeConfig(uint8_t);
    uint8_t readConfig();
    float readTempF();  //Floatinpoint z.B. 24.125
    int32_t readTempD();  //Long * 1/16 = °C
    bool conversionDone();
  
  private:
    void readT(); 
    int _Addr;
    uint8_t Th;
    uint8_t Tl;
};

#endif

ds1631_Example_ease.pde

/*
  ds1631_Example_ease.pde - Easy Example for High-Precision Digital Thermometer 
  Created by ITom Ibach
  Version 20090915
  http://datasheets.maxim-ic.com/en/ds/DS1631-DS1731.pdf
*/

#include <Wire.h>
#include <ds1631.h>

Ds1631 Temp1(0); //addr=0  = all PIN adresses are set to GND

// SETUP
void setup(){
  int AC;  
  // Setup Serial connection
  Serial.begin(19200);
  Serial.println("");
  Serial.println("-----------------------------------");
  Serial.println("DS1631 test: Temp. sensor");
  Serial.println("-----------------------------------");
  Serial.println("");
  
  Wire.begin();             // join I2C bus

  // WRITE into "Access Config" Register
  Temp1.writeConfig(0x0C);  // 0C=Continuous conversion & 12 bits resolution = +-0.0625°C
                            // 08=Continuous conversion & 11 bits resolution = +-0.125°C
                            // 04=Continuous conversion & 10 bits resolution = +-0.25°
                            // 00=Continuous conversion &  9 bits resolution = +-0.5°C
                                                        
  // READ "Access Config" register
  AC = Temp1.readConfig();
  Serial.print("Acces Config 1 (AFTER): "); Serial.print(AC,HEX);  Serial.println("");

}
  
// Main Loop
void loop(){
 
  // Display T° on "Serial Monitor"
  Serial.print("Temperature 1 : "); Serial.print(Temp1.readTempF()); Serial.println(" degC   ");
  delay(500);
  
}

ds1631_Example_LCD.pde

/*
  ds1631_Example_LCD.pde - Example for High-Precision Digital Thermometer with LCD
  The Idee was to hold the Celler as cool als posible 
  Created by ITom Ibach
  Version 20090915
  http://datasheets.maxim-ic.com/en/ds/DS1631-DS1731.pdf
*/

// include the library code:
#include <LiquidCrystal.h>
#include <Wire.h>
#include <ds1631.h>

// these constants won't change.  But you can change the size of
// your LCD using them:
const int numRows = 2;
const int numCols = 16;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
Ds1631 Temp1(0); //addr=0
Ds1631 Temp2(1); //addr=1

void setup() {
  int AC;
  Serial.begin(19200);
  Serial.println("");
  Serial.println("-----------------------------------");
  Serial.println("DS1631 test: Temp. sensor");
  Serial.println("-----------------------------------");
  Serial.println("");
  
  Wire.begin();             // join I2C bus
  
  // set up the LCD's number of rows and columns: 
  lcd.begin(numRows, numCols);

  // WRITE into "Access Config" Register
  Temp1.writeConfig(0x04);  // Continuous conversion & 10 bits resolution
  Temp2.writeConfig(0x04);  // Continuous conversion & 10 bits resolution
  
  // READ "Access Config" register
  AC = Temp1.readConfig();
  Serial.print("Acces Config 1 (AFTER): "); Serial.print(AC,HEX);  Serial.println(' ');
  AC = Temp2.readConfig();
  Serial.print("Acces Config 2 (AFTER): "); Serial.print(AC,HEX);  Serial.println(' ');

  // START conversion to get T°
  Temp1.startConversion();
  Temp2.startConversion();
}

void loop() {
   float TempInnen=Temp1.readTempF();
   float TempAussen=Temp2.readTempF();
   int hysterese=2;
   float diff=TempAussen-TempInnen;
   float SollWert=6;  // The best Temprature for the cellar

   boolean heizen;
   lcd.setCursor(0,0);
   lcd.print('A');lcd.print(':');
   lcd.print(TempAussen); 
   lcd.print(' ');
   lcd.setCursor(9,0);
   lcd.print('D');lcd.print(':');
   lcd.print(diff); lcd.print(' ');
   //Serial.print("Temperature 1 : "); Serial.print(Temp1.readTempF()); Serial.println(" degC   ");
  
   lcd.setCursor(0,1);
   lcd.print('I'); lcd.print(':');
   lcd.print(TempInnen); 
   lcd.print(' ');
   //Serial.print("Temperature 2 : ");  Serial.print(Temp2.readTempF()); Serial.println(" degC   ");
   lcd.setCursor(12,1);
   if (TempInnen <= SollWert){
     heizen=true;
     lcd.print('H'); lcd.print('=');
     if (diff >= hysterese) { 
       lcd.print('1'); 
     }
     else {
       lcd.print('0');
     }       
   }
   else {
     heizen=false;
     lcd.print('K'); lcd.print('=');
     diff=0-diff; 
     if (diff >= hysterese) { 
       lcd.print('1'); 
     }
     else {
       lcd.print('0');
     }       
   }  
   delay(200);
}