CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DS1631 driver bug

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
russk2txb



Joined: 30 Mar 2008
Posts: 109
Location: New Jersey

View user's profile Send private message

DS1631 driver bug
PostPosted: Tue Apr 01, 2008 3:19 pm     Reply with quote

Below is the temperature read routine from DS1631.C, the driver supplied with version 3 compilers. It has two serious bugs.

To understand the bugs it is necessary to understand how the DS1632 chip returns data. The high byte is the integer degrees, plus or minus indicated by the sign bit. The low byte only uses bits 4 to 7, and is the value for the decimal part of the degree. The low byte is NOT a signed number. The low byte must be shifted right 4 bits and then multiplied by .0625 to get the hundredths of a degree (in hi res mode). But even with negative numbers, the low byte is never considered negative, so for instance to get a value of -.5 degrees, the high byte will be -1 and the low byte will be .5.

So the first bug is that datal is a signed integer. This causes sign extension when it is shifted right (if the value is >= 128 (=.5 degrees)), and results in totally wrong values.

The second bug is that the value after being shifted to the low nibble is multiplied by (50/16). I don't understand where this value comes from but it is totally off. For example, if the low nibble, after shifting, has a value of 1, that means the actual value is .0625. But with this formula the value calculated will be 3.125, giving rise to a huge error in the hundredths part of the result. Look below this code block to see the code that produces the correct result:

Code:
signed long read_full_temp() {  // Returns hundredths of degrees F (-67 to 257)
   signed int  datah, datal;
   signed long data;

   i2c_start();
   i2c_write(0x90);
   i2c_write(0xaa);
   i2c_start();
   i2c_write(0x91);
   datah=i2c_read();
   datal=i2c_read(0);
   i2c_stop();

   data=(signed long)datah*100;
   data=data+(((datal >> 4 )*(long)50)/16); // -<--- wrong conversion
   data=data*9;
   data = (data / 5) + 3200;

   return(data);
}


To fix this, first change the variable declarations to:
Code:
long datal;
signed long datah, data;


Then the conversion:
Code:
data = datah * 100;
data += (datal << 8) / 655;

This results in the best approximation to the actual value that can be had when only using 16 bits for datal. The max error is in the order of .01 degrees Celsius.

Also note that the same bugs exist in the alternate DS1631 driver, ds1631mm.c, and possibly others.

Regards, Russell Pillsbury
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group