Difference between revisions of "MIA electric"
(→CAN sniffing) |
(→sandbox) |
||
(16 intermediate revisions by the same user not shown) | |||
Line 5: | Line 5: | ||
** MCP2515 / TJA1050 shield http://blog.dimitarmk.com/wp-content/uploads/2016/12/wiringarduinomcp2515.png (8MHz EUR 4,79) | ** MCP2515 / TJA1050 shield http://blog.dimitarmk.com/wp-content/uploads/2016/12/wiringarduinomcp2515.png (8MHz EUR 4,79) | ||
** https://github.com/latonita/arduino-canbus-monitor (MCP_8MHz, CAN_500KBPS) | ** https://github.com/latonita/arduino-canbus-monitor (MCP_8MHz, CAN_500KBPS) | ||
− | ** OBD-II connector: Pin-6=CAN-high / Pin-14=CAN-low | + | ** OBD-II connector: Pin-6=CAN-high / Pin-14=CAN-low EUR 1,69 |
** CANcool https://github.com/MHS-Elektronik/CANcool | ** CANcool https://github.com/MHS-Elektronik/CANcool | ||
+ | |||
+ | === socketcand ('can over tcp/ip') === | ||
+ | * prerequisites: | ||
+ | ** Linux maschine | ||
+ | ** Arduino + CANbus shield + SLCAN ( https://github.com/latonita/arduino-canbus-monitor ) | ||
+ | * setup: | ||
+ | ** install can-utils <pre>sudo apt-get install can-utils</pre> | ||
+ | ** install socketcand http://kayak.2codeornot2code.org/tutorial.html | ||
+ | * run: | ||
+ | :<pre>slcand -o -s6 -t hw 115200 /dev/ttyusb0</pre> | ||
+ | :<pre>ip link set up slcan0</pre> | ||
+ | :<pre>socketcand -i slcan0</pre> | ||
+ | * usage: | ||
+ | ** http://kayak.2codeornot2code.org/ | ||
+ | |||
+ | === CANcool === | ||
+ | * [http://www.mhs-elektronik.de/index.php?module=content&action=show&page=can_cool website] | ||
+ | * [https://www.mikrocontroller.net/topic/283166 forum] | ||
+ | * [https://github.com/MHS-Elektronik/CANcool sources] | ||
+ | ==== 'Berechnungs-Term' ==== | ||
+ | * operators: | ||
+ | + // addition | ||
+ | - // subtraction | ||
+ | * // multiplication | ||
+ | / // division | ||
+ | << // Bit shift left | ||
+ | >> // Bit shift right | ||
+ | & // AND | ||
+ | | // OR | ||
+ | ~ // XOR | ||
+ | * variables: | ||
+ | d0 1st byte (decimal) | ||
+ | d1 2nd byte (decimal) | ||
+ | d3 3rd byte (decimal) | ||
+ | d4 ... | ||
+ | d5 ... | ||
+ | d6 ... | ||
+ | d7 ... | ||
+ | * samples: | ||
+ | d0 // unsigned char (8-bit) | ||
+ | (d0 - ((d0 >> 7)*256)) // signed char (8-bit) Two's complement | ||
+ | ((d0 << 8) + d1) ^= MSB * 256 + LSB // unsigned short (16-bit) | ||
+ | (((d0 << 8) + d1) - ((d0 >> 7)*65536)) // signed short (16-bit) Two's complement | ||
+ | ((d0 << 24) + (d1 << 16) + (d2 << 8) + d3) // unsigned integer (32-bit) | ||
+ | ((d0 << 24) + (d1 << 16) + (d2 << 8) + d3)-((d0 >> 7)*4294967296)) // signed integer (32-bit) Two's complement | ||
+ | |||
+ | 256 = (1 << 8) | ||
+ | 65536 = (1 << 16) | ||
+ | 16777216 = (1 << 24) | ||
+ | 4294967296 = (1 << 32) | ||
+ | |||
+ | ==== MIA >> Monitor = MIAtor ==== | ||
+ | * parts: | ||
+ | ** Arduino UNO R3 (or CH340 clone EUR 6,49) | ||
+ | ** MCP2515 / TJA1050 shield http://blog.dimitarmk.com/wp-content/uploads/2016/12/wiringarduinomcp2515.png (8MHz EUR 4,79) | ||
+ | ** OBD-II connector: Pin-6=CAN-high / Pin-14=CAN-low EUR 1,69 | ||
+ | ** 20x4 LCD display plus I2C EUR 8,77 | ||
+ | * libaries: | ||
+ | ** https://github.com/marcoschwartz/LiquidCrystal_I2C | ||
+ | ** https://github.com/coryjfowler/MCP_CAN_lib (clockset to MCP_8MHz at mcp_can.h line 98) | ||
+ | * code: | ||
+ | ** based on work of Voltix @ https://miahammia.wordpress.com/2017/10/08/infobox/ | ||
+ | <pre> | ||
+ | // MIA >> Monitor = MIAtor | ||
+ | // all about @ https://bastelbude.grade.de/mediawiki/index.php?title=MIA_electric#MIA_.3E.3E_Monitor_.3D_MIAtor | ||
+ | // based on Voltix's work @ https://miahammia.wordpress.com/2017/10/08/infobox/ | ||
+ | |||
+ | // CANbus | ||
+ | #include <mcp_can.h> // https://github.com/coryjfowler/MCP_CAN_lib (clockset to MCP_8MHz at mcp_can.h line 98) | ||
+ | #include <SPI.h> | ||
+ | |||
+ | // LCD | ||
+ | #include <Wire.h> | ||
+ | #include <LiquidCrystal_I2C.h> // https://github.com/marcoschwartz/LiquidCrystal_I2C | ||
+ | LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for a 20 chars and 4 line display | ||
+ | |||
+ | long unsigned int rxId; | ||
+ | unsigned char len = 0; | ||
+ | unsigned char rxBuf[8]; | ||
+ | float Volts; | ||
+ | float Amps; | ||
+ | float Celsius; | ||
+ | int SOC; | ||
+ | int SOH; | ||
+ | String Status; | ||
+ | String Emergency; | ||
+ | String Regeneration; | ||
+ | float ChargeCurrent; | ||
+ | float ChargeVoltage; | ||
+ | char myBuf[8]; | ||
+ | String LCDline[4]; | ||
+ | |||
+ | MCP_CAN CAN0(10); // Set CS to pin 10 | ||
+ | |||
+ | |||
+ | void myPrint(){ | ||
+ | Serial.println(LCDline[0]); | ||
+ | Serial.println(LCDline[1]); | ||
+ | Serial.println(LCDline[2]); | ||
+ | Serial.println(LCDline[3]); | ||
+ | |||
+ | lcd.setCursor(0,0); | ||
+ | lcd.print(LCDline[0]); | ||
+ | lcd.setCursor(0,1); | ||
+ | lcd.print(LCDline[1]); | ||
+ | lcd.setCursor(0,2); | ||
+ | lcd.print(LCDline[2]); | ||
+ | lcd.setCursor(0,3); | ||
+ | lcd.print(LCDline[3]); | ||
+ | |||
+ | delay(1000); // 1 second | ||
+ | } | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | lcd.init(); // initialize the lcd | ||
+ | lcd.init(); | ||
+ | // Print a message to the LCD. | ||
+ | lcd.backlight(); | ||
+ | LCDline[0] = " Hello world!"; | ||
+ | LCDline[1] = "MIA>>Monitor=MIAtor"; | ||
+ | LCDline[2] = "bastelbude.grade.de"; | ||
+ | LCDline[3] = " ver. 2017-12-21"; | ||
+ | |||
+ | Serial.begin(115200); | ||
+ | CAN0.begin(CAN_500KBPS); // init can bus : baudrate = 500k | ||
+ | pinMode(2, INPUT); // Setting pin 2 for /INT input | ||
+ | |||
+ | |||
+ | Serial.println("MCP2515 Library Receive Example..."); | ||
+ | //myPrint(); | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | if(!digitalRead(2)) // If pin 2 is low, read receive buffer | ||
+ | { | ||
+ | CAN0.readMsgBuf(&len, rxBuf); // Read data: len = data length, rxBuf = data byte(s) | ||
+ | rxId = CAN0.getCanId(); // Get message ID | ||
+ | |||
+ | if (rxId == 0x620) // battery related messageID 620 | ||
+ | { | ||
+ | LCDline[0] = "Bat: "; | ||
+ | |||
+ | Volts = ((float)(rxBuf[2]*256+rxBuf[3]))/100; // Voltage with decimals | ||
+ | Amps = ((float)(rxBuf[0]*256+rxBuf[1]))/10; // current drawn or regenerated, allow negative | ||
+ | Celsius = ((float)rxBuf[4]); // Temperature, allow negative | ||
+ | SOC = ((int)rxBuf[5]); // State Of Charge | ||
+ | |||
+ | LCDline[0] = dtostrf(Volts,4,1,myBuf); //set first line | ||
+ | LCDline[0] += "V | "; | ||
+ | LCDline[0] += dtostrf(Amps,6,1,myBuf); //length of string=6 decimal places=1 | ||
+ | LCDline[0] += "A |"; | ||
+ | LCDline[0] += dtostrf(Celsius,2,0,myBuf); //length of string=2 decimal places=0 | ||
+ | LCDline[0] += "C"; | ||
+ | |||
+ | switch (rxBuf[6]&0x07) { //mask lowest 3 bits (48+49+50) = status | ||
+ | case 0: | ||
+ | Status = "Ready | "; | ||
+ | break; | ||
+ | case 1: | ||
+ | Status = "Run | "; | ||
+ | break; | ||
+ | case 2: | ||
+ | Status = "Downgrad.| "; | ||
+ | break; | ||
+ | case 3: | ||
+ | Status = "Charge | "; | ||
+ | break; | ||
+ | case 4: | ||
+ | Status = "Error | "; | ||
+ | break; | ||
+ | case 5: | ||
+ | Status = "Init | "; | ||
+ | break; | ||
+ | case 6: | ||
+ | Status = "Stop | "; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | if ((rxBuf[6]&0x40)== 0) // bit 54 Emergency | ||
+ | { | ||
+ | Emergency = "noEmergcy"; | ||
+ | } else { | ||
+ | Emergency = "Emergency"; | ||
+ | } | ||
+ | |||
+ | if ((rxBuf[6]>>7)== 1) // bit 55 Regeneration | ||
+ | { | ||
+ | Regeneration = "okRegen | "; | ||
+ | } else { | ||
+ | Regeneration = "noRegen | "; | ||
+ | } | ||
+ | |||
+ | SOH = ((int)rxBuf[7]); // State Of Health | ||
+ | |||
+ | LCDline[1] = Status; //set second line | ||
+ | LCDline[1] += Emergency; | ||
+ | |||
+ | LCDline[2] = Regeneration; // set third line | ||
+ | LCDline[2] += "H="; | ||
+ | LCDline[2] += SOH; | ||
+ | LCDline[2] += " C="; | ||
+ | LCDline[2] += SOC; | ||
+ | LCDline[2] += "%"; | ||
+ | |||
+ | Serial.println(); // new line | ||
+ | |||
+ | Serial.print("ID 620 raw data: "); | ||
+ | for(int i = 0; i<len; i++) // Print each byte of the data | ||
+ | { | ||
+ | if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero | ||
+ | { | ||
+ | Serial.print("0"); | ||
+ | } | ||
+ | Serial.print(rxBuf[i], HEX); | ||
+ | Serial.print(" "); | ||
+ | } | ||
+ | Serial.println(); | ||
+ | |||
+ | LCDline[3] = ""; // set fourth line | ||
+ | for(int i = 0; i<len; i++) // Print each byte of the data | ||
+ | { | ||
+ | if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero | ||
+ | { | ||
+ | LCDline[3] += "0"; | ||
+ | } | ||
+ | sprintf(myBuf,"%hhX",rxBuf[i]); | ||
+ | LCDline[3] += myBuf; | ||
+ | } | ||
+ | |||
+ | myPrint(); // lcd-print and serial-print of all four lines | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | if (rxId == 0x621) // BMS error messageID 621 | ||
+ | { | ||
+ | Serial.print("ID 621 raw data: "); | ||
+ | for(int i = 0; i<len; i++) // Print each byte of the data | ||
+ | { | ||
+ | if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero | ||
+ | { | ||
+ | Serial.print("0"); | ||
+ | } | ||
+ | Serial.print(rxBuf[i], HEX); | ||
+ | Serial.print(" "); | ||
+ | } | ||
+ | Serial.println(); | ||
+ | } | ||
+ | |||
+ | if (rxId == 0x622) // BMS > Charger messageID 622 | ||
+ | { | ||
+ | ChargeCurrent = ((float)(rxBuf[0]*256+rxBuf[1]))/10; // Amps with decimals | ||
+ | ChargeVoltage = ((float)(rxBuf[3]*256+rxBuf[4]))/100; // Voltage with decimals | ||
+ | |||
+ | Serial.print("ID 622 raw data: "); | ||
+ | for(int i = 0; i<len; i++) // Print each byte of the data | ||
+ | { | ||
+ | if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero | ||
+ | { | ||
+ | Serial.print("0"); | ||
+ | } | ||
+ | Serial.print(rxBuf[i], HEX); | ||
+ | Serial.print(" "); | ||
+ | } | ||
+ | Serial.println(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </pre> | ||
=== DC charging === | === DC charging === | ||
Line 41: | Line 314: | ||
* docs | * docs | ||
** http://tesla.o.auroraobjects.eu/Design_Guide_Combined_Charging_System_V3_1_1.pdf | ** http://tesla.o.auroraobjects.eu/Design_Guide_Combined_Charging_System_V3_1_1.pdf | ||
+ | |||
+ | == spare + replacement parts == | ||
+ | * rear shocks | ||
+ | ** https://www.merlinmotorsport.co.uk/p/avo-coil-over-shock-absorber-with-poly-bush-mount-for-1-9-inch-springs-pa | ||
+ | * rims | ||
+ | ** 3x98mm bolt-pattern | ||
+ | |||
[[category:Projekte]] | [[category:Projekte]] |
Latest revision as of 17:21, 26 August 2019
Contents
sandbox
CAN-bus sniffing
- parts
- Arduino UNO R3 (or CH340 clone EUR 6,49)
- MCP2515 / TJA1050 shield (8MHz EUR 4,79)
- https://github.com/latonita/arduino-canbus-monitor (MCP_8MHz, CAN_500KBPS)
- OBD-II connector: Pin-6=CAN-high / Pin-14=CAN-low EUR 1,69
- CANcool https://github.com/MHS-Elektronik/CANcool
socketcand ('can over tcp/ip')
- prerequisites:
- Linux maschine
- Arduino + CANbus shield + SLCAN ( https://github.com/latonita/arduino-canbus-monitor )
- setup:
- install can-utils
sudo apt-get install can-utils
- install socketcand http://kayak.2codeornot2code.org/tutorial.html
- install can-utils
- run:
slcand -o -s6 -t hw 115200 /dev/ttyusb0
ip link set up slcan0
socketcand -i slcan0
CANcool
'Berechnungs-Term'
- operators:
+ // addition - // subtraction * // multiplication / // division << // Bit shift left >> // Bit shift right & // AND | // OR ~ // XOR
- variables:
d0 1st byte (decimal) d1 2nd byte (decimal) d3 3rd byte (decimal) d4 ... d5 ... d6 ... d7 ...
- samples:
d0 // unsigned char (8-bit) (d0 - ((d0 >> 7)*256)) // signed char (8-bit) Two's complement ((d0 << 8) + d1) ^= MSB * 256 + LSB // unsigned short (16-bit) (((d0 << 8) + d1) - ((d0 >> 7)*65536)) // signed short (16-bit) Two's complement ((d0 << 24) + (d1 << 16) + (d2 << 8) + d3) // unsigned integer (32-bit) ((d0 << 24) + (d1 << 16) + (d2 << 8) + d3)-((d0 >> 7)*4294967296)) // signed integer (32-bit) Two's complement 256 = (1 << 8) 65536 = (1 << 16) 16777216 = (1 << 24) 4294967296 = (1 << 32)
MIA >> Monitor = MIAtor
- parts:
- Arduino UNO R3 (or CH340 clone EUR 6,49)
- MCP2515 / TJA1050 shield (8MHz EUR 4,79)
- OBD-II connector: Pin-6=CAN-high / Pin-14=CAN-low EUR 1,69
- 20x4 LCD display plus I2C EUR 8,77
- libaries:
- https://github.com/marcoschwartz/LiquidCrystal_I2C
- https://github.com/coryjfowler/MCP_CAN_lib (clockset to MCP_8MHz at mcp_can.h line 98)
- code:
- based on work of Voltix @ https://miahammia.wordpress.com/2017/10/08/infobox/
// MIA >> Monitor = MIAtor // all about @ https://bastelbude.grade.de/mediawiki/index.php?title=MIA_electric#MIA_.3E.3E_Monitor_.3D_MIAtor // based on Voltix's work @ https://miahammia.wordpress.com/2017/10/08/infobox/ // CANbus #include <mcp_can.h> // https://github.com/coryjfowler/MCP_CAN_lib (clockset to MCP_8MHz at mcp_can.h line 98) #include <SPI.h> // LCD #include <Wire.h> #include <LiquidCrystal_I2C.h> // https://github.com/marcoschwartz/LiquidCrystal_I2C LiquidCrystal_I2C lcd(0x3F,20,4); // set the LCD address to 0x3F for a 20 chars and 4 line display long unsigned int rxId; unsigned char len = 0; unsigned char rxBuf[8]; float Volts; float Amps; float Celsius; int SOC; int SOH; String Status; String Emergency; String Regeneration; float ChargeCurrent; float ChargeVoltage; char myBuf[8]; String LCDline[4]; MCP_CAN CAN0(10); // Set CS to pin 10 void myPrint(){ Serial.println(LCDline[0]); Serial.println(LCDline[1]); Serial.println(LCDline[2]); Serial.println(LCDline[3]); lcd.setCursor(0,0); lcd.print(LCDline[0]); lcd.setCursor(0,1); lcd.print(LCDline[1]); lcd.setCursor(0,2); lcd.print(LCDline[2]); lcd.setCursor(0,3); lcd.print(LCDline[3]); delay(1000); // 1 second } void setup() { lcd.init(); // initialize the lcd lcd.init(); // Print a message to the LCD. lcd.backlight(); LCDline[0] = " Hello world!"; LCDline[1] = "MIA>>Monitor=MIAtor"; LCDline[2] = "bastelbude.grade.de"; LCDline[3] = " ver. 2017-12-21"; Serial.begin(115200); CAN0.begin(CAN_500KBPS); // init can bus : baudrate = 500k pinMode(2, INPUT); // Setting pin 2 for /INT input Serial.println("MCP2515 Library Receive Example..."); //myPrint(); } void loop() { if(!digitalRead(2)) // If pin 2 is low, read receive buffer { CAN0.readMsgBuf(&len, rxBuf); // Read data: len = data length, rxBuf = data byte(s) rxId = CAN0.getCanId(); // Get message ID if (rxId == 0x620) // battery related messageID 620 { LCDline[0] = "Bat: "; Volts = ((float)(rxBuf[2]*256+rxBuf[3]))/100; // Voltage with decimals Amps = ((float)(rxBuf[0]*256+rxBuf[1]))/10; // current drawn or regenerated, allow negative Celsius = ((float)rxBuf[4]); // Temperature, allow negative SOC = ((int)rxBuf[5]); // State Of Charge LCDline[0] = dtostrf(Volts,4,1,myBuf); //set first line LCDline[0] += "V | "; LCDline[0] += dtostrf(Amps,6,1,myBuf); //length of string=6 decimal places=1 LCDline[0] += "A |"; LCDline[0] += dtostrf(Celsius,2,0,myBuf); //length of string=2 decimal places=0 LCDline[0] += "C"; switch (rxBuf[6]&0x07) { //mask lowest 3 bits (48+49+50) = status case 0: Status = "Ready | "; break; case 1: Status = "Run | "; break; case 2: Status = "Downgrad.| "; break; case 3: Status = "Charge | "; break; case 4: Status = "Error | "; break; case 5: Status = "Init | "; break; case 6: Status = "Stop | "; break; } if ((rxBuf[6]&0x40)== 0) // bit 54 Emergency { Emergency = "noEmergcy"; } else { Emergency = "Emergency"; } if ((rxBuf[6]>>7)== 1) // bit 55 Regeneration { Regeneration = "okRegen | "; } else { Regeneration = "noRegen | "; } SOH = ((int)rxBuf[7]); // State Of Health LCDline[1] = Status; //set second line LCDline[1] += Emergency; LCDline[2] = Regeneration; // set third line LCDline[2] += "H="; LCDline[2] += SOH; LCDline[2] += " C="; LCDline[2] += SOC; LCDline[2] += "%"; Serial.println(); // new line Serial.print("ID 620 raw data: "); for(int i = 0; i<len; i++) // Print each byte of the data { if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero { Serial.print("0"); } Serial.print(rxBuf[i], HEX); Serial.print(" "); } Serial.println(); LCDline[3] = ""; // set fourth line for(int i = 0; i<len; i++) // Print each byte of the data { if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero { LCDline[3] += "0"; } sprintf(myBuf,"%hhX",rxBuf[i]); LCDline[3] += myBuf; } myPrint(); // lcd-print and serial-print of all four lines } if (rxId == 0x621) // BMS error messageID 621 { Serial.print("ID 621 raw data: "); for(int i = 0; i<len; i++) // Print each byte of the data { if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero { Serial.print("0"); } Serial.print(rxBuf[i], HEX); Serial.print(" "); } Serial.println(); } if (rxId == 0x622) // BMS > Charger messageID 622 { ChargeCurrent = ((float)(rxBuf[0]*256+rxBuf[1]))/10; // Amps with decimals ChargeVoltage = ((float)(rxBuf[3]*256+rxBuf[4]))/100; // Voltage with decimals Serial.print("ID 622 raw data: "); for(int i = 0; i<len; i++) // Print each byte of the data { if(rxBuf[i] < 0x10) // If data byte is less than 0x10, add a leading zero { Serial.print("0"); } Serial.print(rxBuf[i], HEX); Serial.print(" "); } Serial.println(); } } }
DC charging
CCS
- prerequisites
- explore V2G protocol
- discover BMS <> Charger CANbus conversation
- BMS/Battery e4v.eu
- onboard charger ies-synergy.com
- develop BMS <> PCL communication
- parts
- CCS-socket e.g. Phoenix Contact ~EUR 800,-
- input voltage monitor
- power contactor (+125A disconnecting device) Tyco ~EUR 150,-
- current monitor
- V2G in-vehicle-charge-controller e.g. EVAcharge SE ~EUR 750,-
- ARM microcontroller
- Linux OS
- fully programmable
- PWM duty cycle detection (CP low level communication)
- switchable resistors (CP low level communication)
- HomePlug Green PHY integration (PLC high level communication)
- Proximity pilot signal input (PP)
- lock-motor output
- lock-motor end switch input
- lock-motor fault pin
- CAN transceiver (BMS communication)
- 6 GPIOs (current-monitoring?, voltage-monitoring?, temprature-monitoring?, power contactor-driver?, (contactor-monitoring?))
spare + replacement parts
- rear shocks
- rims
- 3x98mm bolt-pattern