Post Go back to editing

LTC6803-1 - SPI Communication (Voltage Reading from monitor)

Category: Hardware
Product Number: LTC6803-1

Hi,

I developed an active cell balancing board with ltc6803-1 monitor and right now I'm testing it. I followed the demo board schematic for PCB design:

I used a 1M pull-up resistor for all SPI signals (as AD suggestion), as well a 1k pull up resistor for host device (in my case a Teensy 4.1).

Moreover, I'm using the following .cpp and .h ltc6803 (https://github.com/analogdevicesinc/Linduino/tree/master/LTSketchbook/libraries/LTC68031) for coding.

I came across with a problem (explained below), but right now I don't know if it is a HW or SW problem.

Problem description:

My code is straightforward -> I wrote a struct that holds the configuration registers as following:

// This struct contains the 8 bit configurations registers from 0 to 5
typedef struct config_register_group
{
    uint8_t CFGR0;      //10011001  [WDT,GPIO2, GPIO1, LVL PL, CELL10, CDC2, CDC1, CDC0] (Level Polling is enabled!) Cell bit 10 is low when 12 cell are used
    uint8_t CFGR1;     //00000000   [Discharge Cells]
    uint8_t CFGR2;    //1111000     [MC4I, MC3I, MC2I, MC1I, DCC12, DCC11, DCC10, DCC9]
    uint8_t CFGR3;     //11111111   [MC12, MC11, MC10, MC9, MC8, MC7, MC6, MC5]
    uint8_t CFGR4;    // VUV (2.9V) see  table 13 page 24152
    uint8_t CFGR5;    // VOV (4.2V) see  table 13 page 24

}_CONFIGURATION_REGISTER_GROUP;

_CONFIGURATION_REGISTER_GROUP initial_configs = {.CFGR0 = 153, .CFGR1 = 0, .CFGR2 = 240, .CFGR3 = 255, .CFGR4 = 100, .CFGR5 = 200}; //.CFGR4 = 100, .CFGR5 = 200
//10001010 //00000000 //1111000 //11111111 //(2.9V) see  table 13 page 24 //(4.2V) see  table 13 page 24

Then, at Setup(), I'm making the SPI initialization (with SPI.h library)

void LTC6803_initialize()
{

   /* SPI Pin Assignment is done at pins_arduino.h as defautl ones
    * 10 - SS
    * 11 - MOSI
    * 12 - MISO
    * 13 - SCK
   */

  SPI.begin(); // Start SPI communication
  //  LTC6803-1 Runs at 1MHz, MSB first, SPI mode 3
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE3)); // Start SPI transaction
  SPI.setClockDivider(SPI_CLOCK_DIV32);
  SPI.setDataMode(SPI_MODE3);
  SPI.setBitOrder(MSBFIRST);
}

On the loop function I'm trying to write the configurations and then read them back. For that, firstly I'm using the write configuration function:

