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

Applying DS1629 with higher temperature resolution

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
h.a.j.molenaar



Joined: 04 May 2005
Posts: 9

View user's profile Send private message

Applying DS1629 with higher temperature resolution
PostPosted: Thu Jun 23, 2005 3:19 am     Reply with quote

Hi all,
In a small temperature datalogger is the DS1629 from Dallas semiconductor http://www.maxim-ic.com used for converting the temperature.An algoritme is given in the datasheet to obtain a higher temperature resolution.

The data obtained with this higher resolution shows strange steps, so or the component can not measure properly or the algortime implemented by me is not correct.

Question: who have experience with applying the DS1629 with the high resolution temperature measurement.

Greetings Hugo.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 23, 2005 12:03 pm     Reply with quote

Dallas Semiconductor appnote 105 has some C source code at the
end of the document which shows how to do this. Here's the link.
http://www.eetasia.com/ARTICLES/2001APR/2001APR09_AMD_AN.PDF

I think you should post your full routine that does the calculations,
and be sure to post the variable declarations. Also post the printf()
statement that displays the result. If you're new to CCS, there
could easily be problems in your routine with proper variable sizes,
data type casting in math operations, and the printf() format specification.
h.a.j.molenaar



Joined: 04 May 2005
Posts: 9

View user's profile Send private message

Applying DS1629 with higher temperature resolution
PostPosted: Tue Jul 05, 2005 5:13 am     Reply with quote

Hi, it took some time but here is the C-code.
The datasheet and the application note is to my opinion rather confusing.
The high resolution temperatures read from the DS1629 shows jumps of 0.5 degrees. I do not know or it is due to:
- wrong impementation of algoritme.
- the DS1629 instabilitly or so.

Due to memmory size it is not possible to perform a float calculation and
the pic controlls the DS1629 stores the result in external serial eeprom.
Afterwards a dockinstation reads these results. Due the small size of the
datalogger it is not possible to display any register or variable.

