diff --git a/README.md b/README.md
index 2b6276b..9460d88 100644
--- a/README.md
+++ b/README.md
@@ -125,6 +125,7 @@ void loop() {
## Версии
- v2.1 - исправлена getResultTimer
+- v2.2 - улучшен и упрощён алгоритм
## Баги и обратная связь
diff --git a/examples/relay_simulation/relay_simulation.ino b/examples/relay_simulation/relay_simulation.ino
index ac39b83..1aa7ef9 100644
--- a/examples/relay_simulation/relay_simulation.ino
+++ b/examples/relay_simulation/relay_simulation.ino
@@ -10,7 +10,7 @@ void setup() {
Serial.begin(9600);
regulator.setpoint = 40;
regulator.hysteresis = 5;
- regulator.k = 0.5;
+ regulator.k = 0.6;
}
boolean state = 0;
@@ -23,9 +23,9 @@ void loop() {
Serial.print(value);
Serial.print(' ');
- Serial.print(regulator.setpoint - 5 / 2);
+ Serial.print(regulator.setpoint - regulator.hysteresis / 2);
Serial.print(' ');
- Serial.print(regulator.setpoint + 5 / 2);
+ Serial.print(regulator.setpoint + regulator.hysteresis / 2);
Serial.print(' ');
Serial.println(regulator.setpoint);
delay(100);
@@ -34,7 +34,6 @@ void loop() {
void process() {
static float coef = 0;
coef += state ? 0.3 : -0.6;
- if (coef > 2.0) coef = 2.0;
- if (coef < -3.0) coef = -3;
+ coef = constrain(coef, -3, 2);
value += coef;
}
diff --git a/library.properties b/library.properties
index ea32345..97ef06b 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=GyverRelay
-version=2.1
+version=2.2
author=AlexGyver
maintainer=AlexGyver
sentence=Library for relay regulation algorithm
diff --git a/src/GyverRelay.cpp b/src/GyverRelay.cpp
index 0aedb9b..a98c41e 100644
--- a/src/GyverRelay.cpp
+++ b/src/GyverRelay.cpp
@@ -1,47 +1,37 @@
#include "GyverRelay.h"
-GyverRelay::GyverRelay(boolean direction) {
- _direction = direction;
- output = !_direction; // выключить реле сразу
+GyverRelay::GyverRelay(GR_dir dir = REVERSE) {
+ _dir = dir;
+ output = !_dir; // выключить реле сразу
}
-void GyverRelay::setDirection(boolean dir) {
- _direction = dir;
-}
-
-int signum(float val) {
- return ((val > 0) ? 1 : ((val < 0) ? -1 : 0));
+void GyverRelay::setDirection(GR_dir dir) {
+ _dir = dir;
}
// вернёт выход, принимает время итерации в секундах
-boolean GyverRelay::compute(float dt) {
+bool GyverRelay::compute(float dt) {
float signal;
- if (dt > 0) {
- float rate = (input - prevInput) / dt; // производная от величины (величина/секунду)
+ if (dt != 0 && k != 0) {
+ signal = input + (input - prevInput) * k / dt;
prevInput = input;
- signal = input + rate * k;
- } else {
- signal = input;
- }
-
- // жуткая функция реле из лекций по ТАУ
- int8_t F = (signum(signal - setpoint - hysteresis / 2) + signum(signal - setpoint + hysteresis / 2)) / 2;
-
- if (F == 1) output = !_direction;
- else if (F == -1) output = _direction;
+ } else signal = input;
+
+ if (signal < (setpoint - hysteresis / 2)) output = _dir;
+ else if (signal > (setpoint + hysteresis / 2)) output = !_dir;
return output;
}
-boolean GyverRelay::getResult() {
- GyverRelay::compute((millis() - prevTime) / 1000.0f);
+bool GyverRelay::getResult() {
+ compute((millis() - prevTime) / 1000.0f);
prevTime = millis();
return output;
}
-boolean GyverRelay::getResultTimer() {
+bool GyverRelay::getResultTimer() {
if (millis() - prevTime > dT) {
prevTime = millis();
- GyverRelay::compute((float)dT / 1000);
+ compute(dT / 1000.0);
}
return output;
}
\ No newline at end of file
diff --git a/src/GyverRelay.h b/src/GyverRelay.h
index 1778ce3..a9e6939 100644
--- a/src/GyverRelay.h
+++ b/src/GyverRelay.h
@@ -13,32 +13,35 @@
Версии:
v2.1 - исправлена getResultTimer
+ v2.2 - улучшен и упрощён алгоритм
*/
-#ifndef GyverRelay_h
-#define GyverRelay_h
+#ifndef _GyverRelay_h
+#define _GyverRelay_h
#include
-#define NORMAL 0
-#define REVERSE 1
+enum GR_dir {
+ NORMAL,
+ REVERSE,
+};
class GyverRelay {
public:
// принимает установку, ширину гистерезиса, направление (NORMAL, REVERSE)
// NORMAL - включаем нагрузку при переходе через значение снизу (пример: охлаждение)
// REVERSE - включаем нагрузку при переходе через значение сверху (пример: нагрев)
- GyverRelay(boolean direction = REVERSE);
+ GyverRelay(GR_dir dir);
// расчёт возвращает состояние для управляющего устройства (реле, транзистор) (1 вкл, 0 выкл)
- boolean compute(float dt = 0); // моментальный расчёт. Принимает dt в секундах для режима с ОС
- boolean getResult(); // моментальный расчёт. Встроенный таймер для режима с ОС
- boolean getResultTimer(); // расчёт по встроенному таймеру
+ bool compute(float dt = 0); // моментальный расчёт. Принимает dt в секундах для режима с ОС
+ bool getResult(); // моментальный расчёт. Встроенный таймер для режима с ОС
+ bool getResultTimer(); // расчёт по встроенному таймеру
- void setDirection(boolean dir); // направление регулирования (NORMAL, REVERSE)
+ void setDirection(GR_dir dir); // направление регулирования (NORMAL, REVERSE)
float input = 0; // сигнал с датчика (например температура, которую мы регулируем)
float setpoint = 0; // заданная величина, которую должен поддерживать регулятор (температура)
- boolean output = 0; // выход регулятора (0 или 1)
+ bool output = 0; // выход регулятора (0 или 1)
float hysteresis = 0; // ширина окна гистерезиса
float k = 0; // коэффициент усиления по скорости (по умолч. 0)
@@ -47,6 +50,6 @@ class GyverRelay {
private:
uint32_t prevTime = 0;
float prevInput = 0.0;
- boolean _direction = false;
+ GR_dir _dir = REVERSE;
};
#endif
\ No newline at end of file