void LTC6803_wrcfg(uint8_t total_ic,uint8_t config[][6])
{
  uint8_t BYTES_IN_REG = 6;
  uint8_t CMD_LEN = 2 + ( 7*total_ic );
  uint8_t *cmd;
  uint16_t cfg_pec;
  uint8_t cmd_index; //command counter

  cmd = (uint8_t *)malloc(CMD_LEN*sizeof(uint8_t));

  cmd[0] = 0x01; //Write configuration - Code
  cmd[1] = 0xc7; //Write configuration - PEC

  cmd_index = 2;

  for (uint8_t current_ic = total_ic; current_ic > 0; current_ic--)
  {
    //Debugging
    Serial.println("Initial Configuration Send from uC to Monitor: ");
    for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
    {
      cmd[cmd_index] = config[current_ic-1][current_byte];
      Serial.print(cmd[cmd_index]); Serial.println(" "); // Debugging
      cmd_index = cmd_index + 1;

    }
    cfg_pec = pec8_calc(BYTES_IN_REG, &config[current_ic-1][0]);    // calculating the PEC for each ICs configuration register data
    Serial.print("CFG PEC LTC_wrcfg: "); Serial.println(cfg_pec); // Debugging
    cmd[cmd_index ] = (uint8_t)cfg_pec;
    cmd_index = cmd_index + 1;
   
  }

and then read configurations value:

//brief Function that reads configuration of LTC6803-1/-3
int8_t LTC6803_rdcfg(uint8_t total_ic, //Number of ICs in the system
                     uint8_t r_config[][7] //A two dimensional array that the function stores the read configuration data.
                    )
{
  uint8_t BYTES_IN_REG = 7;

  uint8_t cmd[2];
  uint8_t *rx_data;
  int8_t pec_error = 0;
  uint8_t data_pec;
  uint8_t received_pec;

  rx_data = (uint8_t *) malloc((BYTES_IN_REG*total_ic)*sizeof(uint8_t));

  //1
  cmd[0] = 0x02; //Table 6 - Command Code
  cmd[1] = 0xCE; //Table 6 - PEC Byte


  output_low(SS);
  spi_write_read(cmd, 2, rx_data, (BYTES_IN_REG*total_ic));         //Read the configuration data of all ICs on the daisy chain into
  delay(0.15);
  output_high(SS);                          //rx_data[] array


  for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++)       //executes for each LTC6803 in the daisy chain and packs the data
  {
    //into the r_config array as well as check the received Config data
    //for any bit errors
    //4.a
    for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
    {
      r_config[current_ic][current_byte] = rx_data[current_byte + (current_ic*BYTES_IN_REG)];
      Serial.print("Read Configuration: "); Serial.print(r_config[current_ic][current_byte]); Serial.println(" "); // Debugging
    }
    //4.b
    received_pec =  r_config[current_ic][6];
    data_pec = pec8_calc(6, &r_config[current_ic][0]);
    if (received_pec != data_pec)
    {
      pec_error = -1;
    }
  }

Unfortunately, the Serial.print("Read Configuration: "); Serial.print(r_config[current_ic][current_byte]); is always 255 (overflow...) for every 6 cells!
I'm getting a little bit frustrated with that, so I'm begging for help!!!

If any information is missing for helping me, please let me know and I will send as soon as possible.

Best regards,
Henrique



Change post title to be more suggestive
[edited by: Hfree at 3:51 PM (GMT -4) on 4 Jun 2024]
  • I see this is a communication issue. can try probing the SPI lines and see the SPI frame if all the clocks and signal level are coming correct

  • Hello  ,

    Thank you in advance for your help!

    Two weeks ago I noticed that I made some mistakes, but it took me some time to realize.

    Problems:

    1) The digital isolador and all the Pull up resistors for SPI were supplied by LTC6803 Vreg and I missed that Vreg can only source 4mA.

    The digital isolator by itself needs almost 10mA for all channels to work properly at 1MHz.

    My solution was installing a DC/DC isolated Power supply (3V3/5V) to supply the isolated.

    2) I'm not sure if it could be a problem, but the AD recommendation for SPI Pull up resistors is 1Meg, why? It seems to very high, specially if the SPI lines have some parasitc capacitance. What does it suggests to you? 

    Right now I'm waiting for v2 of PCB boards with the new power supply.

    I hope it could works because then I will try to communicate with the ltc3300 balancer! 

    Best regards!

  • Hi  ,

    1) You can go with that isolated DC/DC power supply solution, and you can refer "PROVIDING HIGH SPEED ISOLATION OF THE SPI DATA PORT" section in datasheet regarding this for more insight.
    2) The 1Mega ohm SPI Pullup resistor is recommended ideally for the circuit, one can change the resistor based on their requirement.
    Thanks!

  • Actually, even after install an isolated DC/DC power supply and correct some mistakes, the result is the same:

    I'm writing the configurations to LTC6803-3 and when I try to read back I'm getting the same result -> 255 for every bit that I'm trying to read.

    Anyone with the same problem? Who can help?

    Regards!

  • Hi ,

    1Meg pullups are good as SPI bus lines are push-pull driven. Any low ohmic pull-somewheres just add burden to the drivers. Change your pull-ups to 1Meg for a start.

    Cheers, heke

  • **SOLVED***

    Due to the open-drain topology of the MISO line from the LTC6803, the recommended 1 MΩ pull-up resistor is inadequate for driving a 1 MHz signal.

    For instance, with a 100 pF parasitic capacitance, a 1 MΩ pull-up would result in a cutoff frequency of only 1.5 kHz, which is far too low for a 1 MHz signal.

    Additionally, when using a digital isolator, the pull-up resistor for the MISO (SDO) line must be placed on the isolated side, never on the host side, due to the open-drain configuration. I replaced the 1 MΩ resistor with a 1 kΩ resistor, and it now works perfectly!

    Regards,

    Henrique

  • The SDO line is not a push-pull driven is open drain:

    "from LTC6803 datasheet...

    SDO (Pin 43): Serial Data Output. The SDO pin is an NMOS
    open-drain output if VMODE is tied to VREG. A pull-up resistor
    is needed on SDO. SDO is not used if VMODE is tied to
    V–. See Serial Port in the Applications Information section."

    That's why an 1Meg resistor will never work. I changed mine to 1k and it's working!

  • Hi  ,

    Good find! You are absolutely right. When the SDO is an open drain (i.e. is not vanilla SPI), then one'll need a strong pull-up. Great to hear that you solved it. Please mark this solved so others with same problem can find a solution quickly.

    Have fun! Cheers, heke

  • Hi ,

    Behind the "More" there is a selection "Suggest as Answer". It at least highlights the solution. I did that for your post. I do not know who then accepts the suggestion....