基于树莓派RP2040的简易气象站
基于RP2040GameKit以及ESP32-S2制作一个简单的气象台,能够实时播放5个城市的气象信息
标签
嵌入式系统
RP2040
2022暑假在家练
dukken
更新2022-09-02
北京理工大学
973

基于RP2040的简易气象站总结报告

项目介绍

        我选择的任务是项目三简易气象站,即制作一个简单的气象台,能够实时播放5个城市的气象信息。该项目需要RP2040 Game Kit板通过提供的ESP32-S2的WiFi模块连接网络,并在RP2040 Game Kit上显示某一个城市的气象信息 (包括 天气、时间、温度、湿度、气压、风速等等),另外还需要通过RP2040 Game Kit上的按键切换显示不同城市的天气信息。

设计思路

       本项目主要分为两部分,第一部分是利用ESP32-S2的WIFI模块对网络进行连接,并通过心知天气网提供的API获取相关的天气信息,使用ujson.loads解析有效的json字符串并转化为python对象的字典;第二部分则是lcd显示部分,将获取的天气信息打印在lcd屏幕上,并通过RP2040 Game Kit上的按键切换不同城市的天气信息。

软件流程图

       FvmgAIXGQnBHwf8GqcNb_4YHPK7e

硬件介绍

      (1)  采用树莓派Pico核心芯片RP2040:

  • 双核Arm Cortex M0+内核,可以运行到133MHz

  • 264KB内存
  • 性能强大、高度灵活的可编程IO可用于高速数字接口

  • 片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度

  • 支持MicroPython、C、C++编程

    用到的板上功能:

  • 240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789

  • 2个轻触按键用做输入控制

  • 板上外扩2MB Flash,预刷MicroPython的UF2固件

  • 双排16Pin连接器,有SPI、I2C以及2路模拟信号输入

  • 可以使用MicroPython、C、C++编程

  • USB Type C连接器用于供电、程序下载
    (2)ESP32-S2模组:
  • ESP32-S2 是一款高度集成、高性价比、低功耗、主打安全的单核 Wi-Fi SoC,具备强大的功能和丰富的 IO 接口。
  • ESP32-S2 集成了丰富的外围设备,有 43 个可编程 GPIO,可以灵活配置为 USB OTG、LCD 接口、摄像头接口、SPI、I2S、UART、ADC、DAC 等常用功能。ESP32-S2 具有 LCD 接口和 14 个可配置的电容触摸 GPIO,可为基于触摸屏和触摸板的设备提供良好的 HMI 解决方案
  • WIFI模块:802.11 b/g/n,数据速率高达 150 Mbps,帧聚合 (TX/RX A-MPDU, RX A-MSDU),0.4 µs 保护间隔,工作信道中心频率范围:2412 ~ 2484 MHz

实现功能

        驱动ESP32-S2 WiFi模块访问心知天气网,通过API获取天气信息,并打印在RP2040LCD屏幕上,通过B按键可切换五个城市的天气信息

FnG-QRFx3XRx1JfuQiQ9Ejw1yZYaFrkQ64Z0p_p3MEwNgiYFqva0lIqlFvYNg-KjdU4dE9nc92C59_8YaxJLFlMt8y6uSDppf7JtfUWSbVkRvXp-FnQtCzHnynbgC8JAwHu6VyyVEmPsFiKUk0B1hKHJ6YpeBHh9P_Np04vb

主要代码和说明

屏幕初始化

display.fill(st7789.BLACK)
display.text(font1,"www.eetree.cn",70,230)
display.text(font2,"Initializing...",0,100)#初始化界面

 

网络初始化

#initialize the serialport and network
    network_AT = network.Network(uart = UART(0, baudrate=115200, tx=Pin(12), rx=Pin(13)),
                             recvInfo = "",#receive buffer global variable
                             cmd_restore = 'AT+RESTORE',
                             cmd_mode = 'AT+CWMODE=1',#config as station
                             cmd_inquiry = 'AT+CIPSTA?',#inquiry the IP addr
                             cmd_connectRouter = 'AT+CWJAP="Drama","12345678"',#connect to Router
                             cmd_httpget = 'AT+HTTPCLIENT=2,0,"https://api.seniverse.com/v3/weather/now.json?key=S1LggX5PzW5xN0Wd6&location='+city+'&language=en&unit=c",,,2',
                             cmd_ack = 'OK'
                             )

    if(network_AT.connectNetwork()  == True):
    #STATUS
    #0:config network error
    #1:config network ok
    #2:http get error
    #3:http get ok
        network_status = 1
        print ('Done!')
    else:
        network_status = 0
        print('Network Config Error!')#连接网络

 

