3-phase PV router
Loading...
Searching...
No Matches
utils_relay.h
Go to the documentation of this file.
1
11
12#ifndef UTILS_RELAY_H
13#define UTILS_RELAY_H
14
15#include "types.h"
16#include "type_traits.hpp"
17#include "debug.h"
18
19#include "config_system.h"
20#include "movingAvg.h"
21#include "ewma_avg.hpp"
22#include "utils_pins.h"
23
42{
43public:
44 constexpr relayOutput() = delete;
45
51 explicit constexpr relayOutput(const uint8_t _relay_pin)
52 : relay_pin{ _relay_pin }
53 {
54 }
55
63 constexpr relayOutput(uint8_t _relay_pin, int16_t _surplusThreshold, int16_t _importThreshold)
64 : relay_pin{ _relay_pin }, surplusThreshold{ -abs(_surplusThreshold) }, importThreshold{ abs(_importThreshold) }
65 {
66 }
67
77 constexpr relayOutput(uint8_t _relay_pin, int16_t _surplusThreshold, int16_t _importThreshold, uint16_t _minON, uint16_t _minOFF)
78 : relay_pin{ _relay_pin }, surplusThreshold{ -abs(_surplusThreshold) }, importThreshold{ abs(_importThreshold) }, minON{ _minON * 60 }, minOFF{ _minOFF * 60 }
79 {
80 }
81
87 constexpr auto get_pin() const
88 {
89 return relay_pin;
90 }
91
97 constexpr auto get_surplusThreshold() const
98 {
99 return -surplusThreshold;
100 }
101
107 constexpr auto get_importThreshold() const
108 {
109 return importThreshold;
110 }
111
117 constexpr auto get_minON() const
118 {
119 return minON;
120 }
121
127 constexpr auto get_minOFF() const
128 {
129 return minOFF;
130 }
131
137 auto isRelayON() const
138 {
139 return relayIsON;
140 }
141
147 void inc_duration() const
148 {
149 if (duration < UINT16_MAX)
150 {
151 ++duration;
152 }
153 }
154
160 bool proceed_relay(const int32_t currentAvgPower) const
161 {
162 // To avoid changing sign, surplus is a negative value
163 if (currentAvgPower < surplusThreshold)
164 {
165 return try_turnON();
166 }
167 if (currentAvgPower > importThreshold)
168 {
169 return try_turnOFF();
170 }
171 return false;
172 }
173
178 void printRelayConfiguration(uint8_t idx) const
179 {
180 Serial.print(F("\tRelay configuration: #"));
181 Serial.println(idx + 1);
182
183 Serial.print(F("\t\tPin is "));
184 Serial.println(get_pin());
185
186 Serial.print(F("\t\tSurplus threshold: "));
187 Serial.println(get_surplusThreshold());
188
189 Serial.print(F("\t\tImport threshold: "));
190 Serial.println(get_importThreshold());
191
192 Serial.print(F("\t\tMinimum working time in minutes: "));
193 Serial.println(get_minON() / 60);
194
195 Serial.print(F("\t\tMinimum stop time in minutes: "));
196 Serial.println(get_minOFF() / 60);
197 }
198
199private:
205 bool try_turnON() const
206 {
207 if (relayIsON || duration < minOFF)
208 {
209 return false;
210 }
211
213
214 DBUGLN(F("Relay turned ON!"));
215
216 relayIsON = true;
217 duration = 0;
218
219 return true;
220 }
221
227 bool try_turnOFF() const
228 {
229 if (!relayIsON || duration < minON)
230 {
231 return false;
232 }
233
235
236 DBUGLN(F("Relay turned OFF!"));
237
238 relayIsON = false;
239 duration = 0;
240
241 return true;
242 }
243
244private:
245 const uint8_t relay_pin{ unused_pin };
246 const int16_t surplusThreshold{ -1000 };
247 const int16_t importThreshold{ 200 };
248 const uint16_t minON{ 5 * 60 };
249 const uint16_t minOFF{ 5 * 60 };
250
251 mutable uint16_t duration{ 0 };
252 mutable bool relayIsON{ false };
253};
254
277template< uint8_t N, uint8_t D = 10 >
279{
280public:
285 explicit constexpr RelayEngine(const relayOutput (&ref)[N])
286 : relay(ref)
287 {
288 }
289
297 : relay(ref)
298 {
299 }
300
306 constexpr auto get_size() const
307 {
308 return N;
309 }
310
317 constexpr const auto& get_relay(uint8_t idx) const
318 {
319 return relay[idx];
320 }
321
327 inline static auto get_average()
328 {
329 return ewma_average.getAverageS();
330 }
331
337 inline static void update_average(int16_t currentPower)
338 {
339 ewma_average.addValue(currentPower);
340 }
341
348#if defined(__DOXYGEN__)
349 void inc_duration() const;
350#else
351 void inc_duration() const __attribute__((optimize("-O3")));
352#endif
353
361 void proceed_relays() const
362 {
363 if (settle_change != 0)
364 {
365 // A relay has been toggle less than a minute ago, wait until changes take effect
366 return;
367 }
368
369 if (ewma_average.getAverageS() > 0)
370 {
371 // Currently importing, try to turn OFF some relays
372 uint8_t idx{ N };
373 do
374 {
375 if (relay[--idx].proceed_relay(ewma_average.getAverageS()))
376 {
377 settle_change = 60;
378 return;
379 }
380 } while (idx);
381 }
382 else
383 {
384 // Remaining surplus, try to turn ON more relays
385 uint8_t idx{ 0 };
386 do
387 {
388 if (relay[idx].proceed_relay(ewma_average.getAverageS()))
389 {
390 settle_change = 60;
391 return;
392 }
393 } while (++idx < N);
394 }
395 }
396
404 {
405 Serial.println(F("\t*** Relay(s) configuration ***"));
406 Serial.print(F("\t\tSliding average: "));
407 Serial.println(D);
408
409 for (uint8_t i = 0; i < N; ++i)
410 {
411 relay[i].printRelayConfiguration(i);
412 }
413 }
414
415private:
417
418 mutable uint8_t settle_change{ 60 };
419
421};
422
423template< uint8_t N, uint8_t D > void RelayEngine< N, D >::inc_duration() const
424{
425 uint8_t idx{ N };
426 do
427 {
428 relay[--idx].inc_duration();
429 } while (idx);
430
431 if (settle_change)
432 {
434 }
435}
436
437#endif /* UTILS_RELAY_H */
Implements an Exponentially Weighted Moving Average (EWMA).
Definition ewma_avg.hpp:80
static EWMA_average< D *60/DATALOG_PERIOD_IN_SECONDS > ewma_average
constexpr auto get_size() const
Get the number of relays.
void proceed_relays() const
Proceed all relays in increasing order (surplus) or decreasing order (import).
static auto get_average()
Get the current average.
static void update_average(int16_t currentPower)
Update the sliding average.
const relayOutput relay[N]
void inc_duration() const
Increment the duration's state of each relay.
uint8_t settle_change
constexpr RelayEngine(integral_constant< uint8_t, D > ic, const relayOutput(&ref)[N])
Construct a list of relays with a custom sliding average.
constexpr const auto & get_relay(uint8_t idx) const
Get the relay object.
constexpr RelayEngine(const relayOutput(&ref)[N])
Construct a list of relays.
void printConfiguration() const
Print the configuration of each relay.
Represents a single relay configuration and its behavior.
Definition utils_relay.h:42
constexpr relayOutput()=delete
constexpr auto get_minOFF() const
Get the minimum OFF-time in seconds.
const int16_t importThreshold
const int16_t surplusThreshold
const uint8_t relay_pin
constexpr auto get_surplusThreshold() const
Get the surplus threshold which will turns ON the relay.
Definition utils_relay.h:97
bool proceed_relay(const int32_t currentAvgPower) const
Proceed with the relay.
constexpr relayOutput(uint8_t _relay_pin, int16_t _surplusThreshold, int16_t _importThreshold, uint16_t _minON, uint16_t _minOFF)
Construct a new relay Config object with custom parameters.
Definition utils_relay.h:77
bool try_turnOFF() const
Turn OFF the relay if the 'time' condition is met.
constexpr relayOutput(const uint8_t _relay_pin)
Construct a new relay Config object with default parameters.
Definition utils_relay.h:51
uint16_t duration
const uint16_t minON
constexpr auto get_importThreshold() const
Get the import threshold which will turns OFF the relay.
void printRelayConfiguration(uint8_t idx) const
Print the configuration of the current relay-diversion.
constexpr relayOutput(uint8_t _relay_pin, int16_t _surplusThreshold, int16_t _importThreshold)
Construct a new relay Config object with default/custom parameters.
Definition utils_relay.h:63
auto isRelayON() const
Return the state.
constexpr auto get_pin() const
Get the control pin of the relay.
Definition utils_relay.h:87
const uint16_t minOFF
void inc_duration() const
Increment the duration of the current state.
bool try_turnON() const
Turn ON the relay if the 'time' condition is met.
constexpr auto get_minON() const
Get the minimum ON-time in seconds.
Basic configuration values to be set by the end-user.
constexpr uint8_t DATALOG_PERIOD_IN_SECONDS
Some macro for the Serial Output and Debugging.
#define DBUGLN(...)
Definition debug.h:97
uint8_t i
This file implements an Exponentially Weighted Moving Average template class.
Code for sliding-window average.
Some useful but missing stl functions templates.
Some basics classes/types.
Some utility functions for pins manipulation.
constexpr void setPinON(uint8_t pin)
Set the Pin state to ON for the specified pin.
Definition utils_pins.h:128
constexpr void setPinOFF(uint8_t pin)
Set the Pin state to OFF for the specified pin.
Definition utils_pins.h:160
constexpr uint8_t unused_pin
Definition utils_pins.h:17