// Function : TempSensorRTC
// Parameters : None
// Returns : MSB LSB 16 bit temperature from sensor in rtc
// Affects :
// Description : Reads high resolution temperature from DS1629
// Attention, function returns a long integer as LSB and MSB but the
// buffer needs MSB, LSB. Therefore this two are swapped at the end
// of the function.
//
// Function uses the following equation.
// TempSensorRTSC = temperature (nine bits) - 0.25 degrees + ((count - remain) / count)
// __________________________________________________________________________
signed long int TempSensorRTC()
{
signed long int temperature;
unsigned int remain;
unsigned int count;
unsigned long int resolution;
unsigned long int substraction;
unsigned int swap_byte;

i2c_start();
i2c_write(RTCWRITE); // Write to rtc.
i2c_write(CMD_START_CONVERT); // Start conversion,(takes one
i2c_stop(); // second).
delay_ms(1200); // Wait one second.

i2c_start();
i2c_write(RTCWRITE); // Write to rtc.
i2c_write(CMD_READTEMP);
i2c_stop();

i2c_start(); // Start.
i2c_write(RTCREAD); // Read from rtc.
temperature = i2c_read(1); // MSB of temp, Acknowledge.
temperature <<= 8; // Shift in place.
temperature |= i2c_read(0); // Read LSB.
i2c_stop(); //

i2c_start();
i2c_write(RTCWRITE); // Write to rtc.
i2c_write(CMD_COUNTREMAIN); // read count.
i2c_stop();
i2c_start(); // Repeated start.
i2c_write(RTCREAD); // Read from rtc.
remain = i2c_read(0); // no acknowledge.
i2c_stop();

i2c_start();
i2c_write(RTCWRITE); // Write to rtc.
i2c_write(CMD_COUNTC); // read slope.
i2c_stop();
i2c_start(); // Repeated start.
i2c_write(RTCREAD); // Read from rtc.
count = i2c_read(0); // no acknowledge.
i2c_stop();

if (count != 0) // Only if count is not equal to zero
{ // remain and count have to be taken
// into the calculation.
substraction = (count - remain);
substraction <<= 8; // Multiply substraction with 255.
resolution = substraction / count;// res. is a number between 1 and 255.
// Substract 0.25 degrees and add resolution.
temperature = temperature - 0x0040 + resolution;
}

temperature &= 0xFFF0; // 12 bits precision.
swap_byte = temperature; // swap_byte is LSB.
temperature >>=8; // Shift MSB to LSB position.
(*(&temperature+1))= swap_byte; // Highest byte of temperature.
return(temperature);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 06, 2005 1:01 am     Reply with quote

I'm working on your problem. It might be another day or two
before I can post a reply. I don't have a ds1629, but I do have
a ds1621 and it's very similar, so that's what I'm using to test the code.
h.a.j.molenaar



Joined: 04 May 2005
Posts: 9

View user's profile Send private message

High resolution temperature measurement
PostPosted: Wed Jul 06, 2005 1:32 pm     Reply with quote

Fantastic, I am still working on the problem and let you know if I find out more. Very Happy
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 07, 2005 11:57 am     Reply with quote

I made a working high resolution driver for the ds1621.
It does the final calculations in floating point. I know
you wanted to do it with integer math, but that's really
a separate problem. I thought the most important thing
would be to get a driver that produced a stable output.
This driver should work for the ds1629 if the i2c write
and read addresses are changed to 0x9E and 0x9F.

Here is sample output. The values are in degrees Centigrade.
Code:

22.35  // This is room temperature.
22.35
22.35
22.35
22.35
22.35
22.35  // I just touched the ds1621 for an instant.
22.38  // It's going up slightly.   
22.40
22.55
22.57
22.55  // Now it's cooling down again.
22.55
22.53
22.53
22.51
22.51
22.51
22.48


Here is the demo program that calls the driver.
Code:

#include <16F877.h>
#fuses XT, NOWDT, NOPROTECT, PUT, BROWNOUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)

#include <ds1621hr.c>

void main()
{
float result;

ds1621_init();

while(1)
  {
   result = ds1621_read_temp_hires();
   printf("%3.2f\r\n", result);
   delay_ms(1000);
  }

}


Here is the driver.
Code:

// ds1621hr.c -- High resolution output driver for the ds1621.
//               Output is a floating point number in degrees
//               centigrade.  It should be displayed by printf()
//               with this precision:  %3.2f

// i2c addresses
#define DS1621_I2C_WRITE_ADDRESS    0x90
#define DS1621_I2C_READ_ADDRESS     0x91

// DS1621 commands
#define DS1621_CMD_READ_TEMP        0xAA
#define DS1621_CMD_READ_SLOPE       0xA9
#define DS1621_CMD_READ_COUNTER     0xA8
#define DS1621_CMD_START_CONVERSION 0xEE
#define DS1621_CMD_STOP_CONVERSION  0x22
#define DS1621_CMD_ACCESS_CONFIG    0xAC

#define DS1621_CONFIG_INIT          0x09   // Use one-shot conversions
#define DS1621_CONVERSION_DONE_MASK 0x80

//======================================
void ds1621_init(void)
{
i2c_start();
i2c_write(DS1621_I2C_WRITE_ADDRESS);
i2c_write(DS1621_CMD_ACCESS_CONFIG);
i2c_write(DS1621_CONFIG_INIT);
i2c_stop();
}

//--------------------------------------
int8 ds1621_read_config(void)
{
int8 config;   
i2c_start();
i2c_write(DS1621_I2C_WRITE_ADDRESS); 
i2c_write(DS1621_CMD_ACCESS_CONFIG); 
i2c_start();                 
i2c_write(DS1621_I2C_READ_ADDRESS);         
config = i2c_read(0);         
i2c_stop();
return(config);
}   

//--------------------------------------
float ds1621_read_temp_hires(void)
{
int8 count_remain; 
int8 count_per_degree;
signed int16 temp_read;
float frac_deg;
int16 k;
int8 status;

i2c_start();
i2c_write(DS1621_I2C_WRITE_ADDRESS);         
i2c_write(DS1621_CMD_START_CONVERSION); 
i2c_stop();                   

// Poll the conversion done bit in the Config register.
// When it goes high, then we can proceed.   It should
// go high in 1 second or less.   If it takes 2 seconds,
// we will abort and display an error message.
for(k = 0; k < 2000; k++)
   {
    status = ds1621_read_config();
    if(status & DS1621_CONVERSION_DONE_MASK)
       break;
    delay_ms(1);
   }

if(k == 2000)
  {
   printf("Error: Conversion Timed out.  Result is invalid.\n\r");   
   return(0.0);
  }

i2c_start();
i2c_write(DS1621_I2C_WRITE_ADDRESS); 
i2c_write(DS1621_CMD_READ_TEMP);
i2c_start();             
i2c_write(DS1621_I2C_READ_ADDRESS);         
temp_read = i2c_read();   // Read MSB 
temp_read <<= 8;           
temp_read |= i2c_read(0); // Read LSB 
i2c_stop();

// Read the 8-bit counter value.
i2c_start();
i2c_write(DS1621_I2C_WRITE_ADDRESS); 
i2c_write(DS1621_CMD_READ_COUNTER); 
i2c_start();                     
i2c_write(DS1621_I2C_READ_ADDRESS);         
count_remain = i2c_read(0);               
i2c_stop();

// Read the 8-bit slope value.
i2c_start(); 
i2c_write(DS1621_I2C_WRITE_ADDRESS); 
i2c_write(DS1621_CMD_READ_SLOPE); 
i2c_start();                     
i2c_write(DS1621_I2C_READ_ADDRESS);         
count_per_degree = i2c_read(0);   
i2c_stop();

// The following code mostly follows the CalcHiResTemp() function
// shown on page 18 of AN105 from Dallas Semiconductor.
// Here is the link to that appnote:
// http://www.eetasia.com/ARTICLES/2001APR/2001APR09_AMD_AN.PDF
// (Maxim/Dallas doesn't have the appnote on their website).

temp_read >>= 8;   // Right-justify the 9-bit value and divide by 2 

if(bit_test(temp_read, 7))  // Check if negative number       
   temp_read -= 256;        // If so, convert to two's comp. value   

if(count_per_degree != 0)
   frac_deg = (float)(count_per_degree - count_remain) /
                    ((float)count_per_degree);
else
   frac_deg = .25;       

return((float)temp_read - .25 + frac_deg);

}
h.a.j.molenaar



Joined: 04 May 2005
Posts: 9

View user's profile Send private message

PostPosted: Tue Jul 12, 2005 7:59 am     Reply with quote

PCM programmer, thank you for the effort you have done. It was a usefull help to deal with the problem.

Here follows the calculating algoritme with only (long) integers so that the result is 12 bits long. 8 bits for the temperature and 4 bits for the fraction.
This is like how DS1775 represents the temperature and it facilitates to store the temperature in eeprom.

signed long int TempSensorRTC()
{
signed long int temperature;
unsigned int count_remain;
unsigned int count_per_c;
unsigned long int fraction;

temperature = 0;


// Assume to read all the values from the register
// Read MSB of temperature.
// Read 8-bit counter value.
// Read 8-bit slope value
if (count_per_c != 0) // Only if count_per_c is not equal to
{ // zero, remain and count have to be
// taken into the calculation.
fraction = (count_per_c - count_remain);
fraction <<= 8; // Multiply fraction with 256.
fraction /= count_per_c; }
else
{
fraction = 0x0040;
}
temperature = temperature - 0x0040 + fraction;
temperature &= 0xFFF0; // 12 bits precision.
return(temperature);
}
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