openvehicles / Open-Vehicle-Monitoring-System-3

Open Vehicle Monitoring System - Version 3
http:///www.openvehicles.com/
Other
589 stars 225 forks source link

Possible to add stop charging on Nissan Leaf? #287

Closed dalathegreat closed 2 years ago

dalathegreat commented 4 years ago

0x1BD contains a section to stop charging, by modifying this bit you can stop it. frame.data[1] = (frame.data[1] & 0xE0) | 2; //request charging stop

I am using muxsan CAN bridges, so I'm unsure if this is possible to transfer over to OVMS. But just as an FYI to you guys more knowledgeable of the OVMS system :)

markfinn commented 4 years ago

I couldn't get that (the failsafe request from the HVBAT) to work from OVMS.

But,

can can1 tx standard 1f2 30 71 60 b0 00 3c 03 88 did work. It's a Charge_StatusTransitionReqest with a value of 3 -- "stop". I'm a little hazy on what device is supposed to be sending this normally. The reaction of the car was to turn off the EVSE. I was too far away to hear if any relays in the car flipped. The charge lights kept showing that a charge was in progress. I didn't try to re-start the charge from software yet, but pressing and releasing the EVSE disconnect (not actually unplugging it) did NOT restart the charge, even though the charging status lights went out while the button was pressed.

I generated my message by msg[2] := msg[2] & 0xcf | 0x60, then updating the checksum.

The last byte seems to be a crappy checksum. for the messages I've seen it's ((sum(all the nibbles in the first 7 bytes) + 0xa) & 0xf) | 0x80

I actually don't think this is the right way to do it, I think maybe faking the HVBAT "charge complete" signal or the (EVC?) Keep_SOC would be better. I will try out a few more things in a few days

@dalathegreat your leaf messages repo has been very helpful.

grnbrg commented 4 years ago

I was able to get charging stopped with:

  `can can1 tx standard 1db 00 1a 00 00 00 00 e3`

On the down side, I've collected a P31E1 DTC -- "EV/HEV HV System Interlock Error", but I also set a couple of flags that seemed interesting. :)

The last byte (For 0x1DB, anyway) appears to be a CRC-8, with a polynomial of 0x85, and an initial value and final XOR of 0x0. See http://www.sunshine2k.de/coding/javascript/crc/crc_js.html for a CRC tool.

The good news is that we seem to have proved that turn off an ongoing charge is at least possible!!

BTW: The initial issue post by @dalathegreat appears to have a typo -- based on his CAN bus files, the message to stop charging should be 0x1DB, not 0x1BD.

dalathegreat commented 4 years ago

Amazing progress πŸ‘ Yeah sorry about the typo, 0x1DB is the place to be.

By setting frame 3, bit 4 high, you indicate a full charge has been completed. Maybe this is more gentle? 'LB_Full_CHARGE_flag'

frame.data[3] = (frame.data[3] & 0xEF) | 0x10; //full charge completed

This paired with the frame.data[1] = (frame.data[1] & 0xE0) | 2; //request charging stop

And finally recalculating the CRC, results in a clean termination of the charge, with the charge lights shutting off.

Good that the DBC files were helpful :)

glynhudson commented 4 years ago

The good news is that we seem to have proved that turn off an ongoing charge is at least possible!!

Nice work, this is really cool! Would be a super useful feature :+1:

dalathegreat commented 4 years ago

Anyone have the possibility to try this one? Should be gentle since it's just a request to stop and also flag that battery is full.

can can1 tx standard 1db 00 02 00 10 00 00 e3 df

02 signals the request charging stop 10 signals that full charge is completed e3 signals the PRUN counter (not really needed since it accepts one error message, read more on the github CAN page for more info) df is the CRC

With the OVMS, is it possible to read the previous 0x1DB message and use it as template before applying these requests? The proper way to send this message would be 1db prev 02 prev 10 prev prev prev+1 CRC The +1 should be on the low nibble.

markfinn commented 4 years ago

The command as is didn't do anything for me. I tried it several times to make sure the clock byte wasn't the problem.

I'll look into it more a little later

markfinn commented 4 years ago

Hmm, I wired it in to send on an event using the latest 1db value as a base, and it didn't work:

I (63894) webcommand: HttpCommandStream[0x3fa34284]: 2001444 bytes free, executing: event raise mark.battkill I (63894) v-nissanleaf: mark bat kill1 0x00 0xE0 0xC5 0x6A 0x62 0x00 0x02 0x16 <- this is the last 1db recieved I (63894) v-nissanleaf: mark bat kill2 0x00 0xE2 0xC5 0x10 0x62 0x00 0x03 0x47 <- I sent these I (63904) v-nissanleaf: mark bat kill3 0x00 0xE2 0xC5 0x10 0x62 0x00 0x00 0x4D <-this too

