Diverting solar PV to EV using OpeneEVSE, MQTT and NodeRED

If you have been following my posts in the OpenEV forum category, you will be aware that I have been working towards using OpenEVSE open-source electric car charging station to control EV charge rate based on excess solar PV production and improve OpenEVSE integration and control via MQTT.

Update: We (OpenEnergyMonitor) are proud to announce that we are now the UK / Europe reseller for OpenEVSE charging stations, see OpenEnergyMonitor Online Shop.

Update 2018

Solar PV diversion is now fully integrated into the OpenEVSE Wifi-gateway firmware

I have now implemented a working solar PV diversion prototype using NodeRED, the plan eventually is to build this functionality directly into the OpenEVSE ESP8266 Wifi module, my progress is in the feature/solarpv-divert branch of the openevse Wifi 2.0 repo. However, the nodeRED control is very functional and might well be the preferred choice for users who want functionality.

How it works

The NodeRED flow uses MQTT to interact with the emonPi (to get solar PV gen feed) and OpenEVSE (to get state and set charge rate). NodeRED is pre installed and configured on all emonPi’s, therefore it’s very easy to set up.

The actual charge rate is controlled by the car (my Nissan LEAF in this case), the OpenEVSE requests a particular charge rate by changing the pilot signal duty cycle, see my OpenEVSE blog post for more info. The OpenEVSE ESP8266 wifi module communicates with the OpenEVSE controller via serial. NodeRED communicates with the Esp8266 Wifi module (running firmware V2.0) via MQTT.

The NodeRED flow also supports communication with the OpenEVSE via HTTP, direct serial and Emoncms via GET API. However I recommend using MQTT.

More details and the NodeRED flow .json can be found in the repo:


I tested the implementation by simulating solar PV output, since March is not a good time for solar PV here in North Wales! See the ‘solar-pv-simulation’ folder in the repo for the data I used, and a nodeRED flow to post the .csv (exported from Emoncms) to MQTT.

Charging Modes

There are two charging modes defined:

1: Normal Fast Charge (default)

  • Charging at maximum rate irrespective of solar PV output

2: Eco

  • Charging level is moderated to match solar PV production
  • If use (on-site consumption feed) is provided it will be subtracted (excess solar diversion)
  • Charging will not start until available power > min charge rate (default 6A)
  • Once charging has started charge rate will modulate down to min charge rate (default 6A)
  • Charging will not pause once started since it was decided stopping / starting charging causes excess wear on the EVSE and the car.

Related forum topics:

1 Like

I’ve finally got my basic set-up together but using an ABL EVCC which has an RS485 port for control and monitoring.

Most of my time was wasted on figuring out that the A/B pins on the USB RS-485 adaptor seemed to be mislabeled. :slight_smile:

The EVCC can set a specific range of well known charge currents or vary the PWM from 8%-97% (of the 60A theoretical max). 6A = 10%, 30A = 50% etc.

Initially I turned the EVSE on (with the MQTT relay) once the solar current hit 4A and then simply fed the generated solar current into a function (PWM = amps / 0.6) and set the EVCC if the value was over 8%. I forgot to turn it off between 4A and 4.8A, but that was just one bug.

This worked quite well for about 45 minutes of sun on Tuesday when I was working from home and the car was there :slight_smile:

Next I tried to get smart and only advertised surplus solar once the base load in the house was accounted for but that hasn’t gone so well and I would appreciate some advice;

Problem here is that to calculate the surplus I am taking the consumption and subtracting the EVSE current. This is based on the emonpi solar set-up of Grid + Solar → Usage. However the house usage including the EVSE is not in sync with the EVSE current itself and so the numbers don’t align. I go from 6A to 18A to 0A etc. in a loop.

I tried a Smoothing node to average 3 samples, not much help.
I tried a RBE node and “block if value changes by more than” 4.8A, not much help.
I tried combining the two.

How do you deal with this, if at all?


“Fings wot I have lernt, junior edition”:

  1. Don’t tell the EVSE to not charge when there is zero solar, else your overnight timer does nothing. If there is less than your minimum threshold of solar output (where you normally turn the relay on), set to default current for Economy 7 charging as the power is on for some other reason.

  2. Don’t send a “Do not charge” (ABL PWM = 999) too much. It stops the Outlander from charging until you unplug, turn on the car to reset and plug back in.

So, someone drove into work today mostly on dinosaur juice.

Really? And if the pilot is turned OFF /ON, will the Outlander resume?

Well, I turned the whole EVSE off and on and the Outlander did not restart charging. Only way I got it going - and I was a little worried - was to unplug, start the car an turn off again. No errors on the dash however. I think the charging indicator was blinking when not charging, but I was rushing around trying to “fix” it to be sure.

What happens if there’s a power outage while the car is charging?

The car copes with that fine. I’ve turned the EVSE off and on numerous times. It’s the action of sending the “0999” which means, in their words “charging not allowed” - which I assume translates to some part of the J1772 standard somewhere.

That command is probably turning the pilot signal into a steady signal to make the car stop the charge. That’s too bad the Outlander doesn’t play along.

Well, I cycled to work and left the car at home today (and didn’t charge overnight). I did some additional hacking during my breaks at work, having realised that I don’t actually care about the amount the EVSE/car is consuming. All I care about is not importing anything if I don’t need it.

Above, I implemented my modified flow after the cooling gap at 12:05 ish (Outlanders appear to do this) and you may see that the divert follows the solar much more closely.

The core flow is this one:

Here, the work is done in the Adaptive Amps function which looks like this (excuse the mess):

// receive multiple MQTT topics, save them
if (msg.topic == "home/house/grid_amps") {
    context.set("grid_amps", Number(msg.payload).toFixed(2));
} else if (msg.topic == "home/house/solar_amps") {
    context.set("solar_amps", Number(msg.payload).toFixed(2));
} else {
    // error

var solar_amps = Number(context.get("solar_amps")) || 0;
var grid_amps = Number(context.get("grid_amps")) || 0;

var amps = solar_amps;

 * If we are exporting to the grid then on start-up allow all the 
 * solar production to be diverted if required. Then on subsequent
 * rounds we may be importing from the grid and we then reduce the
 * amount advertised by the amount imported.
 * The following nodes smooth out the changes without needing to
 * try to track the actual EVSE consumption - which lags as much
 * as any other reading, and as we are only interesting in not
 * importing, we may as well just track the grid instead.
 * Next iteration allow for a "soft start" by advertising a decaying
 * amount of spare capacity. This would require state between iterations.
if (grid_amps > 0) {
    amps -= grid_amps;

node.status({text: "Solar: " + solar_amps + " Grid: " + grid_amps + " = Divert " + amps});

msg.payload = amps;
return msg;

Now, I need to work on the edge cases and see what other changes I need to consider for days when the Solar PV production varies quickly etc. The current (no pun intended) “Set PWM” function will always set the minimum 8% while the relay is on, which the Outlander actually treats at 10% (6A) - and this will continue for at least 15 minutes before the latches turn the relay off.

This is why I tend to use the word “present” quite a lot - except when I mean I (as in Amps). :grinning:

1 Like