This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMP100 problems and questions

Other Parts Discussed in Thread: TMP100

Hello everyone. I'm trying to interface a microcontroller with TMP100 (when add0->float and add1->gnd). 

In i2c bus I put 10kohm resistors, and it's communicating with the sensor.

Well I'm sending to the configuration register the resolution 12 bits (0x60) and shutdown (0x01) ok? After put this in the tmp100 I try to read back the configuration register and I got the value that i put + OS/ALERT bit, so it's E1 ok (0x80 + 0x60 + 0x01). OK fine. If I'm never read the temperature registers, I always get E1 in the configuration register. If i read the temperature registers the configuration register automatically goes to 0x81 (the resolution goes to 9bits), I have to always reconfigure it after read a temperature? what is wrong? 

About the temperature data. After read the 2 bytes (assuming I'm using 9bits resolution ok) I do this:

 

value = ((I2CSlaveBuffer[0] << 8) | I2CSlaveBuffer[1]) >> 7;  (shift to create a properly integer).

 //  Sign extend negative numbers

  if (I2CSlaveBuffer[0] & 0x80)

  {

    // Negative number

    *value |= 0xFE00;

  }

But after this. HOW i convert the integer to temperature in ºC?? In the datasheet there is a "resolution" different for 9bit, 10, 11 and 12bits. The integer i need to multiply to the resolution? Only this? I didn't understand how I convert the temperature.

 

  • Hello Vinicius,

    The resolution bits R1 and R0 of the Configuration Register should not change after reading the temperature register. The only time the Configuration Register changes automatically is after a power-up/reset. Can you please share the block of code you use when reading from the temperature registers so I can check that it does not contain errors?

    After you read from the temperature registers, you simply multiply the integer by 1 LSB in order to get the final temperature result. I have given the 1 LSB value for each resolution in the table below.

    RESOLUTION (bits) 1 LSB (°C)
    12 0.0625
    11 0.125
    10 0.25
    9 0.5

     

     

     

     

     

    For example, let's say you are using 12-bit resolution and have a temperature register value of 0x4B0 (1200 in decimal). To calculate the temperature in °C, multiply 1200 * 0.0625 = 75°C. If you are using 9-bit resolution and have a temperature register value of 0x064 (100 in decimal), multiply 100 * 0.5 = 50°C. Keep in mind that negative numbers are represented in twos complement binary form, so you must use the standard method to convert the temperature register bits to their absolute value before converting to °C.

    Best regards,

    Ian Williams
    Linear Applications Engineer
    High Performance Linear and Sensing Products

  • Hi Ian, I created the functions for this device.

     

     

    static bool _tmp100Initialised = false;

     

    static tmp100Error_e tmp100Write8 (uint8_t reg, uint8_t value)

    {

      // Clear write buffers

      uint32_t i;

      for ( i = 0; i < I2C_BUFSIZE; i++ )

      {

        I2CMasterBuffer[i] = 0x00;

      }

     

      I2CWriteLength = 3;

      I2CReadLength = 0;

      I2CMasterBuffer[0] = TMP100_ADDRESS;            // I2C device address

      I2CMasterBuffer[1] = reg;                       // Command register

      I2CMasterBuffer[2] = (value & 0xFF);            // Value to write

      i2cEngine();

      return TMP100_ERROR_OK;

    }

     

    tmp100Error_e tmp100Read8(uint8_t reg, uint8_t *value)

    {

    if (!_tmp100Initialised) tmp100Init();

    uint32_t i;

      // Clear buffers

      for ( i = 0; i < I2C_BUFSIZE; i++ )

      {

        I2CMasterBuffer[i] = 0x00;

    I2CSlaveBuffer[i] = 0x00;

      }

     

      I2CWriteLength = 2;

      I2CReadLength = 1;

      I2CMasterBuffer[0] = TMP100_ADDRESS;       // I2C device Write address

      I2CMasterBuffer[1] = reg;                       // Command register

    I2CMasterBuffer[2] = TMP100_ADDRESS | TMP100_READBIT;       // I2C device Read address

     

     

      i2cEngine();

    // You need a small delay between write and read

      systickDelay(15);

     

      *value = I2CSlaveBuffer[0];

     

      return TMP100_ERROR_OK;

    }

     

    static tmp100Error_e tmp100Read16(uint8_t reg, int16_t *value)

    {

      // Clear write buffers

      uint32_t i;

      for ( i = 0; i < I2C_BUFSIZE; i++ )

      {

        I2CMasterBuffer[i] = 0x00;

      }

     

      I2CWriteLength = 2;

      I2CReadLength = 2;

      I2CMasterBuffer[0] = TMP100_ADDRESS;             // I2C device address

      I2CMasterBuffer[1] = reg;                        // Command register

      // Append address w/read bit

      I2CMasterBuffer[2] = TMP100_ADDRESS | TMP100_READBIT;  

      i2cEngine();

     

      // Shift values to create properly formed integer

    // Depends of the RESOLUTION (THIS PART IS OK?? IT'S TO *** PROPERLY 9-BITS)

      *value = ((I2CSlaveBuffer[0] << 8) | I2CSlaveBuffer[1]) >> 7;

     

      //  Sign extend negative numbers

      if (I2CSlaveBuffer[0] & 0x80)

      {

        // Negative number

        *value |= 0xFE00;  (TWO COMPLEMENT IS CORRECT FOR 9BITS??)

      }

      return TMP100_ERROR_OK;

    }

     

    tmp100Error_e tmp100Init(void)

    {

      // Initialise I2C

      if (i2cInit(I2CMASTER) == false)

      {

        return TMP100_ERROR_I2CINIT;    /* Fatal error */

      }

     

      _tmp100Initialised = true;

     

      return tmp100ConfigWrite (TMP100_RESOLUTION_12BITS |    

    TMP100_CONFIG_SHUTDOWN_SHUTDOWN);

    //Configuring 12bits and SHUTDOWN the sensor

    }

     

    tmp100Error_e tmp100GetTemperature (int16_t *temp)

    {

      if (!_tmp100Initialised) tmp100Init();

     

      // Turn device on  (IS CORRECT TO THE SAME TIME POWERON AND CONFIGURE THE RESOLUTION AGAIN, since you sad after power-up the configuration register is reseted)

      tmp100ConfigWrite (TMP100_RESOLUTION_12BITS | TMP100_CONFIG_SHUTDOWN_POWERON);

     

      // You need a small delay between power on and read

      systickDelay(20);

     

      // Read temperature

      tmp100Error_e error = TMP100_ERROR_OK;

      error = tmp100Read16 (TMP100_REGISTER_TEMPERATURE, temp);

     

      // Shut device back down

      tmp100ConfigWrite (TMP100_CONFIG_SHUTDOWN_SHUTDOWN);

     

      return error;

    }

    tmp100Error_e tmp100ConfigWrite (uint8_t configValue)

    {

      if (!_tmp100Initialised) tmp100Init();

     

      return tmp100Write8 (TMP100_REGISTER_CONFIGURATION, configValue);

    }

     

    In the main code I just do tmp100Init(); and tmp100GetTemperature(&temp);

  • Hello Vinicius,

    Thank you for sharing your code. However, can you please attach the code as a .C or .txt file instead of pasting the text directly into the forum thread? It is easier to see and debug that way.

    Best regards,

    Ian Williams

  • Sorry follow the code.

     

    /**************************************************************************/
    /*! 
        @file     tmp100.c
        @author   Vinicius Cardoso de Vargas
    	@date     29 July 2010
        @version  0.10
    
        @section LICENSE
    
        Copyright (c) 2011, DFAI
        All rights reserved.
    */
    /**************************************************************************/
    
    #include "tmp100.h"
    #include "core/systick/systick.h"
    
    extern volatile uint8_t   I2CMasterBuffer[I2C_BUFSIZE];
    extern volatile uint8_t   I2CSlaveBuffer[I2C_BUFSIZE];
    extern volatile uint32_t  I2CReadLength, I2CWriteLength;
    
    static bool _tmp100Initialised = false;
    
    /**************************************************************************/
    /*! 
        @brief  Writes an 8 bit values over I2C
    */
    /**************************************************************************/
    static tmp100Error_e tmp100Write8 (uint8_t reg, uint8_t value)
    {
      // Clear write buffers
      uint32_t i;
      for ( i = 0; i < I2C_BUFSIZE; i++ )
      {
        I2CMasterBuffer[i] = 0x00;
      }
    
      I2CWriteLength = 3;
      I2CReadLength = 0;
      I2CMasterBuffer[0] = TMP100_ADDRESS;            // I2C device address
      I2CMasterBuffer[1] = reg;                       // Command register
      I2CMasterBuffer[2] = (value & 0xFF);            // Value to write
      i2cEngine();
      return TMP100_ERROR_OK;
    }
    
    /**************************************************************************/
    /*! 
        @brief  Reads a 8 bit values over I2C
    */
    /**************************************************************************/
    tmp100Error_e tmp100Read8(uint8_t reg, uint8_t *value)
    {
    	if (!_tmp100Initialised) tmp100Init();
    	
    	uint32_t i;
    	
      // Clear buffers
      for ( i = 0; i < I2C_BUFSIZE; i++ )
      {
        I2CMasterBuffer[i] = 0x00;
    		I2CSlaveBuffer[i] = 0x00;
      }
    
      I2CWriteLength = 2;
      I2CReadLength = 1;
      I2CMasterBuffer[0] = TMP100_ADDRESS;      									// I2C device Write address
      I2CMasterBuffer[1] = reg;                       						// Command register
    	I2CMasterBuffer[2] = TMP100_ADDRESS | TMP100_READBIT;       // I2C device Read address
    
     
      i2cEngine();
    	
    	// You need a small delay between write and read
      systickDelay(15);
    
      *value = I2CSlaveBuffer[0];
    
      return TMP100_ERROR_OK;
    }
    
    /**************************************************************************/
    /*! 
        @brief  Reads a 16 bit values over I2C
    */
    /**************************************************************************/
    static tmp100Error_e tmp100Read16(uint8_t reg, int16_t *value)
    {
      // Clear write buffers
      uint32_t i;
      for ( i = 0; i < I2C_BUFSIZE; i++ )
      {
        I2CMasterBuffer[i] = 0x00;
      }
    
      I2CWriteLength = 2;
      I2CReadLength = 2;
      I2CMasterBuffer[0] = TMP100_ADDRESS;             // I2C device address
      I2CMasterBuffer[1] = reg;                        // Command register
      // Append address w/read bit
      I2CMasterBuffer[2] = TMP100_ADDRESS | TMP100_READBIT;  
      i2cEngine();
    
      // Shift values to create properly formed integer
    	// Depends of the RESOLUTION
      *value = ((I2CSlaveBuffer[0] << 8) | I2CSlaveBuffer[1]) >> 7;
    
      //  Sign extend negative numbers
      if (I2CSlaveBuffer[0] & 0x80)
      {
        // Negative number
        *value |= 0xFE00;
      }
      return TMP100_ERROR_OK;
    }
    
    /**************************************************************************/
    /*! 
        @brief  Initialises the I2C block
    */
    /**************************************************************************/
    tmp100Error_e tmp100Init(void)
    {
      // Initialise I2C
      if (i2cInit(I2CMASTER) == false)
      {
        return TMP100_ERROR_I2CINIT;    /* Fatal error */
      }
      
      _tmp100Initialised = true;
    
      return tmp100ConfigWrite (TMP100_RESOLUTION_12BITS |
    														TMP100_CONFIG_SHUTDOWN_SHUTDOWN);
    }
    
    /**************************************************************************/
    /*! 
        @brief  Reads the current temperature from the TMP100
    
        @note   This method will assign a signed 16-bit value (int16) to 'temp',
                where each unit represents +/- 0.5�C (for 9bits). 
    */
    /**************************************************************************/
    tmp100Error_e tmp100GetTemperature (int16_t *temp)
    {
      if (!_tmp100Initialised) tmp100Init();
    
      // Turn device on
      tmp100ConfigWrite (TMP100_RESOLUTION_12BITS | TMP100_CONFIG_SHUTDOWN_POWERON);
    
      // You need a small delay between power on and read
      systickDelay(20);
    
      // Read temperature
      tmp100Error_e error = TMP100_ERROR_OK;
      error = tmp100Read16 (TMP100_REGISTER_TEMPERATURE, temp);
    
      // Shut device back down
      tmp100ConfigWrite (TMP100_CONFIG_SHUTDOWN_SHUTDOWN);
    
      return error;
    }
    
    /**************************************************************************/
    /*! 
        @brief  Writes the supplied 8-bit value to the TMP100 config register
    */
    /**************************************************************************/
    tmp100Error_e tmp100ConfigWrite (uint8_t configValue)
    {
      if (!_tmp100Initialised) tmp100Init();
    
      return tmp100Write8 (TMP100_REGISTER_CONFIGURATION, configValue);
    }
    

  • Thanks. I'll take a look and get back to you tomorrow.

    Regards,

    Ian Williams

  • Hello again Vinicius,

    I was pulled into a bunch of meetings today so I didn't have the time to analyze your code in detail. I was able to look over your comments so I do have some feedback.

    1. When you shut down the TMP100 in between reads, are you actually bringing the power supply rail down to 0V or just doing a software shutdown by writing a '1' to the SD bit in the configuration register? A software shutdown (also known as "sleep mode" or "low-power mode") will not cause the registers to reset; only a full power off will cause the registers to reset. 

    2. All of the resolution settings (12-bit, 11-bit, 10-bit, 9-bit) use twos complement notation for negative numbers. For example, if the temperature register is set to 9-bit resolution and the MSB is a '1,' you have a negative number and should convert it to its absolute value using the standard method.

    Best regards,

    Ian Williams

  • Well I correct something that is wrong. The data treatment is now correct and the resolution is ok. About the sleep-mode, Yes I shutdown the software ONLY by software in the function tmp100Init(); After I get the temperature I do again the shutdown by software in the function tmp100GetTemperature(int16_t *temp); By the way In this function first, the software power-on the device again (by software).

     

    So I made some tests by reading the configuration register, then read temperature and then read the configuration register again.  I observed that is every fine and working BUT in he function to get temperature, when I power-on the device i MUST configure the resolution again (R1/R0). If I not configure again in power-on (by SOFTWARE) the resolution is reseted. That's what I observed, so you told that shutdown by software don't reset the register, So there is something wrong or the resolution is lost anyway?

     

    I got the sensor working fine just this detail that when you power-on the sensor again you must to configure the resolution, just that, everyelse is ok.

  • Vinicius,

    I'm happy to hear that you have made good progress debugging your code. Since you are doing a software shutdown, not a full power-down, it's possible that you are unintentionally performing a write to the configuration register when you read the temperature register. I recommend double-checking your read temperature function to make sure the I2C commands you're passing do not write to the configuration register.

    I'll do some testing here to see if I notice anything strange with the configuration register after doing a temperature read. My board won't arrive until tomorrow so I'll get back to you then.

    Best regards,

    Ian Williams

  • Hi.

    Yeah Ian, when I'll read the temperature register I need to write 0x01 in the configuration register to wake-up the sensor right? so if i write 0x01 I'll changing the resolution, i need to "configure" again the resolution to. And after read the new temeprature I need to write 0x01 again in the configuration register to the sensor sleep. because if I'll execute the reading without wake up the sensor, as i tested, i'll always get the same temperature, the first one conversion and the sensor never wake up again just give me the last temperature readed when waked up. Am I right?

     

    Regards

    Vinicius

  • Vinicius,

    You need to reset the SD bit back to '0' to wake-up the device, not set it to '1' since that places it in sleep mode. So whatever you write to the configuration register at wake-up must have an LSB of 0. In this sense you are correct that you must "re-configure" the entire configuration register when you wake up since you don't want to modify the other bits, just the SD bit. 

    You are also correct about reading the temperature during sleep mode: you will always receive the last good result, since no conversions are taking place at that time. Only the I2C circuitry is active during sleep mode.

    Best regards,

    Ian Williams

  • Sorry I wrote wrong, you're right, has to be 0.

    So Everything is working fine now. thank you very much for your attention and explanations.  I just wondering something that I didn't find in datasheet. How much time the sensor needs to wake up + do the conversion. I know about the conversion time, but what about the wake up?

    After your answer you can close this topic.

    Thank you very much for your help and attention.

    Best Regards

    Vinicius Cardoso de Vargas

  • Hello Vinicius,

    You're very welcome for the help and attention.

    The device should wake up within a few μs. If you allow 1ms for wake up time that should be more than enough.

    Best regards,

    Ian Williams

  • Hi,

    Am using TMP100 sensor in my design with the davinci dm6467 as a processor. Am not able to successful with I2C communication with the tempearture sensor device.

    am giving the i2c address as 0x4C (i.e ADD1 -1 and ADD0 -0), both read and write fails.

    we are not sure whats the issue , because same using i2c bus we are able to communicate with onther devices.

    could anyone provide your suggestions.

    note : am just trying to read the all four regsiters at stretch, am doing any soft reset.

    if required i will share the code and am using CCS.

    Thanks

    BAlaji

  • Hello Balaji,

    Don't forget that you must add a read/write bit (1 for read, 0 for write) to the end of the TMP100 slave address. Therefore, for an address of 0x4C (1001100b) you must actually write an address of 0x98 (10011000b). 

    For example, to read register 0 (temperature register) you should do the following:

    1. Start I2C bus by master
    2. Transmit slave address 0x98 (write)
    3. TMP100 will ACK
    4. Transmit pointer register address 0x00
    5. TMP100 will ACK
    6. Start I2C bus by master
    7. Transmit slave address 0x99 (read)
    8. TMP100 will ACK
    9. Read byte 1 from TMP100 register
    10. Master will ACK
    11. Read byte 2 from TMP100 register
    12. Master will ACK
    13. Stop I2C bus by master

    Also make sure that you have pull-up resistors to V+ on your SDA, SCL, and ALERT pins.

    Best regards,

    Ian Williams

  • I am using this thread to add a related question instead of creating a new one: In one-shot mode, how do I know when the conversion is complete?
    I anticipate the following execution sequence happening inside the TMP:
    - Receives 0x80 in the configuration register (address 1).
    - Wakes up and starts conversion which, let's say, takes 80 ms. (Writing 0x80 to the configuration register sets the resolution to 9 bits.)
    - Receives a request on the I2C to read the temperature register (address 0) after few ms, let's say less than 10 ms.
    - Sends the register value which holds data from the previous one-shot conversion which might have happened hours ago.

    Am I correct?

    Best wishes,

    Günter
  • Hi,

     

    Please refer to my comments below following your original statements:

     

    - Receives 0x80 in the configuration register (address 1). Correct, this is the One-shot command sent by master.
    - Wakes up and starts conversion which, let's say, takes 80 ms. (Writing 0x80 to the configuration register sets the resolution to 9 bits.) Correct, actually 75mS for 9-bit according to the data sheet. Upon completion, TMP100 puts the new measurement results in temperature register, overwriting the old data.
    - Receives a request on the I2C to read the temperature register (address 0) after few ms, let's say less than 10 ms. Correct, master sends read command, it doesn’t matter how long this command takes, TMP100 does not care. The master can wait however long as it wishes before retrieving the data, provided there is no reset event in between.
    - Sends the register value which holds data from the previous one-shot conversion which might have happened hours ago. The temperature data currently in the register is the most recent measurement following the above One-shot command.

    Regards,

    Guang-Apps Sensing Products

  • Thanks for the quick reply, Guang. To make sure I understand your comments correctly: The master should wait at least 75 ms between writing the configuration register and reading the temperature register to make sure the master gets a current reading and not one that is possibly hours old (acquired from a previous write to the configuration register).
  • Hi Gunni,

     

    You are welcome.

     

    And yes you are correct; TMP100 needs that amount of time to complete the conversion.

     

    Since the typical conversion time is much shorter, another way to monitor the completion of the conversion is through the ALERT pin, assuming you are not using it as a flag to control other circuitry. This is accomplished through playing with the limit registers and creating a trigger so you’ll know when the conversion finishes.

    Regards,

    Guang-Apps Sensing Products

  • Thank you, that's what I guessed. Since our circuit (which is fixed for the time being) does not have the ALERT pin connected, I (the firmware developer as you might have guessed) shall use a timer to delay between writing the configuration register and reading the temperature register. But out of curiosity I wonder how would one do it using the limit registers. Make the low threshold higher than the high one?
  • Hi Gunni,

     

    Exactly, thereby you would create an artificial condition that guarantees that ALERT changes state after a normal temperature reading.

    Regards,

    Guang-Apps Sensing Products