1、准备条件
(1)EPS32开发板
(2)ssd1036 0.96寸IIC OLED显示屏
2、显示天气时钟部分,感兴趣的同学请参考之前的博客
3、显示太空人图片部分
1)常用的方法是使用framebuf模块,然后使用oled.blit函数即可
imagebuf=framebuf.FrameBuffer(bytearray(b’‘)’),84,64,framebuf.MONO_HLSB)
oled.blit(imagebuf,0,0)
oled.show()
2)怎么把图片转成PBM格式
transpic.py
from PIL import Image
import os
file_dir=os.getcwd()
filelist=[]
buflist=[]
#转换图像文件为pbm
for root, dirs, files in os.walk(file_dir):
for filename in files:
try:
print(filename)
im=Image.open(filename)
im=im.convert('1')
im.save(filename[0:filename.find('.')]+'.pbm')
except:
pass
#读出位图数据
for root, dirs, files in os.walk(file_dir):
pbmfile= [f for f in files if f.endswith(".pbm")]
for filename in pbmfile:
with open(filename,'rb') as f:
f.readline()
width,height=[int(v) for v in f.readline().split()]
data=bytearray(f.read())
#print(data)
#print(width,height)
f.close()
logobuf=filename[:-4]+'=framebuf.FrameBuffer('+str(data)+','+str(width)+','+str(height)+',framebuf.MONO_HLSB)'
buflist.append(logobuf)
print("buflist:", buflist)
for buf in buflist:
print("buf:", buf)
savefile = buf[0]+".txt"
with open(savefile, 'w+') as f:
f.write(buf)
f.write('\r')
代码搬运来自:(我修改了最后的写txt部分,实际上我们拿到buflist就行了,对应pmb格式的16进制数组)
三十岁开始学编程的大叔 / image to pbm · GitCode
代码目录和生成结果:
图片素材:(我是从小红书找的,有很多动态图片素材,自己截屏然后裁减即可)
jpg格式,驱动程序只能识别pbm格式的16进制的数组流
4、最后的代码:
main.py
from lib import urequests
from machine import Pin,I2C
from machine import SoftI2C
from machine import Timer
from machine import RTC
from ssd1306 import SSD1306_I2C #从ssd1306模块中导入SSD1306_I2C子模块
import time,ntptime,network
import ujson
import sys
import framebuf
#创建RTC对象
rtc=RTC()
#创建软件I2C对象
i2c = SoftI2C(sda=Pin(23), scl=Pin(18))
#创建OLED对象,OLED分辨率、I2C接口
oled = SSD1306_I2C(128, 64, i2c)
#定义LED控制对象
led1=Pin(15,Pin.OUT)
led1.value(0)
# 心知天气API申请:https://seniverse.yuque.com
# API_KEY = 'S9hoa4Wza9Hcs2uX_'
#接口;https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c
# LOCATION = 'zhuzhou'
# URL = 'https://api.seniverse.com/v3/weather/now.json'
# UNIT = 'c'
# LANGUAGE = 'zh-Hans'
#路由器WIFI账号和密码
ssid="FAST_0DB8"
password="xxxxxxxxx"
#4张太空人图片pbm格式
out1=framebuf.FrameBuffer(bytearray(b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\x80\xa0\xff\xff\xff\xff\xff\xfe\x100?\xff\xff\xff\xff\xf8\xe7`\x1f\xff\xff\xff\xff\xf1\xff\xc0\x07\xfd\xff\xff\xff\xe7\xff\xc0\x07\xf8\xff\xff\xff\xcf\xff\x80\x01\xfd\xff\xff\xff\xcf\xff\x80\x01\xff\xff\xff\xff\x9f\xff\x80\x00\xff\xff\xff\xff?\xff\x80\x00\xff\xff\xff\xff?\xff\x00\x00\x7f\xff\xff\xff\x7f\xff\x80\x00\x7f\xff\xff\xfe\x7f\xff\x00\x00?\xff\x7f\xfe\x7f\xff\x80\x00?\xff\'\xfe\xff\xff\x80\x00?\xff\x8f\xbc\xff\xff\x80\x00?\xff\x1f>\xff\xff\xc0\x00?\xfeO\xbc\xff\xff\xc0\x00\x1f\xff\xef<\xff\xff\xe0\x00?\xff\xff\xbe\xff\xff\xe0\x00?\xff\xff\xbc\xff\xff\xf0\x00?\xff\xff\x9e\x7f\xff\xf8\x00?\xff\xff\x9e\x7f\xff\xfe\x00?\xfd\xff\xde\x7f\xff\xff\x00\x7f\xfe\xff\xdf\x7f\xff\xff\xe0\x7f\xfe\x7f\xcf?\xff\xff\xfe\x7f\xff?\xef\x9f\xff\xff\xfc\xff\xff\xbf\xe7\x9f\xff\xff\xfc\xff\xff\x9d\xf7\xce\xff\xff\xf8?\xff\xc8\xf3\xe6\xff\xff\xf3\x9f\xff\xec\xfb\xe2?\xff\xe7\xcf\xff\xe5\xf9\xf9\x8f\xff\xcf\xe7\xff\xf3\xfc\xfcG\xff\x1f\xf1\xff\xf9\xfe\xfe\x17\xf8\x7f\xfd\xff\xfd\xfe\x7f\x80\x01\xff\xfc\xff\xfc\xff?\xf0\x0f\xff\xfe\x7f\xfe\xff\x9f\xff%\xef\xff?\xff\x7f\xff\xfeu\xe7\xf1\xbf\xff?\xff\xfc\xf0\xf3\xe4\x9f\xff\xbf\xff\xfe\xf8\xf9\xce_\xff?\xff\xfe|}\xefO\xff\x7f\xff\xff||\xe6\xdf\xff\xff\xff\xff>>p\x9f\xff\xff\xff\xff\xbf\x1f;\xdf\xff\xff\xff\xff\x9f\x1e?\xcf\xff\xff\xff\xff\xcf\x88\x9f\xef\xff\xff\xff\xff\xef\xc3\xcf\xef\xff\xff\xff\xff\xe7\xc7\xef\xe7\xef\xff\xff\xff\xf3\xe3\xef\xe7\xe7\xff\xff\xff\xfb\xe1\xcf\xf7\xf7\xff\xff\xff\xf9\xe4\x1f\xf7\xfb\xff\xff\xff\xfc\xcb\xff\xf7\xf9\xe7\xff\xff\xfe\x1c\xff\xe1\xfd\xf3\xff\xff\xff~?\xcc\xff\xef\xff\xff\xff\xff\x9f\x1e\xff\xfb\xff\xff\xff\xff\xc0|\xff\xff\xff\xff\xff\xff\xf4\xf9\xff\xef\xff\xff\xff\xff\xfd\xf3\xff\xe7\xff\xff\xff\xff\xfc\xc7\xff\xff\xff\xff\xff\xff\xfe\x1f\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff"),64,64,framebuf.MONO_HLSB)
out2=framebuf.FrameBuffer(bytearray(b"\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x1f\xff\xff\xff\xff\xff\xff\x80A\xff\xff\xff\xff\xff\xfe\x11\x14\xff\xff\xfe\xff\xff\xfc\xc5\x06?\xff\xfc\xff\xff\xf9\xdf\xf3\x9f\xff\xff\xff\xff\xf3\xff\xff\xcf\xff\xff\xff\xff\xe7\xfc\x17\xe7\xff\xff\xff\xff\xcf\xe0\x01\xf7\xff\xff\xff\xff\xcf\xc0\x00\xf3\xff\xff\xff\xff\x9f\x80\x009\xff\xff\xff\xf7\xbf\x00\x00\x19\xff\xff\xff\xf7>\x00\x00\x1d\xff\xff\xff\xe7<\x00\x00\x0c\xff\xff\xff\xef|\x00\x00\x0c\xff\xff\xff\xee|\x00\x00\x06\xff\xf7\xff\xcfx\x00\x00\x06\x7f\xf3\xff\xcex\x00\x00\x02\xff\xff\xff\xdex\x00\x00\x06\x7f\xff\xff\xcep\x00\x00\x02\xff\xff\xff\xdfx\x00\x00\x02\x7f\xff\xff\xcex\x00\x00\x06\xff\xff\xe7\xefx\x00\x00\x00\xff\xff\xe7\xef8\x00\x00\x04\xff\xff\xff\xe78\x00\x00\x04\xff\xff\xff\xf7\xbc\x00\x00\x00\x7f\xff\xff\xf3\x9c\x00\x00\x0b\x9f\xff\xff\xf9\xce\x00\x00\x03\xc7\xff\xff\xfd\xce\x00\x00\x17\xf3\xff\xff\xfc\xe7\x00\x00\x07y\xdf\xff\xfes\x80\x00O\x1c\xcf\xff\xffy\xc0\x00\x1f\xceo\xff\xff<x\x04\x7f\xe7\'\xff\xff\x9f\x1e\xa0\xff\xf7\x13\xff\xff\xdf\x80\x83\xff\xfa[\xff\xff\xcf\xf0\x1f\xff\xf8\xe9\xff\xff\xe7\xff\x7f\xff\xed\xe4\xff\xff\xf7\xff?\xff\xc2\xee\xff\xff\xf3\xff\xb7\xff\x99N\x7f\xff\xf9\xff3\xff\xbd\x1f?\xcf\xfd\xff\xb7\xff\x99?\xbf\x97\xfc\xff\xbb\xff\xc3?\x9f\xb3\xfe\xff\x99\xe7\xee?\xcf\xbb\xff\xff\xdd\xc1\xfc\xdf\xe7\x97\xff\xff\xdc\x9d\xf9\xdf\xf7\xef\xff\xff\xce\xdd\xff\xcb\xff\xff\xff\xff\xeeY\xff\xdb\xff\xff\xff\xff\xe0C\xff\xe9\xff\xff\xff\xff\xf3\xbe\xff\xcc\xff\xff\xff\xff\xf7\x98\xf3\xee\xff\xff\xff\xff\xf3\x83\xf3\xc2\x7f\xff\xff\xff\xf87\xf9\x8b?\xff\xff\xff\xfds\xfc=\xbf\xff\xff\xff\xff\xd8\xfdy\xff\xff\xff\xff\xff\xceps\xff\xff\xff\xff\xff\xe7\x02\x07\xff\xff\xff\xff\xff\xf7\xcf<\xff\xff\xff\xff\xff\xf3\xde~\x7f\xff\xff\xff\xff\xf9\xcc\xff\x7f\xff\xff\xff\xff\xfd\xe1\xff?\xf3\xff\xff\xff\xfd\xf7\xff\xff\xf3\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"),64,64,framebuf.MONO_HLSB)
out3=framebuf.FrameBuffer(bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff/\xff\xff\xff\xff\xff\xff\xf8\x00\xff\xff\xff\xff\xff\xff\xe1\xf8?\xff\xff\xff\xff\xff\x8f\xff\x9f\xff\xff\xff\xff\xff?\xff\xc7\xff\xff\xff\xff\xfe\x7f\xff\xe7\xfc\xff\xff\xff\xfc\xff\xff\xf3\xfc\xff\xff\xff\xfd\xff\xff\xe9\xff\xff\xe7\xff\xf9\xff\xff\xe4\xff\xff\xef\xff\xf3\xff\xff\xf2\xff\xff\xff\xff\xf2\xff\xff\xfa\x7f\xff\xff\xff\xf1\xff\xff\xf9y\xff\xff\xff\xe1\xff\xff\xfd=\xff\xff\xff\xe3\xff\xfd\xfc~\xff\xff\xff\xeb\xff\xff\xfc\xbe\x7f\xff\xff\xcb\xff\xff\xfe\xbf\x7f\xff\xff\xcb\xff\xff\xff\x9f?\xff\xff\xe0?\xff\xff\xbf\x9f\xff\xff\xc0\x1f\xff\xff\xbf\xdf\xff\xff\xc0\x07\xff\xff\x9f\xcf\xfd\xff\xe0\x03\xff\xff\xbf\xef\xfe\xff\xc0\x01\xff\xff?\xe7\xfe\xff\xe0\x01\xff\xff?\xf3\xfc\xff\xe0\x00\xff\xffg\xfb\xfd\xfc\xe0\x00\x7f\xff\x07\xf9\xff\xfc\xf0\x00\x7f\xfe;\xfc\xff\xfe\xf0\x00?\xfey\xfe\xff\xfep\x00?\xfc\xfc\xfe\x7f\xfex\x00?\xfc\xfe\xff\x7f\xff|\x00?\xf8\xfe\x7f?\xff<\x00?\xf3\x7f?\x9f\xff\x9e\x00\x1f\xe7?\xbf\xdf\xff\xdf\x00?\xc7\xbf\x9f\xcf\xff\xcf\xc0\x1f\x19\x9f\xcf\xff\xff\xef\xe08=\xcf\xef\xff\xe7\xe7\xf8\x01\xfc\xef\xf7\xff\xcb\xf3\xffI\xfew\xf3\xff\xbb\xfb\xff\xfd\xff3\xf3\xff\xd9\xf9\xff\xfd\xe7\xb9\xe7\xff\xcb\xfd\xff\xfc\xf7\x9d\xcf\xff\xe7\xfc\xff\xfd\xf3\xcc\x9f\xff\xff\xfe\x7f\xfe\xfb\xee?\xff\xff\xff\x7f\xfe\xf9\xc7\xbf\xff\xff\xff?\xfe}\x97\x1f\xff\xff\xff\x9f\xfft;_\xff\xff\xff\xdf\xff {\x1f\xff\xff\xff\xcf\xff\x8cy\x8f\xff\xff\xff\xef\xff\x9e\xbb\xaf\xff\xff?\xe7\xff\xcd\x93\x8f\xff\xff\x1f\xf3\xff\xc9\xc7\xcf\xff\xfe\xef\xfb\xff\xe3\xff\xcf\xff\xfe\xef\xfb\xff\xf8\xff\xc1\xff\xfe\xcf\xff\xff\xfe\x7f\xc4\xff\xff\x1f\xff\xff\xff?\x82\xff\xff\xff\xff\xff\xff\x8f8\xff\xff\xff\xff\xff\xff\xe6y\xff\xff\xff\xff\xff\xff\xf0\xf3\xff\xff\xff\xff\xff\xff\xf9\xe7\xff\xff\xff\xff\xff\xff\xfd\xcf\xff\xff\xff\xff\xff\xff\xfd\x1f\xff\xff\xff\xff\xff\xff\xfc\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'),64,64,framebuf.MONO_HLSB)
out4=framebuf.FrameBuffer(bytearray(b"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf1\xfb\xff\xff\xff\xff\xff\xff\xf8q\xf9\xff\xff\xff\xff\xff\xff\x19\xf9\xff\xff\xff\xff\xff\xff\xcf\xfc\xff\xff\xff\xff\xe0\x7f\xe7\xff\xff\xff\xff\xff\x02\x07\xf3\xff\xff\xff\xff\xfc?\xe1\xf9\xff\xff\xff\xff\xf1\xff\xfc}\xff\xff\xff\xff\xe7\xff\xe3<\xff\xfc\x7f\xff\xcf\xff\xf8\x9e\x7f\xf9\xbf\xff\x9f\xff\xfc\xcf?\xfb\xbf\xff/\xff\xff\'\xbf\xfc?\xff\x0f\xff\xff\x97\x9f\xfe\xff\xfe_\xff\xff\x93\xcf\xff\xff\xfe\x1f\xff\xff\xfb\xe7\xff\xff\xfc\xbf\xff\xfd\xf9\xf7\xff\xff\xfc\xff\xff\xfc\xf9\xf3\xff\xff\xfd\xff\xff\xff\xfd\xf9\xff\xff\xf9\xff\xff\xff\xfc\xff\xfc\x7f\xf9\xff\xff\xff\xfc\xff\xfe\xff\xf9\xff\xff\xff\xfc\xff\xff\xff\xfd\xff\xff\xff\xfd\xff\xff\xff\xf9\xff\xff\xff\xfc\xff\xff\xff\xfd\xff\xff\xff\xfd\xff\xff\xff\xfc\xff\xff\xff\xf9\xff\xff\xff\xfc\xff\xff\xff\xf9\xff\xff\xff\xfc\xff\xff\xff\xf9\xff\xff\xff\xfe\x7f\xff\xff\xf0\x7f\xff\x9f\xff\x7f\xff\xff\xf3\x1f\xff\xdf\xff?\xff\xff\xc1\xcf\xff\xff\xff\x9f\xff\xff\x9d\xe3\xff\xff\xff\xcf\xff\xfe>y\xff\xff\xff\xe7\xff\xfc\xfe<\xff\xff\xff\xf1\xff\xf1\xff\x1e\x7f\xff\xff\xf8\x7f\xe7\xff\x8f?\xff\xff\xfe\n\x8f\xff\xc6_\xff\xff\xff\xc0\x1f\xff\xc0\xcf\xff\xff\xff\xfe\x9f\xff\xe9\xef\xff\xff\xff\xfe\xdf\xff\xf5\xef\xff\xff\xff\xfe\xef\xff\xf0\x8f\xff\xff\xff\xfeg\xff\xfa?\xff\xff\xff\xfec\xff\xf9\x7f\xff\xff\xff\xffs\xff\xf2?\xff\xff\xff\xffq\xff\xcc\xbf\xff\xff\xff\xff8\xff\x99\x9f\xff\xff\xff\xff\xb8~7\xdf\xff\xff\xff\xff\x9d|\xff\xdf\xff?\xff\xff\xd8\xb1\xff\xdf\xff\xbf\xff\xff\xc2G\xff\xcf\xff\xff\xff\xbf\xcf8\xef\xdf\xff\xff\xff\x9f\xef\x03\xe7\xc7\xbf\xff\xff\xcf\xf3O\xf3\x83\x9f\xff\xff\xcf\xf8g\xf89\xdf\xff\xff\xe7\xff\xf3\xf8{\xcf\xff\xc7\xf3\xff\xfc\xf2\xe3\xff\xff\xd3\xfb\xff\xfe\x04\x0f\xff\xff\x99\xf9\xff\xff\x8e_\xff\xff\xdb\xfc\xff\xff\xde\xff\xff\xff\xc3\xfe\x7f\xff\x98\xff\xff\xff\xff\xff\x7f\xff\xc3\xff\xff\xff\xff\xff?\xff\xef\xff\xff\xff\xff\xff\x9f\xfe\xff\xf9\xff\xff\xff\xff\xcf\xff\x7f\xfd\xff"),64,64,framebuf.MONO_HLSB)
outList = [out1, out2, out3, out4]
#WIFI连接
def wifi_connect():
wlan=network.WLAN(network.STA_IF) #STA模式
wlan.active(True) #激活
#start_time=time.time() #记录时间做超时判断
cnt = 0
if not wlan.isconnected():
print("conneting to network...")
oled.fill(0) #清空屏幕
oled.text("conneting to wifi...", 10, 10)
oled.show()
time.sleep(1)
wlan.connect(ssid,password) #输入 WIFI 账号密码
while not wlan.isconnected():
cnt += 1
led1.value(1)
time.sleep(0.5)
led1.value(0)
time.sleep(0.5)
print("cnt", cnt)
#超时判断,15 秒没连接成功判定为超时
if cnt > 15:
print("WIFI Connect Timeout!")
oled.fill(0) #清空屏幕
oled.text("WIFI Connect Timeout!", 10, 10)
oled.show()
time.sleep(1)
return False
return True
else:
print("network information:", wlan.ifconfig())
oled.fill(0) #清空屏幕
oled.text("WIFI Connect OK!", 10, 10)
oled.show()
time.sleep(1)
return True
def sync_ntp():
for i in range(1,11):
try:
"""通过网络校准时间"""
ntptime.NTP_DELTA = 3155644800 # 可选 UTC+8偏移时间(秒),不设置就是UTC0
ntptime.host = 'pool.ntp.org' # 可选,ntp服务器,默认是"pool.ntp.org" 这里使用阿里服务器
ntptime.settime() # 修改设备时间,到这就已经设置好了
print("set ntp time ok!")
oled.fill(0) #清空屏幕
oled.text("set ntp time ok!", 10, 10)
oled.show()
time.sleep(1)
break
except OSError as e:
if e.errno == 116: # [Errno 116] ETIMEDOUT
print("Connection timed out. Retrying...")
# Handle the timeout situation, e.g., retry the operation
else:
# Handle other OSError exceptions
print("An error occurred:", e)
oled.fill(0) #清空屏幕
oled.text("set ntp time timed out. Retrying...", 10, 10)
oled.show()
time.sleep(1)
def fetchWeather():
result = urequests.get("https://api.seniverse.com/v3/weather/now.json?key=S9hoa4Wza9Hcs2uX_&location=shenzhen&language=zh-Hans&unit=c")
return result.text
class CWeather:
def __init__(self, addr="", weather="", temperature=""):
self.addr = addr
self.weather = weather
self.temperature = temperature
g_weather = CWeather()
def threadFetchWeather(tim0):
global g_weather
print("=======================threadFetchWeather=========================")
result = urequests.get("https://api.seniverse.com/v3/weather/now.json?key=S9hoa4Wza9Hcs2uX_&location=shenzhen&language=zh-Hans&unit=c")
text = result.text
result.close()
print("text", text)
j=ujson.loads(text)
print(j['results'][0]['location']['name'])
print(j['results'][0]['now']['text'])
print(j['results'][0]['now']['temperature'])
print(j['results'][0]['last_update'])
print("\r\n\r\n")
g_weather.addr=j['results'][0]['location']['name']
g_weather.weather=j['results'][0]['now']['text']
g_weather.temperature=j['results'][0]['now']['temperature']
sync_ntp()
localTime = time.localtime()
# 设置新的本地时间
new_time = (localTime[0], localTime[1], localTime[2], 0, localTime[3], localTime[4], localTime[5], 0)
#设置RTC时间
rtc.datetime(new_time)
print("set rtc ok!!!")
index=0
def threadShowOled(tim1):
global oled
global g_weather
global index
oled.fill(0) #清空屏幕
oled.blit(outList[index],64,0)
if 3 == index:
index = 0
else:
index += 1
print("show oled:%s %s %s"%(g_weather.addr, g_weather.weather, g_weather.temperature))
if 0 == len(g_weather.addr):
return
oled.text("%s %s"%(g_weather.addr, g_weather.weather),0,0)
oled.text("%s℃"%(g_weather.temperature),0,16)
localtime = rtc.datetime()
print("localtime: ", localtime)
strTime1 = ("%d-%02d-%02d"%(localtime[0], localtime[1], localtime[2]))
print(strTime1)
oled.text("%s"%strTime1,0,32)
strTime2 = ("%02d:%02d:%02d"%(localtime[4], localtime[5], localtime[6]))
print(strTime2)
oled.text("%s"%strTime2,0,48)
oled.show()
if __name__ == '__main__':
#def test():
oled.font_load("GB2312-12.fon")# 所使用的字体时12号字体
print("begin connect wifi")
if wifi_connect():
print("connect wifi success")
else:
print("connect wifi failed")
sys.exit(0)
sync_ntp()
# 天气10分钟获取一次
tim0 = Timer(0)
threadFetchWeather(tim0)
tim0.init(period=1000*60*10, mode=Timer.PERIODIC, callback=threadFetchWeather)
time.sleep(5)
# 时间1s更新刷屏
tim1 = Timer(1)
tim1.init(period=1000, mode=Timer.PERIODIC, callback=threadShowOled)
while True:
pass
代码结构:
详细的代码之前的博客都有
5、成果展示
MicroPython+ESP32+SSD1036 IIC OLED显示太空人表盘