基于RP2040和ESP32S2实现简易气象站制作
本项目依托2022暑假在家一起练,基于RP2040GameKit平台,实现了简易气象站的制作。本项目通过LCD屏幕、1个按键和实现了实时播放5个城市的气象信息功能,取得了良好的效果,具有一定的价值。
标签
RP2040
ESP32-S2
2022暑假在家练
简易气象站
jxwm
更新2022-09-02
北京邮电大学
1368

2022暑假在家一起练

——基于RP2040和ESP32S2实现简易气象站制作

一.项目介绍

本项目依托2022暑假在家一起练,基于RP2040GameKit平台,实现了简易气象站的制作。本项目通过LCD屏幕、2个按键和实现了实时播放5个城市的气象信息功能,取得了良好的效果,具有一定的价值。

项目任务:

  1. RP2040 Game Kit板通过提供的ESP32-S2的WiFi模块连接网络
  2. 在RP2040 Game Kit上显示某一个城市的气象信息 - 时间、温度....
  3. 通过RP2040 Game Kit上的按键能够切换显示不同城市的信息 ,比如:北京、上海、天津、重庆、深圳

二.设计思路

本项目设计围绕RP2040GAMEKIT,首先对RP2040的板载硬件进行实验使用,初步掌握板载的IO硬件以及RP2040能够实现的功能与实际性能。再根据硬件的具体功能,实现设计。设计步骤如下:

1.配置ESP32S2并烧录固件,连接ESP32S2模块与RP2040游戏机板。

FkY5AFzNksQM4Y_-l3Z2lsplvNLK

FvmNaSlk3wreFbA6muRl6FehHzni

采用如图所示flash_download_tool工具烧录文件,选择ESP32S2,develop工作模式,uart通信方式,并在设备管理器中查找到端口号,点击start进行烧录

2.烧录成功后开始写程序。首先配置网络,将心知天气文档获取接口写入文件中,获取实时天气信息。参考链接:

https://www.seniverse.com/

3.最后设计开机进入页面,配置好按键后,以便控制进入与切换地点。

Fqprqlsc7FzDO9nk9kVgrIaUjRWP

 

三.硬件介绍

1.RP2040GameKit游戏机板FkvcCPruExpxO83gylQsMmgxgEQjFmGMuR2PAG2hz3l3_-J88iqXMMHL

  • 采用树莓派Pico核心芯片RP2040:
    • 双核Arm Cortex M0+内核,可以运行到133MHz
    • 264KB内存
    • 性能强大、高度灵活的可编程IO可用于高速数字接口
    • 片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度
    • 支持MicroPython、C、C++编程
  • 板上功能:
    • 240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789
    • 四向摇杆 + 2个轻触按键 + 一个三轴姿态传感器MMA7660用做输入控制
    • 板上外扩2MB Flash,预刷MicroPython的UF2固件
    • 一个红外接收管 + 一个红外发射管
    • 一个三轴姿态传感器MMA7660
    • 一个蜂鸣器
    • 双排16Pin连接器,有SPI、I2C以及2路模拟信号输入
    • 可以使用MicroPython、C、C++编程
    • USB Type C连接器用于供电、程序下载

2.ESP32-S2模块

(1)ESP32-S2 性能: ESP32-S2 是一款高度集成、高性价比、低功耗、主打安全的单核 Wi-Fi SoC,具备强大的功能和丰富的 IO 接口:

  • 为您的连接设备提供安全保障:

               基于 RSA-3072 算法的安全启动

               基于 AES-XTS-256 算法的 Flash 加密

               保护私钥和设备机密不受软件访问

               密码加速器提高云连接性能

               有效抵抗物理故障注入攻击

  • 显示、触摸以及丰富的 IO 功能:

              ESP32-S2 集成了丰富的外围设备,有 43 个可编程 GPIO,可以灵活配置为 USB OTG、LCD 接口、摄像头接口、SPI、I2S、UART、ADC、DAC 等常用功能。ESP32-S2 具有 LCD 接口和 14 个可配置的电容                触摸 GPIO,可为基于触摸屏和触摸板的设备提供良好的 HMI 解决方案。

  • 极端温度下良好的 Wi-Fi 性能
               ESP32-S2 的工作温度是 -40 °C~125 °C,适用于各类工业、消费和照明应用。

(2)ESP32-S2 模组: ESP32-S2 系列模组是通用的 Wi-Fi MCU 模组,功能强大,具有丰富的外设接口,是物联网、可穿戴电子设备和智能家居等应用场景的理想选择。

