回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

#新物联网挑战二#大美六中智能气象站 简单

头像 松静匀乐 2023.07.11 219 3

 

大美六中智能气象站

IMG_20230710_171724.jpg

 

一、研究背景

       随着工业、交通、农业等活动的增加,大气环境质量受到越来越严重的污染,同时水源地的污染也大大影响着人们的生活质量。因此如何及时准确地检测出大气环境和水质的质量,加强环境监测成为人们关注的焦点。

二、智能气象站的需求

        通过学校或者家里的直饮水净化器需要经常更换滤芯以保证水质健康安全,联想到水质检测问题:我们的饮用水质怎么样,是否需要更换滤芯以及更换前后的差距是怎样的,我们能否通过技术实现直观地水质检测及预警,以及这其中的实现原理是怎样的呢?

       与水质安全相类似的大气环境质量也是我们比较关心的,而据了解,就目前气象站的检测已经很容易能够实现,我们六中的校园很美丽,风景如画,爽心悦目,希望来到校园的师生能够每天心情舒畅,开心每一天,而大气环境是一个混沌系统,大气环境质量是人们关心的问题,如何用数字化技术实现大气环境质量的检测,直观呈现和动态预警是我们课题研究的一个方向。为此我们先从大气环境质量检测入手,进而探究水质检测。

       智能气象站的需求主要体现在以下几方面:

      1. 数据的准确性:气象站所收集的数据要反映真实的大气环境情况。只有准确地检测大气中的污染物浓度等参数信息,才能及时地采取有效的环境治理措施。

       2. 数据的及时性:及时地获取大气环境的信息,并能够快速地进行分析处理和报警提示等操作。能够第一时间将检测到的数据快速地传输给后台管理系统,以便后续的数据统计和分析。

       3. 数据的可视化:需要一个直观的显示系统,可以让用户清晰地看到大气中的污染物浓度,以及变化趋势和历史数据等信息。

       4. 数据的多元化:智能气象站需要能够检测不同区域的大气环境质量,并且支持不同媒介的数据展现。

三、智能气象站的研究过程

