-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbathroom_node.c
288 lines (235 loc) · 9.41 KB
/
bathroom_node.c
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
/*
* bathroom_node.c
*
* Created on: 2017-06-06
* Author: Alessandro Martinelli
*/
#include "contiki.h"
#include "sys/etimer.h"
#include "stdio.h" /* For printf() */
#include "dev/button-sensor.h"
#include "dev/leds.h"
#include "dev/sht11/sht11-sensor.h"
#include "random.h"
#define LOWER_THRESHOLD 130
#define UPPER_THRESHOLD 150
#define RANDOM_MAX_VALUE 5
#define SHOWER_ACTIVE 0x80 /* 1 if alarm is active */
#define VENTILATION_ACTIVE 0x40 /* 1 if automatic opening is occurring */
#define LOWER_TH_EXCEDEED 0x20 /* 1 if the gate is unlocked */
#define UPPER_TH_EXCEDEED 0x10 /* 1 if the gate has communicated the end of the auto-opening procedure */
float sht11_TemperatureC(int temprawdata)
{
float _temperature; // Temperature derived from raw value
// Conversion coefficients from SHT11 datasheet
const float D1 = -39.6;
const float D2 = 0.01;
// Convert raw value to degrees Celsius
_temperature = (temprawdata * D2) + D1;
return (_temperature);
}
int obtain_humidity(){
int temprawdata;
int humidityrawdata;
float _linearHumidity; // Humidity with linear correction applied
float _correctedHumidity; // Temperature-corrected humidity
float _temperature; // Raw temperature value
SENSORS_ACTIVATE(sht11_sensor);
humidityrawdata = sht11_sensor.value(SHT11_SENSOR_HUMIDITY);
temprawdata = sht11_sensor.value(SHT11_SENSOR_TEMP);
// Get current temperature for humidity correction
_temperature = sht11_TemperatureC(temprawdata);
SENSORS_DEACTIVATE(sht11_sensor);
// Conversion coefficients from SHT15 datasheet
const float C1 = -4.0; // for 12 Bit
const float C2 = 0.0405; // for 12 Bit
const float C3 = -0.0000028; // for 12 Bit
const float T1 = 0.01; // for 14 Bit @ 5V
const float T2 = 0.00008; // for 14 Bit @ 5V
_linearHumidity = C1 + C2 * humidityrawdata + C3 * humidityrawdata * humidityrawdata;
// Correct humidity value for current temperature
_correctedHumidity = (_temperature - 25.0 ) * (T1 + T2 * humidityrawdata) + _linearHumidity;
float tc = _temperature;
float hc = _correctedHumidity;
printf("temp:%u.%u\nhumidity:%u.%u\n",(int)tc,((int)(tc*10))%10 , (int)hc,((int)(hc*10))%10);
return (_correctedHumidity);
/*
SENSORS_ACTIVATE(sht11_sensor);
int relative_humidity = (sht11_sensor.value(SHT11_SENSOR_HUMIDITY)/164);
SENSORS_DEACTIVATE(sht11_sensor);
return relative_humidity;
*/
/*
float adc_value = sht11_sensor.value(SHT11_SENSOR_HUMIDITY)*100;
float voltage = (adc_value/4095)*5;
float percentRH = (voltage-0.958)/0.0307;
printf("%ld.%03u\n", (long)f, (unsigned)((f-floor(f))*1000));
float raw = sht11_sensor.value(SHT11_SENSOR_HUMIDITY);
float hum = -4 + (0.0504*raw) + ((-2.8 * powf(10, -6))*(raw*raw));
printf("%ld\n", (long)hum);
*/
}
/*
* This event is sent, along with the temperature
* increase, when the humidity increases.
*/
static process_event_t increase_humidity;
/*
* This event is sent, along with the temperature
* decrease, when the humidity decreases.
*/
static process_event_t decrease_humidity;
/*---------------------------------------------------------------------------*/
PROCESS(bathroom_node_main_process, "Bathroom Node Main Process");
PROCESS(bathroom_node_shower_process, "Bathroom Node Shower Process");
PROCESS(bathroom_node_ventilation_process, "Bathroom Node Ventilation Process");
AUTOSTART_PROCESSES(&bathroom_node_main_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(bathroom_node_main_process, ev, data)
{
PROCESS_BEGIN();
// Store the humidity current value. When 0 it is not meaningful.
static int humidity_percentage;
/*
* Variable used as an array of flags. Those flags store the state
* of the system. They are used to perform operations in a consistent manner.
*/
static uint8_t bathroom_status;
increase_humidity = process_alloc_event();
decrease_humidity = process_alloc_event();
// initial value is not meaningful
humidity_percentage = 0;
// at the beginning shower and ventilation are turned off, and no threshold has been exceeded
bathroom_status = 0;
SENSORS_ACTIVATE(button_sensor);
while(1){
PROCESS_WAIT_EVENT();
if(ev == sensors_event && data == &button_sensor){
// Button has been clicked. The shower has been either opened or closed.
if((bathroom_status & SHOWER_ACTIVE) == 0){
// The shower is being turned on, thus humidity is being produced
bathroom_status |= SHOWER_ACTIVE;
process_start(&bathroom_node_shower_process, NULL);
} else {
// The shower is being turned off. Humidity is no more produced.
// Please note the ventilation system is turned off when the humidity
// has fallen below a certain threshold, not when the shower is turned off.
bathroom_status &= ~SHOWER_ACTIVE;
process_exit(&bathroom_node_shower_process);
if((bathroom_status & LOWER_TH_EXCEDEED) == 0){
// If the humidity is very low, we consider this value
// no more meaningful, and the next time the shower will be turned on,
// presumably not before some hours, we will sample this value again.
humidity_percentage = 0;
}
}
} else if(ev == increase_humidity){
// A humidity increase. This may happen only if the
// shower is active; thus, if a spurious event of
// this kind occurs when the shower is off, it must be ignored.
if((bathroom_status & SHOWER_ACTIVE) != 0){
// shower active --> the raise is "valid"
if(humidity_percentage == 0){
// Initial value is taken from actual sensor
humidity_percentage = obtain_humidity();
printf("[bathroom node]: humidity initial value is %d\n", humidity_percentage);
}
humidity_percentage += (uint8_t)(int)data;
printf("[bathroom node]: humidity has increased, now it is %d\n", humidity_percentage);
if(humidity_percentage > UPPER_THRESHOLD){
if((bathroom_status & UPPER_TH_EXCEDEED) == 0){
// The upper threshold has been exceeded just now.
// The ventilation system has to be started
bathroom_status |= UPPER_TH_EXCEDEED;
bathroom_status |= VENTILATION_ACTIVE;
process_start(&bathroom_node_ventilation_process, NULL);
leds_on(LEDS_RED);
leds_on(LEDS_BLUE);
}
} else if (humidity_percentage > LOWER_THRESHOLD){
if((bathroom_status & LOWER_TH_EXCEDEED) == 0){
// The upper threshold has been excedeed just now.
bathroom_status |= LOWER_TH_EXCEDEED;
leds_on(LEDS_GREEN);
}
}
} else {
// raise_humidity event occurred when shower already finished:
// it is a spurious event, and must not be taken into account.
}
} else if(ev == decrease_humidity){
if((bathroom_status & VENTILATION_ACTIVE) != 0){
// A humidity decrease. This may happen only if the
// ventilation system is active; thus, if a spurious event of
// this kind occurs when the ventilation is off, it must be ignored.
humidity_percentage -= (uint8_t)(int)data;
printf("[bathroom node]: humidity has decreased, now it is %d\n", humidity_percentage);
if(humidity_percentage < LOWER_THRESHOLD){
if((bathroom_status & LOWER_TH_EXCEDEED) != 0){
// The lower threshold was being exceeded until now.
// The ventilation system can be stopped
bathroom_status &= ~LOWER_TH_EXCEDEED;
bathroom_status &= ~VENTILATION_ACTIVE;
process_exit(&bathroom_node_ventilation_process);
leds_off(LEDS_GREEN);
leds_off(LEDS_BLUE);
}
} else if(humidity_percentage < UPPER_THRESHOLD){
if((bathroom_status & UPPER_TH_EXCEDEED) != 0){
// The upper threshold was excedeed until now.
bathroom_status &= ~UPPER_TH_EXCEDEED;
leds_off(LEDS_RED);
}
}
} else {
// decrease_humidity event occurred when ventilation already stopped:
// it is a spurious event, and must not be taken into account.
}
}
}
PROCESS_END();
return 0;
}
PROCESS_THREAD(bathroom_node_shower_process, ev, data)
{
PROCESS_BEGIN();
// printf("[bathroom node]: shower turned on\n");
static uint8_t increase;
static struct etimer timer;
etimer_set(&timer,CLOCK_SECOND*3);
while(1){
PROCESS_WAIT_EVENT();
if(ev == PROCESS_EVENT_TIMER && etimer_expired(&timer)){
// increase has to be at least 1 (to avoid the occurrence of too much 0 values)
increase = ((random_rand()%(RANDOM_MAX_VALUE+1))+1);
process_post(&bathroom_node_main_process, increase_humidity, (void*)(int)increase);
etimer_restart(&timer);
} else if(ev == PROCESS_EVENT_EXIT){
// printf("[bathroom node]: shower turned off\n");
etimer_stop(&timer);
}
}
PROCESS_END();
return 0;
}
PROCESS_THREAD(bathroom_node_ventilation_process, ev, data)
{
PROCESS_BEGIN();
// printf("[bathroom node]: ventilation system turned on\n");
static uint8_t decrease;
static struct etimer timer;
etimer_set(&timer, CLOCK_SECOND*3);
while(1){
PROCESS_WAIT_EVENT();
if(ev == PROCESS_EVENT_TIMER && etimer_expired(&timer)){
decrease = (RANDOM_MAX_VALUE+2);
process_post(&bathroom_node_main_process, decrease_humidity, (void*)(int)decrease);
etimer_restart(&timer);
} else if(ev == PROCESS_EVENT_EXIT){
// printf("[bathroom node]: ventilation system turned off\n");
etimer_stop(&timer);
}
}
PROCESS_END();
return 0;
}