Kia Niro BMS
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
Does anyone have an idea if this code will work with the Hyundai / Kia hybrid packs?
Edit: looking deeper it seems that it will
could anyone tell me whether you can use the BMS master and the CAN messages alone instead of directly connecting to the slaves?
Thanks
Edit: looking deeper it seems that it will
could anyone tell me whether you can use the BMS master and the CAN messages alone instead of directly connecting to the slaves?
Thanks
Re: Kia Niro BMS
I think it should be possible to use stock BMS. Looks like a lot of CAN messages are the same or similar between different Hyundai / Kia models and i have Hyundai Santa-Fe PHEV battery working using Savvycan script or zombieverter (there are still some obd-2 errors, but probably not critical)
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
I already went ahead and bought the pack its a Hyundai IONIQ PHEV, its nice to know that it can be done, would you mind sharing your code? Thanks
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
Hello, im trying to use your code and an Arduino to patch into a HEV BMS from a niro as i have been unable to find the CAN commands for the contactors, I have connected to the spi and i think im getting them to talk but the board design is different to that of the CMUs, It has 8X max17845 chips onboard.
I tried playing with the code but i dont know what im doing, and I keep getting "error byte cleared" in serial.
Is it possible to get this to work? could i get some help.
Thank you
I tried playing with the code but i dont know what im doing, and I keep getting "error byte cleared" in serial.
Is it possible to get this to work? could i get some help.
Thank you
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
Yes, this seem to be a integrated BMS, interesting.
So you have connected via SPI to the onborad MAX17841, correct?
My SW is hard coded to 12 slaves with 4+4 cells connected at pos 1-4 and 6-9. This will have to be changed to 8 slaves with 9 cells connected.
The number of slaves also determines the value of check byte so this have to match.
Please provide a serial print out of your results so far, helps a lot for me to determine your progress.
So you have connected via SPI to the onborad MAX17841, correct?
My SW is hard coded to 12 slaves with 4+4 cells connected at pos 1-4 and 6-9. This will have to be changed to 8 slaves with 9 cells connected.
The number of slaves also determines the value of check byte so this have to match.
Please provide a serial print out of your results so far, helps a lot for me to determine your progress.
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
I ment the alive-counter. 0x0C with 12 slaves, 0x08 with 8 slaves. Will need to be changed in 3 places in the SW, daisyChainInit(), writeAllSlaves() and readAllSlaves().
That should get you through the setup.
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
Thankyou this is exactly what i needed to know.
Yes I have connected to the SPI of the MAX17841 and pulled up the respective pins.
So i have edited 0x0c to 0x08 in the code.
does this need to be edited too?
"* Reads data from slaves and stores in arrays *
**********************************************/
void readData()
{
for(int i=0; i<4; i++)
{
readAllSlaves((0x20 + i), true); // Read CELL 1-4 of all slaves
}
for(int i=0; i<4; i++)
{
readAllSlaves((0x25 + i), true); // Read CELL 5-8 of all slaves"
and this
* Stores measured cell voltage data in cellVoltage array *
*********************************************************/
void storeCellVoltage(uint8_t dataRegister, uint8_t readRegisterData[29])
{
if((dataRegister >= 0x20) && (dataRegister <= 0x23)) // Cell voltage registers 1-4
{
uint8_t cellNumberOffset = dataRegister - 0x20;
for(int i=0; i<12; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
}
if((dataRegister >= 0x25) && (dataRegister <= 0x28)) // Cell voltage registers 5-8
{
uint8_t cellNumberOffset = dataRegister - 0x20 - 1;
for(int i=0; i<12; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
Im not exactly sure how to edit this i just want the voltages from 1-8 on each chip, there are 72 channels even though my bms only uses 64 of them there are no thermistors connected to any of the slaves,
Im not very good at coding i can understand some of it but this is way to much for me, if i start editing this its going to be more of a guess than anything else.
Yes I have connected to the SPI of the MAX17841 and pulled up the respective pins.
So i have edited 0x0c to 0x08 in the code.
does this need to be edited too?
"* Reads data from slaves and stores in arrays *
**********************************************/
void readData()
{
for(int i=0; i<4; i++)
{
readAllSlaves((0x20 + i), true); // Read CELL 1-4 of all slaves
}
for(int i=0; i<4; i++)
{
readAllSlaves((0x25 + i), true); // Read CELL 5-8 of all slaves"
and this
* Stores measured cell voltage data in cellVoltage array *
*********************************************************/
void storeCellVoltage(uint8_t dataRegister, uint8_t readRegisterData[29])
{
if((dataRegister >= 0x20) && (dataRegister <= 0x23)) // Cell voltage registers 1-4
{
uint8_t cellNumberOffset = dataRegister - 0x20;
for(int i=0; i<12; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
}
if((dataRegister >= 0x25) && (dataRegister <= 0x28)) // Cell voltage registers 5-8
{
uint8_t cellNumberOffset = dataRegister - 0x20 - 1;
for(int i=0; i<12; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
Im not exactly sure how to edit this i just want the voltages from 1-8 on each chip, there are 72 channels even though my bms only uses 64 of them there are no thermistors connected to any of the slaves,
Im not very good at coding i can understand some of it but this is way to much for me, if i start editing this its going to be more of a guess than anything else.
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
Try this:bigmotherwhale wrote: ↑Thu Oct 26, 2023 1:46 pm void readData()
{
for(int i=0; i<4; i++)
{
readAllSlaves((0x20 + i), true); // Read CELL 1-4 of all slaves
}
for(int i=0; i<4; i++)
{
readAllSlaves((0x25 + i), true); // Read CELL 5-8 of all slaves"
Code: Select all
void readData()
{
for(int i=0; i<8; i++)
{
readAllSlaves((0x20 + i), true); // Read CELL 1-8 of all slaves
}
//readAllSlaves(0x2D, true); // Read AIN1 of all slaves (Cell temperature)
readAllSlaves(0x50, true); // Read DIAG (Die temperature) of all slaves
}
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
Try this:bigmotherwhale wrote: ↑Thu Oct 26, 2023 1:46 pm void storeCellVoltage(uint8_t dataRegister, uint8_t readRegisterData[29])
{
if((dataRegister >= 0x20) && (dataRegister <= 0x23)) // Cell voltage registers 1-4
{
uint8_t cellNumberOffset = dataRegister - 0x20;
for(int i=0; i<12; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
}
if((dataRegister >= 0x25) && (dataRegister <= 0x28)) // Cell voltage registers 5-8
{
uint8_t cellNumberOffset = dataRegister - 0x20 - 1;
for(int i=0; i<12; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
Code: Select all
void storeCellVoltage(uint8_t dataRegister, uint8_t readRegisterData[29])
{
if((dataRegister >= 0x20) && (dataRegister <= 0x27)) // Cell voltage registers 1-8
{
uint8_t cellNumberOffset = dataRegister - 0x20;
for(int i=0; i<8; i++)
{
uint16_t measVoltage = ((readRegisterData[25-i*2] << 8) + readRegisterData[24-i*2]);
measVoltage = (measVoltage >> 2) * (uint32_t)5000 / 0x3FFF;
cellVoltage[i*8 + cellNumberOffset] = measVoltage;
}
}
}
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
I would also comment out this part:
Like this:
Code: Select all
if(dataRegister == 0x2D) // Aux voltage measurements (external temperature sensors)
{
storeCellTemperature(readRegisterData);
}
Code: Select all
/*if(dataRegister == 0x2D) // Aux voltage measurements (external temperature sensors)
{
storeCellTemperature(readRegisterData);
}*/
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
Also this function needs to be changed
To:
Code: Select all
boolean balanceCells(uint16_t lowestCellVoltage)
{
static uint8_t counter = 1;
static uint16_t cellToBalanceFilter = 0x0FFF & 0x5555; // Every odd cell
boolean measureVoltages = false;
//if(1 == counter) Serial.println("Balance cells");
writeAllSlaves(0x18, 0x1500, true); // Set WATCHDOG timer to 5s
if(0 == counter)
{
cellToBalanceFilter = 0x0FFF & ~cellToBalanceFilter; // Every other cell
writeAllSlaves(0x1A, 0x0000, true); // Turn off all cell balancing for one cycle to avoid any switch overlap
}
if(1 == counter)
{
measureVoltages = true; // OK to measure cell voltages
}
for (int i=0; i < 12; i++) // Go through modules to set cells for balancing
{
if(2 == counter) // Only set cells once every counter cycle
{
uint16_t cellToBalance = 0x0000;
for (int j=0; j < 8; j++) // Go through cells to set cells for balancing
{
uint8_t cellNumber = j+i*8;
if ((cellVoltage[cellNumber] > startShuntVoltage) && ((int16_t)(cellVoltage[cellNumber] - lowestCellVoltage) > voltageAllowance)) // Ok to balance
{
if (j < 4)
{
cellToBalance |= (0x01 << j);
}
else if (j >= 4 && j <8)
{
cellToBalance |= (0x01 << (j+1));
}
else //Error
{
cellToBalance = 0x0000;
}
}
}
cellToBalance &= cellToBalanceFilter; // To avoid enabling adjacent balance switches
writeAddressedSlave(0x1A, cellToBalance, i, true); // Send request to set cell balance switches
Serial.print(i+1);
Serial.print(": ");
//Serial.println(cellToBalance, BIN);
for(int i=0; i < 8; i++)
{
if(4 == i) Serial.print(" ");
if(i < 4)
{
Serial.print((uint8_t)((cellToBalance >> i) & 0x01));
}
else
{
Serial.print((uint8_t)((cellToBalance >> (i + 1)) & 0x01));
}
}
Serial.println();
}
if(dieTemperature[i] > 100) // Check die overtemp
{
writeAddressedSlave(0x1A, 0x0000, i, true); // Turn off cell balancing for the module with die overtemp
Serial.print("Die overtemp, module ");
Serial.println(i+1);
}
}
counter++;
if(counter > balanceCellCounterTurnAround)
{
counter = 0;
}
return measureVoltages;
}
Code: Select all
boolean balanceCells(uint16_t lowestCellVoltage)
{
static uint8_t counter = 1;
static uint16_t cellToBalanceFilter = 0x00FF & 0x5555; // Every odd cell
boolean measureVoltages = false;
//if(1 == counter) Serial.println("Balance cells");
writeAllSlaves(0x18, 0x1500, true); // Set WATCHDOG timer to 5s
if(0 == counter)
{
cellToBalanceFilter = 0x0FFF & ~cellToBalanceFilter; // Every other cell
writeAllSlaves(0x1A, 0x0000, true); // Turn off all cell balancing for one cycle to avoid any switch overlap
}
if(1 == counter)
{
measureVoltages = true; // OK to measure cell voltages
}
for (int i=0; i < 8; i++) // Go through modules to set cells for balancing
{
if(2 == counter) // Only set cells once every counter cycle
{
uint16_t cellToBalance = 0x0000;
for (int j=0; j < 8; j++) // Go through cells to set cells for balancing
{
uint8_t cellNumber = j+i*8;
if ((cellVoltage[cellNumber] > startShuntVoltage) && ((int16_t)(cellVoltage[cellNumber] - lowestCellVoltage) > voltageAllowance)) // Ok to balance
{
if (j < 8)
{
cellToBalance |= (0x01 << j);
}
else //Error
{
cellToBalance = 0x0000;
}
}
}
cellToBalance &= cellToBalanceFilter; // To avoid enabling adjacent balance switches
writeAddressedSlave(0x1A, cellToBalance, i, true); // Send request to set cell balance switches
Serial.print(i+1);
Serial.print(": ");
//Serial.println(cellToBalance, BIN);
for(int i=0; i < 8; i++)
{
Serial.print((uint8_t)((cellToBalance >> i) & 0x01));
}
Serial.println();
}
if(dieTemperature[i] > 100) // Check die overtemp
{
writeAddressedSlave(0x1A, 0x0000, i, true); // Turn off cell balancing for the module with die overtemp
Serial.print("Die overtemp, module ");
Serial.println(i+1);
}
}
counter++;
if(counter > balanceCellCounterTurnAround)
{
counter = 0;
}
return measureVoltages;
}
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
Thankyou for helping, I tried the above i think i may have got something wrong as an extra bracket stopped me from compiling, I removed what I thought was the right one and uploaded it and this is what i got. I have included the log and the modified .ino
could you have a look at see i haven't missed something? thanks
could you have a look at see i haven't missed something? thanks
- Attachments
-
- BMS2_7_3_modified.ino
- (47.06 KiB) Downloaded 677 times
-
- error.txt
- (1.2 KiB) Downloaded 596 times
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
Replace the entire readAllSlaves() with this:
Adjusted for 8 slave modules.
Code: Select all
void readAllSlaves(uint8_t dataRegister, boolean setupDone) // Read all slaves
{
uint8_t command = 0x03; // READALL
uint8_t byteList[3] = {command, dataRegister, 0x00};
uint8_t PEC = calculatePEC(byteList, 3);
uint8_t readRegisterData[21];
uint8_t errorByte = 0x00;
static uint8_t resendCounter = 0;
//static uint8_t failCounter = 0;
/*if(failCounter >= 4)
{
//clearBuffers();
failCounter = 0; // Reset counter
Serial.println("Buffers cleared");
}*/
SPI.beginTransaction(MAX17841);
// Load the READALL command sequence into the load queue
digitalWrite(SPI_MAX_CS_PIN, LOW);
SPI.transfer(0xC0); // WR_LD_Q SPI command byte (write the load queue)
SPI.transfer(0x15); // Message length (5 + 2 x n = 21)
SPI.transfer(command); // READALL command byte
SPI.transfer(dataRegister); // Register address
SPI.transfer(0x00); // Data-check byte (seed value = 0x00)
SPI.transfer(PEC); // PEC byte
SPI.transfer(0x00); // Alive-counter byte (seed value = 0x00)
digitalWrite(SPI_MAX_CS_PIN, HIGH);
transmitQueue();
// Read the receive buffer
digitalWrite(SPI_MAX_CS_PIN, LOW);
SPI.transfer(0x93); // RD_NXT_MSG SPI command byte
for(int i=0; i<21; i++)
{
readRegisterData[i] = SPI.transfer(0x93);
}
errorByte |= receiveBufferError();
SPI.endTransaction();
// Verify that the device register data is received correctly during the READALL sequence
if(!((readRegisterData[0] == command) && (readRegisterData[1] == dataRegister)))
{
errorByte |= mismatchBefore;
}
if(setupDone)
{
uint8_t checkPEC = calculatePEC(readRegisterData, 19);
// Check check-byte, PEC and alive-counter
if(!((readRegisterData[18] == 0x00) && (readRegisterData[19] == checkPEC) && (readRegisterData[20] == 0x08)))
{
errorByte |= mismatchAfter;
if(readRegisterData[18] != 0x00)
{
readAllSlaves(0x02, false); // Read STATUS of all slaves with checks ignored
writeAllSlaves(0x02, 0x0000, true); // Clear STATUS register
Serial.println("STATUS cleared");
}
}
}
/*// Print data received
for(int i=0; i<21; i++)
{
Serial.print(readRegisterData[i], HEX);
Serial.print(" ");
}
Serial.println();*/
if(errorByte) // Error
{
resendCounter++;
Serial.println(errorByte, HEX);
errorByte &= 0x00; // Clear errors
Serial.println("errorByte cleared");
if(resendCounter > 2)
{
Serial.println("READALL fail");
resendCounter = 0;
//failCounter++;
return;
}
delay(1);
readAllSlaves(dataRegister, setupDone); // Resend READALL
}
else // No errors, clear counters and store data received
{
resendCounter = 0; // Reset counter
//failCounter = 0; // Reset counter
if((dataRegister >= 0x20) && (dataRegister <= 0x2B)) // Cell voltage measurements
{
storeCellVoltage(dataRegister, readRegisterData);
}
/*if(dataRegister == 0x2D) // Aux voltage measurements (external temperature sensors)
{
storeCellTemperature(readRegisterData);
}*/
if(dataRegister == 0x50) // Die temperature measurements
{
storeDieTemperature(readRegisterData);
}
if(dataRegister == 0x13) // Read SCANCTRL to check if data is ready to be read
{
checkDataReady(readRegisterData);
}
if(dataRegister == 0x02) // Read STATUS and print content
{
// Print data received
for(int i=0; i<21; i++)
{
Serial.print(readRegisterData[i], HEX);
Serial.print(" ");
}
Serial.println();
}
}
}
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
Seems to be getting closer, still seems to have 12 groups in the readout though?
Here is what im getting.
Here is what im getting.
- Attachments
-
- error.txt
- (3.78 KiB) Downloaded 684 times
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
In writeAllSlaves() there is an error in your code:
Should be:
Code: Select all
// Check alive-counter
if(!(readRegisterData[5] == 0x0))
{
errorByte |= mismatchAfter;
}
Code: Select all
// Check alive-counter
if(!(readRegisterData[5] == 0x08))
{
errorByte |= mismatchAfter;
}
- bexander
- Posts: 866
- Joined: Tue Jun 16, 2020 6:00 pm
- Location: Gothenburg, Sweden
- Has thanked: 71 times
- Been thanked: 97 times
Re: Kia Niro BMS
There is also a lot of other places that need to be changed, I realize.
Post your latest code and I will make some changes to it and post it back.
Post your latest code and I will make some changes to it and post it back.
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
Here is the code its been modified just by your suggestions.
Cheers
Cheers
- Attachments
-
- BMS2_7_3_EDITED.ino
- (46.68 KiB) Downloaded 677 times
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
i get errorbyte cleared 1
Would it be a good ide to enable the HEX output in the code to see what the slaves are spitting out?
Would it be a good ide to enable the HEX output in the code to see what the slaves are spitting out?
- Attachments
-
- error.txt
- (1.31 KiB) Downloaded 848 times
-
- Posts: 113
- Joined: Tue Sep 22, 2020 6:48 pm
- Has thanked: 17 times
- Been thanked: 22 times
Re: Kia Niro BMS
It has the correct number of cells but im getting measurecelldata wd timeout
- Attachments
-
- error.txt
- (861 Bytes) Downloaded 650 times