dalathegreat commented 4 years ago

On frame[3] by sending 0x10 instead of 0x6A, you disable a lot of things that you shouldn't. You disable mainrelay permission, set interlock to 0, discharge power status to undefined state, and flip the voltage latch flag.

Sending 0x7A is way better than that. But I still don't get why it doesn't cancel the charge.

So my last suggestion for you markfinn is to try just spamming this while charging 0x00 0xE2 0xC5 0x7A 0x62 0x00 0x03 0x0A

markfinn commented 4 years ago

I'm fully charged now, so I can't try anything more at the moment.

I did try or'ing 0x10 on to frame[3] also but that didn't have a different effect. Coming to think of it nothing happened. no errors, no relay clicking. I think my packets were completely ignored.

dalathegreat commented 4 years ago

If we go back to trying 1F2, you did a mistake in the original attempt

I generated my message by msg[2] := msg[2] & 0xcf | 0x60

It should be msg[2] := msg[2] & 0x9F | 0x60

So we still have things to try! :)

markfinn commented 4 years ago

You're right that I used the wrong mask there, but my result still would have been that same packet.

markfinn commented 4 years ago

I'm going to try man-in-the-middling the 0x1db packet since that seems to work for you. I'll use the clock byte to force my packets to be read by the VCM while the real ones look out of sync. I'm not happy about that as a real solution, but I'd at least like to see why it works for you on MUXSAN but not here.

I'll report back after I write the code and drive some charge off the battery.

markfinn commented 4 years ago

Sending full charge completed and failsafe stop charging request stop DID work.

It was especially responsive when emulating the MITM with the clock byte. It was less responsive when just sending one packet, sometimes not working, and sometimes I think clicking a relay in the car but NOT deactivating the EVSE followed by the relay clicking back and charge continuing.

I am a concerned about using the failsafe to stop charging. I'm pretty sure I read something (probably in the service manual?) that the car counts how many times one of the relays is forced open under power id marks the relay as bad after some number of uses. I would not be surprised if that was the failsafe relay. The manual is laid out in a way that I find very hard to search, so I don't know when I'll find that section again.

brief code chunk:

    case 0x1db:
    {
      if (MITM) {
        unsigned char new1db[8];
        memcpy(new1db, d, 8);
        new1db[1] = (new1db[1] & 0xe0) | 2;
        new1db[3] |= 0x10;
        new1db[6] = (new1db[6] + 1) % 4;
        new1db[7] = leafcrc(7, new1db);
        m_can1->WriteStandard(0x1db, 8, new1db);
      }
//normal 0x1db processing continues here
markfinn commented 4 years ago

As a separate comment... if using failsafe turns out to be bad, I think there are still other options:

0x1f2 Charge_StatusTransitionReqest might still warrant consideration

MITMing the signal from the PDM that says the AC voltage is applied (0x390?). Basically try to look like a power outage.

Another option would be the TargetChargeSoc bit in 0x1f2. we couldn't stop charging with that last one, but we might be able to bring back the 80% mode.

dalathegreat commented 4 years ago

Great work!

I've been using the 0x1db method daily for three weeks. I'll let you know as soon as it triggers a DTC :)

markfinn commented 4 years ago

Here's the relay thing to watch out for

Perform Li-ion Battery Junction Box Data Clear when the Li-ion Battery Junction Box is replaced with a new one. VCM counts the times system main relay is turned off due to a large current and use this information to manage the system main relay deterioration status. As the system main relay deterioration status progresses, a DTC β€œP31DE” is detected and notification that the Li-ion battery junction box needs to be replaced is given. When the Li-ion Battery Junction Box is replaced with a new one, there is a difference between the System Main Relay cutoff count stored in VCM and the actual System Main Relay cutoff count. In this case, VCM will detect the DTC with incorrect timing. So perform Li-ion Battery Junction Box Data Clear to clear the System Main Relay cutoff count stored in VCM.

dalathegreat commented 4 years ago

Nice find, but since the text clearly says VCM counts the times system main relay is turned off due to a large current , I don't think it will increment since we are issuing a request charging stop from HVBAT -> VCM, so the VCM handles the charge stop gracefully. It's not the battery that just decides to open the main relays all of a sudden!

markfinn commented 4 years ago

I'm hoping you're right. My worry is that we aren't actually requesting a graceful termination, but a failsafe one, where the VCM might be dropping the failsafe or main relays without telling the OBC (aka the PDM) to turn off charging current.

or hopefully that L1/L2 charge current wouldn't be considered large compared to the 80KW traction motor, but we might want to get a few months of some testing in before the world at large starts using it.

