Author Topic: LTC2495 readout issue, only half the measurement range is functional  (Read 2087 times)

0 Members and 1 Guest are viewing this topic.

Offline reyntjensmTopic starter

  • Regular Contributor
  • *
  • Posts: 122
  • Country: be
I'm working with a LTC2495 ADC and i'm encountering some readout issues. My result is correct for 1/2 my measurement range. If i want to measure between 0-2V, my result is correct from 0-1V, as soon as the voltage is higher than 1V the result turns out to be a negative number. I guess it has something to do with the bit endianness but i have no clue on how to fix it. The signbit is always positive as it should be.

Code: [Select]
    //read back 3 byte result
    if(!TWI_InitTransmission(address, TWI_READ)){
        return -1;
    }
    uint8_t data_temp[3];
    uint8_t bytes = TWI_ReadN(data_temp, 3);
    if(bytes != 3){
        return -1;
    }
    TWI_EndSession();

    uint8_t overflow = (data_temp[0] >> 7) & ((data_temp[0] >> 6) & 0x01); //Get overflow bit from data_temp[0]
    uint8_t signBit = (data_temp[0] >> 7 ) & 0x01;   //Get sign bit from data_temp[0]

    int32_t temp = (int32_t)((((data_temp[0] & 0x3F)<<10) | (data_temp[1] << 2) | (data_temp[2]>>6))/2);

    float Voltage = ((float)temp / 65536.0) * (float)4.096; //convert to voltage
    *data = Voltage;    //store voltage in data pointer



I hope somebody could pinpoint to my mistake.
« Last Edit: July 19, 2023, 04:35:18 pm by reyntjensm »
 

Offline dobsonr741

  • Frequent Contributor
  • **
  • Posts: 978
  • Country: us
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #1 on: July 19, 2023, 05:28:31 pm »
The ADC is giving you the readout in two's complement. Take a look at the Arduino library, not so elegant but is gets the job done:

https://github.com/NorthernWidget/LTC2495/blob/f500862ad355666da19e3d54d05acfef16ca5531/LTC2495_Library/LTC2495.cpp#L43C3-L43C3
 

Offline reyntjensmTopic starter

  • Regular Contributor
  • *
  • Posts: 122
  • Country: be
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #2 on: July 19, 2023, 05:36:58 pm »
The ADC is giving you the readout in two's complement. Take a look at the Arduino library, not so elegant but is gets the job done:

https://github.com/NorthernWidget/LTC2495/blob/f500862ad355666da19e3d54d05acfef16ca5531/LTC2495_Library/LTC2495.cpp#L43C3-L43C3

Yeah, already found that library. I already had a look at this but still couldn't figure it out. My code is almost identical.
« Last Edit: July 19, 2023, 05:43:18 pm by reyntjensm »
 

Offline tooki

  • Super Contributor
  • ***
  • Posts: 16065
  • Country: ch
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #3 on: July 19, 2023, 09:54:01 pm »
I see a few potential issues:

1. The ADC output itself: it's two's-complement formatted, centered around 1/2Vref. That means that "0V" output value is half your full-scale voltage (1/2Vref). So if you are using Vin- = 0V,
Ref- = 0V and Ref+ = 2V, applying the formula Vref = Ref+ - Ref-, you get a Vref of 2V, so the "0V" output value actually happens when Vin+ = 1/2Vref = 1V, so input voltages below 1V are output as negative values, and values above 1V are output as positive values.

Do not confuse the ADC conversion sign with the sign of the two's-complement (the MSB)! Note that this ADC's output is 16 bits plus the sign. In c data types, we normally describe the size of the datatype inclusive of the sign bit, so a 32-bit unsigned int is 32 value bits and no sign bit, and a 32-bit signed int has 31 value bits and one sign bit (the MSB). So when shifting things around, bear in mind that in the parlance of c data types, the ADC is actually outputting a "17-bit signed int" plus a separate conversion sign bit. Because one sign bit is two's-complement and the other is not, the combination of those two bits can be used to determine when the measurement range is exceeded.


