Created
May 20, 2023 08:20
-
-
Save Corteil/f83ee4708a0838859fcd7e00524226ac to your computer and use it in GitHub Desktop.
added monitoring function and created a simple menu.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// CAN readout of VW type 5 modules | |
// ------- Programa adaptado por Alfonso para comunicar las celdas SDI de VW a 15-04-2022 | |
// ------- Funciona con un Arduino nano, y el MCP2515, la interrupción del integrado interrumpe algunos comandos, pero en general va respondiendo con 1 módulo solo conectado. | |
// | |
// ------- Program adapted by Alfonso to communicate VW SDI cells to 04-15-2022 | |
// ------- It works with an Arduino nano, and the MCP2515, the IC interrupt interrupts some commands, but in general it responds with only 1 module connected. | |
// | |
// | |
// | |
// Link información muy útil: https://openinverter.org/wiki/VW_Hybrid_Battery_Packs | |
// | |
// Revisión programa 0.1: Balanceo para 1 módulo solo, no se ha probado con más módulos. | |
// La equivalencia con la tabla balanceBMS no coincide con el cmcID , por lo que he ajustado a ojo. | |
// Hay que hacer pruebas con todos los módulos que tengo de stock, para ver si todos los CMC responden bien a los comandos de balanceo. | |
// | |
// | |
// Balancing for 1 module only, has not been tested with more modules. | |
// The equivalence with the balanceBMS table does not match the cmcID , so I have adjusted it carefully. | |
// You have to do tests with all the modules that I have in stock, to see if all the CMCs respond well to the balancing commands. | |
// Brian's add ons. | |
// added simple menu enter 'b' for blancing mode or 'm' to monitor battery cell voltages. | |
// | |
// totaled cell voltages for battery voltage. | |
// | |
#include <mcp_can.h> | |
#include <SPI.h> | |
long unsigned int rxId; | |
unsigned char len = 0; | |
unsigned char rxBuf[8]; | |
char msgString[128]; // Array to store serial string | |
unsigned long looptime = 0; | |
#define CAN0_INT 8 // Set INT to pin 2 | |
MCP_CAN CAN0(10); // Set CS to pin 9 de[ending on shield used | |
int controlid = 0x0BA; | |
int controlid2 = 0x0BB; | |
long cmcID[] = {0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, 0x1c8, 0x1cc}; | |
long controlbms1[] = {0x1A55540A, 0x1A55540C, 0x1A555410, 0x1A555412, 0x1A555414, 0x1A555416, 0x1A555418 }; | |
long balanceBMS[8][2] = {0x1A55540A, 0x1A55540B, 0x1A55540C, 0x1A55540D, 0x1A555410, 0x1A555411, 0x1A555412, 0x1A555413, 0x1A555414, 0x1A555415, 0x1A555416, 0x1A555417, 0x1A555418, 0x1A555419, 0x1A55541A, 0x1A55541B}; | |
long moduleidstart, CMC; | |
char mes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | |
char mes2[8], mes3[8]; | |
int minimoVoltage, inicioVoltage; // min voltage, max voltage | |
long mesBalanceo[14]; | |
boolean necesitaBalanceo; //needs Balancing | |
bool monitorFlag = true; | |
uint16_t voltage[30][14]; | |
int modulespresent = 0; | |
int sent = 0; | |
int debug = 0; | |
float totalVoltage = 0; | |
void setup() | |
{ | |
Serial.begin(115200); | |
// Can0.begin(500000); | |
Serial.println("Program Start ..."); | |
// Initialize MCP2515 running at 8MHz with a baudrate of 500kb/s and the masks and filters disabled. | |
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) | |
Serial.println("MCP2515 Initialized Successfully!"); | |
else | |
Serial.println("Error Initializing MCP2515..."); | |
CAN0.setMode(MCP_NORMAL); // Set operation mode to normal so the MCP2515 sends acks to received data. | |
pinMode(CAN0_INT, INPUT); // Configuring pin for /INT input | |
//Serial.println("Time Stamp,ID,Extended,Bus,LEN,D1,D2,D3,D4,D5,D6,D7,D8"); | |
//Serial.println("Vcell 1, Vcell 2, Vcell 3, Vcell 4, Vcell 5, Vcell 6, Vcell 7, Vcell 8, Vcell 9, Vcell 10, Vcell 11, Vcell 12"); | |
} | |
void loop() | |
{ | |
if (CAN0.checkReceive() == 3){ // If CAN0_INT pin is low, read receive buffer | |
// Serial.print(CAN0.checkReceive()); // If it reads 3 it means that it has received a message, decode to see if it is relevant or not. | |
candecode(); | |
} | |
if (Serial.available() > 0){ | |
menu(); // A menu, which doesn't work, but it's in the code. | |
} | |
if (millis() > looptime + 1000){ | |
Serial.println(); | |
if (monitorFlag) { | |
Serial.println(); | |
Serial.println("Monitor Mode On."); | |
} | |
else {- | |
Serial.println(); | |
Serial.println("Balance Mode On."); | |
} | |
looptime = millis(); | |
for(int i=0;i<8;i++){ | |
if(CMC == cmcID[i]){ | |
Serial.println(); | |
Serial.print("CMC = "); | |
CMC = i; | |
Serial.println(CMC+1); | |
//Serial.println(" Looking for balance board ..."); | |
} | |
} | |
for (int y = 0; y < modulespresent; y++){ | |
//Serial.println(); | |
Serial.print("Module "); | |
Serial.print(y+1); | |
Serial.print(" Voltages : "); | |
Serial.print(""); | |
minimoVoltage = voltage[y][1]; // OK, save the minimum | |
// Serial.print( inicioVoltage); | |
totalVoltage = 0; | |
for (int i = 1; i < 13; i++){ | |
//Serial.print(""); | |
if(voltage[y][i] <= minimoVoltage){ // Find the minimum voltage | |
minimoVoltage = voltage[y][i]; // Save the minimum value | |
//Serial.print("_Min_"); | |
} | |
Serial.print(voltage[y][i]); | |
Serial.print("mV "); | |
totalVoltage += voltage[y][i]; | |
if( i<12 ){ Serial.print(","); } | |
} | |
Serial.println(); | |
Serial.print("Cell blance status: "); | |
for (int i = 1; i < 13; i++){ | |
if(voltage[y][i] > minimoVoltage + 4){ // Differential of 4mV to stop equalizing with respect to the minimum value | |
mesBalanceo[i-1] = 0x01; | |
necesitaBalanceo = 1; // needs balance | |
Serial.print("O"); | |
}else{ | |
mesBalanceo[i-1] = 0x00; | |
Serial.print("."); | |
} | |
} | |
Serial.println(); | |
Serial.print("Battery Voltage: "); | |
Serial.print(totalVoltage/1000); | |
Serial.println("V."); | |
} | |
//Serial.print(); | |
//Serial.print(" Minimum cell voltage = "); | |
//Serial.print(minimoVoltage); | |
//Serial.print(" Swinging: "); | |
//Serial.println(necesitaBalanceo); | |
if(necesitaBalanceo && !monitorFlag){ | |
//Serial.println("Balance commard sent"); | |
sendcommandbalance(); | |
} | |
sendcommand(); | |
} | |
} | |
void menu() | |
{ | |
byte incomingByte = Serial.read(); // read the incoming byte: | |
switch (incomingByte) | |
{ | |
case 's': // | |
sendcommand(); | |
break; | |
case 'm': // monitor only mode | |
Serial.println("*** changed mode to montior only. ***"); | |
monitorFlag = true; | |
break; | |
case 'b': // balance mode | |
Serial.println("*** changed mode to balance. ***"); | |
monitorFlag = false; | |
break; | |
} | |
} | |
void sendcommandbalance(){ | |
mes[0] = mesBalanceo[0]; | |
mes[1] = mesBalanceo[1]; | |
mes[2] = mesBalanceo[2]; | |
mes[3] = mesBalanceo[3]; | |
mes[4] = mesBalanceo[4]; | |
mes[5] = mesBalanceo[5]; | |
mes[6] = mesBalanceo[6]; | |
mes[7] = mesBalanceo[7]; | |
CAN0.sendMsgBuf(balanceBMS[CMC-1][0], 1, 8, mes); | |
mes[0] = mesBalanceo[8]; | |
mes[1] = mesBalanceo[9]; | |
mes[2] = mesBalanceo[10]; | |
mes[3] = mesBalanceo[11]; | |
mes[4] = 0x00; | |
mes[5] = 0x00; | |
mes[6] = 0x00; | |
mes[7] = 0x00; | |
CAN0.sendMsgBuf(balanceBMS[CMC-1][1], 1, 8, mes); | |
} | |
void sendcommand() | |
{ | |
mes[0] = 0x00; | |
mes[1] = 0x00; | |
mes[2] = 0x00; | |
mes[3] = 0x00; | |
mes[4] = 0x00; | |
mes[5] = 0x00; | |
mes[6] = 0x00; | |
mes[7] = 0x00; | |
CAN0.sendMsgBuf(controlid, 0, 8, mes); | |
mes[0] = 0x45; | |
mes[1] = 0x01; | |
mes[2] = 0x28; | |
mes[3] = 0x00; | |
mes[4] = 0x00; | |
mes[5] = 0x00; | |
mes[6] = 0x00; | |
mes[7] = 0x30; | |
CAN0.sendMsgBuf(controlid, 0, 8, mes); | |
sent = 1; | |
// Serial.println(); | |
// Serial.print("Command Sent"); | |
// Serial.print(" Present Modules: "); | |
// Serial.print(modulespresent); | |
// Serial.println(); | |
modulespresent = 0; | |
} | |
void candecode() | |
{ | |
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s) | |
//Serial.print(rxId, HEX); | |
//Serial.print("="); | |
//Serial.print(rxId); | |
//Serial.print(" / "); | |
if (sent == 1){ | |
moduleidstart = rxId; | |
sent = 0; | |
debug = 0; // Activa depuración, para ver las tramas que recibe | |
} | |
if (rxId < 1024){ | |
//Serial.print(" "); | |
sent = 0; | |
int ID = rxId - moduleidstart; | |
//Serial.print(ID); | |
//Serial.print(","); | |
CMC = moduleidstart; | |
switch (ID){ | |
case 0: | |
voltage[modulespresent][1] = uint16_t(rxBuf[1] >> 4) + uint16_t(rxBuf[2] << 4) + 1000; | |
voltage[modulespresent][3] = uint16_t(rxBuf[5] << 4) + uint16_t(rxBuf[4] >> 4) + 1000; | |
voltage[modulespresent][2] = rxBuf[3] + uint16_t((rxBuf[4] & 0x0F) << 8) + 1000; | |
voltage[modulespresent][4] = rxBuf[6] + uint16_t((rxBuf[7] & 0x0F) << 8) + 1000; | |
break; | |
case 1: | |
voltage[modulespresent][5] = uint16_t(rxBuf[1] >> 4) + uint16_t(rxBuf[2] << 4) + 1000; | |
voltage[modulespresent][7] = uint16_t(rxBuf[5] << 4) + uint16_t(rxBuf[4] >> 4) + 1000; | |
voltage[modulespresent][6] = rxBuf[3] + uint16_t((rxBuf[4] & 0x0F) << 8) + 1000; | |
voltage[modulespresent][8] = rxBuf[6] + uint16_t((rxBuf[7] & 0x0F) << 8) + 1000; | |
break; | |
case 2: | |
voltage[modulespresent][9] = uint16_t(rxBuf[1] >> 4) + uint16_t(rxBuf[2] << 4) + 1000; | |
voltage[modulespresent][11] = uint16_t(rxBuf[5] << 4) + uint16_t(rxBuf[4] >> 4) + 1000; | |
voltage[modulespresent][10] = rxBuf[3] + uint16_t((rxBuf[4] & 0x0F) << 8) + 1000; | |
voltage[modulespresent][12] = rxBuf[6] + uint16_t((rxBuf[7] & 0x0F) << 8) + 1000; | |
modulespresent++; | |
sent =1; | |
break; | |
} | |
} | |
if (debug == 1) // If CAN0_INT pin is low, read receive buffer | |
{ | |
Serial.print(millis()); | |
if ((rxId & 0x80000000) == 0x80000000) // Determine if ID is standard (11 bits) or extended (29 bits) | |
sprintf(msgString, " Extended ID: 0x%.8lX DLC: %1d Data:", (rxId & 0x1FFFFFFF), len); | |
else | |
sprintf(msgString, ",0x%.3lX,false,%1d", rxId, len); | |
Serial.print(msgString); | |
if ((rxId & 0x40000000) == 0x40000000) { // Determine if message is a remote request frame. | |
sprintf(msgString, " REMOTE REQUEST FRAME"); | |
Serial.print(msgString); | |
} else { | |
for (byte i = 0; i < len; i++) { | |
sprintf(msgString, " , 0x%.2X", rxBuf[i]); | |
Serial.print(msgString); | |
} | |
} | |
Serial.println(); | |
} | |
} | |
/********************************************************************************************************* | |
END FILE | |
*********************************************************************************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated access to public.