-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSistem_Monitoring.ino
307 lines (263 loc) · 7.39 KB
/
Sistem_Monitoring.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
305
306
307
#include <WiFiManager.h>
#include <DHT.h>
#include <ThingSpeak.h>
#include <MQUnifiedsensor.h>
#include <EEPROM.h>
// Pin Definitions
#define LED_PIN 2
#define TRIGGER_PIN 0
#define DHT_PIN 33
#define DSM_PIN 35
#define MQ_PIN 32
// Constants
#define DHT_TYPE DHT22
#define RATIO_CLEANAIR_MQ7 (27.5)
#define DSM_LOW_RATIO_MULTIPLIER (30.0 / 1000.0)
#define DSM_INTERVAL (1000) // DSM501a interval pembacaan
#define TS_INTERVAL (20000) // ThingSpeak interval kirim data
#define CHANNEL_ID_EEPROM_ADDR 0 // Alamat EEPROM untuk menyimpan Channel ID
#define WRITE_API_KEY_EEPROM_ADDR 10 // Alamat EEPROM untuk menyimpan Write API Key
// ThingSpeak Settings
char channelID[21];
char writeAPIKey[41];
WiFiManager wm;
WiFiManagerParameter channel_id_param;
WiFiManagerParameter api_key_param;
WiFiClient client;
DHT dht(DHT_PIN, DHT_TYPE);
// MQUnifiedsensor MQ7(BOARD, VOLTAGE_RESOLUTION, ADC_BIT_RESOLUTION, MQ_PIN, "MQ-7");
MQUnifiedsensor MQ7("ESP-32", 3.3, 12, MQ_PIN, "MQ-7");
float mq7Value = 0;
float humi = 0;
float tempC = 0;
float tempF = 0;
float dsm_consentrate = 0;
float dsm_particle = 0;
unsigned long dsm_lowPulse = 0;
unsigned long dsm_previousTime = 0;
unsigned long ts_previousTime = 0;
void setup()
{
WiFi.mode(WIFI_STA);
Serial.begin(115200);
Serial.setDebugOutput(true);
loadFromEEPROM();
delay(3000);
Serial.println("Starting");
pinMode(LED_PIN, OUTPUT);
pinMode(TRIGGER_PIN, INPUT);
configureWiFiManager();
configureDHT();
configureMQ7();
configureDSM501a();
configureThingSpeak();
}
void configureWiFiManager()
{
// Setup WiFi Manager di sini
new (&channel_id_param) WiFiManagerParameter("channelid", "ThingSpeak Channel ID", channelID, 20);
new (&api_key_param) WiFiManagerParameter("apikey", "ThingSpeak API Key", writeAPIKey, 40);
wm.addParameter(&channel_id_param);
wm.addParameter(&api_key_param);
wm.setConfigPortalBlocking(false);
wm.setSaveParamsCallback(saveParamCallback);
std::vector<const char *> menu = {"wifi", "info", "param", "sep", "restart", "exit"};
wm.setMenu(menu);
wm.setClass("invert");
if (wm.autoConnect())
{
Serial.println("Connected to WiFi");
}
else
{
Serial.println("Config portal running");
}
}
void configureDHT()
{
// Setup DHT22 di sini
dht.begin();
}
void configureMQ7()
{
// Setup MQ-7 di sini
// Set math model to calculate the PPM concentration and the value of constants
MQ7.setRegressionMethod(1); //_PPM = a*ratio^b
MQ7.setA(99.042); // Configure the equation to calculate CO concentration value
MQ7.setB(-1.518); // Configure the equation to calculate CO concentration value
MQ7.init();
Serial.print("Calibrating sensor, please wait");
float calcR0 = 0;
for (int i = 0; i < 10; i++)
{
MQ7.update();
calcR0 += MQ7.calibrate(RATIO_CLEANAIR_MQ7);
Serial.print(".");
delay(1000);
}
MQ7.setR0(calcR0 / 10);
Serial.println(" done!");
if (isinf(calcR0) || calcR0 == 0)
{
Serial.println("Warning: Connection issue with MQ7 sensor. Please check wiring and supply.");
while (1)
;
}
}
void configureDSM501a()
{
// Setup DSM501a di sini
pinMode(DSM_PIN, INPUT);
dsm_previousTime = millis();
}
void configureThingSpeak()
{
// Setup ThingSpeak di sini
ThingSpeak.begin(client);
}
void saveToEEPROM()
{
EEPROM.put(CHANNEL_ID_EEPROM_ADDR, channelID);
EEPROM.put(WRITE_API_KEY_EEPROM_ADDR, writeAPIKey);
EEPROM.commit();
}
void loadFromEEPROM()
{
EEPROM.get(CHANNEL_ID_EEPROM_ADDR, channelID);
EEPROM.get(WRITE_API_KEY_EEPROM_ADDR, writeAPIKey);
}
void saveParamCallback()
{
strcpy(channelID, channel_id_param.getValue());
strcpy(writeAPIKey, api_key_param.getValue());
// Save to EEPROM
saveToEEPROM();
}
float getParticlemgm3(float r)
{
/*
* with data sheet...regression function is
* y=0.1776*x^3-2.24*x^2+ 94.003*x
*/
// https://github.com/R2D2-2019/R2D2-2019/wiki/Is-the-given-formula-for-calculating-the-mg-m3-for-the-dust-sensor-dsm501a-correct%3F
float mgm3 = 0.001915 * pow(r, 2) + 0.09522 * r - 0.04884;
return mgm3 < 0.0 ? 0.0 : mgm3;
}
void loop()
{
digitalWrite(LED_PIN, HIGH);
delay(100);
int currentWiFiStatus = WiFi.status();
static int lastWiFiStatus = WL_IDLE_STATUS;
if (currentWiFiStatus != lastWiFiStatus)
{
lastWiFiStatus = currentWiFiStatus;
if (currentWiFiStatus != WL_CONNECTED)
{
Serial.println("WiFi disconnected. Reconnecting...");
wm.startConfigPortal("OnDemandAP");
}
}
// WiFi Manager
wm.process();
// DSM501a
dsm_lowPulse += pulseIn(DSM_PIN, LOW);
if ((millis() - dsm_previousTime) > DSM_INTERVAL)
{
Serial.println("============================");
float lowRatio = (dsm_lowPulse * DSM_LOW_RATIO_MULTIPLIER) / DSM_INTERVAL;
dsm_consentrate = 1.1 * pow(lowRatio, 3) - 3.8 * pow(lowRatio, 2) + 520.0 * lowRatio + 0.62; // using spec sheet curve
dsm_particle = getParticlemgm3(lowRatio);
Serial.print("Air Quality : ");
if (dsm_consentrate < 1000)
{
Serial.println("Air is Clean");
}
else if (dsm_consentrate < 10000)
{
Serial.println("Air is Good");
}
else if (dsm_consentrate < 20000)
{
Serial.println("Air is Moderate");
}
else if (dsm_consentrate < 50000)
{
Serial.println("Air is Heavy");
}
else
{
Serial.println("Air is Hazardous");
}
Serial.print("Concentration PM2.5 : ");
Serial.print(dsm_consentrate);
Serial.println(" ppm");
Serial.print("Particles PM2.5 : ");
Serial.print(dsm_particle);
Serial.println(" μg/m³");
dsm_lowPulse = 0;
// MQ-7
MQ7.update();
mq7Value = MQ7.readSensor();
Serial.print("Carbon monoxide : ");
Serial.print(mq7Value);
Serial.println(" ppm");
// DHT-22
humi = dht.readHumidity();
tempC = dht.readTemperature();
tempF = dht.readTemperature(true);
if (isnan(tempC) || isnan(tempF) || isnan(humi))
{
Serial.println("Failed to read from DHT sensor!");
}
else
{
Serial.print("Humidity : ");
Serial.print(humi);
Serial.println("%");
Serial.print("Temperature : ");
Serial.print(tempC);
Serial.print("°C ~ ");
Serial.print(tempF);
Serial.println("°F");
}
dsm_previousTime = millis();
Serial.println("============================");
}
// ThingSpeak
if ((millis() - ts_previousTime) > TS_INTERVAL)
{
Serial.println("============================");
ts_previousTime = millis();
ThingSpeak.setField(1, tempC);
ThingSpeak.setField(2, tempF);
ThingSpeak.setField(3, humi);
ThingSpeak.setField(4, mq7Value);
ThingSpeak.setField(5, dsm_consentrate);
ThingSpeak.setField(6, dsm_particle);
bool sentSuccessfully = false;
int attempts = 0;
while (!sentSuccessfully && attempts < 3)
{
int responseCode = ThingSpeak.writeFields(String(channelID).toInt(), writeAPIKey);
if (responseCode == 200)
{
sentSuccessfully = true;
Serial.println("Channel update successful.");
}
else
{
Serial.println("Problem updating channel. HTTP error code " + String(responseCode));
attempts++;
delay(1000);
}
}
if (!sentSuccessfully)
{
Serial.println("Failed to send data to ThingSpeak after several attempts.");
}
Serial.println("============================");
}
digitalWrite(LED_PIN, LOW);
delay(100);
}