(3)ESP32-S2 开发板: 乐鑫的 ESP32-S2 系列开发板有丰富的外设接口和功能模块,方便用户快速构建原型,满足用户开发物联网应用的需求。

参考链接:

https://www.espressif.com/zh-hans/support/download/documents

FnMo8i15c9Be0qhN6zgEn3frx4Yg

四.功能介绍

1.初始化开机界面:屏幕显示“按A键进入天气预报”

FsgdpTAoSAxR6R663fbm_Ykl4W-Q

2.按下A键后开始连接网络

FrqBk0kaP0EXyOIiDODUmBSgKvhP

3.网络连接成功后显示第一个城市的实时天气情况:温度、湿度、压强,以及地点、时间等。

FqlEZiD3kYRe3cuSN-u2aMPZJh2Z

这里展示的是北京的天气情况,温度29度,压强1000mb,湿度67%.

可以看见屏幕底下出现两行小字,分别表示按下A退出程序,按下B切换城市.

FvLkyO1zgwIKRPIT7oPN91zQVTrn

 

5.按下B切换城市:

Fj_xntWwCggS943L4bZOP-Z06Beo

6.按下A键退出

FiU6cpVWGmH06SLttX4XTbnof8t2

7.再次按下A即可重新开始运行程序

 

五.主要代码

import os
import time,utime
import ujson
import machine
import _thread
import lcd_gui
import network
import st7789 as st7789
from machine import UART,Pin, ADC,RTC,SPI
from buzzer_music import music
from time import sleep

image_sunny = "logo/0sunny.ebm"#48x48
image_cloudy = "logo/7cloudy.ebm"#58x41
image_overcast = "logo/9overcast.ebm"#58x38
image_rain = "logo/13rain.ebm"#58x57
image_snow = "logo/23snow.ebm"#58x55


#按键配置
buttonB = Pin(5,Pin.IN, Pin.PULL_UP)
buttonA = Pin(6,Pin.IN, Pin.PULL_UP)

display_info= lcd_gui.LCD_Display()

st7789_res = 0
st7789_dc  = 1
#buttonB    = 5

disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)
spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
display = st7789.ST7789(spi0, disp_width, disp_width,
                          reset=machine.Pin(st7789_res, machine.Pin.OUT),
                          dc=machine.Pin(st7789_dc, machine.Pin.OUT),
                          xstart=0, ystart=0, rotation=0)

#initialize the serialport and network
def getdata():
    global i
    global record
    if(buttonB.value()==0):
        i=i+1
        print("start")
        netconnectpic()
    elif buttonB.value()==1 and record==1:
        return 0
    elif buttonA.value()==0:
        return 0
    network_AT = network.Network(uart = UART(0, baudrate=115200, tx=Pin(12), rx=Pin(13)),
                              recvInfo = "",# receive buffer global variable
                              cmd_retore = 'AT+RESTORE',
                              cmd_mode = 'AT+CWMODE=1',#config as station
                              cmd_inquiry = 'AT+CIPSTA?',#inquiry the IP addr
                              cmd_connectRouter = 'AT+CWJAP="yourwife","password"',#connect to Router
                              cmd_httpget = 'AT+HTTPCLIENT=2,0,"https://api.seniverse.com/v3/weather/now.json?key=yourkey&location='+loc[i%5]+'&language=en&unit=c",,,2',
                              cmd_ack = 'OK'
                              )

    #network_AT.sendATCMD(network_AT.cmd_retore,network_AT.cmd_ack,5000)
    time.sleep(3)
    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!')
    time.sleep(3)
    
    while True:
        
        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)
     
            weather_json = ujson.loads(weatherInfo_str)
            weather_location = weather_json['results'][0]['location']['name']
            print(weather_location,end=' ')
            weather_country = weather_json['results'][0]['location']['country']
            print(weather_country,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='℃ ')
            weather_time = weather_json['results'][0]['last_update']
            print(weather_time)
            weather_pressure = weather_json['results'][0]['now']['pressure']
            print(weather_pressure)
            weather_humidity = weather_json['results'][0]['now']['humidity']
            print(weather_humidity)
            # code
            # 1-3 sunny -- 1
            # 4-8 cloudy -- 2
            # 9- overcast -- 3
            # 10-18 rain -- 4
            # 19-25 snow -- 5
            weather_now = int(weather_now)
            display.fill(st7789.BLACK)
            display.fill_rect(12, 10, 220, 5, st7789.RED)
            display.line(12,10,12,220,st7789.RED)
            display.fill_rect(12, 220, 220, 5, st7789.RED)
            display.line(230,10,230,220,st7789.RED)
            if(0 < weather_now <= 3 ):
                weather_now_code = 1 #sunnny
                display_info.lcd_display_image(image_sunny,15,48,48)
                display_info.lcd_display_text16x32("Sunny",20,70)
            elif(weather_now <= 8):
                weather_now_code = 2 #cloudy
                display_info.lcd_display_image(image_cloudy,15,41,58)
                display_info.lcd_display_text16x32("Cloudy",15,70)
            elif(weather_now == 9):
                weather_now_code = 3 #overcast
                display_info.lcd_display_image(image_overcast,15,38,58)
                display_info.lcd_display_text16x32("Overcast",15,70)
            elif(weather_now <= 18):
                weather_now_code = 4 #rain
                display_info.lcd_display_image(image_rain,15,57,58)
                display_info.lcd_display_text16x32("Rain",15,70)
            elif(weather_now <= 25):
                weather_now_code = 5 #snow
                display_info.lcd_display_image(image_snow,15,55,58)
                display_info.lcd_display_text16x32("Snow",15,70)
            else:
               weather_now_code = 0
            print(weather_now_code)
            #位置信息
            display_info.lcd_display_text16x32(weather_location+"  "+weather_country,15,130)
            #温度信息
            display_info.lcd_display_text16x32(weather_temp+" C",15,100)
            display_info.lcd_display_text8x8("o",55,105)
            #时间信息
            display_info.lcd_display_text8x8(weather_time[0:10],115,50)
            #压强信息、相对湿度
            display_info.lcd_display_text16x32(weather_pressure+"mb"+"  "+weather_humidity+"%",15,160)
            #time.sleep(60)
            network_status = 1
            record=0
            break
