esp32c3 micropython oled实时天气信息

合宙esp32c3单片机实现天气显示
该博客基于合宙esp32c3 micropython框架,利用优化过的ssd1306驱动,在单片机上实现天气显示。从网站获取天气数据,转成json提取有效信息,设置查找树优化结构,根据天气状态显示中文和对应图,还可更改显示城市。

目录

简介

效果展示

代码

main.py

ssd1306.py

font.py

实现思路


简介

合宙esp32c3 micropython框架,只支持128*64 I2C oled

ssd1306驱动我优化过的,与其他的不一样,为避免出错,使用我的驱动

把下面两个py文件放入单片机内,

搜索心知天气,注册账号,获得免费的key

效果展示

代码

main.py

import network
import urequests
from ssd1306 import SSD1306_I2C
from machine import Pin, I2C
import ujson
from font import textc

i2c = I2C(0, scl=Pin(5), sda=Pin(4))
oled = SSD1306_I2C(i2c)

url = 'https://api.seniverse.com/v3/weather/now.json?key=你的密钥&location=guangzhou&language=zh-Hans&unit=c'


class Weather():
    def __init__(self, ssid, password):
        
        wifi=network.WLAN(network.STA_IF)
        wifi.active(True)
        #连接wifi,有一定几率连接失败
        while not wifi.isconnected():
            wifi.connect(ssid,password)
            oled.fill(0)
            oled.text('connecting...',0,0)
            oled.show()
        #更新显示连接wifi信息   
        oled.fill(0)
        oled.text('connect to szsb',0,0)
        oled.show()

        response = urequests.get(url)
        parsed = ujson.loads(response.text)
        weather_info = parsed['results'][0]['now']
        temperature = weather_info['temperature']
        weather_state = weather_info['text']
        #下面两条语句的作用是一样的,二选一,把unicode编码转为中文字符
        # x=eval('u"%s"' % weather_state)
        x = ujson.loads('"%s"' % weather_state)
        oled.text(temperature + '`c', 80, 48)
        textc(oled, '广', 80, 16)
        textc(oled, '州', 96, 16)
        oled.vline(60, 0, 64)
        if len(weather_state) == 2:
            textc(oled, x[0], 16, 48)
            textc(oled, x[1], 32, 48)
            if x[1] == '雨':
                if weather_state == '大雨':
                    max_rainy = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0C, 0x10, 0x10, 0x08, 0x08, 0x10, 0x60, 0x80,
                                 0x80, 0x80,
                                 0x80, 0x60, 0x20, 0x10, 0x10, 0x08, 0x08, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x60, 0x91, 0x8A, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x0A, 0x09,
                                 0x08, 0x08,
                                 0x08, 0x08, 0x09, 0x0A, 0x09, 0x08, 0x08, 0x08, 0x08, 0x09, 0x92, 0x61, 0x00, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0xC0, 0x20, 0x20, 0x26, 0xC9, 0x11, 0x09, 0xC6, 0x20, 0x20, 0x26,
                                 0xC9, 0x11,
                                 0x09, 0xC6, 0x20, 0x20, 0x26, 0xC9, 0x11, 0x09, 0xC6, 0x20, 0x20, 0x20, 0xC0, 0x00,
                                 0x00, 0x00
                                 ]
                    oled.p32(max_rainy, 16, 8)
                elif weather_state == '中雨':
                    mid_rainy = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
                                 0x01, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x08, 0x08, 0x30, 0x40, 0x40, 0x80, 0x00, 0x00,
                                 0x00, 0x80,
                                 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x30, 0x08, 0x08, 0x08, 0x06, 0x01, 0x01, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x60, 0x90, 0x11, 0x12, 0x14, 0x12, 0x11, 0x10, 0x10, 0x10, 0x11, 0x12,
                                 0x14, 0x12,
                                 0x11, 0x10, 0x10, 0x10, 0x11, 0x12, 0x14, 0x12, 0x11, 0x10, 0x10, 0x10, 0x20, 0xC0,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x80, 0x40,
                                 0x40, 0x40,
                                 0x80, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00
                                 ]
                    oled.p32(mid_rainy, 16, 8)
                elif weather_state == '小雨':
                    min_rainy = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
                                 0x01, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x08, 0x08, 0x30, 0x40, 0x40, 0x80, 0x00, 0x00,
                                 0x00, 0x80,
                                 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x30, 0x08, 0x08, 0x08, 0x06, 0x01, 0x01, 0x00,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x60, 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x12,
                                 0x14, 0x12,
                                 0x11, 0x10, 0x10, 0x10, 0x11, 0x12, 0x14, 0x12, 0x11, 0x10, 0x10, 0x10, 0x20, 0xC0,
                                 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
                                 0x40, 0x40,
                                 0x80, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00
                                 ]
                    oled(min_rainy, 16, 8)
            else:
                cloud = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06,
                         0x03, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x06, 0x02, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00,
                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0xC4, 0x44, 0x00, 0x00,
                         0x00, 0x7F, 0x40, 0x40, 0x40, 0x47, 0x47, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x23, 0x63, 0xC3, 0x00,
                         0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF,
                         0x7F, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x07, 0x07, 0xFF, 0x00, 0x30, 0x18, 0x08, 0x00,
                         0x00, 0x00, 0x00, 0xE0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
                         0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00
                         ]
                oled.p32(cloud, 16, 8)
        else:
            textc(oled, x, 24, 48)
            if x == '晴':
                sunny = [
                    0x00, 0x00, 0x00, 0x18, 0x1C, 0x0E, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
                    0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x0E, 0x1C, 0x18, 0x00, 0x00, 0x00,
                    0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x80, 0x80, 0x80, 0x80, 0x83, 0x83,
                    0x83, 0x83, 0x80, 0x80, 0x80, 0x80, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
                    0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x01, 0x01, 0x01, 0x01, 0xC1, 0xC1,
                    0xC1, 0xC1, 0x01, 0x01, 0x01, 0x01, 0x02, 0xFC, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
                    0x00, 0x00, 0x00, 0x18, 0x38, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
                    0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x70, 0x38, 0x18, 0x00, 0x00, 0x00
                ]
                oled.p32(sunny, 16, 8)
            elif x == '阴':
                shadow = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                          0x00,
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                          0x00,
                          0x00, 0x00, 0x01, 0x03, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F,
                          0x0F,
                          0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x01, 0x00,
                          0x00,
                          0x18, 0x7C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                          0xFF,
                          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0x7C,
                          0x18,
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                          0x00,
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                          0x00]
                oled.p32(shadow, 16, 8)
        oled.show()