2. Your data processing:

The above tells us that you have a 17-bit signed int which you need to convert to a 32-bit signed int. That means shifting the smaller number to the right, but padding the left with the MSB of the smaller number. (E.g. 4-bit 0101 -> 8-bit 0000 0101, but 4-bit 1101 -> 8-bit 1111 1101. See https://en.wikipedia.org/wiki/Sign_extension )

In C, bitwise shifting has some undefined behaviors (i.e. the behavior may vary by platform, compiler, etc), in particular regarding negative numbers.

To make sure we're on the same page, this is how I understand the data format as you're pulling it in:
byte 0: [bit 23: ADC conversion sign] [bit 22: MSB (i.e. two's complement sign)] [bits 21...16]
byte 1: [bits 15...08]
byte 2: [bit 07] [bit 06: LSB] [bits 05...00: zero padding]

What we want to end up with inside your variable temp is:
[bits 31...16: MSB repeated] [bits 15...01] [bit 0: LSB]

Right now, your MSB starts off as bit 6 of byte 0 and gets shifted 10 to the left, so at bit 16. But you need it to be at bit 31.

I'm sure a better programmer than me can provide a cleaner/more efficient way to do this, but I think this is what fundamentally needs to happen:

1. Create a uint32_t (I'll call it "rawbits").
2. OR byte 2 with rawbits.
3. Cast byte 1 to a uint32_t, shift it left by 8 bits, then OR it with rawbits.
4. Cast byte 0 to a uint32_t, shift it left by 16 bits, then OR it with rawbits.
5. Shift rawbits to the left by 9 bits.
6. OR rawbits with temp.
7. Shift temp to the right by 15 bits. This should fill to the left with the MSB.
 
The following users thanked this post: reyntjensm

Offline tooki

  • Super Contributor
  • ***
  • Posts: 16065
  • Country: ch
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #4 on: July 19, 2023, 11:09:01 pm »
The ADC is giving you the readout in two's complement. Take a look at the Arduino library, not so elegant but is gets the job done:

https://github.com/NorthernWidget/LTC2495/blob/f500862ad355666da19e3d54d05acfef16ca5531/LTC2495_Library/LTC2495.cpp#L43C3-L43C3

Yeah, already found that library. I already had a look at this but still couldn't figure it out. My code is almost identical.
It's obvious your code is copied from there with minor modifications, but bear in mind that as best I can tell, that library is not great to begin with. You copied the "overflow" code without understanding what it does: there's an overflow if bits 6 and 7 are both 1, and there's a negative overflow if they're both 0. Neither bit alone tells you there's an overflow.

As best I can tell, that code is stripping off the MSB (the two's-complement sign bit) entirely and then plunking the remaining 16 bits into a 16-bit signed int. That means that the digit next to the MSB is being used as the MSB, which works fine for -32768 to +32767, but fails for -65536...-32769 and +32768...+65535. I guess the author never came close to using their full-scale values, so never noticed they're stripping off a digit.
 

Offline tooki

  • Super Contributor
  • ***
  • Posts: 16065
  • Country: ch
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #5 on: July 26, 2023, 11:08:37 am »
Did you get it working?
 

Offline reyntjensmTopic starter

  • Regular Contributor
  • *
  • Posts: 122
  • Country: be
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #6 on: August 28, 2023, 08:59:25 pm »
Did you get it working?

Sorry for my late reply. It took some time but i got it working in the en! Do you need some help with it?
 

Offline tooki

  • Super Contributor
  • ***
  • Posts: 16065
  • Country: ch
Re: LTC2495 readout issue, only half the measurement range is functional
« Reply #7 on: August 31, 2023, 09:47:31 am »
Did you get it working?

Sorry for my late reply. It took some time but i got it working in the en! Do you need some help with it?
Nope, just curious if my datasheet analysis ended up being helpful for you! :)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->