Skip to content

Commit cb52218

Browse files
authored
Merge pull request #117 from treepleks/PV_divert_ratio
divert_PV_ratio: adjustable requirement on available PV power before starting charge or incrementing current
2 parents 12828a0 + 35fdb08 commit cb52218

File tree

5 files changed

+28
-12
lines changed

5 files changed

+28
-12
lines changed

divert_sim/RapiSender.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <Arduino.h>
22
#include "RapiSender.h"
3-
#include "debug.h"
43
#include "openevse.h"
54
#include "input.h"
65

@@ -9,6 +8,7 @@
98
#ifdef ENABLE_DEBUG
109
#define DBG
1110
#endif
11+
#define DBUGF
1212

1313
static CommandItem commandQueueItems[RAPI_MAX_COMMANDS];
1414

divert_sim/divert_sim.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@
77
#endif
88

99
#include "Console.h"
10-
#include "emonesp.h"
1110
#include "RapiSender.h"
1211
#include "openevse.h"
1312
#include "divert.h"
14-
#include "emonesp.h"
1513
#include "event.h"
1614

1715
#include "parser.hpp"
@@ -25,6 +23,7 @@ long pilot = 32; // OpenEVSE Pilot Setting
2523
long state = OPENEVSE_STATE_SLEEPING; // OpenEVSE State
2624
String mqtt_solar = "";
2725
String mqtt_grid_ie = "";
26+
uint32_t flags;
2827

2928
int date_col = 0;
3029
int grid_ie_col = -1;
@@ -38,8 +37,9 @@ bool kw = false;
3837
extern double smoothed_available_current;
3938
double divert_attack_smoothing_factor = 0.4;
4039
double divert_decay_smoothing_factor = 0.05;
40+
double divert_PV_ratio = 0.5;
4141
uint32_t divert_min_charge_time = (10 * 60);
42-
double voltage = DEFAULT_VOLTAGE; // Voltage from OpenEVSE or MQTT
42+
double voltage = 240; // Voltage from OpenEVSE or MQTT
4343

4444
time_t parse_date(const char *dateStr)
4545
{

src/app_config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ uint32_t flags;
5656
String ohm;
5757

5858
// Divert settings
59+
double divert_PV_ratio;
5960
double divert_attack_smoothing_factor;
6061
double divert_decay_smoothing_factor;
6162
uint32_t divert_min_charge_time;
@@ -109,6 +110,7 @@ ConfigOpt *opts[] =
109110
new ConfigOptDefenition<String>(ohm, "", "ohm", "o"),
110111

111112
// Divert settings
113+
new ConfigOptDefenition<double>(divert_PV_ratio, 1.1, "divert_PV_ratio", "dpr"),
112114
new ConfigOptDefenition<double>(divert_attack_smoothing_factor, 0.4, "divert_attack_smoothing_factor", "da"),
113115
new ConfigOptDefenition<double>(divert_decay_smoothing_factor, 0.05, "divert_decay_smoothing_factor", "dd"),
114116
new ConfigOptDefenition<uint32_t>(divert_min_charge_time, (10 * 60), "divert_min_charge_time", "dt"),

src/app_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ extern String mqtt_announce_topic;
4646
extern String time_zone;
4747

4848
// Divert settings
49+
extern double divert_PV_ratio;
4950
extern double divert_attack_smoothing_factor;
5051
extern double divert_decay_smoothing_factor;
5152
extern uint32_t divert_min_charge_time;

src/divert.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@
2323
// Or modulate charge rate based on on excess power (if grid feed (positive import / negative export) is available) i.e. power that would otherwise be exported to the grid is diverted to EVSE.
2424
// Note: it's Assumed EVSE power is included in grid feed e.g. (charge rate = gen - use - EVSE).
2525

26-
// If EVSE is sleeping charging will not start until solar PV / excess power > min chanrge rate
27-
// Once charging begins it will not pause even if solaer PV / excess power drops less then minimm charge rate. This avoids wear on the relay and the car
28-
29-
#define GRID_IE_RESERVE_POWER 100.0
26+
// It's better to never import current from the grid but because of charging current quantification (min value of 6A and change in steps of 1A),
27+
// it may be better to import a fraction of the charge current and use the next charging level sooner, depending on electricity buying/selling prices.
28+
// The marginal fraction of current that is required to come from PV is the divert_PV_ratio. The requiring a pure PV charge is obtained by
29+
// setting divert_PV_ratio to 1.0. This is the best choice when the kWh selling price is the same as the kWh night buying price. If instead the night tarif
30+
// is the same as the day tarif, any available current is good to take and divert_PV_ratio optimal setting is close to 0.0. Beyond 1.0, the excess of
31+
// divert_PV_ratio indicates the amount of power (in kW) that OpenEVSE will try to preserve. A value of 1.1 will start charging only when the
32+
// PV power - 100 W (reserve) reaches the minimum charging power (reproducing the legacy behavior of OpenEVSE).
33+
34+
// If EVSE is sleeping, charging will start as soon as solar PV / excess power exceeds the divert_PV_ratio fraction of the minimum charging power.
35+
// Once charging begins it will not pause before a minimum amount of time has passed and this even if solar PV / excess power drops less then minimum charge rate.
36+
// This avoids wear on the relay and the car.
3037

3138
// Default to normal charging unless set. Divert mode always defaults back to 1 if unit is reset (divertmode not saved in EEPROM)
3239
byte divertmode = DIVERT_MODE_NORMAL; // default normal mode
@@ -162,7 +169,7 @@ void divert_update_state()
162169
if (Igrid_ie < 0)
163170
{
164171
// If excess power
165-
double reserve = GRID_IE_RESERVE_POWER / voltage;
172+
double reserve = (1000.0 * ((divert_PV_ratio > 1.0) ? (divert_PV_ratio - 1.0) : 0.0)) / voltage;
166173
DBUGVAR(reserve);
167174
available_current = (-Igrid_ie - reserve);
168175
}
@@ -184,11 +191,16 @@ void divert_update_state()
184191
}
185192
DBUGVAR(available_current);
186193

187-
double scale = available_current > smoothed_available_current ? divert_attack_smoothing_factor : divert_decay_smoothing_factor;
194+
double scale = (available_current > smoothed_available_current ? divert_attack_smoothing_factor : divert_decay_smoothing_factor);
188195
smoothed_available_current = (available_current * scale) + (smoothed_available_current * (1 - scale));
189196
DBUGVAR(smoothed_available_current);
190197

191198
charge_rate = (int)floor(available_current);
199+
// if the remaining current can be used with a sufficient ratio of PV current in it, use it
200+
if ((available_current - charge_rate) > min(1.0, divert_PV_ratio))
201+
{
202+
charge_rate += 1;
203+
}
192204

193205
if(OPENEVSE_STATE_SLEEPING != state) {
194206
// If we are not sleeping, make sure we are the minimum current
@@ -197,12 +209,13 @@ void divert_update_state()
197209

198210
DBUGVAR(charge_rate);
199211

200-
if(smoothed_available_current >= min_charge_current)
212+
// the smoothed current suffices to ensure a sufficient ratio of PV power
213+
if (smoothed_available_current >= (min_charge_current * min(1.0, divert_PV_ratio)))
201214
{
202215
// Cap the charge rate at the configured maximum
203216
charge_rate = min(charge_rate, static_cast<int>(max_charge_current));
204217

205-
// Change the charge rate is needed
218+
// Change the charge rate if needed
206219
if(current_charge_rate != charge_rate)
207220
{
208221
// Set charge rate via RAPI

0 commit comments

Comments
 (0)