连接网络并通过API获取天气信息

 if(network_status == 0):
            if(network_AT.connectNetwork() == True):
                print('config network Done!')
                network_status = 1
            else:
                network_status = 0
                print ('Network Config Error!')
        elif(network_status == 1):
            if(network_AT.httpGet() == True):
                #time.sleep(3)
                network_status = 3
                print('HttpGet Done!')
            else:
                network_status = 2
        elif(network_status == 2):
            network_status = 1
            time.sleep(1)
            print ('HttpGet try again!')
        elif(network_status == 3):
            #parse json info
            print(network_AT.recvInfo)
            str_start = network_AT.recvInfo.find('{')
            print(str_start)
            str_end = network_AT.recvInfo.find(']}')
            print(str_end)
            weatherInfo_str = network_AT.recvInfo[str_start:str_end+2]
            print(weatherInfo_str)#网络连接成功并获取天气信息

 

解析jason为python字典

weather_json =ujson.loads(weatherInfo_str) 
            weather_location = weather_json['results'][0]['location']['name']
            print(weather_location,end=' ')
            weather_now = weather_json['results'][0]['now']['code']
            print(weather_now,end=' ')
            weather_temp = weather_json['results'][0]['now']['temperature']
            print(weather_temp,end='°C')
            weather_pressure = weather_json['results'][0]['now']['pressure']
            print(weather_pressure,end='Pa')
            weather_humidity = weather_json['results'][0]['now']['humidity']
            print(weather_humidity,end='%')
            weather_wind_speed = weather_json['results'][0]['now']['wind_speed']
            print(weather_wind_speed,end=' ')
            weather_time = weather_json['results'][0]['last_update']
            print(weather_time)#解析json为python对象

 

打印天气信息

display.fill(st7789.BLACK)
            weather_now = int(weather_now)
            if(0 <= weather_now <= 3):
                weather_now_code = 1 #sunny
                display.text(font2,"Sunny",50,30)
            elif(weather_now <= 8):
                weather_now_code = 2 #cloudy
                display.text(font2,"Cloudy",50,30)
            elif(weather_now == 9):
                weather_now_code = 3 #overcast
                display.text(font2,"Overcast",50,30)
            elif(weather_now <= 18):
                weather_now_code = 4 #rainy
                display.text(font2,"Rainy",50,30)
            elif(weather_now <= 25):
                weather_now_code = 5 #snowy
                display.text(font2,"Snowy",50,30)
            print(weather_now_code)
        
        
            display.text(font2,weather_location,80,100)
            display.text(font2,weather_temp+"C",100,70)
            display.text(font1,"o",140,65)
            display.text(font1,"Pressure:"+weather_pressure+"Pa",80,160)
            display.text(font1,"Humidity:"+weather_humidity+"%",0,180)
            display.text(font1,"Wind Speed"+weather_wind_speed+"km/h",100,180)
            display.text(font1,weather_time[0:10],80,210)
            network_status = 1
            break#在lcd屏幕上打印天气信息

 

按键切换城市天气信息

if(buttonB.value() == 0):
        count=count+1
        print(count)
        #按下B键则count+1切换城市
        
    if(count==9990):
        CityWeather('hainan')
        print(count)
        time.sleep(10)
        
    if(count==9991):
        CityWeather('beijing')
        print(count)
        time.sleep(10)
        
    if(count==9992):
        CityWeather('nanchang')
        print(count)
        time.sleep(10)
        
    if(count==9993):
        CityWeather('chengdu')
        print(count)
        time.sleep(10)
        
    if(count==9994):
        CityWeather('chongqing')
        print(count)
        time.sleep(10)
        
    if(count==9995):
        print(count)
        count=9990#循环城市天气

 

遇到的主要难题及解决方法

首先是ESP32-S2的WiFi模块,先前未接触过相关知识导致对网络连接部分存在许多不解之处,先是查看ESP-AT用户指南学习AT命令集,在参考老师直播所演示的方法完成了网络连接部分的建立与测试

然后是ESP32-S2与RP2040的连接,在观看直播并查看板块资料后确定了连接引脚,才完成了上述的网络连接测试

之后关于心知天气API,我查阅了官网的一系列指南,了解了如何访问网站的API获取所需的天气信息,在老师与同学的耐心解答下学习了如何将json解析为python字典

接下来是LCD屏幕的显示,我参考了之前LCDTest的脚本,初步了解了如何利用SPI驱动LCD,再打开ST7789脚本学习了相关的函数,进一步了解了LCD屏幕的驱动方法成功将获取的天气信息打印在了LCD屏幕上

最后关于按键切换城市天气,我参考了过去同学们使用RP2040制作小游戏的例子学习了按键的使用方法,完成了最终的目标,但是仍然存在一点小问题,即按键切换城市天气不够灵敏,往往需要数秒时间才能完成切换,与用户的交互性还有待提升

未来的计划或建议

未来我还计划完善我所编写的程序,提高程序的响应速度和与用户的交互性能,另外还需要封装重复代码再调用,感觉总体的思路可以进一步简化,此外还打算在屏幕上实现展示天气图片的功能

建议将实例代码中的注释完善一下,有部分代码注释不够明晰难以理解

 

 

附件下载
weather station.zip
团队介绍
北京理工大学彭流溢
团队成员
dukken
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号