SPI communication between Arduino UNO and LTC6804-1

Hello all

I'm going to start a project in which, I need to use a microcontroller to read measured data by a battery monitoring IC, with part number LTC6804-1. Since I'm not very experienced in programming and electronics, I chose ATmega328 on Arduino UNO board. In the first step, Arduino, needs to communicate with LTC6804 through 4 wire SPI to read measured data. So, Arduino needs to send ADC measure and read data to the LTC6804 along with a specific 'CRC' code. In return, LTC6804 will send back asked register byte value along with corresponding CRC code.
So, I haven't worked with SPI and moreover, I don't know how to deal with CRC code. Is that just as easy to keep the first byte (data) and ignore the second byte (CRC)? Is there any point that I haven't looked into yet and need to take it into consideration?

Thanks,
Mahmoud

mamuti:
So, Arduino needs to send ADC measure and read data to the LTC6804 along with a specific 'CRC' code.

I don't think you have that worded correctly. The Arduino most likely sends a "data readout request" with the data being ADC outputs. The Arduino doesn't send any ADC data to the sensor, it's the other way around.

mamuti:
So, I haven't worked with SPI and moreover, I don't know how to deal with CRC code.

Check this out for SPI. This describes the built in arduino library for SPI comms. This will make your life real easy.

Check this out for CRC Stuff. Especially note slide 23.

mamuti:
Is that just as easy to keep the first byte (data) and ignore the second byte (CRC)?

Yes, BUT only for when receiving data from the sensor. You CANNOT ignore CRC when transmitting to the sensor (i.e. requesting ADC data).

Also, it would be helpful to review page 44 and 65 of the datasheet

Thank you very much for your helpful materials. Looking into datasheet of LTC6804-1 and also reading SPI documentation for ARDUINO, I built attached sketch. I don't know if here is good place for asking about programming; but, I would be thankful if you could provide me with any feedback (At this step, I only need to measure one cell voltage).

Thanks

SPI_1.ino (1.47 KB)

Code in tags:

// SPI library of IDE
#include "SPI.h"
// chosing slave select pin
const int ss=10;
// declaring functions and general setups
void setup() {
  // bausrate for serial monitor
  Serial.begin (9600);
  Serial.println ();
  digitalWrite(ss, HIGH);
  //set as master 
  pinMode(ss,OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  // 1 Mhz maximum bit per second supported by LTC6804-1
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}

void loop() {
  //Hex code for ADC measurement command for cells 1 & 7
  //7khz mode is selected (MD=[1,0])
  //discharging is desabled
  byte comm0=0x03;
  //int comm1=0x70;
  byte comm1=0x61; 
  //Hex code for PEC related to ADC measurement command for cells 1&7
  byte pec0=0x7f;
  byte pec1=0x5e;
  // sending above commands by asserting ss pin
  digitalWrite(ss,LOW);
  SPI.transfer(comm0);
  SPI.transfer(comm1);
  SPI.transfer(pec0);
  SPI.transfer(pec1);


//Hex code for Read command for cells in group A and corresponding PEC bytes
  comm0=0x00;
  comm1=0x04;
  pec0=0x07;
  pec1=0xc2;

  digitalWrite(ss,LOW);
  SPI.transfer(comm0);
  SPI.transfer(comm1);
  SPI.transfer(pec0);
  SPI.transfer(pec1);
  //delayMicroseconds (20);
  
  byte V10=SPI.transfer(0);
  byte V11=SPI.transfer(0);
  

  byte V20=SPI.transfer(0);
  byte V21=SPI.transfer(0);
  byte V30=SPI.transfer(0);
  byte V31=SPI.transfer(0);
  byte pec_v1_0=SPI.transfer(0);
  byte pec_v2_0=SPI.transfer(0);
  
  digitalWrite(ss,HIGH);

  Serial.println (V10, DEC);
  Serial.println (V11, DEC);

}

I don't have a whole lot of SPI experience, but take a look here. You shouldn't be using SPI.setBitOrder(). Instead, you need to use SPI.beginTransaction(SPISettings()) - see link. You also don't need to worry about doing the SS or CS pin control yourself, the library does that already assuming you wired everything correctly.

Forgetting your actual sensor, lets just focus on getting SPI working correctly: Take a look at this example and revise your code accordingly.

/*
  Digital Pot Control

  This example controls an Analog Devices AD5206 digital potentiometer.
  The AD5206 has 6 potentiometer channels. Each channel's pins are labeled
  A - connect this to voltage
  W - this is the pot's wiper, which changes when you set it
  B - connect this to ground.

 The AD5206 is SPI-compatible,and to command it, you send two bytes,
 one with the channel number (0 - 5) and one with the resistance value for the
 channel (0 - 255).

 The circuit:
  * All A pins  of AD5206 connected to +5V
  * All B pins of AD5206 connected to ground
  * An LED and a 220-ohm resisor in series connected from each W pin to ground
  * CS - to digital pin 10  (SS pin)
  * SDI - to digital pin 11 (MOSI pin)
  * CLK - to digital pin 13 (SCK pin)

 created 10 Aug 2010
 by Tom Igoe

 Thanks to Heather Dewey-Hagborg for the original tutorial, 2005

*/


// inslude the SPI library:
#include <SPI.h>


// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;

void setup() {
  // set the slaveSelectPin as an output:
  pinMode(slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin();
}

void loop() {
  // go through the six channels of the digital pot:
  for (int channel = 0; channel < 6; channel++) {
    // change the resistance on this channel from min to max:
    for (int level = 0; level < 255; level++) {
      digitalPotWrite(channel, level);
      delay(10);
    }
    // wait a second at the top:
    delay(100);
    // change the resistance on this channel from max to min:
    for (int level = 0; level < 255; level++) {
      digitalPotWrite(channel, 255 - level);
      delay(10);
    }
  }

}

void digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin, LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin, HIGH);
}

Notice how the above code is written for SPI comms.

Lastly, about the sensor. Where in the code do you compute/send the CRC (cyclic redundancy check)?