交流群号:245022761(IT项目交流群)
要求:设计一个小型的气象监测站,检测温湿度、大气压力、空气质量等参数,并显示在1602液晶显示屏上。
设计方案:
1、使用温湿度传感器检测温度和湿度,并在显示屏第一行上显示。
2、使用大气压传感器测量大气压,并在显示屏第二行上显示。
3、使用激光颗粒物传感器检测空气中PM2.5含量,并在显示屏第二行上显示。
设备选型:
主控中心:Arduino Mega 2560
Arduino Mega 2560是基于ATmega2560的微控制板,有54路数字输入/输出端口(其中15个可以作为PWM输出),16路模拟输入端口,4路UART串口,16MHz的晶振,USB连接口,电池接口,ICSP头和复位按钮。简单地用USB连接电脑或者用交直流变压器就能使用。
温湿度传感器:DHT11
DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有枀高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个 NTC 测温元件,并与一个高性能 8 位单片机相连接。
引脚说明
1、VDD 供电 3.3~5.5V DC
2、DATA 串行数据,单总线
3、NC 空脚
4、GND 接地,电源负极
大气压传感器:BMP085
BMP085是德国BOSCH公司生产的一款低功耗、高精度的MEMS数字气压传感器。BMP085的供电电压为1.8 V~3.6 V,典型值为2.5 V。它由电阻式压力传感器、A/D转换器和带有E2PROM的控制单元组成,控制单元通过I2C总线与移动设备的微处理器连接。E2PROM中存储了11个校准参数,这11个校准参数涉及到参考温度下的零点漂移、零点漂移的温度系数以及灵敏度的温度系数等,用于对气压值进行温度补偿。
BMP085的气压测量范围为300hPa~1100hPa(海拔高度-500 m~9000 m),温度测量范围为-40 ℃~+85 ℃。在低功耗模式下,BMP085精度为0.06 hPa(0.5 m),在高精度模式下其精度可以达到0.03 hPa(0.25 m),转换速率可以达到128次/s,能够满足系统对速度和精度的要求。
激光颗粒物传感器:GP2Y1051AUOF
GP2Y1010AU0F是日本夏普公司开发的一款光学灰尘浓度检测传感器。此传感器内部成对脚分布的红外发光管和光电晶体管,利用光敏原理来工作。用于检测特别细微的颗粒,如香烟颗粒、细微灰尘。依靠输出脉冲的高度来判断颗粒浓度。
系统连接图:
撰写代码:
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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332n#include "DHT11.h" #include <Wire.h> #include <LiquidCrystal.h> LiquidCrystal lcd(12,11,A4,A5,A6,A7);//1602 DHT11 myDHT11(2);//温湿度输出引脚 //气压传感器------------------------- #define BMP180ADD 0x77 // I2C address of BMP180 //write is (0xEE) read is (0xEF) unsigned char OSS; /**********************MSB LSB******/ int ac1; // 0xAA 0xAB int ac2; // 0xAC 0xAD int ac3; // 0xAE 0xAE unsigned int ac4; // 0xB0 0xB1 unsigned int ac5; // 0xB2 0xB3 unsigned int ac6; // 0xB4 0xB5 int b1; // 0xB6 0xB7 int b2; // 0xB8 0xB9 int mb; // 0xBA 0xBB int mc; // 0xBC 0xBD int md; // 0xBE 0xBF float temperature; double pressure; double pressure2; long b5; double altitude; //PM2.5--------------------------------------------------------- #define COV_RATIO 0.2 //ug/mmm / mv #define NO_DUST_VOLTAGE 400 //mv #define SYS_VOLTAGE 5000 //ADC参考电压 const int vout = 5; //pm2.5输出引脚 float density, voltage; int adcvalue; int Filter(int m) { static int flag_first = 0, _buff[10], sum; const int _buff_max = 10; int i; if(flag_first == 0) { flag_first = 1; for(i = 0, sum = 0; i < _buff_max; i++) { _buff[i] = m; sum += _buff[i]; } return m; } else { sum -= _buff[0]; for(i = 0; i < (_buff_max - 1); i++) { _buff[i] = _buff[i + 1]; } _buff[9] = m; sum += _buff[9]; i = sum / 10.0; return i; } } //----------------------------------- void setup(void) { lcd.begin(16,2); //初始化LCD1602 lcd.print("Welcome to use!"); //液晶显示Welcome to use! delay(1000); //延时1000ms lcd.clear(); //液晶清屏 Serial.begin(9600); //send and receive at 9600 baud Wire.begin(); OSS = 2; // Oversampling Setting 0: single 1: 2 times 2: 4 times 3: 8 times BMP180start(); } void loop(void) { //lcd.clear(); //液晶清屏 Serial.print("---------n"); delayMicroseconds(280); adcvalue = analogRead(vout); adcvalue = Filter(adcvalue); //电压 voltage = (SYS_VOLTAGE / 1024.0) * adcvalue * 11; if(voltage >= NO_DUST_VOLTAGE) { voltage -= NO_DUST_VOLTAGE; density = voltage * COV_RATIO; } else density = 0; Serial.print("PM: "); Serial.print(3*density/100); Serial.print(" ug/m3n"); lcd.setCursor(8,1); //设置液晶开始显示的指针位置,1列,2行 lcd.print("PM:"); //液晶显示 lcd.print(3*density/100); delay(500); Serial.print("---------n"); myDHT11.DHT11_Read(); //读取温湿度值 Serial.print("HUMI = "); Serial.print(myDHT11.HUMI_Buffer_Int); Serial.println(" %RH"); Serial.print("TMEP = "); Serial.print(myDHT11.TEM_Buffer_Int); Serial.println(" C"); lcd.setCursor(0,0); //设置液晶开始显示的指针位置,1列,2行 lcd.print("T:"); //液晶显示 lcd.print(myDHT11.HUMI_Buffer_Int); lcd.print((char)223); //液晶显示“°” lcd.print("C"); //液晶显示“C” delay(500); lcd.setCursor(7,0); //设置液晶开始显示的指针位置,1列,2行 lcd.print("H:"); //液晶显示 lcd.print(myDHT11.TEM_Buffer_Int); lcd.print(" %RH"); //液晶显示“C” delay(500); //延时1s Serial.print("---------n"); calculate(); show(); delay(500); } //大气压 /** calculate centure **/ void calculate() { temperature = bmp180GetTemperature(bmp180ReadUT()); temperature = temperature*0.1; pressure = bmp180GetPressure(bmp180ReadUP()); pressure2 = pressure/101325; pressure2 = pow(pressure2,0.19029496); altitude = 44330*(1-pressure2); //altitude = 44330*(1-(pressure/101325)^0.19029496); } /** print reslut **/ void show() { Serial.print("Temp: "); Serial.print(temperature, 1); //10 hexadecimal Serial.println(" C"); Serial.print("Pressure: "); Serial.print(pressure, 0); //10 hexadecimal Serial.println(" Pa"); Serial.print("altitude:"); Serial.print(altitude); Serial.println("m"); lcd.setCursor(0,1); //设置液晶开始显示的指针位置,1列,2行 lcd.print("P:"); //液晶显示 lcd.print(pressure/1000.0); } /**BMP180 satrt program**/ void BMP180start() { /*MSB*/ ac1 = bmp180ReadDate(0xAA); //get full data ac2 = bmp180ReadDate(0xAC); ac3 = bmp180ReadDate(0xAE); ac4 = bmp180ReadDate(0xB0); ac5 = bmp180ReadDate(0xB2); ac6 = bmp180ReadDate(0xB4); b1 = bmp180ReadDate(0xB6); b2 = bmp180ReadDate(0xB8); mb = bmp180ReadDate(0xBA); mc = bmp180ReadDate(0xBC); md = bmp180ReadDate(0xBE); } /***BMP180 temperature Calculate***/ short bmp180GetTemperature(unsigned int ut) { long x1, x2; x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; //x1=((ut-ac6)*ac5)/(2^15) x2 = ((long)mc << 11)/(x1 + md); //x2=(mc*2^11)/(x1+md) b5 = x1 + x2; //b5=x1+x2 return ((b5 + 8)>>4); //t=(b5+8)/(2^4) } /***BMP180 pressure Calculate***/ long bmp180GetPressure(unsigned long up) { long x1, x2, x3, b3, b6, p; unsigned long b4, b7; b6 = b5 - 4000; x1 = (b2 * (b6 * b6)>>12)>>11; x2 = (ac2 * b6)>>11; x3 = x1 + x2; b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2; x1 = (ac3 * b6)>>13; x2 = (b1 * ((b6 * b6)>>12))>>16; x3 = ((x1 + x2) + 2)>>2; b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; b7 = ((unsigned long)(up - b3) * (50000>>OSS)); if (b7 < 0x80000000) p = (b7<<1)/b4; else p = (b7/b4)<<1; x1 = (p>>8) * (p>>8); x1 = (x1 * 3038)>>16; x2 = (-7357 * p)>>16; p += (x1 + x2 + 3791)>>4; return p; } /*** Read 1 bytes from the BMP180 ***/ int bmp180Read(unsigned char address) { unsigned char data; Wire.beginTransmission(BMP180ADD); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP180ADD, 1); while(!Wire.available()); return Wire.read(); } /*** Read 2 bytes from the BMP180 ***/ int bmp180ReadDate(unsigned char address) { unsigned char msb, lsb; Wire.beginTransmission(BMP180ADD); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP180ADD, 2); while(Wire.available()<2); msb = Wire.read(); lsb = Wire.read(); return (int) msb<<8 | lsb; } /*** read uncompensated temperature value ***/ unsigned int bmp180ReadUT() { unsigned int ut; Wire.beginTransmission(BMP180ADD); Wire.write(0xF4); // Write 0x2E into Register 0xF4 Wire.write(0x2E); // This requests a temperature reading Wire.endTransmission(); delay(5); // Wait at least 4.5ms ut = bmp180ReadDate(0xF6); // read MSB from 0xF6 read LSB from (16 bit) return ut; } /*** Read uncompensated pressure value from BMP180 ***/ unsigned long bmp180ReadUP() { unsigned char msb, lsb, xlsb; unsigned long up = 0; Wire.beginTransmission(BMP180ADD); Wire.write(0xF4); // Write 0x34+(OSS<<6) into register 0xF4 Wire.write(0x34 + (OSS<<6)); // 0x34+oss*64 Wire.endTransmission(); delay(2 + (3<<OSS)); // Wait for conversion, delay time dependent on OSS Wire.beginTransmission(BMP180ADD); Wire.write(0xF6); // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB) Wire.endTransmission(); Wire.requestFrom(BMP180ADD, 3); while(Wire.available() < 3); // Wait for data to become available msb = Wire.read(); lsb = Wire.read(); xlsb = Wire.read(); up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);//16 to 19 bit return up; }
DHT11.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#include "DHT11.h" //定义变量 unsigned char HUMI_Buffer_Int = 0; unsigned char TEM_Buffer_Int = 0; DHT11::DHT11(int pin) { DHT11_DQ = pin; } //**************************************************** //初始化DHT11 //**************************************************** void DHT11::DHT11_Init() { pinMode(DHT11_DQ,OUTPUT); digitalWrite(DHT11_DQ,LOW); //拉低总线,发开始信号; delay(30); //延时要大于 18ms,以便 DHT11 能检测到开始信号; digitalWrite(DHT11_DQ,HIGH); delayMicroseconds(40); //等待 DHT11 响应; pinMode(DHT11_DQ,INPUT_PULLUP); while(digitalRead(DHT11_DQ) == HIGH); delayMicroseconds(80); //DHT11 发出响应,拉低总线 80us; if(digitalRead(DHT11_DQ) == LOW); delayMicroseconds(80); //DHT11 拉高总线 80us 后开始发送数据; } //**************************************************** //读一个字节DHT11数据 //**************************************************** unsigned char DHT11::DHT11_Read_Byte() { unsigned char i,dat = 0; unsigned int j; pinMode(DHT11_DQ,INPUT_PULLUP); delayMicroseconds(2); for( i=0; i<8; i++) { while(digitalRead(DHT11_DQ) == LOW); //等待 50us; delayMicroseconds(40); //判断高电平的持续时间,以判定数据是‘0’还是‘1’; if(digitalRead(DHT11_DQ) == HIGH) dat |= (1<<(7-i)); //高位在前,低位在后; while(digitalRead(DHT11_DQ) == HIGH); //数据‘1’,等待下一位的接收; } return dat; } //**************************************************** //读取温湿度值,存放在TEM_Buffer和HUMI_Buffer //**************************************************** void DHT11::DHT11_Read() { DHT11_Init(); HUMI_Buffer_Int = DHT11_Read_Byte(); //读取湿度的整数值 DHT11_Read_Byte(); //读取湿度的小数值 TEM_Buffer_Int = DHT11_Read_Byte(); //读取温度的整数值 DHT11_Read_Byte(); //读取温度的小数值 DHT11_Read_Byte(); //读取校验和 delayMicroseconds(50); //DHT11拉低总线50us pinMode(DHT11_DQ,OUTPUT); digitalWrite(DHT11_DQ,HIGH); //释放总线 }
测试结果:
1602显示
串口数据
最后
以上就是现实百褶裙最近收集整理的关于【Arduino】基于Arduino单片机的小型气象站设计的全部内容,更多相关【Arduino】基于Arduino单片机内容请搜索靠谱客的其他文章。
发表评论 取消回复