w = Weather('szsb', '55555555')

ssd1306.py

import framebuf
# 寄存器定义
SET_CONTRAST        = const(0x81)
SET_ENTIRE_ON       = const(0xa4)
SET_NORM_INV        = const(0xa6)
SET_MEM_ADDR        = const(0x20)
SET_COL_ADDR        = const(0x21)
SET_PAGE_ADDR       = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_DISP            = const(0xae)
SET_SEG_REMAP       = const(0xa0)
SET_MUX_RATIO       = const(0xa8)
SET_COM_OUT_DIR     = const(0xc0)
SET_DISP_OFFSET     = const(0xd3)
SET_COM_PIN_CFG     = const(0xda)
SET_DISP_CLK_DIV    = const(0xd5)
SET_PRECHARGE       = const(0xd9)
SET_VCOM_DESEL      = const(0xdb)
SET_CHARGE_PUMP     = const(0x8d)


class SSD1306:
    def __init__(self,external_vcc):
        self.width = 128
        self.height = 64
        self.external_vcc = external_vcc
        self.pages = 8
        self.init_display()

    def init_display(self):
        for cmd in (
            SET_DISP | 0x00, #熄屏
            SET_MEM_ADDR, 0x00, #水平寻址
            SET_DISP_START_LINE | 0x00,#显示起始行地址
            SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
            SET_MUX_RATIO, 63,
            SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
            SET_DISP_OFFSET, 0x00,
            SET_COM_PIN_CFG, 0x12,
            # timing and driving scheme
            SET_DISP_CLK_DIV, 0x80,
            SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
            SET_VCOM_DESEL, 0x30, # 0.83*Vcc
            # display
            SET_CONTRAST, 0xff, # maximum
            SET_ENTIRE_ON, # output follows RAM contents
            SET_NORM_INV, # not inverted
            # charge pump
            SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
            0x2e, # 禁止滚动
            0xae | 0x01): #开屏
            self.write_cmd(cmd)
        self.fill(0)
        self.show()
        
    def v_scroll(self, d=1): 
        self.write_cmd(0x2e) # 关闭滚动
        if d:
            self.write_cmd(0x26) # 向左
            self.write_cmd(0x00)
            self.write_cmd(0x07) # 起始页
            self.write_cmd(0x00) # 滚动帧率
            self.write_cmd(0x00) # 结束页
        else:
            self.write_cmd(0x27) # 向左
            self.write_cmd(0x00)
            self.write_cmd(0x00) # 起始页
            self.write_cmd(0x00) # 滚动帧率
            self.write_cmd(0x07) # 结束页
            
        self.write_cmd(0x00)
        self.write_cmd(0xff)
        self.write_cmd(0x2f) # 开启滚动
    
    def poweroff(self):
        self.write_cmd(const(0xae) | 0x00)#熄屏

    def contrast(self, contrast):
        self.write_cmd(SET_CONTRAST)
        self.write_cmd(contrast)

    def invert(self, invert):
        self.write_cmd(SET_NORM_INV | (invert & 1))

    def show(self):
        self.write_cmd(SET_COL_ADDR)
        self.write_cmd(0)
        self.write_cmd(127)
        self.write_cmd(SET_PAGE_ADDR)
        self.write_cmd(0)
        self.write_cmd(63)
        self.write_framebuf()

    def fill(self, c):
        self.framebuf.fill(c)

    def pixel(self, x, y, c):
        self.framebuf.pixel(x, y, c)

    def text(self, string, x, y, c=1):
        self.framebuf.text(string, x, y, c)

    def hline(self,x,y,w,c=1):
        self.framebuf.hline(x,y,w,c)
    
    def vline(self,x,y,h,c=1):
        self.framebuf.vline(x,y,h,c)
        
    def line(self,x1,y1,x2,y2,c=1):
        self.framebuf.line(x1,y1,x2,y2,c)
        
    def rect(self,x,y,w,h,c=1,f=False):
        self.framebuf.rect(x,y,w,h,c,f)
        
    def ellipse(self,x,y,xr,yr,c,f=False,m=15):
        self.framebuf.ellipse(x,y,xr,yr,c,f,m)
        
    def cube(self,x,y,l):
        self.rect(x,y,l,l)
        self.rect(x+int(0.5*l),int(y-0.5*l),l,l)
        self.line(x,y,int(x+0.5*l),int(y-0.5*l),1)
        self.line(x+l,y,int(x+1.5*l),int(y-0.5*l),1)
        self.line(x,y+l,int(x+0.5*l),int(y+0.5*l),1)
        self.line(x+l,y+l,int(x+1.5*l),int(y+0.5*l),1)
    
    def p8(self,page,x,y):
        for e in range(8):
            byte=bin(page[e]).replace('0b','')
            while len(byte)<8:
                byte='0'+byte
            for i in range(8):
                if byte[i]=='1':
                    self.pixel(x+e,y+i,int(byte[i]))
    
    def p16(self,page,x,y):
        for e in range(32):
            byte=bin(page[e]).replace('0b','')
            while len(byte)<8:
                byte='0'+byte
            for i in range(8):
                if byte[i] and e<16:
                    self.pixel(x+e,y+i,int(byte[i]))
                elif byte[i] and e>=16:
                    self.pixel(x-16+e,y+8+i,int(byte[i]))

    def p32(self,page,x,y):
        for e in range(128):
            byte=bin(page[e]).replace('0b','')
            while len(byte)<8:
                byte='0'+byte
            for i in range(8):
                if byte[i] and e<32:
                    self.pixel(x+e,y+i,int(byte[i]))
                elif byte[i] and 32<=e<64:
                    self.pixel(x+e-32,y+8+i,int(byte[i]))
                elif byte[i] and 64<=e<96:
                    self.pixel(x+e-64,y+16+i,int(byte[i]))
                elif byte[i] and 96<=e<128:
                    self.pixel(x+e-96,y+24+i,int(byte[i]))

