Post Go back to editing

LTC6804-2 Non-linear/Incorrect Voltage Readings

Category: Hardware
Product Number: LTC6804-2

We're building a BMS using an LTC6804-2 with an Arduino Micro connected over SPI (non-iso). We've attached a schematic and Arduino code below.

Our LTC6804-2 chips have been giving us jumping/non-linear voltage readings for all 12 Cells.

As for the discontinuities, when cell voltages are higher than 3.277 V (2^15 *0.1 mV) the measurements are close to correct, but between 1.625 V and 3.250 V, they read as 1.625 V lower than their true value, which could be the result of a bit error in the reading or otherwise missing certain bits. At lower voltages there are also numerous discontinuities in the reading. The readings are all stable for a given input, they're just often wrong. For the primary issue, it seems that the second most significant bit is remaining 0 for the lower half of the range, where it should be switching to 1 for the second quarter of the range.

We also noticed that as we increased the voltage above 3.300 V, the voltages started to level off and become non-linear. The non-linear readings have a big effect on the overall accuracy - E.g. 3.50 V, 4.0 V and 4.5 V all get read as ~3.4 V, so we we are unable to monitor accurately.

The fact that the readings are able to be correct at certain values indicates that the chip/board connections should all be correct, along with SPI communication and the Arduino code.

We have tried the following with no luck:

  • Tried multiple chips and batteries
  • Changing SPI clock frequencies to 500 kHz down from 1 MHz
  • Changing the set_adc speeds to all 6 configurations
  • Changing the WRCFG array to most conceivable configurations (with/without under/overvoltage protect values, GPIO's on/off, REFON/SWTRD/ADCOPT on/off, DCTO[3] on/off)
  • Reading individual registers using LTC6804_rdcv_reg (still see bad values)
  • Shorting the SWTEN pin to Vref
  • Removing all floats etc from the Arduino code and checking the conversions before it is sent as a CAN message and using different rewriting methods.

Any help would be dearly appreciated.



  • It sounds like you're experiencing voltage saturation, which can occur when the voltage being measured exceeds the range of the analog-to-digital converter (ADC) on the microcontroller. When this happens, the ADC output becomes non-linear and inaccurate, which can make it difficult to measure the voltage accurately.

    To address this issue, you could consider:

    1. Using a voltage divider circuit to reduce the input voltage to within the range of the ADC. A voltage divider consists of two resistors in series, with the input voltage applied across the resistors and the output voltage taken from the junction between them. By choosing appropriate resistor values, you can create a voltage divider that scales the input voltage down to a level that the ADC can handle.

    2. Using an external ADC with a higher input voltage range. Many external ADCs are available with higher input voltage ranges than the built-in ADC on microcontrollers. You could connect one of these ADCs to your microcontroller and use it to measure the voltage accurately.

    3. Reducing the voltage range of the input signal. If you can't use a voltage divider or external ADC, you could try reducing the voltage range of the input signal by using a voltage regulator or a zener diode to clamp the voltage to a lower level.

    It's worth noting that the accuracy of the voltage measurements can also be affected by noise, so you should ensure that the input signal is filtered and free from any electrical interference.

  • Try reducing R16 to 3.3kohm or reducing your communication speed.  Depending on layout 5kohm may not be sufficient for 1mbps communication.

    I also don't see a 100nF capacitor to GND on the V+ pin after the 100R from cell 12 input.  This too could cause multiplexer and ADC reference problems.

  • Thank you for your recommendation. We attempted each of these solutions. (100n capacitor, 3.3k resistor, and reducing comm. speed to 500k) Unfortunately, the problem has persisted as we described in the original post.

    Are there any other configurations in hardware or software which you think could cause this problem?

  • Thanks for your detailed reply. We checked for each pin that the input voltage was within the range of the ADC (based on the datasheet and measurements of Vreg). Do you know any other problems which might cause this behavior?

  • Where does V+ come from?  I'm struggling to find it in the schematic.  It's important that it is the same DC voltage as the top of the battery stack.  If it goes too far below, the multiplexer will stop working (see mux decoder check on datasheet p27).

    But the first problem still sounds like bit errors to me.  Checking that the received PEC code is correct will help to debug whether it's actually a bit error or not.  If it is, the next place I'd probably look is the clock duty cycle.

  • Thank you very much again - We did indeed find a PEC error so it is almost certainly bit errors occurring during SPI comms. That portion of the code wasn't triggering before due LTC6804_rdcv being assigned as an unsigned int in the header file instead of a signed int - so setting the pec_error to -1 would return 255 instead of -1. Anyway, we will now look at the clock duty cycle and other SPI settings as you suggest.

    If you have any other recommendations, this being the case, we'd deeply appreciate it. Thank you so so much again!

    (V+ can be found on the first page of our schematic kind of between and below the two chips U6 and IC2, we believe it should be okay)

  • I see now.  I don't see a 100nF capacitor on V+, it's important that one is somewhere after the 100R to provide power when the IC draws variable amounts of current.  This may also contribute to the problem as V+ is used to derive DRIVE and the primary ADC reference.

    See the reference schematic for an example of how V+ should be connected to the top cell:

  • We have since done this, along with reducing the 5k pull-up to 3.3k, but neither have effected the PEC issue yet unfortunately. We're continuing to try to change the SPI settings. - Thank you very much again

  • We found that somewhere in the header files the SPI rate was being set to 4 MHz - we added the following line at the beginning of our void loop which fixed the issue:

    SPI.setClockDivider(SPI_CLOCK_DIV16); // Set clock divider to 16 for 1 MHz SPI clock

    Thank you again!!