markfinn commented 4 years ago

Not ready to merge, but here's the working code. I have the "charge complete" bit change commented out because it seemed to be weird to have the 3 lights come on when stopping the charge and I thought the car might not have restarted charging after that, but It should be tried again now that I fixed a few other bugs.

markfinn@bcc85a5acb5014cf8c4de8f7e482b1f991ee6b36

dalathegreat commented 4 years ago

Great work @markfinn , and this way to stop the charge has already been tested on >5 cars since September now in a NL based conversion garage πŸ˜„

markfinn commented 4 years ago

firmware for the brave: https://github.com/markfinn/Open-Vehicle-Monitoring-System-3/releases/tag/3.2.008-leaf-chg-stop-1

It uses a config option to enable so it shouldn't be too scary to try.

grnbrg commented 4 years ago

@markfinn -- Your firmware seems to stop charging nicely, but it still (as does everything else I've tried) throws a DTC, although this one doesn't seem to have much negative effect. The DTC is P317E - "HV BATTERY SYSTEM (High voltage battery system)" and "VCM detects an error signal that is received from LBC via CAN communication for 0.02 seconds or more." The other 0x1db messages I have tried have usually caused a P31E1 DTC, which if not cleared before attempting to start would cause a couple of other DTCs, associated with the Brake and ABS system -- C118C, C1A6E and C1A70.

Also, the charge request doesn't appear to be cancelled. When I clear the P317E DTC, and disconnect/reconnect the EVSE, the charge starts again. I'll see what the 0x1f2 messages do tomorrow..... :)

markfinn commented 4 years ago

Weird, I've used it a bunch of times with no codes. What year is your car? Do you have the charge timer set? The car is off when you try it?

For me those answers are 2016 US model SL, no timer, car off. Also I'm charging from a "cheap" 40A L2 charger.

grnbrg commented 4 years ago

2015 SV, I've got a timer set, but it's not active for the test period. Car is off, and plugged in when the charge start command is run remotely.

markfinn commented 4 years ago

That P317E code sounds like it's complaining about exactly what I'm doing... Raising the failsafe stop signal. That's not great.

I wonder if uncommenting the full-charge flag Dala suggested would help you.

If you play with 1f2 I suspect my csum routine isn't right. It worked for me the other day but today all my packets were ignored. I only had a few packets captured to deduce from and probably didn't get it all. I've got a commit in my repo that I was using to send 1f2 packets from an event I could raise in the console if you want to start from something.

markfinn commented 4 years ago

Ok, fixed and force-pushed the 1f2 checksum. Not only did my code not follow my own algorithm but I found what was wrong with that first swag at the algorithm: if you include the packet ID nibbles and the nibble that shares the byte with the csum it works out without any fudge factor

Markfinn@ea86ebe0a0c9d675469 has the fixed csum code and will mostly stop a charge with 1f2 if you run event raise mark.battkill2

dalathegreat commented 4 years ago

This seems to be really vehicle specific somehow. I just got word of a 62kWh swapped 2014 Leaf, that when triggering the chargestop using only 1db message, it triggers the DTC P317E.

@markfinn , the 1f2 method, does it stop charging AND stop the charge lights? If it doesn't stop the chargelights, maybe doing 1f2 and then 1db could be an option?

markfinn commented 4 years ago

I haven't tried the 1f2 for a while, so I'm not sure at the moment.

My guess right now for the DTC P317E is that it's a model year thing. 2016 OK, <=2015 bad. Does that match with what you've seen?

I think I founf one more quirk this morning with usig 0x1db failsafe... It seems to stop me climate timer from warming up the car later. Does it work for you?

dalathegreat commented 4 years ago

@markfinn Yes, I noticed too that after the charge has been stopped with 1db method, climate timers are not able to start. Annoying!

Maybe we should still try to get this functionality to the main OVMS release branch? It would still be very beneficial for Nissan Leaf owners looking to slow down battery degradation, even with all the current quirks.

glynhudson commented 4 years ago

Nice work guys, I think even it it throws a DTC it would be good to have this functionality merged into OVMS main release branch. I've seen this DTC before when a charger stops unexpectedly, I think it's harmless. Ideally the OVMS app could warn the user with a popup that stopping a charge will throw a DTC. In my experiance switched the car on then off again clears the DTC from the dashboard.

It would be a super nice feature to be able to set a SoC limit for OVMS to auto stop charging.

markfinn commented 4 years ago

Alright, I'll finish cleaning this up and get a pull request going.

dalathegreat commented 4 years ago

Ping @markfinn , any progress? :)

TrueSolutions commented 4 years ago

@dalathegreat been looking at message and would you know sequence to start the onboard charger ? Working with a OBC sitting on bench with connected to battery and junction box of a leaf Gen1 Trying to work out how out how to turn on and off charger with out a VCM to charge battery.