class SSD1306_I2C(SSD1306):
    def __init__(self,i2c, addr=0x3c, external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.temp = bytearray(2)
        # buffer需要8 * 128的显示字节加1字节命令
        self.buffer = bytearray(8 * 128 + 1)
        self.buffer[0] = 0x40  # Co=0, D/C=1
        self.framebuf = framebuf.FrameBuffer1(memoryview(self.buffer)[1:], 128, 64)
        super().__init__(external_vcc)
    def write_cmd(self, cmd):
        self.temp[0] = 0x80 # Co=1, D/C#=0
        self.temp[1] = cmd
        self.i2c.writeto(self.addr, self.temp)

    def write_framebuf(self):
        self.i2c.writeto(self.addr, self.buffer)

        

font.py

def u6674(oled,x,y):     
    oled.rect(x+1,y+2,4,11)
    oled.hline(x+2,y+7,2)
    oled.hline(x+6,y+2,9)
    oled.hline(x+7,y+4,7)
    oled.hline(x+6,y+6,9)
    oled.vline(x+10,y,7)
    oled.rect(x+7,y+8,7,8)
    oled.rect(x+7,y+10,7,3)
    oled.hline(x+8,y+15,4,0)
def u591a(oled,x,y):
    def duo1(x,y):
        oled.line(x+3,y+4,x+7,y)
        oled.hline(x+6,y+2,6)
        oled.line(x+4,y+3,x+6,y+5)
        oled.line(x+11,y+2,x+4,y+9)
    duo1(x,y)
    x+=3
    y+=6
    duo1(x,y)
def u9634(oled,x,y):
    oled.hline(x+2,y+1,11)
    oled.hline(x,y+6,15)
    oled.line(x+7,y+7,x+1,y+13)
    oled.hline(x+2,y+13,10)
    oled.line(x+9,y+10,x+13,y+14)
def u4e91(oled,x,y):
    oled.rect(x+2,y+4,11,7)
    oled.vline(x+7,y,16)
def u5927(oled,x,y):
    oled.hline(x+1,y+5,14)
    oled.vline(x+7,y+1,9)
    oled.line(x+6,y+10,x+1,y+15)
    oled.line(x+8,y+10,x+13,y+15)
    oled.pixel(x+14,y+15,1)
def u5c0f(oled,x,y):
    oled.vline(x+7,y+1,13)
    oled.line(x+5,y+6,x+1,y+10)
    oled.line(x+9,y+4,x+13,y+8)
    oled.line(x+6,y+14,x+5,y+13)
def u96e8(oled,x,y):
    oled.hline(x+1,y+1,14)
    oled.vline(x+7,y+2,13)
    oled.rect(x+1,y+5,13,11)
    oled.hline(x+2,y+15,9,0)
    oled.line(x+4,y+8,x+5,y+9)
    oled.line(x+4,y+11,x+5,y+12)
    oled.line(x+9,y+8,x+10,y+9)
    oled.line(x+9,y+11,x+10,y+12)
def u9634(oled,x,y):
    oled.vline(x+1,y+1,15)
    oled.hline(x+2,y+1,4)
    oled.line(x+5,y+2,x+2,y+5)
    oled.line(x+5,y+8,x+2,y+5)
    oled.hline(x+2,y+9,4)
    oled.vline(x+7,y+1,12)
    oled.line(x+6,y+12,x+4,y+15)
    oled.hline(x+8,y+1,5)
    oled.vline(x+13,y+1,14)
    oled.line(x+12,y+15,x+11,y+14)
    oled.rect(x+7,y+5,7,4)
def u5e7f(oled,x,y):
    oled.line(x+7,y+1,x+8,y+2)
    oled.line(x+1,y+14,x,y+15)
    oled.hline(x+2,y+3,12)
    oled.vline(x+2,y+4,10)
def u5dde(oled,x,y):
    oled.vline(x+1,y+5,3)
    oled.vline(x+3,y+1,12)
    oled.vline(x+6,y+5,3)
    oled.vline(x+8,y+2,12)
    oled.vline(x+10,y+5,3)
    oled.vline(x+12,y+1,14)
    oled.line(x+2,y+13,x+1,y+14)
def u4e0a(oled,x,y):
    oled.vline(x+6,y+1,14)
    oled.hline(x+7,y+6,6)
    oled.hline(x+1,y+14,14)
def u6d77(oled,x,y):
    oled.line(x+2,y+1,x+3,y+2)
    oled.line(x+1,y+5,x+2,y+6)
    oled.line(x+2,y+13,x+4,y+11)
    oled.line(x+9,y,x+5,y+4)
    oled.hline(x+7,y+2,7)
    oled.rect(x+7,y+4,6,9,1,True)
    oled.hline(x+5,y+8,10)
    oled.rect(x+8,y+5,4,3,0)
    oled.rect(x+8,y+9,4,3,0)
    oled.pixel(x+13,y+12,1)
    oled.vline(x+12,y+13,2)
#该字典存储着一些中文的函数指针
cc_dict={'6674':u6674,'591a':u591a,'u9634':u9634,'4e91':u4e91,'5927':u5927,'u5c0f':u5c0f,'96e8':u96e8,'9634':u9634,'5e7f':u5e7f,'5dde':u5dde,'4e0a':u4e0a,'6d77':u6d77}
#显示中文的函数,接受oled对象,要显示的中文,位置
def textc(oled,c,x,y):
    c=hex(ord(c)).replace('0x','')
    cc_dict[c](oled,x,y)
   

实现思路

从网站获取天气数据,根据文本的字典结构,为了方便,转成json进行有效信息的提取。

获取的天气状态一共有小雨,中雨,大雨,阴,晴,多云

按照天气状态分为两组,两个字的和一个字的

设置了一个查找树,对两个字的进行快速查找,优化if结构

如果选择好了天气状态,就在特定位置显示中文(16*16)和天气状态对应的图(32*32)

剩下的就是显示城市和温度了

我的代码默认是广州,你也可以更改其他城市

在font.py中,我以笔画的方式存储了天气状态对应的中文,还有‘广州’对应的中文,相当于自己建立了一个小字库,当然也可以更改为其他方式显示中文,如取模,烧写特殊固件

<think>我们已知用户使用的是天问ESP32C3-PRO开发板,需要驱动OLED显示屏(型号未明确,但根据常见情况可能是SSD1306或SH1106驱动的128x64 OLED)。根据用户提供的引用,我们有两种可能的驱动方式:I2C和SPI。由于用户没有明确说明使用的OLED接口,我们将提供两种方式的示例代码(I2C和SPI),并说明如何选择。 注意:用户引用的两篇资料中,第一篇是使用SH1106驱动的OLED(与SSD1306不兼容),第二篇是使用SPI接口的SSD1306。因此,我们需要先确定用户OLED的驱动芯片和接口方式。 步骤: 1. 确认OLED显示屏的驱动芯片(SSD1306或SH1106)和通信接口(I2C或SPI)。 通常,OLED有4个引脚(I2C)或7个引脚(SPI)。常见4线I2C接口:GND、VCC、SCL、SDA;SPI接口:GND、VCC、D0(SCK)、D1(MOSI)、RES、DC、CS。 2. 根据开发板的引脚图,将OLED正确连接到天问ESP32C3-PRO开发板上。天问ESP32C3-PRO开发板的引脚图需要参考其官方文档。但我们可以提供常见的引脚连接方式: - I2C连接: SCL -> GPIO5(或其他I2C时钟引脚) SDA -> GPIO4(或其他I2C数据引脚) - SPI连接(参考引用[2]中的连接方式,但注意ESP32C3的引脚可能与示例中的ESP32-C3不同): SCK (D0) -> GPIO6 MOSI (D1) -> GPIO7 RES -> GPIO5 DC -> GPIO4 CS -> GPIO10(如果使用) 3. 在MicroPython中,我们需要使用相应的库来驱动OLED。对于SSD1306,有现成的库;对于SH1106,则需要使用特定的驱动(如引用[1]中提到的sh1106.py)。 4. 编写代码。 由于用户没有明确说明,我们将分别提供I2C和SPI两种连接方式的示例代码(假设为SSD1306驱动)。如果用户使用的是SH1106,则需要替换驱动库。 情况1:使用I2C接口(假设OLED驱动为SSD1306) 情况2:使用SPI接口(假设OLED驱动为SSD1306) 注意:天问ESP32C3-PRO开发板的MicroPython固件需要支持I2C和SPI。 示例代码1:I2C连接 ```python from machine import Pin, SoftI2C import ssd1306 # 初始化I2C,使用软件I2C,指定SCL和SDA引脚 i2c = SoftI2C(scl=Pin(5), sda=Pin(4)) # 假设SCL接GPIO5,SDA接GPIO4 # 创建OLED对象,128x64分辨率,I2C地址一般为0x3C oled = ssd1306.SSD1306_I2C(128, 64, i2c, 0x3C) # 清屏 oled.fill(0) # 在指定位置显示文本 oled.text("Hello, World!", 0, 0) oled.text("Twen-ASR", 0, 16) oled.text("MicroPython", 0, 32) oled.text("OLED Test", 0, 48) # 显示内容 oled.show() ``` 示例代码2:SPI连接(参考引用[2]) ```python from machine import Pin, SoftSPI from ssd1306 import SSD1306_SPI # 初始化SPI spi = SoftSPI(baudrate=80000000, polarity=0, phase=0, sck=Pin(6), mosi=Pin(7), miso=Pin(8)) # 注意:miso可以不用,但这里指定为GPIO8 # 初始化OLED,参数:宽度、高度、SPI对象、DC引脚、RES引脚、CS引脚 # 根据引用[2],DC=4, RES=5, CS=10(如果CS引脚未使用,可以不接,但代码中需要设置为None,并在初始化时省略,但SSD1306_SPI需要CS引脚) oled = SSD1306_SPI(128, 64, spi, dc=Pin(4), res=Pin(5), cs=Pin(10)) # 清屏 oled.fill(0) # 显示文本 oled.text("Line1", 0, 0) oled.text("Line2", 0, 16) oled.text("Line3", 0, 32) oled.text("Line4", 0, 48) # 显示 oled.show() ``` 如果用户使用的是SH1106驱动的OLED,则需要先下载sh1106.py驱动文件,并将其上传到开发板。然后使用如下代码(以I2C为例): ```python from machine import Pin, SoftI2C import sh1106 # 确保sh1106.py文件已上传到开发板 i2c = SoftI2C(scl=Pin(5), sda=Pin(4)) oled = sh1106.SH1106_I2C(128, 64, i2c, Pin(16), 0x3C) # 注意:SH1106可能需要RESET引脚,这里假设RESET接GPIO16,如果没有接,可以省略 oled.fill(0) oled.text(&#39;SH1106 Test&#39;, 0, 0, 1) oled.show() ``` 注意事项: - 引脚连接需要根据实际硬件调整。 - 如果使用硬件I2C/SPI,可以改用`machine.I2C`或`machine.SPI`。 - 如果显示不正常(如花屏),请检查驱动芯片类型(SSD1306或SH1106)和连接方式。 由于用户使用的是天问ESP32C3-PRO开发板,其引脚布局可能与示例不同,请参考开发板原理图确认可用引脚。 如果用户没有提供具体的OLED型号和连接方式,建议先尝试I2C连接,因为I2C接线简单(只需4根线)。 最后,用户需要将代码保存到开发板上(如main.py),然后重启运行。 相关问题: 1. 如何将MicroPython固件烧录到天问ESP32C3-PRO开发板? 2. 如何将sh1106.py或ssd1306.py驱动文件上传到MicroPython设备? 3. 如何确定OLED显示屏的I2C地址? 4. 如何解决OLED显示花屏的问题?</think>### MicroPython 天问 ESP32C3-PRO 驱动 OLED 教程 #### 硬件连接 根据引用资料[^1][^2],OLEDESP32C3-PRO 的推荐连接方式如下(以 SH1106/SSD1306 驱动芯片为例): | OLED 引脚 | ESP32C3-PRO GPIO | 功能说明 | |-----------|------------------|----------| | VCC | 3.3V | 电源正极 | | GND | GND | 电源地 | | SCL | GPIO5 | 时钟线 | | SDA | GPIO4 | 数据线 | | RES | GPIO6 | 复位引脚 | | DC | GPIO7 | 数据/命令 | | CS | GPIO10 | 片选引脚 | > **注意**:实际连接需参考 OLED 模块说明书,I2C 接口只需连接 SDA/SCL/VCC/GND 四线 #### 步骤 1:准备驱动文件 1. 下载 OLED 驱动库(根据芯片型号选择): - [SH1106 驱动文件](https://github.com/robert-hh/SH1106) - [SSD1306 驱动文件](https://github.com/stlehmann/micropython-ssd1306) 2. 使用 Thonny IDE 将驱动文件上传到开发板: ```python # 保存为 sh1106.py 或 ssd1306.py ``` #### 步骤 2:I2C 接口示例代码 ```python from machine import Pin, SoftI2C import sh1106 # 或 import ssd1306 # 初始化 I2C (GPIO4=SDA, GPIO5=SCL) i2c = SoftI2C(sda=Pin(4), scl=Pin(5), freq=400000) # 初始化 OLED (SH1106 示例) oled = sh1106.SH1106_I2C(128, 64, i2c, None, 0x3C) # 清屏并显示文本 oled.fill(0) # 清屏(0=黑色,1=白色) oled.text("Twen-ASR", 0, 0) oled.text("ESP32-C3 PRO", 0, 16) oled.text("OLED Test", 0, 32) oled.show() ``` #### 步骤 3:SPI 接口示例代码 ```python from machine import Pin, SoftSPI import ssd1306 # 初始化 SPI (GPIO7=MOSI, GPIO6=SCK) spi = SoftSPI(baudrate=8000000, mosi=Pin(7), sck=Pin(6)) # 初始化 OLED (SSD1306 示例) oled = ssd1306.SSD1306_SPI(128, 64, spi, dc=Pin(5), # DC 引脚 res=Pin(4), # RES 引脚 cs=Pin(10)) # CS 引脚 # 显示图形内容 oled.fill(0) oled.rect(0, 0, 128, 64, 1) # 绘制边框 oled.text("SPI Mode", 20, 25) oled.show() ``` #### 常见问题解决 1. **花屏问题**: - 确认驱动芯片型号(SH1106 与 SSD1306 不兼容) - 检查复位引脚是否接好 - 尝试降低 SPI 波特率(如改为 `baudrate=1000000`) 2. **不显示内容**: ```python # 添加硬件复位代码 rst = Pin(6, Pin.OUT) rst.value(0) rst.value(1) ``` 3. **I2C 地址检测**: ```python import machine i2c = machine.SoftI2C(scl=machine.Pin(5), sda=machine.Pin(4)) print("I2C devices:", i2c.scan()) # 通常为 0x3C 或 0x3D ``` > 参考接线图: > ``` > OLED ESP32C3-PRO > ------------------- > VCC → 3.3V > GND → GND > SCL → GPIO5 > SDA → GPIO4 > RES → GPIO6 (可选) > DC → GPIO7 (SPI必需) > CS → GPIO10 (SPI必需) > ``` [^1]: SH1106 驱动接线参考 [^2]: SPI 模式示例代码基础
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值