def initpic():
    
    global record
    display.fill(st7789.BLACK)
    display_info.lcd_display_image(image_cloudy,20,41,58)
    display_info.lcd_display_image(image_snow,85,55,58)
    display_info.lcd_display_image(image_sunny,165,48,48)
    display_info.lcd_display_text16x32("WEATHER REPORT",10,110)
    display_info.lcd_display_text16x32("press A enter",10,180)
    while True:
        if buttonA.value()==0:
            netconnectpic()
            while True:
                getdata()
                record=1
                time.sleep(3)
                display_info.lcd_display_text8x8("long press A to exit",20,195)
                display_info.lcd_display_text8x8("long press B to change",20,210)
                if buttonA.value()==0:
                    break
            break
def endpic():
    display.fill(st7789.BLACK)
    display_info.lcd_display_text16x32("BYE-BYE~",80,120)
    display_info.lcd_display_text8x8("press A to restart",40,180)
    while True:
        if buttonA.value()==0:
            time.sleep(5)
            global record
            record=0
            main()
def netconnectpic():
        display.fill(st7789.BLACK)
        display_info.lcd_display_text16x32("network",10,70)
        display_info.lcd_display_text16x32("connecting...",10,120)

def main():
    initpic()
    endpic()
record=0    
loc=['beijing','shanghai','tianjin','chongqing','shenzhen']
i=0
main()



1.代码解析:在YourWIFE 和 PASSWORD中分别填入自己的wife和密码,以便联网获取信息。在心知天气中获得的信息存储在weather_json中,打开httpget里的链接可以看到传递的信息。

参考链接:

其中your_api_key为自己的密钥。location为所查询城市的天气情况
2.遇到的问题及总结:
(1)在如何切换城市时遇到了困难,因为联网有一段时间的掩饰,所以在联网前或者联网后只按下一次按钮是检测不到的。所以通过while循环的方法,加上if判断,实时检测是否按下B键切换城市。
(2)运行程序时会突然终止报错,经检测发现是网络问题。将设备移动到网络信号好的地方即可。

六.活动总结与未来计划

通过对本项目的学习,我对esp32模块又有了进一步的了解,其联网获取信息的功能锻炼了我的动手能力和编程能力,对嵌入式开发有了新的体会,受益匪浅。未来期望再次参加活动,了解并学习更多的知识,掌握更多的技能,开拓电子芯片在生活中运用的视野,改变思维模式,在专业上有既定的发展方向。

附件下载
main.py
其余文件见百度网盘链接:https://pan.baidu.com/s/16kkiRnqOw8NFMxuFKNwDjQ 提取码:loco
团队介绍
北京邮电大学2020级学生
团队成员
T-&10
北京邮电大学2020级学生
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号