EEVblog Electronics Community Forum

Electronics => Projects, Designs, and Technical Stuff => Topic started by: scttnlsn on May 12, 2017, 06:34:03 pm

Title: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on May 12, 2017, 06:34:03 pm
I've tried replicating the circuit described in https://www.eevblog.com/forum/projects/correct-way-to-measure-high-voltage-battery-pack/msg248302/ (https://www.eevblog.com/forum/projects/correct-way-to-measure-high-voltage-battery-pack/msg248302/) but I'm having some issues and hoping someone can help me out.

I have 4 LiFePO4 cells in series and I'm using LT1990 precision differential amps to try and monitor the voltage of each cell.  All 4 cells are currently at 3.35V and I've attached a schematic of my circuit.

I was getting some unexpected readings:

VCELL2 = 3.418V
VCELL3 = 3.395V
VCELL4 = 3.344V

And so I tried it out with the separate +12V and -5V rails (as shown in https://www.eevblog.com/forum/projects/correct-way-to-measure-high-voltage-battery-pack/msg248302/ (https://www.eevblog.com/forum/projects/correct-way-to-measure-high-voltage-battery-pack/msg248302/)) and some bypass caps.  Here's what I'm getting with the split supply:

VCELL2 = 3.342V
VCELL3 = 3.271V
VCELL4 = 3.344V

That still doesn't seem right to me since those values are pretty far outside the expected error of the amp.  Does anyone have any advice for me?

Thanks a lot!
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: tatus1969 on May 12, 2017, 07:29:10 pm
can't see anything obviously wrong. You do nothing that the chip shouldn't be able to do. Maybe a problem somewhere else? Are you loading the battery during your test? That could cause voltage drops and ground offsets. How did you measure the true voltage, how the opamp result?

I see that these chips are quite expensive. Maybe this one is an alternative solution: BQ76925. I have tested source code for it.
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on May 12, 2017, 07:39:56 pm
The only load on the cells with the +13.4V supply is the LT1990s themselves.  When testing with the +12V/-5V I was using a separate supply and so there was no load at all on the battery.  The cells are all brand new and so I expect the internal resistance of each to be quite low.

I measured the true voltage of each cell with a multimeter directly across the cell terminals and read 3.350V (+/- 0.001V) for each.  When reading the output of the amps I'm using the same multimeter with COM connected to GND and I probe the OUT pin of the LT1990s.

I began playing around with the BQ76920.  Would be interested to see the code you're using for the BQ76925 if you don't mind sharing it.

Thanks!
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: tatus1969 on May 12, 2017, 07:58:57 pm
no problem, here it is (STM32 family). It is a bit interwoven with the rest of the module through some globals (e.g. time = 0.5ms tick, fCellConversion = raw 10 bit ADC conversion result from VCOUT pin, VCC=3.3V), but I hope it is still clear enough.

Code: [Select]
float fCellConversion = 0;
float fCellVoltageRaw[6] = {0,0,0,0,0,0};
float fCellVoltage[6] = {0,0,0,0,0,0};
float fRefOffset = 0;
float fRefGain = 0;
float fAdcGain = 0;
float fCellOffset[6] = {0,0,0,0,0,0};
float fCellGain[6] = {0,0,0,0,0,0};
float fBalTemp = 0;
bool balPresent = FALSE;
enum
{
  CHECK_CHARGER,
  CHECK_CONNECTION,
  MEASURE_VREF,
  MEASURE_V0,
  MEASURE_V1,
  MEASURE_V2,
  MEASURE_V3,
  MEASURE_V4,
  MEASURE_V5,
  MEASURE_TEMP,
  DO_BALANCING,
} balState = CHECK_CONNECTION;
uint32_t balSwitches = 0;
bool bChargerConnected = FALSE;
uint32_t timeout_bal = 0;
uint32_t timeout_chrg_check = 0;
bool bBalSwap = FALSE;
bool bChargeEnable = FALSE;
bool bChargeComplete = FALSE;

///////////////////////////////////////////////////////////////////////////////

void waitTicks( uint32_t ticks )
{
  uint32_t then;
 
  then = time + ticks;

  while( (int32_t)(then - time) > 0 );
}

///////////////////////////////////////////////////////////////////////////////

void wait( float delay )
{
  waitTicks( (uint32_t)(delay / TIME_STEP) );
}

///////////////////////////////////////////////////////////////////////////////

bool WaitI2CEvent( uint32_t flag )
{
  uint32_t event, timeout = 1000;
 
  do
  {
     event = I2C_GetLastEvent(I2C1);
     if( !--timeout )
     {
       return FALSE;
     }
  }
  while( (event & flag) == 0 );
 
  return TRUE;
}

///////////////////////////////////////////////////////////////////////////////

void WriteBalancer( uint8_t reg, uint8_t value)
{
  I2C_GenerateSTART(I2C1, (FunctionalState)ENABLE);
  if( !WaitI2CEvent(I2C_FLAG_SB) )
  {
    I2C_GenerateSTOP(I2C1, (FunctionalState)ENABLE);
    return;
  }

  I2C_Send7bitAddress(I2C1, (0x20 | reg) << 1, I2C_Direction_Transmitter);
  if( !WaitI2CEvent(I2C_FLAG_ADDR) )
  {
    I2C_GenerateSTOP(I2C1, (FunctionalState)ENABLE);
    return;
  }

  I2C_SendData(I2C1, value);
  WaitI2CEvent(I2C_FLAG_BTF);

  I2C_GenerateSTOP(I2C1, (FunctionalState)ENABLE);
  while( I2C_GetLastEvent(I2C1) & I2C_FLAG_BUSY );
}


///////////////////////////////////////////////////////////////////////////////

uint8_t ReadBalancer( uint8_t reg )
{
  uint8_t result;
 
  I2C_GenerateSTART(I2C1, (FunctionalState)ENABLE);
  if( !WaitI2CEvent(I2C_FLAG_SB) )
  {
    I2C_GenerateSTOP(I2C1, (FunctionalState)ENABLE);
    return 0;
  }
 
  I2C_Send7bitAddress(I2C1, (0x20 | reg) << 1, I2C_Direction_Receiver);
  if( !WaitI2CEvent(I2C_FLAG_BTF) )
  {
    I2C_GenerateSTOP(I2C1, (FunctionalState)ENABLE);
    return 0;
  }
 
  result = I2C_ReceiveData(I2C1);
 
  I2C_GenerateSTOP(I2C1, (FunctionalState)ENABLE);
  while( I2C_GetLastEvent(I2C1) & I2C_FLAG_BUSY );
 
  return result;
}

///////////////////////////////////////////////////////////////////////////////

int32_t compl2( uint32_t number, uint32_t bits )
{
  number &= ( 1 << bits ) - 1;
  if( number & (1 << (bits - 1) ) )
   return (int32_t)number - (int32_t)(1 << bits);
  else
   return (int32_t)number;
}

///////////////////////////////////////////////////////////////////////////////

enum
{
  BAL_STATUS = 0x00,
  BAL_CELL_CTL,
  BAL_BAL_CTL,
  BAL_CONFIG_1, 
  BAL_CONFIG_2, 
  BAL_POWER_CTL, 
  BAL_CHIP_ID = 0x07, 
  BAL_VREF_CAL = 0x10, 
  BAL_VC1_CAL, 
  BAL_VC2_CAL, 
  BAL_VC3_CAL, 
  BAL_VC4_CAL, 
  BAL_VC5_CAL, 
  BAL_VC6_CAL, 
  BAL_VC_CAL_EXT1, 
  BAL_VC_CAL_EXT2, 
  BAL_VREF_CAL_EXT = 0x1B, 
};

void updateBalancer( void )
{
  I2C_InitTypeDef I2C_InitStruct;
  uint8_t reg1, reg2;
  uint16_t reg3;
  float fBalTempRaw;
 
  // wait balancer discharging period before performing next action
  if( timeout_bal > time )
  {
    return;
  }

  // stop balancing in case it is enabled
  WriteBalancer( BAL_BAL_CTL, 0 );

  // check if all cells are full and balanced
  bChargeComplete = TRUE;
  for( int i=0; i<6; i++ )
  {
      bChargeComplete &= (fCellVoltage[i] >= 4.19f) && (fCellVoltage[i] <= 4.21f);
  }
 
  // control charging switch based on charger presence, cell voltages, temperature, and balancer activity
  bChargeEnable = ( balPresent
                 && bChargerConnected
                 && !bChargeComplete
                 && (fBattTemp < 50.0f)
                 && (balSwitches == 0) ) ? TRUE:FALSE;
  if(bChargeEnable)
  {
    GPIO_WriteBit( GPIOB, GPIO_CHRG_EN, Bit_SET );
  }
  else
  {
    GPIO_WriteBit( GPIOB, GPIO_CHRG_EN, Bit_RESET );
  }
 
  // work through balancer state machine
  switch( balState )
  {
  //////////////////////////////////////////////////////////////////////////////
  case CHECK_CHARGER:

    // periodically check if charger is still connected
    if( time > timeout_chrg_check )
    {
      // This disconnects the charger voltage from the bus voltage,
      // which is necessary to detect if the charger is still connected.
      GPIO_WriteBit( GPIOB, GPIO_CHRG_EN, Bit_RESET );
     
      // allow some time to discharge input capaticance
      waitTicks(20);
     
      // check if charger is connected
      bChargerConnected = (fChrgVoltage > 24.0f) ? TRUE:FALSE;
     
      // update timeout for next check
      timeout_chrg_check += (uint32_t)(5.0f / TIME_STEP);
    }
    // loop through all states again
    balState = CHECK_CONNECTION;
    break;
   
  //////////////////////////////////////////////////////////////////////////////
  case CHECK_CONNECTION:
    if( ReadBalancer( BAL_CHIP_ID ) == 0x10 )
    {
      WriteBalancer( BAL_CONFIG_2,  0x01 ); // VCOUT gain 0.6, VREF  = 3.0V nom
      WriteBalancer( BAL_POWER_CTL, 0x47 ); // SLEEP_DIS, vc+ref+thermistor enabled
     
      // Calculate VREF offset and gain
      reg1 = ReadBalancer( BAL_VREF_CAL );
      reg2 = ReadBalancer( BAL_VREF_CAL_EXT );
      fRefOffset =        (float)compl2( ((reg2 & 0x06) << 3) | (reg1 >> 4  ), 6 ) * 0.001f;
      fRefGain   = 1.0f + (float)compl2( ((reg2 & 0x01) << 4) | (reg1 & 0x0F), 5 ) * 0.001f;
     
      // Calculate VC[0..5] offset and gain
      reg1 = ReadBalancer( BAL_VC_CAL_EXT1 );
      reg2 = ReadBalancer( BAL_VC_CAL_EXT2 );
      reg3 = ((uint16_t)(reg1 & 0xF0) << 4) | reg2;
      for( int i=0; i<6; i++ )
      {
        reg1 = ReadBalancer( BAL_VC1_CAL + i );
        fCellOffset[i] =        (float)compl2( (((reg3 >> (11 - 2*i)) & 0x01 ) << 4) | (reg1 >> 4  ), 5 ) * 0.001f;
        fCellGain  [i] = 1.0f + (float)compl2( (((reg3 >> (10 - 2*i)) & 0x01 ) << 4) | (reg1 & 0x0F), 5 ) * 0.001f;
      }
     
      balPresent = TRUE;

      // connection successful, continue with next state
      balState = MEASURE_VREF;
    }
    else
    {     
      fCellVoltage[0] =
      fCellVoltage[1] =
      fCellVoltage[2] =
      fCellVoltage[3] =
      fCellVoltage[4] =
      fCellVoltage[5] = 0;

      // perform I2C reset in case of lockup
      I2C_Cmd(I2C1, (FunctionalState)DISABLE);
      I2C_SoftwareResetCmd( I2C1, (FunctionalState)ENABLE );
      I2C_SoftwareResetCmd( I2C1, (FunctionalState)DISABLE );
      I2C_InitStruct.I2C_ClockSpeed          = 50000;
      I2C_InitStruct.I2C_Mode                = I2C_Mode_I2C;
      I2C_InitStruct.I2C_DutyCycle           = I2C_DutyCycle_2;
      I2C_InitStruct.I2C_OwnAddress1         = 0;
      I2C_InitStruct.I2C_Ack                 = I2C_Ack_Disable;
      I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
      I2C_Init(I2C1, &I2C_InitStruct);
      I2C_Cmd(I2C1, (FunctionalState)ENABLE);

      balPresent = FALSE;
     
      // balancer does not respond, back to charger detection
      balState = CHECK_CHARGER;
    }   
    break;
   
  //////////////////////////////////////////////////////////////////////////////
  case MEASURE_VREF:
    WriteBalancer( BAL_CELL_CTL, 0x30 ); // VREF * 0.85
    waitTicks(5);
    fAdcGain = ( ( 3.0f * fRefGain + fRefOffset ) * 0.85f ) / fCellConversion;
   
    if( fAdcGain < 20e-6 ||  fAdcGain > 80e-6 )
    {
      // value out of range, assume problem with balancer and restart
      balState = CHECK_CHARGER;
    }
    else
    {
      // continue with next state
      balState = MEASURE_V0;
    }
    break;
   
  //////////////////////////////////////////////////////////////////////////////
  case MEASURE_V0:
  case MEASURE_V1:
  case MEASURE_V2:
  case MEASURE_V3:
  case MEASURE_V4:
  case MEASURE_V5:
    WriteBalancer( BAL_CELL_CTL, 0x10 | (balState - MEASURE_V0) ); // VC[0..5]
    waitTicks(5);
    fCellVoltageRaw[balState - MEASURE_V0] =
      ( fCellConversion * fAdcGain + fCellOffset[balState - MEASURE_V0] ) * fCellGain[balState - MEASURE_V0] / 0.6f;

    balState++;
    break;
   
  //////////////////////////////////////////////////////////////////////////////
  case MEASURE_TEMP:
    WriteBalancer( BAL_CELL_CTL, 0x16 ); // Vtemp,int
    waitTicks(5);
    fBalTempRaw = 25.0f - ( ( fCellConversion * fAdcGain - 1.2f ) * 1.35f /*+++ datasheet gain and offset seem to be wrong? */ ) / 4.4e-3f;
    if( fBalTemp == 0.0f )
    {
      fBalTemp = fBalTempRaw;
    }
    else
    {
      fBalTemp = fBalTemp * 0.9f + fBalTempRaw * 0.1f;
    }

    // continue with next state
    balState = DO_BALANCING;
    break;
   
  //////////////////////////////////////////////////////////////////////////////
  case DO_BALANCING:
    // update cell voltage values
    for( int i=0; i<6; i++ )
    {
      if( fCellVoltageRaw[i] > 0.0f && fCellVoltageRaw[i] < 10.0f )
      {
        if( fCellVoltage[i] == 0 )
        {
          fCellVoltage[i] = fCellVoltageRaw[i];
        }
        fCellVoltage[i] = fCellVoltage[i] * 0.9f + fCellVoltageRaw[i] * 0.1f;
      }
    }

    // perform balancing as necessary
    balSwitches = 0;
    if( !bChargeComplete )
    {
      // check which cell needs balancing
      for( int i=0; i<6; i++ )
      {
        if( fCellVoltage[i] > 4.2f  )
        {
          balSwitches |= (1<< i);
        }
      }
     
      // adjacent cells cannot be balanced simultaneously
      if( bBalSwap )
      {
        bBalSwap = FALSE;
       
        balSwitches &= ~((balSwitches & (1+4+16)) << 1);
        balSwitches &= ~((balSwitches & (1+4+16)) >> 1);
      }
      else
      {
        bBalSwap = TRUE;

        balSwitches &= ~((balSwitches & (2+8+32)) << 1);
        balSwitches &= ~((balSwitches & (2+8+32)) >> 1);
      }
     
      // apply balancing
      if( balSwitches )
      {
        WriteBalancer( BAL_BAL_CTL, balSwitches );
       
        // start 1 sec discharge timer
        timeout_bal = time + (uint32_t)(1.0f / TIME_STEP);
      }
    }
   
    // continue with next state
    balState = CHECK_CHARGER;
    break;
   
  //////////////////////////////////////////////////////////////////////////////
  default:
    while(1);
  }
}

Depending on what you want to do, this solution could also be an option:

https://www.eevblog.com/forum/projects/introducing-my-project-'kicksurfer'/msg1203499/#msg1203499 (https://www.eevblog.com/forum/projects/introducing-my-project-'kicksurfer'/msg1203499/#msg1203499)
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on May 12, 2017, 08:10:40 pm
Thanks.  I'll take a look at both of those.

I'd still like to get the LT1990 circuit figured out so if anyone else has suggestions, I'm all ears.
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: digsys on May 15, 2017, 12:24:56 am
Quote from: scttnlsn
I'd still like to get the LT1990 circuit figured out so if anyone else has suggestions, I'm all ears.
Just a bit busy right now, but I'll definitely sort it out in a couple hrs-ish. They are slightly tricky to use, but I've never had an issue with them - awesome chips.
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: digsys on May 15, 2017, 01:22:41 pm
Some notes: I found that the LT1990 definitely needs a -ve rail, irrespective of what the specs say. The MAX1044 cct I posted is simple and very efficient.
You say you did try the separate 12V and -5V rails. Was it as per my posted cct? 0V must be referenced to all supply rails and Battery Pack 0V?
The full circuit / layout details are in my gallery - www.pbase.com/digsys/image/161061592/original (http://www.pbase.com/digsys/image/161061592/original)
I'm assuming you're checking against a reasonably accurate DMM? Did you have a rf cap and 50-100K resistor across the inputs? as per my cct. I find it helps a lot
with surface noise, especially when there is NO load. Have you run a check against a DMM, on the cells? - without a load AND with a say 100mA load.
I can't see anything obvious at this point, so we'd need more test results. As I said, never had a problem with accuracy once I sorted those couple issues.
Post back and I'll investigate further.
There are other lower voltage diff-amps in that series - " LT1990, LT1991, LT1995, LT1996 - one of the others may suit you better "
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on May 15, 2017, 07:39:37 pm
Yes, I'm using separate +12V and -5V rails for the V+ and V- pins on the LT1990s.  I'm not using the MAX1044 at this point but rather just using two external power supplies to provide the two voltages.  I tried everything again and this time added some 51K resistors across the cells (did not have those before).  Updated schematic is attached.

With no load:

cell # / cell voltage / amp output
1 / 3.333 / N/A
2 / 3.335 / 3.324
3 / 3.338 / 3.330
4 / 3.339 / 3.287

With constant 100mA load:

cell # / cell voltage / amp output
1 / 3.329 / N/A
2 / 3.330 / 3.315
3 / 3.332 / 3.319
4 / 3.330 / 3.278

I think those resistors improved the accuracy but some of these values still seem a bit far off to me.  I'm probing the output of each LT1990 with a Uni-T UT61E.  COM is connected to GND and the other probe on the output pin of the LT1990s.

Thanks for the full schematic.  Curious what sort of accuracy you typically see on the outputs of these amps?  Also, I'm curious to hear more about the reason for those 50K resistors.  How are they helping and what have you seen in the past without them?

Thanks for your help!
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: digsys on May 15, 2017, 11:26:19 pm
Quote from: scttnlsn
1 / 3.333 / N/A        1 / 3.329 / N/A
2 / 3.335 / 3.324     2 / 3.330 / 3.315
3 / 3.338 / 3.330     3 / 3.332 / 3.319
4 / 3.339 / 3.287     4 / 3.330 / 3.278
I think those resistors improved the accuracy but some of these values still seem a bit far off to me.  I'm probing the output of each LT1990 with a Uni-T UT61E.  COM is connected to GND and the other probe on the output pin of the LT1990s.
Thanks for the full schematic.  Curious what sort of accuracy you typically see on the outputs of these amps?  Also, I'm curious to hear more about the reason for those 50K resistors.  How are they helping and what have you seen in the past without them? 
To answer your last question - 2 reasons - 1/Surface charge / ion migration. Unloaded cells (pretty much all types) suffer charge migration when they go off load.
This gives false readings as to the actual voltage. A perfect example (but for a different reason) is - Put a cell under heavy load, remove the load - and track the voltage.
It starts to climb for a while, and eventually sort of stabilizes. But ion movement / charge is still occurring. I chose 50K as a compromise, during a race, I go as low as <10K.
During the huge dynamics of a race, I need to know the cell voltages pretty accurately, and can't wait for things to settle ??
2/ RF noise. We have huge amounts of noise from our 1.2KW solar MPPTs and 20KW 3phase motor controller. You do your best to minimize it, but it's pretty impossible to get rid
of it all. The RC helps a lot. My new packs have RF/caps on every cell (module). Very few chemistries can handle switching / line noise above a few / several 100Hz
Without this dampening, I've recorded up to 40V ripple on a 180VDC pack. Even though this may be for a special case ie solar race car, I do it on EVERY pack I make,
regardless of the use. Just a safety precaution.
Going back to your problem - not sure - The readings are better, as you say, but I can't think of a reason right now. ALl ours are accurate to app 0.1% and up to 1-2-3% under
extreme dynamics, but that's expected. Maybe try one of the other ICs in that familly I listed? Guess it's back to leg work :-)
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: tatus1969 on May 16, 2017, 08:47:58 am
if your problem is noise, then I would add an RC filter like below. What you have drawn in your last schematic is not yet that. Basically all BMS IC manufacturers do it like this.

(https://www.eevblog.com/forum/projects/introducing-my-project-'kicksurfer'/?action=dlattach;attach=313987)
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on May 16, 2017, 02:59:17 pm
Thank you both for your suggestions and explanations.  I'll continue to play around and try different things and will post back if I discover something that works.  I'll also take a look at those other LT parts.

In the meantime I have a TI BQ769x0 BMS IC that is doing the trick.
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: digsys on May 16, 2017, 10:13:49 pm
Yeah, it's an tough one. Maybe a ground path issue? after all, your down in the mVs. Maybe a decoupling issue? At least you know the chip works, so go from there.
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: prandov on September 14, 2017, 09:24:00 pm
Did you come up with a configuration that worked and were ever you able to stabilize your measurements with the LT1990? Also, would adding a 1V offset eliminate the need for the -5V?
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on September 20, 2017, 12:41:30 pm
I never got the LT1990 configuration working well enough and ended up going with a completely different approach (optoisolated ADC per cell)
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: prandov on September 25, 2017, 03:44:37 pm
I've been using regular LM662 op-amps set up as difference amplifiers powered by B+. It works reliably for 8s batteries, but was hoping to find a more integrated solution. As you discovered, the LT 1990 seems like a great choice.
Did you try any of the TI or Analog options - Like the INA149 or the AD8479?
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: scttnlsn on September 25, 2017, 07:50:57 pm
No, I did not try either of those, though they both look promising.  Would be curious to hear back if you give them a shot.
Title: Re: Measuring cell voltages in series pack with LT1990
Post by: jvspin on November 14, 2017, 10:34:34 pm
Apologies for resurrecting an old topic but I was curious where the LT1990 was being used and came across this thread.

The input range specifications on the datasheet imply the LT1990 needs the inputs to the internal amplifier to be at least 1V above V- and 0.85V below V+ for the part to operate correctly.

In your circuit, tying both the reference pin (1) and V- (4) to ground would put the internal amplifier inputs to at best, 0.496V above V- due to the 1M:38.3k resistor divider.
13.4V (top of the stack)/27=0.496V. This will not work correctly.

If you use the formula in the datasheet and plug VREF=0V into the equation you get an input range of 27V to 112V on a single +5V,0V supply.

The part should work fine in your circuit on +12V/-5V supplies with the REF pins at ground. I can think of two possible reasons for the errors you're seeing.

1) The most likely reason is that the reference pins from each part are not tied together before going to a single ground point. The output voltage of each part is referred to it's REF pin, so any error voltage on the REF pin due to currents flowing in the line to ground will show up as an error in the output.

To check if this is the problem, instead of measuring from the output of each LT1990 to ground, measure from each part's output to its reference input (pin 1).

2) The Gain1 and Gain2 pins are not completely open. Any currents from these pins can cause a gain error.