dalathegreat commented 4 years ago

@TrueSolutions Check this thread https://mynissanleaf.com/viewtopic.php?f=44&t=30915 , let's keep this thread about the stop-charge

mjkapkan commented 4 years ago

@markfinn Great solution! I just made a pull request with new HVAC metrics added and updated the main documentation page as well. So would suggest to fetch that one to avoid conflicts.

mjkapkan commented 4 years ago

Added parts of your code to my fork and it works great! I can finally proceed with testing my smart charge controller plugin. The only problem I found is that it does not remember that charging is stopped if you enable the remote climate control after stopping the charge with this new method. So we could either work around this by saving the last charge state in the OVMS config or finding another way to stop the charge?

dalathegreat commented 4 years ago

I'd really hope we could get someone to land this as a PR to the main branch!

mjkapkan commented 4 years ago

Used this method for over a week now. Seems to not cause any issues. But before putting this on the main branch we need to handle the last charge state within OVMS. I can do that, but would be great to know first if @markfinn maybe has a better solution for that and we just need to wait a bit...

dteirney commented 4 years ago

@markfinn or @mjkapkan, how's this great work shaping up for getting released so all the leaf owners out there can stop charging after (intentionally or accidentally) starting charging?

mjkapkan commented 4 years ago

If @markfinn does not have a better alternative. I propose we move forward with my suggestion to save the last charge state within OVMS in order to stop charging in case climate control has been stopped.

mjkapkan commented 4 years ago

I have been testing this for a few months. Will clean up and push this to the main repo. Will keep this optional with a switch in the settings menu.

markfinn commented 4 years ago

Sorry, I promise I still exist!

The reason I stopped pushing on this change very hard all those months ago was that I experienced some weirdness after I would stop a charge. Nothing permanent and no codes were thrown, but The charger and status lights would act oddly for a charge or two after. I had planned to do more testing and see if there was a better bit to set or some way to make the car sell angry after a force stop. I never actually did that.

If you merge this, I would add something to the docs or help for the feature that it might make the next charge not start exactly normally.

dalathegreat commented 4 years ago

I've started to amass quite the customer base using this way to stop charging. I've been using it everyday since november 2019. But this is with the CAN-bridge, and not OVMS.

Def good to have a toggle for it, just in case!

mjkapkan commented 4 years ago

Sorry, I promise I still exist!

The reason I stopped pushing on this change very hard all those months ago was that I experienced some weirdness after I would stop a charge. Nothing permanent and no codes were thrown, but The charger and status lights would act oddly for a charge or two after. I had planned to do more testing and see if there was a better bit to set or some way to make the car sell angry after a force stop. I never actually did that.

If you merge this, I would add something to the docs or help for the feature that it might make the next charge not start exactly normally.

Hi, thanks for the feedback! What kind of charger are you getting these issues with? Also is it 3kW or 6kW? Also is your car 1st or 2nd gen? I usually charge at 6kW PodPoint and haven't experienced any issues using this method.

But anyway maybe this is related to that charge state issue as when you have a timer the charger does not start. But for that I have added the charging request status that is tracked by OVMS.

drc38 commented 4 years ago

Out of interest and as an alternative method has anyone tried setting the current limit to zero?

dalathegreat commented 4 years ago

Out of interest and as an alternative method has anyone tried setting the current limit to zero?

@drc38 Yes, but this can only be done with a proper MITM attack. This does not stop the charge, the car stays on and just balances the battery.

dalklein commented 4 years ago

@dalathegreat Good to know it can go to zero, at some point I want to add something which makes the car 'smart' and charges only if it sees that my solar is producing some excess, letting the house battery fill up first.

dalathegreat commented 3 years ago

To combat the PRUN check that triggers DTCs on @markfinn 's solution, we could try spamming 4x messages in a row with the request to stop. See this youtube video for more info on the subject: https://www.youtube.com/watch?v=oENNNfy5GSM

markfinn commented 3 years ago

I've been wondering about that after seeing you mention that being the cause for the errors. I think I naively assumed that the preempted messages would get ignored.

Have you gotten any sense of what kind of delay is needed, if any, between messages or could I blast out all four at once?

dalathegreat commented 3 years ago

I have a gut feeling it wont work, since most embedded devices run their applications at set interval periods to save CPU. But let's try it. The 0x1DB is sent at 10ms, so to squeeze in 4x extra with maximum chance of the actual application picking up the values, the timing needs to be spread out as much as possible. This is what I recommend: Original3 - 2ms - Fake0 - 2ms - Fake1 - 2ms -Fake2 - 2ms -Fake3 - 2ms - Original0