研究过程.png

       我们的研究过程按照先确定选题、再起草项目报告、然后技术实现完成检测系统的搭建,再根据实际情况不断优化和完善的研究思路开展项目活动,期间借助思维可视化工具(如百度脑图等)进行及时记录,包括故障现象截图及解决方法等,积累研究过程性经验,方便积累和总结分享。

        在学习的基础上结合自己的实际,理解基础上进行创新,比如我们参照了【云雀】大美二高在线气象站:(https://makelog.dfrobot.com.cn/article-312505.html),完成了基本数据的准备,包括软件准备、升级行空板SIoTV2,正如李老师所说,如果按照方法能顺利升级成功,那是幸运的;如果升级不成功,也无所谓,不用管他。我手头有两块行空板,其中一块是后来入手的很顺利的升级成功了,而之前的那一块总是提示有文件需要更新,索性我先视而不见了。

更新升级SIOTV2.png

四、智能气象站的设计

       为了满足上述需求,我们可以从以下几个方面来设计智能气象站:

       1. 环境传感器:使用云雀气象仪中的各种传感器可以采集大气中的风速、风向、温度、湿度、气压等信息,还有PM1.0、PM2.5、PM10(此三项来自Gravity: PM2.5空气质量传感器)和AQI、TVOC、eCO2(此三项来自Gravity: ENS160 空气质量传感器),其中Gravity: ENS160 空气质量传感器能直接输出多种IAQ(TVOC、eCO2、AQI)数据。采用多种传感器可用于监测不同标准下的大气污染物。总之,要根据不同的需求选择不同的传感器,然后依据等级标准判断当前环境的质量等级,进而采取必要的措施。

       2. 数据处理单元:将传感器采集到的数据进行处理,包括实时的数据分析、异常检测和处理等。在数据处理单元上,可以设置一些算法,如神经网络算法、遗传算法以及模糊逻辑等算法,以便对传感器所采集到的数据进行处理和分析。

       在完成了基本硬件的搭建后,接下来就是确定区分标准,以下是自己搜集到的

        二氧化碳浓度参考

 

CO2浓度.png

        AQI等级参考

image.png

 

      eCO2/CO2浓度参考

image.png

 

       TVOC浓度参考

image.png

 

         空气污染指数(AQI)与PM1.0,PM2.5污染物浓度值对应表,其中AQI指数空气质量等级24小时PM1.0平均浓度
 

AQI与PM1.0.png

        以下是自己基于以上标注设计的程序截图:

screenshots-调整项目运行正常20230714.mp-1689348193427.png

        具体程序分解:

        (1)气象台程序初始化

image.png
image.png

        过程中因为这里曾经用了个time导致程序报错,费了老大劲才找到原因,改成了time2后故障排除。

        (2)添加气象相关数据变量:变量赋值,因为需要不断采集数据,加了等待和循环执行

image.png

        (3)行空板数据更新,也修正了之前标点不统一的问题:image.png

        (4)将气象数据发送MQTT服务器中,也就是将变量数据发送到相应主题下:

image.png

         (5)预警信息反馈

image.png
image.png
image.png

        同时附加python程序代码:

#  -*- coding: UTF-8 -*-

# MindPlus

# Python

import base64

from io import BytesIO

from PIL import Image

from pinpong.extension.unihiker import *

from pinpong.board import Board,Pin

from DFRobot_Atmospherlum import *

from dfrobot_rp2040_sci import *

from pinpong.board import Board

from unihiker import Audio

from unihiker import GUI

import time

import siot

import cv2

# 事件回调函数

def u_thread1_function():

    while True:

        if vd.grab():

            ret, grab = vd.read()

            siot.publish(topic="siot/摄像头", data=base642base64(grab))

        time.sleep(0.02)

def on_message_callback(client, userdata, msg):

    if (msg.topic == msg.topic):

        if (msg.payload.decode() == "发布"):

            thread3=u_gui.start_thread(u_thread3_function)

def u_thread3_function():

    siot.publish(topic="siot/接收通知", data="发布成功!")

    time.sleep(2)

    siot.publish(topic="siot/接收通知", data=" ")


siot.init(client_id="6011530819265551",server="192.168.1.45",port=1883,user="siot",password="dfrobot")

Board().begin()

u_gui=GUI()

u_audio = Audio()

siot.connect()

siot.loop()

siot.set_callback(on_message_callback)

siot.getsubscribe(topic="siot/大美六中在线气象站")

siot.publish(topic="siot/大美六中在线气象站", data="hello")

yunque_i2c = DFRobot_Atmospherlum_I2C(0x42)

while (yunque_i2c.begin() != 0):

    print("yunque_i2c initialize failed!!")

    time.sleep(1)

print("Sensor initialize success!!")

yunque_i2c.set_local_time()

time.sleep(1)

 

SCI1 = DFRobot_RP2040_SCI_IIC(addr=0x21)

while SCI1.begin() != 0:

    print("Initialization Sensor Universal Adapter Board failed.")

    time.sleep(1)

print("Initialization Sensor Universal Adapter Board done.")


 def frame2base64(frame):

    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    img = Image.fromarray(frame) #将每一帧转为Image

    output_buffer = BytesIO() #创建一个BytesIO

    img.save(output_buffer, format='JPEG') #写入output_buffer

    byte_data = output_buffer.getvalue() #在内存中读取

    base64_data = base64.b64encode(byte_data) #转为BASE64

    return base64_data #转码成功 返回base64编码


 def base642base64(frame):

    data=str('data:image/png;base64,')

    base64data = str(frame2base64(frame))

    framedata = base64data[2:(len(base64data)-1)]

    base642base64_data = data + str(framedata)

    return base642base64_data

vd = cv2.VideoCapture()

vd.open(-1)

while not (vd.isOpened()):

    print("摄像头初始化中")

print("摄像头初始化完成")

thread1=u_gui.start_thread(u_thread1_function)

aa=u_gui.draw_text(text="大美六中在线气象站",x=0,y=0,font_size=18, color="#0000FF")

fs=u_gui.draw_text(text="风速:",x=0,y=30,font_size=18, color="#0000FF")

qy=u_gui.draw_text(text="气压",x=0,y=60,font_size=18, color="#0000FF")

fx=u_gui.draw_text(text="风向:",x=0,y=90,font_size=18, color="#0000FF")

wd=u_gui.draw_text(text="温度",x=0,y=120,font_size=18, color="#0000FF")

sd=u_gui.draw_text(text="湿度",x=0,y=150,font_size=18, color="#0000FF")

gx=u_gui.draw_text(text="光线",x=0,y=180,font_size=18, color="#0000FF")

sy=u_gui.draw_text(text="声音",x=0,y=210,font_size=18, color="#0000FF")

time2=u_gui.draw_text(text="更新时间",x=0,y=240,font_size=15, color="#0000FF")

time1=u_gui.draw_text(text=" ",x=0,y=270,font_size=15, color="#0000FF")

 

while True:

    time.sleep(3)

    GengXinShiJian = (yunque_i2c.get_time_stamp())

    KongQiZhiLiangAQI = SCI1.get_value0("AQI")

    KongQiZhiLiangPM1 = SCI1.get_value0("PM1.0")

    KongQiZhiLiangPM10 = SCI1.get_value0("PM10")

    KongQiZhiLiangTVOC = SCI1.get_value0("TVOC")

    FengSu = (yunque_i2c.get_value("speed"))

    FengXiang = (yunque_i2c.get_value("dir"))

    QiYa = (yunque_i2c.get_value("Pressure"))

    ShiDu = (yunque_i2c.get_value("Humi"))

    WenDu = (yunque_i2c.get_value("Temp"))

    ShengYin = u_audio.sound_level()

    GuangXian = light.read()

    ShiNaCO2 = SCI1.get_value0("ECO2")

    KongQiZhiLiangPM25 = SCI1.get_value0("PM2.5")

    qy.config(text=(str((str("气压:") + str(QiYa))) + str((yunque_i2c.get_unit("Pressure")))))

    fs.config(text=(str((str("风速:") + str(FengSu))) + str((yunque_i2c.get_unit("speed")))))

    fx.config(text=(str("风向:") + str(FengXiang)))

    wd.config(text=(str((str("温度:") + str(WenDu))) + str((yunque_i2c.get_unit("Temp")))))

    sd.config(text=(str((str("湿度:") + str(ShiDu))) + str((yunque_i2c.get_unit("Humi")))))

    time1.config(text=GengXinShiJian)

    sy.config(text=(str((str("声音:") + str((str(ShengYin))))) + str("dB")))

    gx.config(text=(str((str("光线:") + str((str(GuangXian))))) + str("cd")))

    siot.publish_save(topic="siot/time1", data=GengXinShiJian)

    siot.publish_save(topic="siot/fs", data=FengSu)

    siot.publish_save(topic="siot/fx", data=FengXiang)

    siot.publish_save(topic="siot/wendu", data=WenDu)

    siot.publish_save(topic="siot/shidu", data=ShiDu)

    siot.publish_save(topic="siot/qiya", data=QiYa)

    siot.publish_save(topic="siot/校园AQI", data=KongQiZhiLiangAQI)

    siot.publish_save(topic="siot/校园PM2.5", data=KongQiZhiLiangPM25)

    siot.publish_save(topic="siot/室内CO2", data=ShiNaCO2)

    siot.publish_save(topic="siot/校园PM1.0", data=KongQiZhiLiangPM1)

    siot.publish_save(topic="siot/校园PM10", data=KongQiZhiLiangPM10)

    siot.publish_save(topic="siot/校园TVOC", data=KongQiZhiLiangTVOC)

    siot.publish_save(topic="siot/fengsufengxiang", data=(str((str((str((str("风速:") + str(FengSu))) + str((yunque_i2c.get_unit("speed"))))) + str(","))) + str(FengXiang)))

    if ((int(float(ShiNaCO2))) > 1500):

        siot.publish(topic="siot/室内CO2报警", data="CO₂超标,需要通风")

    elif ((int(float(ShiNaCO2))) > 1000):

        siot.publish(topic="siot/室内CO2报警", data="CO₂ 污染,建议通风")

    elif ((int(float(ShiNaCO2))) > 800):

        siot.publish(topic="siot/室内CO2报警", data="CO₂ 略浓,建议通风")

    else:

        siot.publish(topic="siot/室内CO2报警", data="CO₂ 正常")

    if ((int(float(KongQiZhiLiangPM25))) > 75):

        siot.publish(topic="siot/校园PM2.5报警", data="空气质量污染")

    elif ((int(float(KongQiZhiLiangPM25))) > 35):

        siot.publish(topic="siot/校园PM2.5报警", data="空气质量良好")

    else:

        siot.publish(topic="siot/校园PM2.5报警", data="空气质量优秀")

    if ((int(float(KongQiZhiLiangTVOC))) > 6000):

        siot.publish(topic="siot/空气质量TVOC预警", data="空气质量污染")

    elif ((int(float(KongQiZhiLiangTVOC))) > 750):

        siot.publish(topic="siot/空气质量TVOC预警", data="空气质量较差")

    elif ((int(float(KongQiZhiLiangTVOC))) > 50):

        siot.publish(topic="siot/空气质量TVOC预警", data="空气质量良好")

    else:

        siot.publish(topic="siot/空气质量TVOC预警", data="空气质量优良")

    if ((int(float(KongQiZhiLiangAQI))) == 5):

        siot.publish(topic="siot/AQI提醒", data="空气质量极差,请加强透风")

    elif ((int(float(KongQiZhiLiangAQI))) == 4):

        siot.publish(topic="siot/AQI提醒", data="空气质量差,加强通风,请寻找污染源")

    elif ((int(float(KongQiZhiLiangAQI))) == 3):

        siot.publish(topic="siot/AQI提醒", data="空气质量一般,加强通风,靠近水源")

    elif ((int(float(KongQiZhiLiangAQI))) == 2):

        siot.publish(topic="siot/AQI提醒", data="空气质量好,保持通风")

    elif ((int(float(KongQiZhiLiangAQI))) == 1):

        siot.publish(topic="siot/AQI提醒", data="空气质量非常好")

    if ((int(float(KongQiZhiLiangPM10))) > 250):

        siot.publish(topic="siot/校园PM10报警", data="空气质量严重污染")

    elif ((int(float(KongQiZhiLiangPM10))) > 150):

        siot.publish(topic="siot/校园PM10报警", data="空气质量重度污染")

    elif ((int(float(KongQiZhiLiangPM10))) > 115):

        siot.publish(topic="siot/校园PM10报警", data="空气质量中度污染")

    elif ((int(float(KongQiZhiLiangPM10))) > 75):

        siot.publish(topic="siot/校园PM10报警", data="空气质量轻度污染")

    elif ((int(float(KongQiZhiLiangPM10))) > 35):

        siot.publish(topic="siot/校园PM10报警", data="空气质量良好")

    else:

        siot.publish(topic="siot/校园PM10报警", data="空气质量优秀")

    if ((int(float(KongQiZhiLiangPM1))) > 420):

        siot.publish(topic="siot/校园PM1.0报警", data="空气质量严重污染")

    elif ((int(float(KongQiZhiLiangPM1))) > 350):

        siot.publish(topic="siot/校园PM1.0报警", data="空气质量重度污染")

    elif ((int(float(KongQiZhiLiangPM1))) > 250):

        siot.publish(topic="siot/校园PM1.0报警", data="空气质量中度污染")

    elif ((int(float(KongQiZhiLiangPM1))) > 150):

        siot.publish(topic="siot/校园PM1.0报警", data="空气质量轻度污染")

    elif ((int(float(KongQiZhiLiangPM1))) > 50):

        siot.publish(topic="siot/校园PM1.0报警", data="空气质量良好")

    else:

        siot.publish(topic="siot/校园PM1.0报警", data="空气质量优秀")

      过程性感悟:在过程中每个故障都是有原因的,所以排查故障,根据蛛丝马迹找到故障原因,然后解决就可以逢凶化吉,吉无不利了。根据需要创建的主题Topic:

SIOT1.png
SIOT2.png
SIOT3.png

       3. 云端存储单元:将检测到的数据上传至云端存储,方便后续数据分析、统计和查询。对于数据缺失、网络异常等情况,可以设置一些机制,如备份、恢复和报警等机制,以便能够第一时间解决问题。

        4. 前端显示单元:通过前端显示系统,可以直观地显示大气污染物浓度、空气质量级别、变化趋势等信息。可以通过手机、电脑和其他设备来进行查看。

大美六中气象站.png

       5. 智能报警单元:当污染物浓度超过安全标准时,可以自动发出报警提示。在发出报警提示后,还可以通过不同的通知方式进行人员信息提醒,以便能够及时采取进一步措施。

      IMG_20230707_085838.jpg

IMG_20230708_092222.jpg

IMG_20230708_092617.jpg

IMG_20230708_171229.jpg

IMG_20230708_171247.jpg

六中校园检测场景近景.jpg

六中校园检测场景全景.jpg

室内大气环境质量检测场景.jpg

校园泽雅湖畔检测场景.jpg

        以上的智能气象站,在水质检测上也同样适用。只需要更换探头,加入水质传感器即可。

       四、研究总结

        研究过程中遇到了诸多问题,首先是技术上,然后是如何将技术应用在解决校园气象站具体应用场景中,我们想到了可以通过检测教室内或者办公室内空气质量,为采取必要的通风措施提供预警提示,也用来检测校园大环境下的大气五要素(风速、风力、气压、温度和湿度等)在过程中会遇到一些故障,比如行空板显示重影的问题可以通过调整程序的先后顺序,不变化的放在前边,需要循环更新的放在后边,问题就解决了。

重影故障.jpgIMG_20230712_231101.jpg

        在研究过程中,我们实现了技术体验过程,那么如何用这个技术来解决真实的生活问题,往往是更有意义和价值的。

        在技术实现过程中,有些可以进一步优化,感觉可视化大屏有些功能还可以更加人性化,比如,在这个项目研究过程中,我们觉得可以加入一些互动模块,让学生或者体验者能够搜索一些感兴趣的气象相关的常识,可以增加一些链接到GhatGPT之类的接口,方便学生个性化的有针对性的学习。

        还有我自身想进一步探索需要完善或者进一步优化落实的,从技术上如何实现常态化不间断检测,摆脱电脑束缚,让云雀气象仪能够实现远程供电和运行。

        智能气象站的设计方案,可以实现对大气环境质量的及时、准确、可视化检测。它能够收集各种传感器的数据,并通过后台处理进行二次分析和展示。同时,智能气象站还能够为用户提供建议和预警提示,以便及时采取治理措施。在未来,它还将成为监测环境质量和提供环保服务的重要工具。

 

       

评论

user-avatar
  • _深蓝_

    _深蓝_2024.07.25

    厉害!赞一个

    0
    • 三春牛-创客

      三春牛-创客2024.07.17

      厉害!

      0
      • 松静匀乐

        松静匀乐2023.07.14

        不知道是否发布成功了

        0