PDA

View Full Version : DS 3231 temperature reading



visnja30
- 4th June 2015, 15:47
Hello everyone,
I made a clock with DS3231 chip and clock works great. Now I would like to have and temperature display with this chip but I do not know how to do that. Does someone have a sample program to calculate the temperature from it in the positive and negative values
Best regards Visnja

Tabsoft
- 5th June 2015, 04:31
This would be somewhat easy to do.
The temperature is reported in 2 byte registers.
Register 011h is the temperature integer and is 2's complement form to support negative numbers.
Register 12h is the fractional portion register (where the fractional value is reported in the upper 2 most significant bits b7 and b6).

To read the temperature just define some variables and use I2Cread to read registers 11h and 12h from the chip.



TempInt var byte ' variable for temperature integer from register 11h
TempFrac var byte. ' variable for temperature fraction for register 12h
TempAddr var byte ' I2C slave address of the DS3231
TempRegister var byte ' variable for starting register to read
TempSign var bit ' Variable to hold sign bit

TempRegister = $11
TempAddr = $xx ' change xx to 8bit slave address of the DS3231

I2Cread SDA, SCL, TempAddr, TempRegister, [TempInt, TempFrac]


The fractional value is returned in the upper (b7:b6) of the TempFrac variable.
Shift the fractional value 6 bits to the right so that that b7 & b6 become b1 & b0.



TempFrac = (TempFrac >> 6)


The fractional value is in increments of .25 degrees.
So you will need to multiply the new shifted value in TempFrac by 25.



TempFrac = (TempFrac * 25)


You will need to test to see if the integer portion is a negative value by checking b7.
If b7 is a 1 then the temperature is negative and the number is a 2's complement of the absolute value, so you will have to convert it to a normal number.



TempSign = TempInt.7 ' save the sign bit for later

If TempSign = 1 then
' convert the 2's compliment number to a regular integer
TempInt = (TempInt XOR $FF) + 1 ' Google 2's compliment to get more info
Else

Endif


Now you have all the pieces you need for the temperature.
Sign Integer.Fraction

To print it on the LCD all you have to do is see if you need to print a "+" or "-" sign based on TempSign.



If TempSign = 0 then
LCDOUT $FE, $80, "+", dec TempInt, ".", TempFrac
Else
LCDOUT $FE, $80, "-", dec TempInt, ".", TempFrac
Endif


You can combine most of this into a smaller more compact series of statements, but you can see how it's done.

You want to read the Datasheet regarding the temperature conversion (when the chip reads its internal temperature sensor). It only does this process every so often so you will need to account for that timing in your program.

visnja30
- 5th June 2015, 21:54
Thank you for your reply

I tried your example and it works great in a positive temperature conditions but in negative temperatures I have bad results.

When DS3231 cool off with a freeze spray I get this result -1,075 or -1,555

I think the ice of freeze spray does not cause a problem as seconds and minutes are displayed OK.

For now negative temperatures are not necessary but it would be nice if those temperature were correctly displayed on LCD.

Tabsoft
- 6th June 2015, 02:56
Well, why don't you post your code and perhaps we can see what's happening.:biggrin:

visnja30
- 6th June 2015, 14:37
TempRegister CON $11 'temperature integer REGISTER
TempRegisterFRA CON $12 'temperature fraction REGISTER


TempInt var byte ' variable for temperature integer from register 11h
TempFrac var byte ' variable for temperature fraction for register 12h
TempSign var bit ' Variable to hold sign bit


main:

LCDOut $fe,1

B0 = 0
button Taster0, 0, 100, 10, B0, 1, meni0



I2CRead SDA, SCL, RTC, SecReg, [sec,MINs,hr,day,date,mon,yr]


LCDOut $fe,2, HEX2 hr, ":", HEX2 MINs, ":", HEX2 sec
LCDOut $fe,$c0, HEX2 date, "/", HEX2 mon, "/","20" ,HEX2 yr




I2Cread SDA, SCL, rtc, TempRegister, [TempInt, TempFrac]

