Reading/converting SPI data? [solved]

Hi, I’m working with the LTC6803-4 here, and I’ve had a bit of success so far in that I seem to be communicating with the chip, and it’s spitting out values at me. The problem is the values seem to be … wrong, and repetitive.

This is the code here:

#include "SPI.h"

#define LT_SPI_START digitalWrite(10,LOW)
#define LT_SPI_END digitalWrite(10,HIGH)
byte config[6] = { 0xE9,0x00,0x00,0xFC,0x71,0xC8 };  //Default config
float current_voltages[12];


#define WRCFG 0x01  // Write config registers
#define RDCFG 0x02  // Read config registers
#define RDCV 0x04   // Read all cell voltages
#define RDCVA 0x06  // Read cells 1-4
#define RDCVB 0x08  // Read cells 5-8
#define LTCADDR 0x80 // LTC's Address - 0000

void setup(){
  pinMode(10, OUTPUT);
  Serial.begin(9600);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE3);
  SPI.setClockDivider(SPI_CLOCK_DIV64);
  // Write LTC configs
  LT_SPI_START;
  sendToSPI(LTCADDR);  // Non-broadcast command
  sendToSPI(WRCFG);  // Write config
  sendMultipleToSPI(config, 6);
  LT_SPI_END; 
  // Finish LTC config
}

void loop(){
  // STUFF!
  beginCellVolt(); // Start cell 1-6 conversion
  readCellVolt(current_voltages,LTCADDR);
  for (int i; i<6; i++){
    Serial.print(current_voltages[i]);
    Serial.print(" | ");
  }
 Serial.println(" ");
 delay(1000);
  
}







// ---- FUNCTIONS ----

void beginCellVolt() {
  //for (int i=17; i<=23; i++){ // Read cells 1-6 to save time
  LT_SPI_START;
  sendToSPI(RDCV);
  delay(15); //Time for conversions, 1.4ms max per cell
  LT_SPI_END;
}

// Reads cell voltage registers  
void readCellVolt(float* cell_voltages, byte board) {
  LT_SPI_START;
  sendToSPI(board);  // Board address is selected
  sendToSPI(RDCV);  // Cell voltages to be read
  byte cvr[8];  // Buffer to store unconverted values
  getMultipleFromSPI(cvr, RDCV, 8);
  LT_SPI_END; 

  // Converting cell voltage registers to cell voltages
  cell_voltages[0] = (cvr[0] & 0xFF) | (cvr[1] & 0x0F) << 8;
  cell_voltages[1] = (cvr[1] & 0xF0) >> 4 | (cvr[2] & 0xFF) << 4;
  cell_voltages[2] = (cvr[3] & 0xFF) | (cvr[4] & 0x0F) << 8;
  cell_voltages[3] = (cvr[4] & 0xF0) >> 4 | (cvr[5] & 0xFF) << 4;
  cell_voltages[4] = (cvr[6] & 0xFF) | (cvr[7] & 0x0F) << 8;
  cell_voltages[5] = (cvr[7] & 0xF0) >> 4 | (cvr[8] & 0xFF) << 4;
  
  for(int i=0;i<6;i++) {
    cell_voltages[i] = cell_voltages[i]*1.5*0.001;
  }
}  

// Send data to LTC
void sendMultipleToSPI(byte * data, int n) {
  for(int i=0; i<n; i++) {
    SPI.transfer(data[i]);
  }
  SPI.transfer(getPEC(data, n));
}

// Get data from LTC
byte * getMultipleFromSPI(byte * data, byte info, int n) {
  for(int i=0; i<n; i++) {
    data[i] = SPI.transfer(info);
  }
  byte pec = SPI.transfer(info);
}

void sendToSPI(byte data) {
  sendMultipleToSPI(&data, 1);
}

void readConfig(byte*config,byte board) {
  LT_SPI_START;   
  sendToSPI(board);  // Board address is selected
  sendToSPI(RDCFG);  // Configuration is read
  getMultipleFromSPI(config, RDCFG, 6);
  LT_SPI_END;
}

// Calculate PEC, n is  size of DIN
byte getPEC(byte * din, int n) {
  byte pec, in0, in1, in2;
  pec = 0x41;
  for(int j=0; j<n; j++) {
    for(int i=0; i<8; i++) {
      in0 = ((din[j] >> (7 - i)) & 0x01) ^ ((pec >> 7) & 0x01);
      in1 = in0 ^ ((pec >> 0) & 0x01);
      in2 = in0 ^ ((pec >> 1) & 0x01);
      pec = in0 | (in1 << 1) | (in2 << 2) | ((pec << 1) & ~0x07);
    }
  }
  return pec;
}

More specifically, the readCellVolt function. The battery voltage values are 12 bit, so I gather there’s a bit of shifting going on to collect the values, then convert them, but for some reason with that code, I’m getting values like:

4.95 | 6.14 | 4.97 | 6.14 | 4.69 | 1.73 |

And if I increase the cvr buffer size, I get

4.95 | 6.14 | 4.97 | 6.14 | 4.69 | 6.14 |

This is the datasheet, and relevant info on page 24-25: http://cds.linear.com/docs/en/datasheet/680324fa.pdf

Is there a problem with the shifting or something? This is the first time I’ve really dealt with hardware at the bit level, so I have no idea what I’m doing. I’m surprised the code even works :smiley:

EDIT: Nevermind, got it. The datasheet seems to be a little confusing in regard to calculating the values. It says to subtract 512 from the cell voltages, which actually gives me the right value, but earlier when I was setting UB/OV voltages, it said to subtract -32/-31, which would give me the wrong values. Oh well :slight_smile:

Dan

Hi, I am also working on LTC6803 and i am trying to read my cell voltage through arduino but i get unstable values. can you pls help me with your modified code.

Thanks in advance!!

hello, do you guys make the ltc6803-4 work? I am also working on a project based on LTC6803-4 but it seems like I cannot write a configuration to it, and it seems like the arduino uno and ltc6803-4 is not communicating. When I write a configuration and read it back, all I read is 0 0 0 0 0 0 which is not what I have sent to it. Any ideas on how to solve this? Thanks