void setup() {
// Delay for programming
delay(2000);
// Set pin modes and interrupts
pinMode(VOLT_A, INPUT);
pinMode(VOLT_B, INPUT);
pinMode(CURRENT_A, INPUT);
pinMode(CURRENT_B, INPUT);
pinMode(TEMP_A, INPUT);
pinMode(TEMP_B, INPUT);
pinMode(THROTTLE_SIM, OUTPUT);
pinMode(RELAY_OUT, OUTPUT);
pinMode(CRUISE_BUTTON, INPUT);
pinMode (SLAVE_SELECT_PIN, OUTPUT);
pinMode(CRUISE_EN, OUTPUT);
pinMode(FAULT_PIN, INPUT);
pinMode(ALERT_PIN, INPUT);
pinMode(DRDY_PIN, INPUT);
pinMode(CONV_PIN, OUTPUT);
pinMode(LED_A, OUTPUT);
pinMode(LED_B, OUTPUT);
attachInterrupt(0, magnetInterrupt, FALLING);
// Write initial pin states
digitalWrite(RELAY_OUT, HIGH);
digitalWrite(CRUISE_EN, LOW);
digitalWrite(CONV_PIN, LOW);
digitalWrite(SLAVE_SELECT_PIN, HIGH);
// Begin serial communication for serial debug
Serial.begin(57600);
delay(100);
// Set SPI preferences
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV32);
SPI.setBitOrder(MSBFIRST);
// Connect to Android device
acc.powerOn();
delay(1000);
// Connect to BMS shield
setupDevices();
}
void setupDevices() {
resetDevices();
delay(200);
setAddresses(); //0xa5 reset 0x3c reset register 0x3f broadcast all devices
delay(10);
bqWrite(0x01,ADC_CONTROL,0x04);
delay(10);
bqWrite(0x02,ADC_CONTROL,0x04);
delay(10);
}
void bqWrite(byte deviceAddress, byte regAddress, byte regData) {
SPI.setDataMode(SPI_MODE1);
// Shift the device bit and set bit 0
byte logicalAddress = deviceAddress << 1;
logicalAddress |= 1 << 0; // Set bit 0, test bitSet(x,n)
byte crcInput[3] = {
logicalAddress, regAddress, regData };
// Take the SS pin low to select the chip
digitalWrite(SLAVE_SELECT_PIN,LOW);
// Send and receive SPI
SPI.transfer(logicalAddress);
SPI.transfer(regAddress);
SPI.transfer(regData);
SPI.transfer(pec(crcInput));
// Take the SS pin high to de-select the chip
digitalWrite(SLAVE_SELECT_PIN,HIGH);
SPI.setDataMode(SPI_MODE0);
}
byte *bqRead(byte deviceAddress, byte regAddress, byte length) {
SPI.setDataMode(SPI_MODE1);
// Shift the device bit and clear bit 0
byte logicalAddress = deviceAddress << 1;
logicalAddress &= ~(1 << 0); // Clear bit 0, test bitClear(x,n)
// Create buffer for receivedData and clear it
static byte receivedData[20];
memset(receivedData, 0, sizeof(receivedData));
// take the SS pin low to select the chip:
digitalWrite(SLAVE_SELECT_PIN,LOW);
// Send and receive SPI
SPI.transfer(logicalAddress);
SPI.transfer(regAddress);
SPI.transfer(length);
for (int i = 0; i < length + 1; i++) {
receivedData[i] = SPI.transfer(0x00);
}
// take the SS pin high to de-select the chip:
digitalWrite(SLAVE_SELECT_PIN,HIGH);
SPI.setDataMode(SPI_MODE0);
// Return data read from registers
return receivedData;
}
int resetDevices() {
// Write reset code to reset register
bqWrite(0x3F,RESET,0xA5);
}
void setAddresses() {
// Set bottom address to 1
bqWrite(0x00,ADDRESS_CONTROL,0x01);
delay(10);
// Set and clear AR bit of ALERT_STATUS
byte alertSet = 0x00;
bitSet(alertSet, 7);
bqWrite(0x01,ALERT_STATUS,alertSet);
delay(10);
bqWrite(0x01,ALERT_STATUS,0x00);
delay(10);
// Set top address to 2
bqWrite(0x00,ADDRESS_CONTROL,0x02);
delay(10);
// Set and clear AR bit of ALERT_STATUS
bqWrite(0x02,ALERT_STATUS,alertSet);
delay(10);
bqWrite(0x02,ALERT_STATUS,0x00);
delay(10);
}
int getCellVoltage(byte cellNumber) {
byte deviceAddress;
byte cellAddress;
switch (cellNumber) {
case 0x01:
deviceAddress = 0x01;
cellAddress = VCELL1;
break;
case 0x02:
deviceAddress = 0x01;
cellAddress = VCELL2;
break;
case 0x03:
deviceAddress = 0x01;
cellAddress = VCELL3;
break;
case 0x04:
deviceAddress = 0x01;
cellAddress = VCELL4;
break;
case 0x05:
deviceAddress = 0x01;
cellAddress = VCELL5;
break;
case 0x06:
deviceAddress = 0x01;
cellAddress = VCELL6;
break;
case 0x07:
deviceAddress = 0x02;
cellAddress = VCELL1;
break;
case 0x08:
deviceAddress = 0x02;
cellAddress = VCELL2;
break;
case 0x09:
deviceAddress = 0x02;
cellAddress = VCELL3;
break;
case 0x0A:
deviceAddress = 0x02;
cellAddress = VCELL4;
break;
case 0x0B:
deviceAddress = 0x02;
cellAddress = VCELL5;
break;
case 0x0C:
deviceAddress = 0x02;
cellAddress = VCELL6;
break;
}
bqWrite(deviceAddress,ADC_CONVERT,0x01);
delay (100);
byte *cellRaw = bqRead(deviceAddress,cellAddress,0x02);
delay(10);
int cellVoltage = (cellRaw[0] * 256) + cellRaw[1];
prevCellVoltages[cellNumber - 1] = convertCellVoltage(cellVoltage);
return cellVoltage;
}
double convertCellVoltage(int cellVoltageInt) {
return ((double) cellVoltageInt) * (6250.0 / 16383.0);
}
byte *getCellVoltages() {
byte *lowCells = bqRead(0x01, VCELL1, 0x0C);
delay(10);
byte *highCells = bqRead(0x02, VCELL1, 0x0C);
delay(10);
// Create buffer for cell data and clear it
static byte cellData[12];
memset(cellData, 0, sizeof(cellData));
for (int i = 0; i < 6; i++) {
cellData[i] = lowCells[i];
}
for (int j = 0; j < 6; j++) {
cellData[6+j] = highCells[j];
}
return cellData;
}
double convCellVoltage(byte hibyte, byte lobyte) {
// Use given conversion equation to convert 14 bit cell voltage to double
return (((double) hibyte * 256.0) + (double) lobyte) * (6250.0 / 16383.0);
}
byte pec(byte crcBuffer[]) {
byte crc = 0;
int temp = 0;
for (int i = 0; i < sizeof(crcBuffer) + 1; i++) {
temp = crc ^ crcBuffer[i];
crc = crcTable[temp];
}
return crc;
}