校园网络气象站的设计与实现
Posted 铁熊玩创客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了校园网络气象站的设计与实现相关的知识,希望对你有一定的参考价值。
0x01 项目背景
在很多学校里、景区里我们总能见到这样的气象信息大屏幕,能实时显示温度、湿度、气压等气象数据。相较于传统的气象百叶箱,这样的大屏幕气象站有更好的实时性、实用性和科技感,人们从很远处就能清楚地看到气象数据。作为一名创客老师,本着“自己动手,丰衣足食”的创客精神,就开始构思自己设计一个校园网络气象站。
![](https://image.cha138.com/20221104/cf82cfd38ac84a92ad07539fe1c01064.jpg)
0x02 项目分析
根据初步思路整理,我希望设计的是一面安装在校园大厅的气象信息墙,采集的气象数据为校园里的实时气象数据。考虑到整块大屏幕的成本较高,我准备使用多块小屏幕显示不同的气象数据的方式。为了提高项目整体的稳定性,为每块屏幕单独配物联网主控,利用 WiFi 实现气象数据的传输,同时也方便将气象数据上传到物联网平台供后期研究。
作为校园里使用的气象信息墙,最基础的显示信息应该有温度、湿度和气压等信息。为了引导学生保持安静,还可以增加检测噪音的功能,如果噪音值过高,还要额外提醒学生注意保持安静。另外,为了让学生能及时掌握上下课时间,还可以增加时钟功能,帮助学生更好地树立时间观念。
![](https://image.cha138.com/20221104/64af8c7aba7843c59081c8a10ecc6954.jpg)
气象数据检测模块以 WeMos D1 mini 为主控,连接 DHT11 温湿度传感器、BMP280 气压传感器和声音传感器,用于检测所需要的气象信息,将检测到的数据通过 Blynk 物联网平台发送到相应对的显示模块上。
温度显示模块以 WeMos D1 mini 为主控,用 2*4 点阵屏作为显示单元,将从气象数据检测模块接收到的温度数值显示在点阵屏上。湿度显示模块、噪声显示模块和气压显示模块也是同样的原理。
时钟显示模块以 WeMos D1 mini 为主控,用 2*8 点阵屏作为显示单元,直接从网络获取标准时间,无需手动调整时间。
0x03 硬件设计
为了保证气象信息墙的稳定性,避免出现因长期使用导致的导线接触不良等情况,传感器与主控的连接应该尽可能减少杜邦线的使用。因此,重新设计一块转接 PCB,用于焊接本项目中需要用到的各种传感器和模块。
该转接板用于显示模块时,转接板上只需要接 WeMos D1 mini 主控和 MAX7219 点阵屏幕。
而作为气象数据发送模块时,需要接 DHT11 温湿度传感器、BMP280 气压传感器、声音传感器和 WeMos D1 mini 主控。
综上需求,为转接板分配引脚如下:
模块 | 模块引脚名 | 主控引脚名 |
---|---|---|
MAX7219 点阵屏 | CLK | GPIO14 |
CS | GPIO12 | |
DIN | GPIO13 | |
DHT11 温湿度传感器 | DATA | GPIO2 |
RGB 灯带 | SIG | GPIO15 |
噪音传感器 | RX | GPIO12 |
TX | GPIO13 | |
BMP280 | SCL | GPIO5 |
SDA | GPIO4 |
借助于立创 EDA 设计软件,先设计转接板的原理图,并为各个传感器分配连接引脚。
![](https://image.cha138.com/20221104/c2871644933848bd97113220019a5bff.jpg)
根据原理图,生成 PCB,并调整各元器件布局。根据 MAX7219 点阵屏的尺寸,确定转接板上点阵屏接口位置,同时对应于点阵屏上的螺丝孔位,设计用于固定的四个螺丝孔。其他传感器根据其大小排布其位置。位置确认无误后,就可以对 PCB 进行布线了,对于新手而言,设计简单的电路板时可以直接使用软件自带的自动布线功能。自动布线虽然会存在一些问题,但是比较适合新手使用。
![](https://image.cha138.com/20221104/259b8c53e9144a6a915ecb9028a6a86f.jpg)
设计完成后,还可以直接看到电路板完成后平面和立体效果。也可以通过生成立体效果来检查各个元器件之间的安装距离,根据立体效果再对转接板做适当调整。
![](https://image.cha138.com/20221104/cbf54ecc07eb4390ade5b093b5d5ff96.jpg)
![](https://image.cha138.com/20221104/12450f2a64924d3b8b185c0fa137b272.jpg)
0x04 硬件焊接
设计好转接板后,通过嘉立创平台下单生产,等上几天后就能收到自己设计的转接板了。
![](https://image.cha138.com/20221104/f04f4b5551814ab19ec0e44ad0862ba8.jpg)
在 MAX7219 背面焊接 5P 排针,方便与转接板焊接,再安装 4 个用于固定的铜柱,铜柱位置与转接板上的螺丝孔位置对应。
![](https://image.cha138.com/20221104/db1e2ef51c0e4cf08402a6ddb1ace113.jpg)
为转接板焊接排母和电源座,然后将其安装到点阵屏背后的铜柱上,装上 WeMos d1 mini 主控。这样就完成了一个显示模块的设计,利用同样的方法焊接 3 个显示模块,为不同的模块上传不同的程序,就能显示对应的气象数据了。
![](https://image.cha138.com/20221104/a9d5ebb01fe64293a1b6297bb6bac3d6.jpg)
而在焊接气象数据发送模块时稍许复杂一点,还需要将各个传感器焊接到转接板上。为发送模块上传程序后,该模块就会将气象数据发送给各个显示模块。
![](https://image.cha138.com/20221104/ec975815ac6b4d5992dc24e8b2bf7818.jpg)
0x05 程序编写
为了能实现各块 WeMos d1 mini 主控之间的数据通信,同时又能将温湿度数据发布到物联网平台,我采取使用 Blynk 物联网平台,实现数据的联通。利用 Blynk 的桥接功能,可以实现多块主控之间的数据传递。
因此,在开始编程之间,需要在 Blynk APP 中创建项目,并为该项目添加 5 个设备,不同的设备会有不同的授权码。
![](https://image.cha138.com/20221104/18569581f2e140ffb0cffcd5386962b6.jpg)
然后在该项目中添加 3 个显示组件用于显示温度、湿度和气压,再添加一个仪表组件显示声音分贝值。
![](https://image.cha138.com/20221104/a5285a9de486473198c9c832baf9c827.jpg)
5.1 分贝值的读取
普通的声音传感器检测到的只是声音响度的模拟值,无法直接转换成声音的分贝值。在这个项目中,我需要测出声音的分贝值,因此需要采用了一个分贝传感器。
该分贝传感器采用串口通信方式,以下为该模块的参数:
串行波特率:115200,无校验位,1 位停止位;
数据包格式:起始符+命令+数据+校验值,一帧数据包总长度为 6 字节;
如:BB AA 01 7F 02 E7;
起始符:BB AA,表示一帧的开始;
命令:01,表示此帧为返回分贝值数据;
数据:7F 02,表示检测到的分贝值为 63.9dB。低字节在前,高字节在后,且每单位为 0.1dB;
校验值:E7,为 BB,AA,01,7F,02 的算术和校验值。
![](https://image.cha138.com/20221104/9be5b87758c343b7bae9ed29940a0a90.jpg)
据此说明,则可以通过串口读取到的数据计算出该传感器检测到的分贝数值。利用如下程序获取声音分贝值:
if (mySerial.available() > 0)
//获取噪声值
if (mySerial.read() == 0xBB)
if (mySerial.read() == 0xAA)
if (mySerial.read() == 0x01)
Noise_L = mySerial.read();
Noise_H = mySerial.read();
Noise = (Noise_H * 256 + Noise_L) / 10.0;
利用该模块检测室内正常情况下的分贝值,一般室内相对安静的情况下,分贝值在 40dB 左右。
![](https://image.cha138.com/20221104/5e75d41448e54b61a5d6871c590ac21a.jpg)
5.2 气象数据发送模块程序
作为气象数据发送模块,首先需要为该模块网络,为了提高实用性,通过手机配网的方式让模块连接入网络,所以需要在初始化程序中将该模块设置为 AP 模式。
利用定时器函数,每隔 50 毫秒读取一次声音分贝值,每隔 1 秒读取温度、湿度和气压值,读取到数值后,将数值通过 blynk 桥接发送到各个显示模块。
/*
气象数据发送端
*/
#define BLYNK_PRINT Serial
#define SEALEVELPRESSURE_HPA (1013.25)
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <SoftwareSerial.h>
#include <WiFiManager.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
#include <Wire.h>
#include <DHT.h>
#define SOUND_TX 13
#define SOUND_RX 12
SimpleTimer timer;
char temp_auth[] = "ql-7tUUaTYd3Hx1fl9LOvsl-RV4CCWDH";
char press_auth[] = "QwyARDcUsln_hNKOkMPLzkSHjvhEFmE8";
char bme_auth[] = "N0mnni2CNtITos-Jb4tm5rgwb-OldPOs";
char hum_auth[] = "0hN9wThrJrK8Ie_oy4OeDlxGBE2evnyR";
char sound_auth[] = "FlVPYSmNpCzJRBN3mzwQf9MHbkRBcgRr";
WidgetBridge bridge_temp(V0), bridge_press(V1), bridge_hum(V2), bridge_sound(V3);
Adafruit_BMP280 bmp;
DHT dht(2, 11);
float Noise, Noise_average, Noise_total, Temp, Hum, Pressure;
int Noise_H, Noise_L, i;
SoftwareSerial mySerial(SOUND_TX, SOUND_RX);
BLYNK_CONNECTED()
bridge_press.setAuthToken(press_auth);
bridge_hum.setAuthToken(hum_auth);
bridge_temp.setAuthToken(temp_auth);
bridge_sound.setAuthToken(sound_auth);
void Get_Data()
if (mySerial.available() > 0)
//获取噪声值
if (mySerial.read() == 0xBB)
if (mySerial.read() == 0xAA)
if (mySerial.read() == 0x01)
Noise_L = mySerial.read();
Noise_H = mySerial.read();
Noise = (Noise_H * 256 + Noise_L) / 10.0;
i++;
Noise_total += Noise;
if (i == 20)
i = 0;
Noise_average = Noise_total / 20;//计算1秒内的平均噪声值
Noise_total = 0;
//读取并发送温度、湿度、气压值
Hum = dht.readHumidity();
Pressure = bmp.readPressure();
Temp = bmp.readTemperature();
bridge_press.virtualWrite(V0, Pressure);
bridge_hum.virtualWrite(V0, Hum);
bridge_temp.virtualWrite(V0, Temp);
bridge_sound.virtualWrite(V0, Noise_average*0.75);
Serial.println(Noise_average*0.75);
void setup()
Serial.begin(9600);
mySerial.begin(115200);
WiFiManager wifiManager;
if (!wifiManager.autoConnect("Weather Station"))
//设置模块在未联网状态下进入AP模式,等待联网
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.reset();
delay(5000);
bmp.begin(0x76);
dht.begin();
Blynk.config(bme_auth, "blynk.mixly.org", 8080);
timer.setInterval(50L, Get_Data);//每隔1s,运行Get_Data函数
void loop()
timer.run();
Blynk.run();
5.3 模块配网
为了便于模块在不同 WiFi 环境下使用,我程序中没有将连接的 WiFi 信息固定,而是采用 AP 配网的方式进行。上传程序后,打开串口监视器,可以发现模块进入了 AP 配网模式,在该模式下,模块会成为一个无线接入点,会发出一个 WiFi 信号,如该模块发出的 WiFi 信号名称为 Weather Station。
![](https://image.cha138.com/20221104/4e14f88da06d4b01bfb94452a13ff339.jpg)
用手机搜索该名称的 WiFi 信号,并接入到该信号,然后手机会自动跳转到网络配置界面,选择 Configure WiFi,然后会扫描出附近可用的 WiFi 信号,选择我们常用的信号并输入密码,稍等片刻后,该模块就可以连接到指定的 WiFi 上。利用同样的方法,为后面每一个模块连接到 WiFi 上,保证每一个模块都可以正确连接到网络。
![](https://image.cha138.com/20221104/a905cbcd9d06468e8c5510d8552c60c3.jpg)
气象数据发送模块连接到网络后,就可以在 Blynk App 中查询到相关气象数据,在 App 中设置了不同的组件来呈现不同的数据,还可以通过 Super Chart 组件呈现出一段时间内气象数据的变化情况。
![](https://image.cha138.com/20221104/47def3cc45ea46cc9310b07fc5520704.jpg)
5.4 设计显示字体
为了提高数值的辨识度,需要重新设计点阵屏显示的数字字体,根据屏幕尺寸,设计两种尺寸的字体。
用大字体作为温湿度数值的整数部分和时钟模块的小时分钟显示,用小字体作为温湿度数值的小数部分和时钟模块的秒钟显示。
大字体占用 8*16 的点阵空间,小字体占用 5*8 的点阵空间。记录每个字的点阵分布,设计字体文件,方便显示模块调用字体。字体显示效果如下图:
![](https://image.cha138.com/20221104/9d36d634f2f54c1ebfa7060adcaeffe9.jpg)
5.5 显示模块程序
作为显示模块,主要负责从发送端接收到显示数据,然后将数值在屏幕上显示出来。模块联网后,先对点阵屏进行初始化设置,然后通 Blynk 虚拟管脚接收数值。由于各个模块的授权码不同,所以各个模块接收到的数值也不相同。温度显示模块接收到的是温度值,湿度显示模块接收到的湿度值。
#define BLYNK_PRINT Serial
#define CSPin 12
#include <Wire.h>
#include <WiFiManager.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <BlynkSimpleEsp8266.h>
#include "Tiny5pt7A.h"
#include "FreeMono12pt7b.h"
char hum_auth[] = "0hN9wThrJrK8Ie_oy4OeDlxGBE2evnyR";
float Hum;
Max72xxPanel myMatrix = Max72xxPanel(CSPin, 4, 2);
BLYNK_WRITE(V0)
//通过虚拟管脚接收湿度数值
Hum = param.asFloat();
myMatrix.fillScreen(0);
myMatrix.setCursor(60, 6);
myMatrix.setFont(&FreeMono12pt7b);
//用大字体显示湿度值的整数部分
myMatrix.print(int(Hum));
myMatrix.setFont(&Tiny5pt7A);
//用小字体显示湿度值的小数部分
myMatrix.print(int(Hum * 10) % 10);
myMatrix.write();
void setup()
Serial.begin(115200);
WiFiManager wifiManager;
//对MAX7219点阵屏初始化设置
myMatrix.setIntensity(15);
myMatrix.fillScreen(LOW);
for (int i = 0; i < 8; i++)
myMatrix.setRotation(i, 1);
for (int 4 = 0; i < 8; i++)
myMatrix.setPosition(i, i - 4, 1);
myMatrix.setCursor(5, 0);
myMatrix.print("Hum");
myMatrix.write();
if (!wifiManager.autoConnect("Hum"))
//设置模块在未联网状态下进入AP模式,等待联网
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.reset();
delay(5000);
Blynk.config(hum_auth, "blynk.mixly.org", 8080);
void loop()
Blynk.run();
以上是湿度显示模块程序,温度显示模块、气压显示模块等其他模块,只需要修改授权码即可。
各显示模块上传程序后,就可以通过网络从气象数据发送端获取到对应的气象数据,模块上显示效果如下图所示。
![](https://image.cha138.com/20221104/4a89e9512cdd4ecb9b4aba7d8c80d4de.jpg)
5.6 彩虹灯带模块
彩虹灯带在在正常情况下会不断变换颜色,为校园网络气象站增加一抹绚丽的色彩。但是当检测到的噪音超过一定数值时,彩虹灯带会先变黄色;如果噪音持续变大,彩虹灯带会变成红色,提醒附近的学生要保持安静。
![](https://image.cha138.com/20221104/650ee2c3d81b46d99677ca7d7d113a31.jpg)
#define BLYNK_PRINT Serial
#define RGBPin 15
#define NUMPIXELS 150
#include <Wire.h>
#include <WiFiManager.h>
#include <SimpleTimer.h>
#include <BlynkSimpleEsp8266.h>
#include <Adafruit_NeoPixel.h>
SimpleTimer timer;
char sound_auth[] = "FlVPYSmNpCzJRBN3mzwQf9MHbkRBcgRr";
float Noise;
int YELLOW_TIME, RED_TIME,hue;
Adafruit_NeoPixel rgb_display = Adafruit_NeoPixel(NUMPIXELS, RGBPin, NEO_GRB + NEO_KHZ800);
BLYNK_WRITE(V0)
Noise = param.asFloat();
Serial.println(Noise);
if (Noise > 75)
RED_TIME = 6;
else if (Noise > 65)
YELLOW_TIME = 6;
void rainbow()
for (int i = 0; i <= NUMPIXELS; i ++ )
for (int j = 0; j <= NUMPIXELS; j++ )
hue = (i + j) % (NUMPIXELS+1) * (65536/NUMPIXELS);//计算每一盏灯的颜色值
rgb_display.setPixelColor(j , rgb_display.ColorHSV(hue, 255, 255));
rgb_display.show();
delay(5);
void DisplayTime()
if (RED_TIME)
for (int j = 0; j <= NUMPIXELS; j ++)
rgb_display.setPixelColor(j, 0xff0000);//全部亮红色
rgb_display.show();
RED_TIME--;
else if (YELLOW_TIME)
for (int j = 0; j <= NUMPIXELS; j ++)
rgb_display.setPixelColor(j, 0xffff00);//全部亮黄色
rgb_display.show();
YELLOW_TIME--;
else
rainbow();
void setup()
Serial.begin(115200);
WiFiManager wifiManager;
rgb_display.begin();
if (!wifiManager.autoConnect("RGB"))
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.reset();
delay(5000);
Serial.println("local ip");
Serial.println(WiFi.localIP());
Blynk.config(sound_auth, "blynk.mixly.org", 8080);
timer.setInterval(1550L, DisplayTime);
void loop()
timer.run();
Blynk.run();
0x06 时间显示模块
校园里的很多时钟都是采用传统的时钟,传统的时钟经常会出现因电池损耗而渐渐变得不准时,需要人工去重新调整时间。而我们发现,手机上的时钟却可以一直都很准时,从来不用担心因没电而导致不准时。这是因为现在的手机都可以连接到互联网上,而网络上有提供标准授时的时间服务器。
提供标准授时的服务器叫 NTP 服务器,我们可以通过 WeMos D1 mini 主控去连接该服务器,然后获取到最新的时间,通过点阵屏显示出来。
#define CSPin 12
#include <TimeLib.h>
#include <WiFiManager.h>
#include <NtpClientLib.h>
#include <SimpleTimer.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include "FreeMono12pt7b.h"
#include "Tiny5pt7A.h"
SimpleTimer timer;
int8_t timeZone = 8;//设置时区
const PROGMEM char *ntpServer = "ntp1.aliyun.com";//设置时间服务器
Max72xxPanel myMatrix = Max72xxPanel(CSPin, 8, 2);
void DisplayTime() //显示内容
String currentTime = "" ;
String colon = (NTP.getTimeSecond() % 2 == 0) ? ":" : " ";//每隔1秒显示冒号
currentTime += (NTP.getTimeHour24() < 10) ? "0" + String(NTP.getTimeHour24()) : String(NTP.getTimeHour24());
currentTime += colon;
currentTime += (NTP.getTimeMinute() < 10) ? "0" + String(NTP.getTimeMinute()) : String(NTP.getTimeMinute());
myMatrix.fillScreen(LOW);
myMatrix.setCursor(60, 6);
myMatrix.setFont(&FreeMono12pt7b);
myMatrix.print(currentTime);//显示 时:分
myMatrix.setFont(&Tiny5pt7A);
myMatrix.print((NTP.getTimeSecond() < 10) ? "0" + String(NTP.getTimeSecond()) : String(NTP.getTimeSecond()));
//显示 秒
myMatrix.write();
void setup()
Serial.begin(9600);
WiFiManager wifiManager;
myMatrix.setIntensity(15);
myMatrix.fillScreen(LOW);
for (int i = 0; i < 16; i++)
myMatrix.setRotation(i, 1);
myMatrix.setCursor(4, 0);
myMatrix.print("Clock");
myMatrix.write();
if (!wifiManager.autoConnect("Clock"))
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.reset();
delay(5000);
Serial.println("local ip");
Serial.println(WiFi.localIP());
NTP.setInterval (600);//设置与NTP时间服务器同步时间间隔
NTP.setNTPTimeout (1500);
NTP.begin (ntpServer, timeZone, false);
timer.setInterval(1000L, DisplayTime);//每隔1s,运行Display函数
void loop()
timer.run();
为时间显示模块配置网络后就能显示正确的时间了。
![](https://image.cha138.com/20221104/67d57587b74c4133bdebfc87bdb3c182.jpg)
0x07 外观设计与安装
校园网络气象墙以将一棵树作为主体的造型,将各个显示模块安装在不同位置的树叶上,实现各个气象数据的显示。
![](https://image.cha138.com/20221104/bda23dee98884acaab6060f593d9b196.jpg)
将设计图制作成实体模型,树叶部分选取材质需要有一定的透光性,这样可以将显示模块直接装在内部,点阵屏的光亮正好可以透出来,光线会变得更柔和。彩虹灯带沿着草坪轮廓粘贴安装,从左侧引线到达电源箱。
气象站的各个模块采用 5V 供电,每个显示模块需要 1-1.5A 左右的电流,其中时间显示模块需要 2A 左右的电流,灯带需要 2A 左右的电流,因此整个作品大概需要 8A 左右的电流。为了保证电源有足够的冗余,给整个作品提供的电源需要 5V 10A 以上。将电源模块隐藏在左侧盒子中,预留一定的空隙,保持空气流通,避免电源模块温度过高。
气象检测模块的安装位置要选择通风性好,避免高温的位置,由于每一块点阵屏都会有发热的情况,不可以将气象检测模块安装到树叶内部。
![](https://image.cha138.com/20221104/4c5433b453294698b0401c629b4deb27.jpg)
0x08 结束语
当整个作品完成后,可以为校园里的同学们提供实时的温湿度情况和时间显示。帮助学生更好地了解温湿度情况和时间,同时通过噪音检测功能可以很好的提醒学生要在课间保持安静。
欢迎转发朋友圈。如需转载,请注明出处和原作者。
点个赞与在看支持一下吧 ↓↓↓
以上是关于校园网络气象站的设计与实现的主要内容,如果未能解决你的问题,请参考以下文章