-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathair_purifier.ino
317 lines (282 loc) · 11 KB
/
air_purifier.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
308
309
310
311
312
313
314
315
316
317
#include <string.h>
#include <DHT.h>
#include <SoftwareSerial.h>
#include <Wire.h>
/**** 핀 안내 ****/
/*
* *************** 미세먼지 센서 선 연결 방법(왼쪽부터) ********************
* { 1: 쓸데없음(우리가 자른 선), 2(PM10): 디지털 12번 핀, 3: 5V 핀, 4(PM25): 사용 안함(만약 측정값이 이상한 경우 2번 선 대신 이 선을 디지털 12번에 꽂아도 좋음), 5: GND 핀 }
* ************** CO2 NDIR 센서 연결 방법(기판 오른쪽 핀 안내 참조) ******************
* { T: 아날로그 4번 핀, R: 아날로그 5번 핀, V+: 5V 핀, V-: GND 핀 }
* ************* CO2 화학식 센서 연결 방법 *******************
* { 빨간 선: 5V 핀, 검은 선: GND 핀, 파란 선: 아날로그 1번 핀 }
* ************* 온습도 센서 연결 방법 ***************
* { 빨간 선: 5V 핀, 검은 선: GND 핀, 고동색 선: 디지털 11번 핀 }
*
* ************* LCD 쉴드 **********
* LCD 쉴드에 연결되어 있는 선을 아두이노위에 얹는다고 가정할 때 정확히 일치하는 곳에 연결하면 됨.
*
* ************* 절대 건드리지 말아야 할 핀!! ********
* 아날로그 3번 핀 - 모터 쉴드용
* 디지털 2번 핀 - 모터 쉴드용
*/
#define DHTPIN 11 // DHT sensor pin(Digital 11)
#define MG_PIN (A1) //define which analog input channel you are going to use for co2 chemical sensor
SoftwareSerial mySerial(A4, A5); // NDIR SENSOR PINS(TX, RX)
#define MD_PIN 12 //Microdust sensor pin(Digital 12)
/******************************** Humidity and Temperature sensor *****************************/
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
int temp = 0;
int humid = 0;
/********************* CO2 Sensor (Chemical Way) **********************/
/************************Hardware Related Macros************************************/
#define BOOL_PIN (13)
#define DC_GAIN (8.5) //define the DC gain of amplifier
/***********************Software Related Macros************************************/
#define READ_SAMPLE_INTERVAL (50) //define how many samples you are going to take in normal operation
#define READ_SAMPLE_TIMES (5) //define the time interval(in milisecond) between each samples in
//normal operation
/**********************Application Related Macros**********************************/
//These two values differ from sensor to sensor. user should derermine this value.
#define ZERO_POINT_VOLTAGE (0.258) // CO2 센서 보정 시 입력해야 하는 부분(자세한 내용은 아래 참조)
#define REACTION_VOLTGAE (0.030) //define the voltage drop of the sensor when move the sensor from air into 1000ppm CO2
/*****************************Globals***********************************************/
float CO2Curve[3] = {2.602, ZERO_POINT_VOLTAGE, (REACTION_VOLTGAE / (2.602 - 3))};
int percentage;
float volts;
/********************** CO2 Sensor (Chemical Way) END **********************/
/*********************************** CO2 SENSOR(NDIR) WAY) ******************************/
byte cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
char response[9];
String ppmString = " ";
/******************************** MICRODUST SENSOR **************************************/
unsigned long duration; //지속시간
unsigned long starttime; //시작시간
unsigned long curtime; //종료시간
unsigned long sampletime_ms = 30000; // 30초 = 먼지 측정 주기(간격)-조정하세요 ; (1초=1000으로 설정)
unsigned long lowpulseoccupancy = 0; //지속시간 누적
float ratio = 0;
float concentration = 0; // using spec sheet curve
float pcsPerCF = 0; //입자당 CF를 0으로 초기화
float ugm3 = 0; //세제곱미터(큐빅 미터)당 마이크로 그램(㎍/㎥)
int i = 0;
int dht_sw = 0;
int air_sw = 0;
// Motor Shield
int pwmPin = 3; // Analog Pin 3
int dirPin = 2; //Digital Pin 2
static int iSpeed = 0;
static int iAcc = 5;
/**** DELAYED LOOP SETTINGS ****/
#define LCD_UPDATE_TIMES 250
#define CO2_NDIR_UPDATE_TIMES 5000
#define CO2_CHEM_UPDATE_TIMES 500
#define DHT_UPDATE_TIMES 1000
int last_lcd_update = 0;
int last_co2_ndir_update = 0;
int last_co2_chem_update = 0;
int last_dht_update = 0;
/**** Serial Connection Input Settings ****/
#define INPUT_SIZE 30
void setup() {
Serial.begin(9600);
/**** Motor Reset ****/
analogWrite(pwmPin, 0);
digitalWrite(dirPin, LOW);
/**** CO2 Sensor(Chem) Register ****/
pinMode(BOOL_PIN, INPUT); //set pin to input
digitalWrite(BOOL_PIN, HIGH); //turn on pullup resistors
/**** CO2 Sensor(NDIR) Register ****/
mySerial.begin(9600);
/**** Microdust Sensor Register ****/
pinMode(3, INPUT);
starttime = millis();
last_lcd_update = millis() - LCD_UPDATE_TIMES;
last_co2_ndir_update = millis() - CO2_NDIR_UPDATE_TIMES;
last_co2_chem_update = millis() - CO2_CHEM_UPDATE_TIMES;
last_dht_update = millis() - DHT_UPDATE_TIMES;
/**** LCD Register ****/
Serial.println("ready");
}
void loop() {
/** Collect Microdust samples and control motor by settings ***/
collectSamples();
/*
* TIMED LOOPS
*/
if((millis() - last_lcd_update) >= LCD_UPDATE_TIMES) {
if (iSpeed >= 0) {
analogWrite(pwmPin, iSpeed);
digitalWrite(dirPin, LOW);
} else {
analogWrite(pwmPin, -iSpeed);
digitalWrite(dirPin, HIGH);
}
}
if((millis() - last_co2_chem_update) >= CO2_CHEM_UPDATE_TIMES) {
volts = MGRead(MG_PIN);
percentage = MGGetPercentage(volts, CO2Curve);
//Serial.print("Current Chem Sensor Volt:");
//Serial.print(volts);
//Serial.print("V");
//Serial.print("\n");
last_co2_chem_update = millis();
}
if((millis() - last_co2_ndir_update) >= CO2_NDIR_UPDATE_TIMES) {
mySerial.write(cmd, 9);
mySerial.readBytes(response, 9);
int responseHigh = (int) response[2];
int responseLow = (int) response[3];
int ppm = (256*responseHigh)+responseLow;
ppmString = String(ppm);
/*
for(int x=0;x<9;x++)
{
Serial.print((int)response[x], HEX);
Serial.print(" ");
}
Serial.print("\n");
//Serial.println((int)response, HEX);
Serial.println("High:" + (String)responseHigh + " Low:" + (String)responseLow);
Serial.print("PPM ");
Serial.println(ppm);
Serial.println("-----------------------------------");
*/
}
if((millis() - last_dht_update) >= DHT_UPDATE_TIMES) {
temp = dht.readTemperature();
humid = dht.readHumidity();
/* Send Infomations */
Serial.print(getNDIRPPM());
Serial.print(" ");
Serial.print(getChemPPM());
Serial.print(" ");
Serial.print(getDustInfo());
Serial.print(" ");
Serial.print(temp);
Serial.print(" ");
Serial.print(humid);
Serial.print("\n");
}
/*
* SERIAL CONNECTION
*/
while(Serial.available() > 0) {
String command = Serial.readStringUntil(' ');
String data = Serial.readStringUntil('\n');
/*
Serial.print(command);
Serial.print(" ");
Serial.print(data);
Serial.print("\n");
*/
if(command == "setmotorspeed") {
int serialSpeed = data.toInt();
if(serialSpeed > 255 || serialSpeed < 0) {
Serial.println("false");
} else {
iSpeed = serialSpeed;
Serial.println("true");
}
}
}
}
/**** MOTOR RELATED FUNCTIONS ****/
void controlMotor(int level) {
iSpeed += level;
if(iSpeed >= 255) {
iSpeed = 255;
} else if(iSpeed < 0) {
iSpeed = 0;
}
}
/**** CO2 SENSOR(CHEM) RELATED FUNCTIONS ****/
String getChemPPM() {
if (percentage == -1) {
return "<400";
} else {
return String(percentage);
}
}
/***************************** MGRead *********************************************
Input: mg_pin - analog channel
Output: output of SEN-000007
Remarks: This function reads the output of SEN-000007
************************************************************************************/
float MGRead(int mg_pin)
{
int i;
float v = 0;
for (i = 0; i < READ_SAMPLE_TIMES; i++) {
v += analogRead(mg_pin);
delay(READ_SAMPLE_INTERVAL);
}
v = (v / READ_SAMPLE_TIMES) * 5 / 1024 ;
return v;
}
/***************************** MQGetPercentage **********************************
Input: volts - SEN-000007 output measured in volts
pcurve - pointer to the curve of the target gas
Output: ppm of the target gas
Remarks: By using the slope and a point of the line. The x(logarithmic value of ppm)
of the line could be derived if y(MG-811 output) is provided. As it is a
logarithmic coordinate, power of 10 is used to convert the result to non-logarithmic
value.
************************************************************************************/
int MGGetPercentage(float volts, float *pcurve)
{
if ((volts / DC_GAIN ) >= ZERO_POINT_VOLTAGE) {
return -1;
} else {
return pow(10, ((volts / DC_GAIN) - pcurve[1]) / pcurve[2] + pcurve[0]);
}
}
/**** CO2 SENSOR(NDIR) RELATED FUNCTIONS ****/
String getNDIRPPM() {
return ppmString;
}
/************************************ MICRODUST SENSOR RELATED FUNCTIONS ****************************/
void collectSamples() {
duration = pulseIn(MD_PIN, LOW);
lowpulseoccupancy = lowpulseoccupancy + duration;
curtime = millis(); //아두이노 내부, 현재 시간;
if ((curtime - starttime) >= sampletime_ms) //대기시간 > = 30s
{
ratio = lowpulseoccupancy / (sampletime_ms * 10.0); // // 비율 정수값 0=>100
// concentration = 미세먼지 센서 제조사에서 출력하는 값
concentration = 1.1 * pow(ratio, 3) - 3.8 * pow(ratio, 2) + 520 * ratio + 0.62; // using spec sheet curve
pcsPerCF = concentration * 100; // 입자 농도에 100을 곱하면 입자당 CF값
// org ugm3 = pcsPerCF / 13000; //입자당 CF를 나누면 세제곱미터당 마이크로그램 미세먼지 값
ugm3 = pcsPerCF / 1300; //입자당 CF를 1300으로 미세먼지 값
// Serial.print("duration:");
// Serial.print(duration);
// Serial.print(" / ");
// Serial.print("ugm3:");
// Serial.print(ugm3);
// Serial.print(" / ");
// Serial.print("lowpulseoccupancy:");
// Serial.print(lowpulseoccupancy);
// Serial.print(" / ");
// Serial.print("ratio:");
// Serial.print(ratio);
// Serial.print(" / ");
// Serial.print("concentration:");
// Serial.print(concentration);
// Serial.print(" / ");
// Serial.print(" pcs/0.01cf:");
// Serial.println(pcsPerCF);
// Serial.println("\n");
// Serial.print("f-concentration:");
// Serial.println(float(concentration/500));
lowpulseoccupancy = 0;
starttime = millis();
}
}
float getDustInfo() {
if(concentration == 0) {
return -1;
} else {
return ugm3;
}
}