-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalve_actuator.h
164 lines (132 loc) · 5.5 KB
/
valve_actuator.h
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
#include "esphome.h"
typedef unsigned long MilliSec;
class ActuationTime : public Component, public Sensor {
public:
static ActuationTime* instance; // singleton instance
float actuationTime = 0;
void setup() override {
}
void loop() override {
}
void setActuationTime(float duration) {
actuationTime = duration;
publish_state(actuationTime);
}
};
class PeakCurrent : public Component, public Sensor {
public:
static PeakCurrent* instance; // singleton instance
float peakCurrent = 0;
void setup() override {
}
void loop() override {
}
void setPeakCurrent(float amps) {
peakCurrent = amps;
publish_state(peakCurrent);
}
void setCurrent(float amps) {
if (amps > peakCurrent) {
setPeakCurrent(amps);
}
}
};
class ValvePosition : public PollingComponent, public TextSensor {
public:
static ValvePosition* instance; // singleton instance
ValvePosition() : PollingComponent(60000) {} // call update() every 60s
enum ValveStates {
valveUnknown, // position of valve is unknown
valveClosed, // water is NOT being directed to the solar panels
valveOpening, // valve is moving from closed towards open
valveOpened, // water IS being directed to the solar panels
valveClosing, // valve is moving from open towards closed
};
bool valvePowerRelayOn = false; // relay enables power to valve actuator
bool valveDirectionRelayOn = false; // relay controls valve turning direction
ValveStates valveState = valveUnknown; // current valve position state
MilliSec valveStateTime = 0; // time of last valveState update
void setup() override {
}
void update() override {
}
//
// setValveState
//
void setValveState(ValveStates newState) {
if (newState != valveState) {
// state changed
valveStateTime = millis(); // record state change time
valveState = newState; // update state
publish_state(valveStateText(newState));
}
}
const char* const valveStateText(ValveStates state) {
switch (state) {
case valveClosed: return "closed";
case valveOpening: return "opening";
case valveOpened: return "opened";
case valveClosing: return "closing";
default: return "unknown";
}
}
//
// setters
//
void setValvePowerRelayOn(bool relayOn) {
if (relayOn != valvePowerRelayOn) {
// power relay changed, update state
valvePowerRelayOn = relayOn;
if (valvePowerRelayOn) {
// relay just turned on, reset actuation time and peak measurements
PeakCurrent::instance->setPeakCurrent(0);
ActuationTime::instance->setActuationTime(0);
// update valve state based on turning direction
// actuator power is on, set one of the moving states based on direction
setValveState(valveDirectionRelayOn ? valveOpening : valveClosing);
}
}
}
void setValveDirectionRelayOn(bool relayOn) {
if (relayOn != valveDirectionRelayOn) {
// direction relay changed, update state
valveDirectionRelayOn = relayOn;
if (valvePowerRelayOn) {
// actuator changed direction while power was on, reset actuation time
ActuationTime::instance->setActuationTime(0);
// actuator changed direction while power was on, update direction
setValveState(valveDirectionRelayOn ? valveOpening : valveClosing);
}
}
}
//
// setCurrent - current tells us whether valve position is moving or not
//
void setCurrent(float amps) {
MilliSec msInState = millis() - valveStateTime;
float secInState = msInState / 1000.0;
if (amps > 0) {
// update peak current tracking
PeakCurrent::instance->setCurrent(amps);
// we have current, actuator is moving, update state
ESP_LOGD("custom","----- actuator current %0.3f, valve is %s, elapsed: %0.1fs", amps,
valveDirectionRelayOn ? "OPENING" : "CLOSING", secInState);
ActuationTime::instance->setActuationTime(secInState);
setValveState(valveDirectionRelayOn ? valveOpening : valveClosing);
} else {
// no actuator current, actuator stopped by its limit switch (or power relay off)
if (valveState == valveOpening) {
ESP_LOGD("custom","----- actuator current 0 while OPENING, valve OPENED, elapsed: %0.1fs", secInState);
ActuationTime::instance->setActuationTime(secInState);
setValveState( valveOpened );
} else if (instance->valveState == valveClosing) {
ESP_LOGD("custom","----- actuator current 0 while CLOSING, valve CLOSED, elapsed: %0.1fs", secInState);
ActuationTime::instance->setActuationTime(secInState);
setValveState( valveClosed );
}
}
}
};
ActuationTime* ActuationTime::instance = 0;
PeakCurrent* PeakCurrent::instance = 0;
ValvePosition* ValvePosition::instance = 0;