forked from dingo35/SmartEVSE-3.5
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathevse_ctx.h
More file actions
485 lines (434 loc) · 16 KB
/
evse_ctx.h
File metadata and controls
485 lines (434 loc) · 16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
/*
* evse_ctx.h - Shared EVSE context struct, HAL typedefs, and constants
*
* This header is the single source of truth for the state machine module's
* types and constants. It is included by both the firmware build and the
* native test suite.
*
* Each constant block is wrapped with #ifndef guards so that firmware
* headers (main.h, main_c.h) can coexist without redefinition errors.
*/
#ifndef EVSE_CTX_H
#define EVSE_CTX_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <limits.h>
#ifndef NR_EVSES
#define NR_EVSES 8
#endif
// ---- States (from main_c.h) ----
#ifndef STATE_A
#define STATE_A 0
#define STATE_B 1
#define STATE_C 2
#define STATE_D 3
#define STATE_COMM_B 4
#define STATE_COMM_B_OK 5
#define STATE_COMM_C 6
#define STATE_COMM_C_OK 7
#define STATE_ACTSTART 8
#define STATE_B1 9
#define STATE_C1 10
#define STATE_MODEM_REQUEST 11
#define STATE_MODEM_WAIT 12
#define STATE_MODEM_DONE 13
#define STATE_MODEM_DENIED 14
#define NOSTATE 255
#endif
// ---- Modes (from main.h) ----
#ifndef MODE_NORMAL
#define MODE_NORMAL 0
#define MODE_SMART 1
#define MODE_SOLAR 2
#endif
// ---- Error flags (from main_c.h) ----
#ifndef NO_ERROR
#define NO_ERROR 0
#define LESS_6A 1
#define CT_NOCOMM 2
#define TEMP_HIGH 4
#define EV_NOCOMM 8
#define RCM_TRIPPED 16
#define RCM_TEST 32
#define Test_IO 64
#define BL_FLASH 128
#define NO_SUN 256
#endif
// ---- Priority scheduling constants ----
#ifndef PRIO_MODBUS_ADDR
#define PRIO_MODBUS_ADDR 0
#define PRIO_FIRST_CONNECTED 1
#define PRIO_LAST_CONNECTED 2
#endif
#ifndef SCHED_INACTIVE
#define SCHED_INACTIVE 0
#define SCHED_ACTIVE 1
#define SCHED_PAUSED 2
#endif
#define IDLE_CURRENT_THRESHOLD 10 /* 1.0A in deciamps */
// ---- PWM constants ----
#ifndef PWM_5
#define PWM_5 50
#define PWM_95 950
#define PWM_96 960
#define PWM_100 1000
#endif
// ---- Pilot voltage levels (as returned by pilot reading) ----
#ifndef PILOT_12V
#define PILOT_12V 12
#define PILOT_9V 9
#define PILOT_6V 6
#define PILOT_3V 3
#define PILOT_DIODE 1
#define PILOT_SHORT 255
#define PILOT_NOK 0
#endif
// ---- Phase switching states (from main.h Switch_Phase_t) ----
// In C++ firmware builds, these are enum values in Switch_Phase_t (main.h).
// Only define as macros for pure C builds (module, tests).
#ifndef __cplusplus
#ifndef NO_SWITCH
#define NO_SWITCH 0
#define GOING_TO_SWITCH_1P 1
#define GOING_TO_SWITCH_3P 2
#endif
#endif
// ---- Access status ----
// In firmware this is an enum in main.h; we only define it if not already present.
#ifndef EVSE_CTX_ACCESS_DEFINED
#ifndef __cplusplus
typedef enum { OFF = 0, ON = 1, PAUSE = 2 } AccessStatus_t;
#else
// In C++ firmware builds, AccessStatus_t is already defined as an enum in main.h
#endif
#define EVSE_CTX_ACCESS_DEFINED
#endif
// ---- EnableC2 values (from main.h) ----
// Firmware: enum EnableC2_t { NOT_PRESENT, ALWAYS_OFF, SOLAR_OFF, ALWAYS_ON, AUTO };
#ifndef EVSE_CTX_ENABLEC2_DEFINED
#ifndef __cplusplus
typedef enum {
NOT_PRESENT = 0,
ALWAYS_OFF = 1,
SOLAR_OFF = 2,
ALWAYS_ON = 3,
AUTO = 4
} EnableC2_t;
#endif
#define EVSE_CTX_ENABLEC2_DEFINED
#endif
// ---- Default config values (from main.h) ----
#ifndef MAX_MAINS
#define MAX_MAINS 25
#endif
#ifndef MAX_CURRENT
#define MAX_CURRENT 13
#endif
#ifndef MIN_CURRENT
#define MIN_CURRENT 6
#endif
#ifndef MAX_CIRCUIT
#define MAX_CIRCUIT 16
#endif
#ifndef MAX_SUMMAINS
#define MAX_SUMMAINS 0
#endif
#ifndef MAX_SUMMAINSTIME
#define MAX_SUMMAINSTIME 0
#endif
#ifndef START_CURRENT
#define START_CURRENT 4
#endif
#ifndef STOP_TIME
#define STOP_TIME 10
#endif
#ifndef IMPORT_CURRENT
#define IMPORT_CURRENT 0
#endif
#ifndef MAX_TEMPERATURE
#define MAX_TEMPERATURE 65
#endif
#ifndef CHARGEDELAY
#define CHARGEDELAY 60
#endif
#ifndef COMM_TIMEOUT
#define COMM_TIMEOUT 11
#endif
#ifndef COMM_EVTIMEOUT
#define COMM_EVTIMEOUT 64
#endif
#ifndef SOLARSTARTTIME
#define SOLARSTARTTIME 40
#endif
#ifndef EMA_ALPHA_DEFAULT
#define EMA_ALPHA_DEFAULT 100 /* 100 = no smoothing (opt-in via config) */
#endif
#ifndef SMART_DEADBAND_DEFAULT
#define SMART_DEADBAND_DEFAULT 10 /* 1.0A in deciamps */
#endif
#ifndef API_MAINS_STALENESS_DEFAULT
#define API_MAINS_STALENESS_DEFAULT 120 /* Default staleness timeout in seconds */
#endif
#ifndef EM_API_METER
#define EM_API_METER 9 /* MainsMeterType value for API/MQTT feed (matches EM_API in meter.h) */
#endif
#ifndef RAMP_RATE_DIVISOR_DEFAULT
#define RAMP_RATE_DIVISOR_DEFAULT 4 /* Symmetric /4 for both up and down */
#endif
#ifndef SOLAR_FINE_DEADBAND_DEFAULT
#define SOLAR_FINE_DEADBAND_DEFAULT 5 /* 0.5A in deciamps (was effectively 3) */
#endif
#ifndef NOCURRENT_THRESHOLD_DEFAULT
#define NOCURRENT_THRESHOLD_DEFAULT 10 /* 10 ticks (~100ms) before LESS_6A (was 3) */
#endif
#ifndef SOLAR_CHARGE_DELAY_DEFAULT
#define SOLAR_CHARGE_DELAY_DEFAULT 15 /* 15s charge delay after solar stop (was 60s) */
#endif
#ifndef SOLAR_MIN_RUN_TIME_DEFAULT
#define SOLAR_MIN_RUN_TIME_DEFAULT 60 /* 60s min charge time before NoCurrent can trigger LESS_6A */
#endif
#ifndef SETTLING_WINDOW_DEFAULT
#define SETTLING_WINDOW_DEFAULT 5 /* 5 seconds settling after current change */
#endif
#ifndef MAX_RAMP_RATE_DEFAULT
#define MAX_RAMP_RATE_DEFAULT 30 /* Max 3.0A change per regulation cycle (deciamps) */
#endif
#ifndef PHASE_SWITCH_HOLDDOWN_DEFAULT
#define PHASE_SWITCH_HOLDDOWN_DEFAULT 300 /* 5 min on 1P before allowing 3P upgrade */
#endif
#ifndef PHASE_SWITCH_SEVERE_DEFAULT
#define PHASE_SWITCH_SEVERE_DEFAULT 30 /* 30s for severe shortage (fast switch) */
#endif
#ifndef MAX_DELTA_PER_CYCLE
#define MAX_DELTA_PER_CYCLE 30 /* Max 3.0A Balanced[] change per cycle (deciamps) */
#endif
#ifndef RFIDLOCKTIME
#define RFIDLOCKTIME 60
#endif
#ifndef GRID_RELAY_MAX_SUMMAINS
#define GRID_RELAY_MAX_SUMMAINS 18
#endif
// ---- Node info (from main.h) ----
#ifndef EVSE_CTX_NODE_DEFINED
typedef struct {
uint8_t Online;
uint8_t ConfigChanged;
uint8_t EVMeter;
uint8_t EVAddress;
uint8_t MinCurrent;
uint8_t Phases;
uint32_t Timer;
uint32_t IntTimer;
uint16_t SolarTimer;
uint8_t Mode;
} evse_node_t;
#define EVSE_CTX_NODE_DEFINED
#endif
// ---- HAL (Hardware Abstraction Layer) ----
typedef struct evse_hal {
void (*set_cp_duty)(uint32_t duty_cycle);
void (*contactor1)(bool on);
void (*contactor2)(bool on);
void (*set_pilot)(bool connected);
void (*actuator_lock)(void);
void (*actuator_unlock)(void);
void (*actuator_off)(void);
void (*on_state_change)(uint8_t old_state, uint8_t new_state);
} evse_hal_t;
// ---- Solar debug snapshot (Issue #19) ----
// Populated by evse_calc_balanced_current() each cycle.
// Network layer can publish via MQTT/WebSocket without impacting 10ms tick.
typedef struct {
int32_t IsetBalanced; /* Raw calculated value */
int32_t IsetBalanced_ema; /* EMA-smoothed value */
int32_t Idifference; /* Grid headroom */
int32_t IsumImport; /* Isum - ImportCurrent */
int16_t Isum; /* Grid import (positive) / export (negative) */
int16_t MainsMeterImeasured; /* Measured mains current */
uint16_t Balanced0; /* Distributed current for EVSE 0 */
uint16_t SolarStopTimer; /* Solar stop countdown */
uint16_t PhaseSwitchTimer; /* Phase switch countdown */
uint16_t PhaseSwitchHoldDown; /* Hold-down countdown */
uint8_t NoCurrent; /* Shortage counter */
uint8_t SettlingTimer; /* Settling window countdown */
uint8_t Nr_Of_Phases_Charging; /* Current phase count */
uint8_t ErrorFlags; /* Active error flags */
} evse_solar_debug_t;
// ---- Load balancing diagnostic snapshot (Plan 02, Issue #25) ----
// Populated by evse_calc_balanced_current() each cycle when LoadBl == 1.
// Network layer can publish via MQTT without impacting regulation timing.
typedef struct {
int32_t IsetBalanced; /* Final IsetBalanced after all adjustments */
int32_t Idifference; /* Raw grid headroom / deficit */
int32_t IdiffFiltered; /* EMA-filtered Idifference */
int32_t Baseload; /* Non-EVSE mains consumption */
int32_t Baseload_EV; /* Non-EVSE consumption on EV meter */
uint16_t Balanced[NR_EVSES]; /* Per-EVSE current allocations */
uint16_t BalancedMax[NR_EVSES]; /* Per-EVSE maximum limits */
uint8_t ActiveEVSE; /* Number of charging EVSEs */
uint8_t OscillationCount; /* Adaptive gain oscillation counter */
uint8_t NoCurrent; /* Shortage counter */
uint8_t ScheduleState[NR_EVSES]; /* Priority scheduling state per EVSE */
bool PriorityScheduled; /* True if priority scheduling ran this cycle */
bool Shortage; /* True if IsetBalanced < ActiveEVSE * MinCurrent */
bool DeltaClamped; /* True if distribution smoothing clamped any EVSE */
} evse_lb_diag_t;
// ---- The full EVSE state context ----
typedef struct {
// --- Core state ---
uint8_t State;
// --- Operating config ---
uint8_t Mode;
uint8_t LoadBl;
uint8_t Config; // 0=Socket, 1=Fixed Cable
// --- Authorization ---
AccessStatus_t AccessStatus;
uint8_t RFIDReader;
bool OcppMode;
float OcppCurrentLimit;
bool CPDutyOverride;
// --- Power limits ---
uint16_t MaxMains;
uint16_t MaxCurrent;
uint16_t MinCurrent;
uint16_t MaxCircuit;
uint16_t MaxCircuitMains; /* Max current (A) on subpanel circuit, 0 = disabled */
int32_t CircuitMeterImeasured; /* Max per-phase current from circuit meter (dA), 0 when disabled */
uint16_t MaxCapacity;
uint16_t MaxSumMains;
uint8_t MaxSumMainsTime;
uint16_t GridRelayMaxSumMains;
bool GridRelayOpen;
// --- Current distribution ---
uint16_t Balanced[NR_EVSES];
uint16_t BalancedMax[NR_EVSES];
uint8_t BalancedState[NR_EVSES];
uint16_t BalancedError[NR_EVSES];
uint16_t ChargeCurrent;
int32_t IsetBalanced;
uint16_t OverrideCurrent;
// --- Priority scheduling ---
uint8_t PrioStrategy; /* PRIO_MODBUS_ADDR / PRIO_FIRST_CONNECTED / PRIO_LAST_CONNECTED */
uint16_t RotationInterval; /* 0=disabled, 30-1440 minutes */
uint16_t IdleTimeout; /* 30-300 seconds, doubles as anti-flap window */
uint8_t Priority[NR_EVSES]; /* Sorted EVSE indices by priority */
uint32_t ConnectedTime[NR_EVSES]; /* Uptime seconds when EVSE entered STATE_C */
uint16_t IdleTimer[NR_EVSES]; /* Seconds since activation (counts up) */
uint16_t RotationTimer; /* Countdown in seconds for rotation */
uint8_t ScheduleState[NR_EVSES]; /* SCHED_INACTIVE / SCHED_ACTIVE / SCHED_PAUSED */
uint32_t Uptime; /* Monotonic seconds counter */
// --- Meter readings ---
int16_t Isum;
int16_t MainsMeterIrms[3];
int16_t MainsMeterImeasured;
int16_t EVMeterIrms[3];
int16_t EVMeterImeasured;
uint8_t MainsMeterType;
uint8_t EVMeterType;
uint8_t MainsMeterTimeout;
uint8_t EVMeterTimeout;
// --- API mains staleness detection ---
uint16_t api_mains_staleness_timer; /* Countdown in seconds, reset on API data arrival */
uint16_t api_mains_timeout; /* Configurable staleness timeout: 0=disabled, default 120s */
bool api_mains_stale; /* true when API mains data is stale */
// --- Metering diagnostic counters ---
uint32_t meter_timeout_count; /* Number of CT_NOCOMM timeout events */
uint32_t meter_recovery_count; /* Number of CT_NOCOMM recovery events */
uint32_t api_stale_count; /* Number of API staleness detection events */
// --- Error handling ---
uint8_t ErrorFlags;
uint8_t ChargeDelay;
uint8_t NoCurrent;
// --- Stop/start cycling prevention (Issue #17) ---
uint8_t NoCurrentThreshold; /* NoCurrent ticks before triggering LESS_6A */
uint8_t SolarChargeDelay; /* Shorter charge delay for solar mode (seconds) */
uint16_t SolarMinRunTime; /* Min charge time before NoCurrent can trigger LESS_6A (seconds) */
// --- Timers ---
uint16_t SolarStopTimer;
uint16_t MaxSumMainsTimer;
uint8_t StateTimer;
uint8_t AccessTimer;
uint8_t C1Timer;
// --- Phase switching ---
EnableC2_t EnableC2;
uint8_t Nr_Of_Phases_Charging;
uint8_t Switching_Phases_C2;
bool phasesLastUpdateFlag;
bool LimitedByMaxSumMains;
// --- Capacity tariff headroom (Plan 13) ---
int16_t CapacityHeadroom_da; /* Remaining headroom in deciamps; INT16_MAX = unconstrained */
// --- Phase switching timers (Issue #16) ---
uint16_t PhaseSwitchTimer; /* Countdown for 3P↔1P switching (separate from SolarStopTimer) */
uint16_t PhaseSwitchHoldDown; /* Min time on 1P before allowing 3P upgrade (countdown) */
uint16_t PhaseSwitchHoldDownTime; /* Configurable hold-down duration (seconds) */
uint16_t PhaseSwitchSevereTime; /* Timer for severe shortage (seconds) */
// --- Modem ---
bool ModemEnabled;
uint8_t ModemStage;
uint8_t ToModemWaitStateTimer;
uint8_t ToModemDoneStateTimer;
uint8_t LeaveModemDoneStateTimer;
uint8_t LeaveModemDeniedStateTimer;
int8_t DisconnectTimeCounter;
char RequiredEVCCID[32];
char EVCCID[32];
// --- Solar config ---
uint16_t StartCurrent;
uint16_t StopTime;
uint16_t ImportCurrent;
// --- Slow EV compatibility (Issue #18) ---
uint8_t SettlingWindow; /* Seconds to suppress regulation after current change */
uint8_t SettlingTimer; /* Countdown: when >0, regulation is suppressed */
uint16_t LastBalanced; /* Previous Balanced[0] to detect current changes */
uint8_t MaxRampRate; /* Max deciamps change per regulation cycle */
// --- Measurement smoothing & dead band (Plan 01, Issue #15) ---
int32_t IsetBalanced_ema; /* EMA-smoothed IsetBalanced (deciamps) */
uint8_t EmaAlpha; /* EMA weight 0-100: higher = more responsive */
uint8_t SmartDeadBand; /* Dead band for smart mode regulation (deciamps) */
uint8_t RampRateDivisor; /* Symmetric ramp divisor for smart/solar (>=1) */
uint8_t SolarFineDeadBand; /* Dead band for solar fine regulation (deciamps) */
// --- Distribution smoothing (Plan 02, Issue #24) ---
uint16_t BalancedPrev[NR_EVSES]; /* Previous cycle's Balanced[] (for delta clamping) */
// --- Adaptive gain / oscillation dampening (Plan 02, Issue #22) ---
int32_t IsetBalancedPrev; /* Previous cycle's IsetBalanced (for change tracking) */
int32_t IdiffPrev; /* Previous cycle's Idifference (for sign-flip detection) */
uint8_t OscillationCount; /* Consecutive sign flips detected (0 = stable) */
// --- Idifference EMA filter (Plan 02, Issue #23) ---
int32_t IdiffFiltered; /* EMA-smoothed Idifference: new = old*3/4 + raw/4 */
// --- Safety ---
int8_t TempEVSE;
uint16_t maxTemp;
uint8_t RCmon;
bool RCMFault;
// --- Misc ---
uint8_t DiodeCheck;
bool PilotDisconnected;
uint8_t PilotDisconnectTime;
uint8_t ActivationMode;
uint8_t ActivationTimer;
// --- Node tracking ---
evse_node_t Node[NR_EVSES];
// --- HAL ---
evse_hal_t hal;
// --- Solar debug snapshot (Issue #19) ---
evse_solar_debug_t solar_debug;
// --- Load balancing diagnostic snapshot (Issue #25) ---
evse_lb_diag_t lb_diag;
// --- Test instrumentation (for assertions) ---
#ifdef EVSE_TESTING
uint32_t last_pwm_duty;
bool contactor1_state;
bool contactor2_state;
bool pilot_connected;
int transition_count;
uint8_t transition_log[64];
#endif
} evse_ctx_t;
#ifdef __cplusplus
}
#endif
#endif // EVSE_CTX_H