TempFrac = (TempFrac >> 6)
TempFrac = (TempFrac * 25)



TempSign = TempInt.7 ' save the sign bit for later

If TempSign = 1 then TempInt = (TempInt XOR $FF) + 1




If TempSign = 0 then
LCDOUT $FE, $80+9, "+", dec TempInt, ".",DEC TempFrac
Else
LCDOUT $FE, $80+9, "-", dec TempInt, ".",DEC TempFrac
Endif




GoTo main



The piece of main part of the code in which I read time, date and temperature.
The example shows only the registers and variables to read temperature

Tabsoft
- 6th June 2015, 16:48
Okay, there are a couple of issues.
The strange numbers for negative temperatures are caused by (2) issues.
1. The LCDOUT commands are being used with the DEC modifier.
This will not always output the same number of characters and may leave previously printed characters on the screen.
It will depend on the value to be displayed.
Use the DEC2 modifier instead. This will force the output to always be (2) characters.
Since th DS3231 only has a temperature range of -40 to +85, this will be fine.

2. The DS3231 only uses a simple bit <b7> to indicate the sign. It does not really encode to 2s compliment.
Adjusted the test and handling of negative values below.

See if this works for you now.



''You really should not use constants for the address parameter for I2CREAD & I2CWRITE
'' From the PBP Manual
''Constants should not be used for the Address as the size can vary dependent on the size of the constant.
''Also, expressions should not be used as they can cause an improper Address size to be sent.

''TempRegister CON $11 'temperature integer REGISTER
''TempRegisterFRA CON $12 'temperature fraction REGISTER


TempRegister var byte ' variable to hold DS3231 register address to read/write


TempInt var byte ' Variable for temperature integer from register 11h
TempFrac var byte ' Variable for temperature fraction for register 12h
TempSign var bit ' Variable to hold sign bit


main:

LCDOut $fe,1

B0 = 0
button Taster0, 0, 100, 10, B0, 1, meni0



I2CRead SDA, SCL, RTC, SecReg, [sec,MINs,hr,day,date,mon,yr]


LCDOut $fe,2, HEX2 hr, ":", HEX2 MINs, ":", HEX2 sec
LCDOut $fe,$c0, HEX2 date, "/", HEX2 mon, "/","20" ,HEX2 yr



TempRegister = $11h ' DS3231 Temperature REgister High Byte (Integer portion)
I2Cread SDA, SCL, rtc, TempRegister, [TempInt, TempFrac]

TempFrac = (TempFrac >> 6) ' Shift <b7:b6> to <b1:b0>
TempFrac = (TempFrac * 25) ' Fractional portion is in .25 increments. Increment values are 0-3 (.00, .25, .50, .75)



TempSign = TempInt.7 ' save the sign bit for later

'''If TempSign = 1 then TempInt = (TempInt XOR $FF) + 1 'Do not use this, the DS3231 uses simple <b7> sign with <b6:b0> as absolute temperature value




If TempSign = 0 then ' Positive temperature
LCDOUT $FE, $80+9, "+", DEC2 TempInt, ".",DEC2 TempFrac 'Change to DEC2 to make sure LCD does not leave characters from previous temperature printout
Else ' Negative temperature
TempInt.7 = 0 ' Clear <b7> and use only the absolute value of 11h register value <b6:b0>
LCDOUT $FE, $80+9, "-", DEC2 TempInt, ".",DEC2 TempFrac 'Change to DEC2 to make sure LCD does not leave characters from previous temperature printout
Endif




GoTo main

visnja30
- 7th June 2015, 16:56
Now I can not try the code because I ran out of frezze spray. For a day or two when a freez spray come to me, I will tried it.

Tabsoft
- 7th June 2015, 20:50
Once you get your freeze spray.

Take a reading but don't convert the TempInt byte.
Just read it and display it on the LCD in Hex2 format.
That way you can see the raw value from the 3231.

Do this when the 3231 is at room temperature and then again after lightly applying the spray.

Once you have both hex values, post them here and we can take a look.