LTC2495 readout issue, only half the measurement range is functional - Page 1
Forum section: electronics / projects

author: reyntjensm
author_rank: Regular Contributor
timestamp: July 19, 2023, 03:17:51 pm
content: 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://read back 3 byte resultif(!TWI_InitTransmission(address, TWI_READ)){return -1;}uint8_t data_temp;uint8_t bytes = TWI_ReadN(data_temp, 3);if(bytes != 3){return -1;}TWI_EndSession();uint8_t overflow = (data_temp >> 7) & ((data_temp >> 6) & 0x01); //Get overflow bit from data_tempuint8_t signBit = (data_temp >> 7 ) & 0x01; //Get sign bit from data_tempint32_t temp = (int32_t)((((data_temp & 0x3F)<<10) | (data_temp << 2) | (data_temp>>6))/2);float Voltage = ((float)temp / 65536.0) * (float)4.096; //convert to voltage*data = Voltage; //store voltage in data pointerI hope somebody could pinpoint to my mistake.

author: dobsonr741
author_rank: Frequent Contributor
timestamp: July 19, 2023, 05:28:31 pm
content: 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

author: reyntjensm
author_rank: Regular Contributor
timestamp: July 19, 2023, 05:36:58 pm
content: Quote from: dobsonr741 on July 19, 2023, 05:28:31 pmYeah, already found that library. I already had a look at this but still couldn't figure it out. My code is almost identical.

author: tooki
author_rank: Super Contributor
timestamp: July 19, 2023, 09:54:01 pm
content: 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 ishalf 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 bitsplus the sign. In c data types, we normally describe the size of the datatypeinclusive of the sign bit, so a 32-bit unsigned int is 32 value bits and no sign bit, and a 32-bit signed int has31value 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 aseparateconversion 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-bit0101 -> 8-bit0000 0101, but 4-bit1101 -> 8-bit1111 1101. Seehttps://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 variabletempis:[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 withrawbits.3. Cast byte 1 to a uint32_t, shift it left by 8 bits, then OR it withrawbits.4. Cast byte 0 to a uint32_t, shift it left by 16 bits, then OR it withrawbits.5. Shiftrawbitsto the left by 9 bits.6. ORrawbitswithtemp.7. Shifttempto the right by 15 bits. This should fill to the left with the MSB.

author: tooki
author_rank: Super Contributor
timestamp: July 19, 2023, 11:09:01 pm
content: Quote from: reyntjensm on July 19, 2023, 05:36:58 pmIt'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 anegativeoverflow 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.

author: tooki
author_rank: Super Contributor
timestamp: July 26, 2023, 11:08:37 am
content: Did you get it working?

author: reyntjensm
author_rank: Regular Contributor
timestamp: August 28, 2023, 08:59:25 pm
content: Quote from: tooki on July 26, 2023, 11:08:37 amSorry for my late reply. It took some time but i got it working in the en! Do you need some help with it?

author: tooki
author_rank: Super Contributor
timestamp: August 31, 2023, 09:47:31 am
content: Quote from: reyntjensm on August 28, 2023, 08:59:25 pmNope, just curious if my datasheet analysis ended up being helpful for you!