Send iMiev Battery Data to MQTT / SmartHome / HomeAssistant. Here is how.

Mitsubishi i-MiEV Forum

Help Support Mitsubishi i-MiEV Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

Raphael303

Member
Joined
Nov 23, 2017
Messages
9
Thanks to the work done in this forum and the known CanIDs the following can be done to get iMiev Battery Data from the iMiev to MQTT / HomeAssistant or any other SmartHome System capable of MQTT. (NodeRed etc.)
The only disadvantage I see is that you will only get data when the iMiev is charging (ignition/key is irrelevant) I have not managed to get data from the battery by requesting it, when the ignition was off. Never tried it with ignition on, though.

This works just the same with ANY EV where you know the CAN IDs to read. Just the Json below would need to be changed.

Here is how:
  • Get MeatPi WiCanOBD - https://github.com/meatpiHQ/wican-fw (Around 40$) (Great support on GitHub!)
  • Plug WiCanOBD into iMiev
  • Connect to your Wlan - according to manual (above)
  • Install newest firmware - according to manual (above)
  • Setup with your MQTT server / login - according to manual (above)
  • Connect to WiCan via FTP with filezilla as described here: https://github.com/meatpiHQ/wican-fw/issues/66
  • Edit the file "mqtt_canfilt.json" and replace its content with the json-content bellow
  • Reboot and get the MQTT-data anyway you know how - for example via NodeRed (flow below) or by creating MQTT-Sensors in HomeAssistant

Here is the jSon File, if you want / know, more data to be sent to MQTT you can of course add the necessary IDs and conversions.

