-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPump.cpp
156 lines (134 loc) · 4.57 KB
/
Pump.cpp
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
#include "Pump.h"
#include "Arduino.h"
#include "PinHandler.h"
#include "MailHandler.h"
#include "DeepSleep.h"
void setupPump()
{
pinMode((uint8_t)EPin::eWaterSensorUpper, INPUT_PULLDOWN);
pinMode((uint8_t)EPin::eWaterSensorLower, INPUT_PULLDOWN);
// sensors are not directly coonected to 3,3V
// to make sure no power loss occures during deep sleep
pinMode((uint8_t)EPin::eSensorOutUpper, OUTPUT);
pinMode((uint8_t)EPin::eSensorOutLower, OUTPUT);
digitalWrite((uint8_t)EPin::eSensorOutUpper, HIGH);
digitalWrite((uint8_t)EPin::eSensorOutLower, HIGH);
pinMode((uint8_t)EPin::ePumpOut, OUTPUT);
delay(50);
}
// max time the pump can be stay off, if we are over this time
// we should turn on the pump because maybe the sensors are damaged
constexpr unsigned long getMaxInactionTimoutMS()
{
// 5 days
return 5 * 24 * 60 * 60 * 1000;
}
constexpr unsigned long getMaxPumpingTimoutMS()
{
// 10 minutes
return 10 * 60 * 1000;
}
bool readSensor(EPin sensor)
{
// invalid
if(sensor != EPin::eWaterSensorLower && sensor != EPin::eWaterSensorUpper)
return false;
// I don't know how stable the sensors are so the signal is only active if all measured values are high
bool bSensorActive = true;
for(int i = 0 ; i <= 5; ++i)
{
if(i!=0)
delay(10);
bSensorActive &= digitalRead((uint8_t)sensor);
}
//char log[20];
//sprintf(log, "Sensor %i is %s",(uint8_t)sensor, bSensorActive?"high":"low");
//Serial.println(log);
return bSensorActive;
}
bool TankFull(unsigned long ulLastPumpAction)
{
// upper and lower sensors are normaly closed for safety reasons
bool bTankFull = !readSensor(EPin::eWaterSensorUpper);
bool bTankEmpty = readSensor(EPin::eWaterSensorLower);
if(bTankFull)
return true;
// if upper sensor says no water, but lower sensor says yes turn the pump on after max inactive time to be sure,
// maybe upper sensor was damaged?
// if both sensors are damaged than all hope is lost :)
if(!bTankEmpty && ulLastPumpAction != 0 &&
millisReal() - ulLastPumpAction > getMaxInactionTimoutMS())
{
Serial.println("Max inactive timeout reached - enable pump");
sendMail("WaterPump - Timeout", "Inacitve Timeout reached", "Pump will be activated<b>check Sensors!!");
return true;
}
return false;
}
bool TankEmpty()
{
// lower sensor is normally closed for safety
// is sensor is active -> water level is below sensor -> empty
return readSensor(EPin::eWaterSensorLower);
}
void togglePump(bool bEnable)
{
digitalWrite((uint8_t)EPin::ePumpOut, bEnable);
}
void pumpControlLoop(unsigned long& ulLastPumpAction)
{
if(!TankFull(ulLastPumpAction))
return;
Serial.println("Tank full -> start emptying");
sendMail("WaterPump - Tank full", "Tank full", "Pump will be activated");
// if this is true there has to be a sensor failure
static bool bDoNotTrustSensor = false;
{
bool bDoNotTrustSensorOld = bDoNotTrustSensor;
bDoNotTrustSensor = TankFull() && TankEmpty();
// to reduce spam
if(bDoNotTrustSensor && !bDoNotTrustSensorOld)
sendMail("WaterPump - Sensor failure", "Sensor failure", "invalid sensor states, check hardware");
}
unsigned long startTime = millis();
togglePump(true);
bool bSafetySwitchOccured = false;
do
{
// check if pump is active for too long - sensor failure?
if(millis() - startTime > getMaxPumpingTimoutMS())
{
bSafetySwitchOccured = true;
break;
}
delay(500);
sendBufferedMails();
// if we do not trust the sensor we wait for the timeout inside to keep it from switching off instantly
}while(!TankEmpty() || bDoNotTrustSensor);
togglePump(false);
ulLastPumpAction = millisReal();
if(bSafetySwitchOccured)
{
Serial.println("Switching pump off after lower sensor did not get active after 30m!!");
if(bDoNotTrustSensor)
{
sendMail("WaterPump - Pump Off with Invalid Sensor", "Invalid sensor state", "Pump was operated without sensor because of an invalid sensor state<br>"
"Check hardware");
}
else if(TankFull())
{
sendMail("WaterPump - Hardware FAILURE", "Emergency switch off", "Pump was switched off automatically,<br>"
"tank full sensor is still hight!! Sensor or pump failure!");
}
else
{
sendMail("WaterPump - Emergency Switch OFF", "Emergency switch off", "Pump was switched off automatically,<br>"
"because the tank empty sensor did not get active after 30 minutes!! Check tank & hardware");
}
}
else
{
Serial.println("Tank empty -> switch off pump");
sendMail("WaterPump - Tank empty", "Tank empty", "Pump will be switched off.");
}
}