DS1621

I spent the weekend trying to interface a DS1621 thermometer i2c chip to my RCW4400w.

I ran into quite a bit of trouble (and i’m familiar interfacing to this chip from other micro’s) – and there wasn’t any information on the web or this forum, so now that I’ve got it working I wanted to post some code samples to help others.

I used i2c.lib but not i2c_devices.lib, because the DS1621 needs slightly different parameters than are supported by the more high-level library.

For all of these, THERM_ADDRESS is defined to 0x90, which would be A0,A1,A2 on the DS1621 tied to ground.

After a basic i2c_init() I initialize the chip by sending it a 0x0 control code to put it in continuous mode, then a 0xEE to start temp conversion:


void init_temp()
{
   i2c_start_tx();
   i2c_write_char(THERM_ADDRESS);
   i2c_write_char(0xAC);
   i2c_write_char(0x0);

   i2c_start_tx();
   i2c_write_char(THERM_ADDRESS);
   i2c_write_char(0xEE);

   i2c_stop_tx();

   wait(1000);
}

I wait 1 second at the end of that function because it takes 1 second for the first temperature conversion to be ready to read. That’s a wait function I made, use whatever you’d like.

Here’s how I get the actual temperature:


float get_temp()
{
   char data[2];
   float ret;

   i2c_start_tx();
   i2c_write_char(THERM_ADDRESS);
   i2c_write_char(0xAA);
   i2c_write_char(0xAA);
   i2c_start_tx();
   i2c_write_char(THERM_ADDRESS+1);
   i2c_read_char(&data[0]);
   i2c_send_ack();
   i2c_read_char(&data[1]);
   i2c_send_nak();
   i2c_stop_tx();

   ret = (float)(data[0]);
   if(data[1]>0) ret+=0.5;
   return ret;
}

That gets both bytes of the temperature, and adds the half-celsius-degree onto the end of the MSB to return a valid float celsius value. Convert this to F by multiplying by 1.8 and adding 32 if you’d like.

You can also stop the conversion to save energy as follows:


void stop_temp()
{
   i2c_start_tx();
   i2c_write_char(THERM_ADDRESS);
   i2c_write_char(0x22);
   i2c_stop_tx();
}

The biggest problem I had getting this working was actually in the size of the pullup resistors. I ended up having to use extremely small pullups to get the DS1621 to respond. about 1.5k on the clock, and 500ohm on the data. If you have trouble make sure you play with your resistor values, or hook to an oscope as I did to debug.

Also, all those i2c_write_char calls will return a 0 if an ack was received – however, if your pullups are the wrong size it may register an ack always even if nothing was sent.

Hope I save someone else some time on this! Good luck!

Hi,

Thanks for the post, I think it’s really helpful for someone who is trying to use the I2C bus (like I am :slight_smile: ).
I’m trying to connect a camera module (c3088) to a Rabbit RCM5400 microcontroller. The I2C bus is needed to configure the control registers of the camera.
My question is related to the size of the resistors: is there a way to compute the size of the pull up resistors or it’s just a kind of a “trial and error”?

Thanks,
Square

It’s definitely possible to calculate the values, there is a page here with a bunch of information you can wade through:

http://www.interfacebus.com/IC_Output_Input_Pullup_Resistor_Values.html

The problem for me is typically that I’m working on a breadboard, which has lots of capacitance, sometimes unpredictable resistance, etc – So trial and error tends to be the easiest way to hone in on a value that is going to get me a high enough voltage to register as a high bit, and low enough to register as a low bit – You can reference your datasheets to see what these voltage limits are.

If you don’t have an o-scope to check if you are getting the high and low voltages you expect, program your micro to keep the pin high, or low, and measure the circuit with a volt-meter – that should let you test one side of the equation at least.

Hello,

Thanks for your reply. I managed to solve the resistor problem. Although not by adjusting the size of the resistors, but by increasing the clock cycles. I hooked it to an oscilloscope and saw that my waveform wasn’t sharp enough so I increased the length of the clock cycles (by modifying the cWAIT_5_us macro in the I2C.LIB, and now the a clock cycle is around 40 us) such that the resistors will have enough time to pull up the signals.
And now I’m facing another problem. For some reason, the value that I read from the camera module is 0xFF all the time. Do you have any idea what could be the problem?

Thanks,
Square