Code:
{
  {
    "can_flt": [
        {
            "CANID": 884,
            "Name": "SOC1",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "(B0-10)/2",
            "Cycle": 9999
        },
        {
            "CANID": 883,
            "Name": "BatteryVolts",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "(B4*256+B5)/10",
            "Cycle": 9999
        },
        {
            "CANID": 883,
            "Name": "CellMaxVolt",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "(B0 + 210) / 100",
            "Cycle": 9999
        },
        {
            "CANID": 883,
            "Name": "CellMinVolt",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "(B1 + 210) / 100",
            "Cycle": 9999
        },
        {
            "CANID": 884,
            "Name": "SOC2",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "(B1-10)/2",
            "Cycle": 9999
        },
        {
            "CANID": 884,
            "Name": "CellMaxTemp",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B4-50",
            "Cycle": 9999
        },
        {
            "CANID": 884,
            "Name": "CellMinTemp",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B5-50",
            "Cycle": 9999
        },
        {
            "CANID": 884,
            "Name": "Battery100Cap",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B6/2",
            "Cycle": 9999
        },
        {
            "CANID": 905,
            "Name": "ChargeVoltsDC",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "2*B0+0.5",
            "Cycle": 9999
        },
        {
            "CANID": 905,
            "Name": "ChargeVoltsAC",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B1",
            "Cycle": 9999
        },
        {
            "CANID": 905,
            "Name": "ChargeAmpsDC",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B2/10",
            "Cycle": 9999
        },
        {
            "CANID": 905,
            "Name": "ChargerTemp1",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B3-50",
            "Cycle": 9999
        },
        {
            "CANID": 905,
            "Name": "ChargerTemp2",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B4-50",
            "Cycle": 9999
        },
        {
            "CANID": 905,
            "Name": "ChargeAmpsAC",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B6/10",
            "Cycle": 9999
        },
        {
            "CANID": 1042,
            "Name": "Odometer",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B2*65536+B3*256+B4",
            "Cycle": 9999
        },
        {
            "CANID": 646,
            "Name": "OutdoorTemp",
            "PID": -1,
            "StartBit": 0,
            "BitLength": 8,
            "Expression": "B3-50",
            "Cycle": 9999
        }
        ]}

Here is a node red flow to get the data from MQTT and send each to a separate Debug-Node

Code:
[{"id":"a88c67ea87483243","type":"debug","z":"387e7197d6bc2272","name":"SOC1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":320,"wires":[]},{"id":"ad37989ca23a9e9a","type":"debug","z":"387e7197d6bc2272","name":"SOC2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":790,"y":340,"wires":[]},{"id":"9e81ddf40702ce38","type":"debug","z":"387e7197d6bc2272","name":"debug 81","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":360,"wires":[]},{"id":"5e21d034d0e323f1","type":"debug","z":"387e7197d6bc2272","name":"debug 82","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":380,"wires":[]},{"id":"7a62e9ade27d1c40","type":"debug","z":"387e7197d6bc2272","name":"debug 83","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":400,"wires":[]},{"id":"a8249754724c2a3b","type":"debug","z":"387e7197d6bc2272","name":"debug 84","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":420,"wires":[]},{"id":"3de5984943a69458","type":"debug","z":"387e7197d6bc2272","name":"debug 85","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":440,"wires":[]},{"id":"e0d7067a8b772b40","type":"debug","z":"387e7197d6bc2272","name":"debug 86","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":460,"wires":[]},{"id":"35047cd9dd4c4123","type":"debug","z":"387e7197d6bc2272","name":"debug 87","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":480,"wires":[]},{"id":"c2ed070d573f5647","type":"debug","z":"387e7197d6bc2272","name":"debug 88","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":500,"wires":[]},{"id":"5a8d28d49e07392c","type":"debug","z":"387e7197d6bc2272","name":"debug 89","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":520,"wires":[]},{"id":"beb0448d43cd49a1","type":"debug","z":"387e7197d6bc2272","name":"debug 90","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":540,"wires":[]},{"id":"60f627d009ce8e0c","type":"debug","z":"387e7197d6bc2272","name":"debug 91","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":560,"wires":[]},{"id":"8ca7999e2879d514","type":"debug","z":"387e7197d6bc2272","name":"debug 92","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":580,"wires":[]},{"id":"8e59721c1cd40964","type":"debug","z":"387e7197d6bc2272","name":"debug 93","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":600,"wires":[]},{"id":"eb5271cbacf8544b","type":"debug","z":"387e7197d6bc2272","name":"debug 94","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":800,"y":620,"wires":[]},{"id":"c960c70417f219b5","type":"function","z":"387e7197d6bc2272","name":"Parse CAN EV1","func":"// Your variables\nvar SOC1, SOC2, Battery100Cap, CellMaxTemp, CellMinTemp, BatteryVolts, CellMaxVolt, CellMinVolt, ChargeAmpsAC, ChargeAmpsDC, ChargeVoltsAC, ChargeVoltsDC, ChargerTemp1, ChargerTemp2, Odometer, OutdoorTemp;\n\n// Initialize all variables to null to ensure no data is sent if a variable is not updated\nSOC1 = SOC2 = Battery100Cap = CellMaxTemp = CellMinTemp = BatteryVolts = CellMaxVolt = CellMinVolt = ChargeAmpsAC = ChargeAmpsDC = ChargeVoltsAC = ChargeVoltsDC = ChargerTemp1 = ChargerTemp2 = Odometer = OutdoorTemp = null;\n\n// Check if the incoming message payload has one of the expected keys\nvar key = Object.keys(msg.payload)[0]; // Get the key from the incoming message\nvar value = msg.payload[key]; // Get the value associated with the key\n\n// Assign the incoming value to the corresponding variable\nswitch (key) {\n    case 'SOC1': SOC1 = value; break;\n    case 'SOC2': SOC2 = value; break;\n    case 'Battery100Cap': Battery100Cap = value; break;\n    case 'CellMaxTemp': CellMaxTemp = value; break;\n    case 'CellMinTemp': CellMinTemp = value; break;\n    case 'BatteryVolts': BatteryVolts = value; break;\n    case 'CellMaxVolt': CellMaxVolt = value; break;\n    case 'CellMinVolt': CellMinVolt = value; break;\n    case 'ChargeAmpsAC': ChargeAmpsAC = value; break;\n    case 'ChargeAmpsDC': ChargeAmpsDC = value; break;\n    case 'ChargeVoltsAC': ChargeVoltsAC = value; break;\n    case 'ChargeVoltsDC': ChargeVoltsDC = value; break;\n    case 'ChargerTemp1': ChargerTemp1 = value; break;\n    case 'ChargerTemp2': ChargerTemp2 = value; break;\n    case 'Odometer': Odometer = value; break;\n    case 'OutdoorTemp': OutdoorTemp = value; break;\n    // Add more cases as needed\n    default: node.warn(\"Unexpected key: \" + key); // Warn if an unexpected key is received\n}\n\n// Return the variables as message payloads for the corresponding outputs\nreturn [SOC1, SOC2, Battery100Cap, CellMaxTemp, CellMinTemp, BatteryVolts, CellMaxVolt, CellMinVolt, ChargeAmpsAC, ChargeAmpsDC, ChargeVoltsAC, ChargeVoltsDC, ChargerTemp1, ChargerTemp2, Odometer, OutdoorTemp].map(function (data) {\n    return data !== null ? { payload: data } : null;\n});\n","outputs":16,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":460,"wires":[["a88c67ea87483243"],["ad37989ca23a9e9a"],["9e81ddf40702ce38"],["5e21d034d0e323f1"],["7a62e9ade27d1c40"],["a8249754724c2a3b"],["3de5984943a69458"],["e0d7067a8b772b40"],["35047cd9dd4c4123"],["c2ed070d573f5647"],["5a8d28d49e07392c"],["beb0448d43cd49a1"],["60f627d009ce8e0c"],["8ca7999e2879d514"],["8e59721c1cd40964"],["eb5271cbacf8544b"]]},{"id":"80c20fc9b8646b6e","type":"mqtt in","z":"387e7197d6bc2272","name":"","topic":"wican/84f703413a1d/can/rx","qos":"0","datatype":"auto-detect","broker":"1044669fd246f1da","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":460,"wires":[["5962c475f4beb5b1","c960c70417f219b5"]]},{"id":"5962c475f4beb5b1","type":"debug","z":"387e7197d6bc2272","name":"debug 95","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":300,"y":360,"wires":[]},{"id":"1044669fd246f1da","type":"mqtt-broker","name":"Mosquitto","broker":"192.168.1.103","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closeRetain":"false","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

I hope this helps someone.

I can now not only monitor the Charging of the iMiev, but I can also charge only to a certain point. Furthermore I have automations which check the battery state in the evening (turn on charging for 10 seconds) then decides if the car needs to be charged for the next day during the night and charges up to a desired level. This is handy for me, because I try to charge during the night only as rarely as possible, since we have solar panels and a powerwall (sortof) and charging the EV through the night should only be done when absolutely necessary.
 
Brilliant, well done!!

So if I understand correctly with this setup I could set a schedule to avail of cheap night tariffs (2am-6am) and limited the charge to 80% not having to worry at what time I plug in the car?

[edit] For that to work one would need an EVSE that’s also integrated, yes?
 
MickeyS70 said:
Brilliant, well done!!

So if I understand correctly with this setup I could set a schedule to avail of cheap night tariffs (2am-6am) and limited the charge to 80% not having to worry at what time I plug in the car?

[edit] For that to work one would need an EVSE that’s also integrated, yes?

There are levels to this:

  • Level 1: Turn on charger at specific times only - use just a timer-plug. (Assuming your charger starts charging when connected to mains, while being connected to iMiev (original and EVSE does)
  • Level 2: Turn on charger at specific times only - With some SmartHome Server like HomeAssistant: You only need a smart plug with ESP-Home or ZiGbee.
  • Level 3: Turn on charger at specific times only AND charge only to certain level - As Level 2 + WiCan to stop charging at a certain level.
  • Level 4: Turn on charger at specific times only AND charge only to certain level AND regulate the Charge-Power according to excess power or whatnot - As Level 3 + Some Wallbox which can be controlled by your smarthomeserver. **

**To control an EVSE Wallbox from home assistant use an ESP32 + https://github.com/syssi/esphome-evse-wallbox/blob/main/esp32-example-rev15.yaml

I do level 4 here with ESP32s connected to my EVSE wall boxes. One is a self made one, with the usual EVSE components + ESP32, the other is the cheapest which "Stark in strom" ever sold (not available anymore) which can be ESP32/Wifi-ized VERY VERY easily. We have two iMievs and I have a nodered flow organizing Excess-Charge for the two iMievs. Ramping up power to the two gradually as solar power becomes available. My RodeRed Flow for the Excess charging needs work, because managing two cars really is not so simple, but I will get there.
Whats working really well is the control of the EVSE wallbox through ESP-home and the code above, + The reading of the CAN of the imiev. Really very solid both, now. For now? :)
 
While starting a Level 1 EVSE on a timer is OK, disconnecting it under load might be asking for trouble.
It’s considered safer to tie into the CP line and apply a 12VDC voltage to stop charging but simply interrupting the signal also works.

No issues if your EVSE is wired for remote start/stop or indeed has a proper scheduling function.

Just curious, assuming your EVs aren’t home during working/solar time, how do you make use of excess energy? Do you have a (big) battery or is there still plenty of sunshine left (at least during summer)?
 
MickeyS70 said:
While starting a Level 1 EVSE on a timer is OK, disconnecting it under load might be asking for trouble.
It’s considered safer to tie into the CP line and apply a 12VDC voltage to stop charging but simply interrupting the signal also works.

No issues if your EVSE is wired for remote start/stop or indeed has a proper scheduling function.

Just curious, assuming your EVs aren’t home during working/solar time, how do you make use of excess energy? Do you have a (big) battery or is there still plenty of sunshine left (at least during summer)?

I have been switching the original iMiev-Charger on/off from the plug for years and haven't had any problems.

The problem with turning the power off from the EVSE is, that while it is charging to turn charging off without cutting power is to set the charge-amps register (1000) to 0 Amps. The EVSE firmware doesn't actually have a "stop" function. It just sets charge power to 0. And it is the charger of the car, which then cuts off.

This works with our newer iMiev (16kwh) battery (2018) but not with out 2012 iMiev with the 12kWh battery. With the old iMiev, if you stop EVSE charging by setting register 1000 to 0 it sort of "crashes" and only starts charging again if you cut power to the charger, or unplug, re-plug.

Also the old iMiev can not charge with 6 Amps. The lowest is 7 Amps. If you set it to 6 Amps, it behaves erratically. Also very easily observable if you have the original Mitsubishi Charger with 6 Amps which came with our 2018 iMiev. We can't charge the old iMiev with that one.

As for cutting power when it is going full 3.3kw, I have never had any issues with that. I'm not using a smart plug though, but an industry KNX-actor.

We have a battery, but it is only 20kwh, of which about 14kwh are actually usable if you treat it right. 4 Tesla Modules and a SimpBMS hooked up to 3 Victron MultiplusII 5000 in three-phase-mode. We sometimes do need to charge the iMievs during the night, but its capacity is nowhere close to what would be needed.

Luckily this is rarely the case, since during summer we are both often home around 16.00. Given a commute of 50k, the little bit of sunshine left in that day often still yields 5-8kwh for each of the batteries (we have 15k peak Solar).

Luckily 2.0 we both have some home office possibilities and some days my commute is shorter as I work in a city farther away and just go to the train station by car. So, given our life-style we can get it down to about 1-2 times a week where we have to charge the cars during the night. For those nights, thanks to wican I can now limit the charge to 70%, since this is enough for the commute.
 
Raphael303 said:
This works with our newer iMiev (16kwh) battery (2018) but not with out 2012 iMiev with the 12kWh battery.

Do you mean that the battery of the 2012 model has degraded to 12kWh as I wasn’t aware I-Mievs were available with smaller packs?
 
MickeyS70 said:
Raphael303 said:
This works with our newer iMiev (16kwh) battery (2018) but not with out 2012 iMiev with the 12kWh battery.

Do you mean that the battery of the 2012 model has degraded to 12kWh as I wasn’t aware I-Mievs were available with smaller packs?

tbh. I'm not sure if the battery of the old ones was indeed smaller, or if they just limited their capacity. With the 2012 version they were sold with a range of 100k, later the range was 120-150k. At least here in Switzerland.

The battery of our 2012 iMiev broke down some years ago and mitsubishi replaced it under warranty even outside the warranty because we were bellow 50'000km.

Then, when they replaced the battery they did their "formatting" thing where they discharge the battery a couple of times with a resistor. After that their test yields an Amperehour reading which they then enter into the car, and that is the new max. The fresh battery had a reading of something between 36 and 40ah. Can't remember, but I remember calculating the kwh from it and ending up with something odd 12kwh. They showed me some test protocol.

Later a mitsubishi-tech confirmed that the first generation had either a smaller pack, or it was setup to use less of it. He didn't know. He just performs the tests according to the book and the software tells him what to enter into the car.

By the way: The ion and czero were certainly available in 14.5kwh hour versions.
 
Yes, C-Zeros & Ions only have 80cells once they switched to newer LEV50N packs, however I’m pretty sure all I-Mievs outside Japan kept a 16KWh, 88cell battery.

A pristine 16KWh pack should have around 45Ah, looks like the capacity in your 2012 model was artificially reduced or the replacement battery wasn’t exactly ‘new’.
 
Back
Top