-
Notifications
You must be signed in to change notification settings - Fork 0
/
IC_IR_Continuous_Box.ino
304 lines (261 loc) · 7.79 KB
/
IC_IR_Continuous_Box.ino
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/***************************************************
IAS - Instituto Superior Técnico
MSc in Biomedical Engineering
Rita Silva 86805
Vicente Garção 86810
This code uses MPC9808 IC contact temperature sensor, MLX90614
IR non-contact temperature sensor and NodeMCU ESP32
****************************************************/
#include <Wire.h>
#include <Adafruit_MLX90614.h>
#include <Wire.h>
#include "Adafruit_MCP9808.h"
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
Adafruit_MLX90614 mlx = Adafruit_MLX90614();
//variables for kalman 1st pass IR
double Q=0.004;
double R=1.000;
double xhat=26.500;
double P=2.000;
double xhatminus=0.000;
double Pminus=0.000;
double K=0.000;
double M=26.500;
double vm[]={xhat,P,xhatminus,Pminus,K,M,Q,R};
//variables for ambient kalman IR
double xhatA=26.000;
double PA=1.000;
double xhatminusA=0.000;
double PminusA=0.000;
double KA=0.000;
double MA=26.000;
double vmA[]={xhatA,PA,xhatminusA,PminusA,KA,MA,Q,R};
//variables for IIR filter IR
double y=26.000;
double alpha=0.000;
double a=0.00004;
double tamb=1.000;
double vmf[]={tamb,alpha,y,a};
//variables for kalman 2st pass IR
double QPOST=0.0001;
double RPOST=1.000;
double xhatPOST=26.000;
double PPOST=1.000;
double xhatminusPOST=0.000;
double PminusPOST=0.000;
double KPOST=0.000;
double MPOST=26.000;
double vmPOST[]={xhatPOST,PPOST,xhatminusPOST,PminusPOST,KPOST,MPOST,QPOST,RPOST};
//variables for kalman 1st pass IC
double QC=0.00001;
double RC=1.000;
double xhatC=26.000;
double PC=1.000;
double xhatminusC=0.000;
double PminusC=0.000;
double KC=0.000;
double MC=26.00;
double vmC[]={xhatC,PC,xhatminusC,PminusC,KC,MC,QC,RC};
//variables for kalman 2st pass IC
double QCPost=0.00001;
double RCPost=1.000;
double xhatCPost=26.000;
double PCPost=1.000;
double xhatminusCPost=0.000;
double PminusCPost=0.000;
double KCPost=0.000;
double MCPost=26.00;
double vmCPost[]={xhatCPost,PCPost,xhatminusCPost,PminusCPost,KCPost,MCPost,QCPost,RCPost};
boolean x=false;
int pin_LEDON = 19;
int pin_switchON = 4;
// variables to hold the new and old switch states
boolean oldSwitchStateON = HIGH;
boolean newSwitchState1ON = HIGH;
boolean newSwitchState2ON = HIGH;
boolean newSwitchState3ON = HIGH;
boolean LEDstatusON = LOW;
//variables for when the sensor outputs nan
float d=0.0;
int nanI=0;
//variables for initial stabilization
int counter=0;
int counter1=0;
int counter2=1;
double rr=0.0;
double counteraux=1.0;
double result=36.00;
int counter1I=0;
int counter2I=0;
int counter3I=0;
double rrI=0.0;
void setup() {
Serial.begin(115200);
mlx.begin();
pinMode(pin_LEDON, OUTPUT);
digitalWrite(pin_LEDON,LOW);
pinMode(pin_switchON, INPUT_PULLUP);
while (!Serial); //waits for serial terminal to be open, necessary in newer arduino boards.
Serial.println("Both Sensors Test");
// Make sure the sensor is found, you can also pass in a different i2c
// address with tempsensor.begin(0x19) for example, also can be left in blank for default address use
// Also there is a table with all addres possible for this sensor, you can connect multiple sensors
// to the same i2c bus, just configure each sensor with a different address and define multiple objects for that
// A2 A1 A0 address
// 0 0 0 0x18 this is the default address
// 0 0 1 0x19
// 0 1 0 0x1A
// 0 1 1 0x1B
// 1 0 0 0x1C
// 1 0 1 0x1D
// 1 1 0 0x1E
// 1 1 1 0x1F
if (!tempsensor.begin(0x18)) {
Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");
while (1);
}
Serial.println("Found MCP9808!");
tempsensor.setResolution(3); // sets the resolution mode of reading, the modes are defined in the table bellow:
// Mode Resolution SampleTime
// 0 0.5°C 30 ms
// 1 0.25°C 65 ms
// 2 0.125°C 130 ms
// 3 0.0625°C 250 ms
}
static void kalman(double v[]) {
v[2]=v[0];
v[3]=v[1]+v[6];
v[4]=(v[3])/(v[3]+v[7]);
v[0]=v[2]+v[4]*(v[5]-v[0]);
v[1]=(1-v[4])*v[3];
}
static void filtertemp(double vmIIR[], double v[], double vA[]) {
double deriv=fabs(vA[0]-vmIIR[0]);
vmIIR[1]=(2/(1+exp(-vmIIR[3]/deriv)))-1;
double aux=vmIIR[2];
vmIIR[2]=vmIIR[1]*v[0]+(1-vmIIR[1])*aux;
vmIIR[0]=vA[0];
}
void loop() {
newSwitchState1ON = digitalRead(pin_switchON);
delay(1);
newSwitchState2ON = digitalRead(pin_switchON);
delay(1);
newSwitchState3ON = digitalRead(pin_switchON);
// if all 3 values are the same we can continue
if ( (newSwitchState1ON==newSwitchState2ON) && (newSwitchState1ON==newSwitchState3ON) ) {
if ( newSwitchState1ON != oldSwitchStateON ) {
// has the button switch been closed?
if ( newSwitchState1ON == LOW ) {
if ( LEDstatusON == LOW ) { digitalWrite(pin_LEDON, HIGH); LEDstatusON = HIGH; x=true; tempsensor.wake();}
else { digitalWrite(pin_LEDON, LOW); LEDstatusON = LOW; x=false; tempsensor.shutdown_wake(1);}
}
oldSwitchStateON = newSwitchState1ON;
}
}
if(x==true) {
//IC
float c = tempsensor.readTempC();
//checking for very low or very high values or nan
if(c<15.0 || c>44.0 || isnan(c)){
if(isnan(c)){
Serial.println("nan");
}
c=d;
nanI+=1;
if(nanI==20) {
Serial.println("Ocorreu um erro. Verificar a conexão.");
digitalWrite(pin_LEDON, LOW);
LEDstatusON = LOW;
x=false;
nanI=0;
}
}
d=c;
//filtering
//kalman 1st pass
vmC[5]=c;
kalman(vmC);
//kalman 2nd pass
vmCPost[5]=vmC[0];
kalman(vmCPost);
//code for initial stabilization
if(counter1<30) {
counter1+=1;
}
else {
if (counter2<=10){
rr+=vmCPost[0]/10;
counter2+=1;
}
else {
counteraux=(120-counter)/120;
result=counteraux*rr+(1-counteraux)*vm[0];
if (counter<120){
counter+=1;
}
if(result>37.5) {
Serial.println("ALERT: POSSIBLE FEVER DETECTED");
}
else {
if(result>37.2) {
Serial.println("ALERT: POSSIBLE PRE-FEBRILE STATE DETECTED");
}
}
//raw temp
//Serial.print(c, 3);
//Serial.print(",");
Serial.print(result, 3);
Serial.print(",");
}
}
//IR
//initial stabilization
if(counter1I<10) {
counter1I+=1;
}
else {
if (counter2I<10){
rrI+=mlx.readObjectTempC()/10;
counter2I+=1;
}
else {
if(counter3I<1) {
vmf[2]=rrI;
vm[0]=rrI;
vm[5]=rrI;
vmPOST[0]=rrI;
vmPOST[5]=rrI;
counter3I+=1;
}
else {
//ambient temperature Kalman
vmA[5]=mlx.readAmbientTempC();
kalman(vmA);
//object temperature Kalman 1st pass
vm[5]=mlx.readObjectTempC();
kalman(vm);
//object temperature IIR filter
filtertemp(vmf,vm,vmA);
//object temperature Kalman 2nd pass
vmPOST[5]=vmf[2];
kalman(vmPOST);
if(vmPOST[0]>37.5) {
Serial.println("ALERT: POSSIBLE FEVER DETECTED");
}
else {
if(vmPOST[0]>37.2) {
Serial.println("ALERT: POSSIBLE PRE-FEBRILE STATE DETECTED");
}
}
}
//raw temp
//Serial.print(mlx.readObjectTempC(), 3);
//Serial.print(",");
//result
Serial.println(vmPOST[0], 3);
}
}
}
delay(1000);
}