一、测试环境
我们同样使用在Wokwi网站上选择Micropython with ESP32进行仿真,来进行温度和湿度的检测。
ESP32官方技术参考手册:
https://www.espressif.com.cn/sites/default/files/documentation/esp32_technical_reference_manual_en.pdfhttps://www.espressif.com.cn/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf中文资料可查看乐鑫官网:
技术文档 | 乐鑫科技Downloads: SDK & Demos, APKs, Tools and Documents for Espressif Systems products and solutionshttps://www.espressif.com.cn/zh-hans/support/documents/technical-documents
二、硬件环境
温度湿度DHT22使用说明和显示屏ssd1366使用说明
wokwi-dht22 Reference | Wokwi DocsDigital Humidity and Temperature sensor.https://docs.wokwi.com/parts/wokwi-dht22board-ssd1306 Reference | Wokwi DocsMonochrome 128x64 OLED display with I2C interfacehttps://docs.wokwi.com/parts/board-ssd1306三、代码说明
main.py
'''
oled温湿度报警,
可手动设定警戒值的报警装置,可以用于一些特定环境的温湿度控制
可以自己设定间隔时间
可以通过串口进行最高最低温度的设置等,省的设置一堆按钮显得乱
'''
from machine import Pin,PWM,I2C,Timer,UART
import time,machine,ssd1306,dht
uart1=UART(1,115200) #调用串口uart1
uart1.init(115200,bits=8,parity=None,stop=1) #初始化串口相关参数
Tim_S=Timer(0) #定时器对象,很怪,有了这个定时器,下面的蜂鸣器没有了短促的鸣叫
key=Pin(27, Pin.OUT) # 蜂鸣器接GPIO27口
Buzzer= PWM(key) #定义蜂鸣器
Buzzer.duty(0) #控制蜂鸣器初始关闭状态
global data
data = dht.DHT22(Pin(15)) #实例化15号管脚,21被占用了
i2c = I2C(0, scl=Pin(22), sda=Pin(21)) #对应管脚
oled_width = 128 ##画幅大小。oled屏幕宽度128
oled_height = 64 #画幅大小。oled屏幕高度64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) #调用,设置像素大小
i=0
space=3000 #设置数据更新时间,默认三秒,可修改但是要为整型。
point=['','.','..','...'] #oled显示“...”动态,表示在工作
Warn_tem_Max=29.0 # 设置最高温度。可修改为浮点型
Warn_tem_Min=26.0 # 设置最高温度。可修改为浮点型
Warn_hum_Max=60.0 # 设置最大湿度。可修改为浮点型
Warn_hum_Min=40.0 # 设置最小湿度。可修改为浮点型
L_Blue=Pin(2,Pin.OUT) #内置小灯,判断状态,命令设置成功闪亮
def Voice_On(): #开启调用
Buzzer.duty(512) #设置蜂鸣器占空比
Buzzer.freq(2000) #设置蜂鸣器频率
time.sleep(0.5)
Buzzer.duty(0)
time.sleep(0.5)
def Voice_Off(): #关闭调用
Buzzer.duty(0) #蜂鸣器关闭
def Open_Test(t):
data.measure() #先调用测量函数,获取温湿度
global temp
temp=data.temperature()
global humi
humi=data.humidity()
def max_or_min():
global tem_Max
global tem_Min
global hum_Max
global hum_Min
if int(temp)>tem_Max:
tem_Max=int(temp)
if int(temp)hum_Max:
hum_Max=int(humi)
if int(humi)0: #考虑放在定时器中,因为循环内很难监测到
Dir=uart1.read()
Dir=str(Dir) #转换为字符串型
#Dir=Dir.lower(),字符小写就涉及到回车的问题,无法转变,会异常,所以我可以提前切出来想要的部分
Dir=Dir[2:-3] #提前切掉b'...\n'这个东西,在让这个正常的字符串去变小写
if Dir.find('space')>=0:
Dir=Dir[5:]
if Is_Int(Dir)==True:
space=int(Dir)
Tim_S.init(period=space,mode=Timer.PERIODIC,callback=Open_Test)
twink()
elif Dir.find('tmax')>=0:
Dir=Dir[4:]
if Is_Float(Dir)==True:
Warn_tem_Max=float(Dir)
twink()
elif Dir.find('tmin')>=0:
Dir=Dir[4:]
if Is_Float(Dir)==True:
Warn_tem_Min=float(Dir)
twink()
elif Dir.find('hmax')>=0:
Dir=Dir[4:]
if Is_Float(Dir)==True:
Warn_hum_Max=float(Dir)
twink()
elif Dir.find('hmin')>=0:
Dir=Dir[4:]
if Is_Float(Dir)==True:
Warn_hum_Min=float(Dir)
twink()
#串口这部分也可以考虑写成函数,看起来能简洁些
diagram.json
{
"version": 1,
"author": "魔都飘雪",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": -68.61, "left": -8.02, "attrs": {} },
{ "type": "wokwi-dht22", "id": "dht1", "top": -71.8, "left": 118.28, "attrs": {} },
{ "type": "board-ssd1306", "id": "oled1", "top": 23.53, "left": -135.32, "attrs": {} },
{
"type": "wokwi-buzzer",
"id": "bz1",
"top": -81.64,
"left": -146.94,
"attrs": { "volume": "0.5" }
}
],
"connections": [
[ "esp:TX0", "$serialMonitor:RX", "", [] ],
[ "esp:RX0", "$serialMonitor:TX", "", [] ],
[ "dht1:VCC", "esp:3V3", "red", [ "v0" ] ],
[ "dht1:SDA", "esp:D15", "green", [ "v0" ] ],
[ "dht1:GND", "esp:GND.1", "black", [ "v0" ] ],
[ "oled1:VCC", "esp:3V3", "red", [ "v-12.04", "h-51.43", "v113.03", "h241.73", "v-40.86" ] ],
[
"oled1:GND",
"esp:GND.2",
"black",
[ "v-12.72", "h-41.98", "v114.4", "h127.33", "v-50.39" ]
],
[ "oled1:SDA", "esp:D21", "green", [ "v-103.15", "h173.6", "v86.85" ] ],
[ "bz1:1", "esp:GND.2", "green", [ "v8.67", "h101.46", "v72.79" ] ],
[ "bz1:2", "esp:D27", "green", [ "v8.67", "h96.78", "v53.56" ] ],
[ "oled1:SCL", "esp:D22", "green", [ "v-108.86", "h178.16", "v59.06" ] ]
],
"serialMonitor": { "display": "plotter", "newline": "lf" }
}
ssd1366.py(ssd1306屏幕的驱动)
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from micropython import const
import framebuf
import math
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xa4)
SET_NORM_INV = const(0xa6)
SET_DISP = const(0xae)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
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, width, height, external_vcc, color=framebuf.MONO_VLSB):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
fb = framebuf.FrameBuffer(self.buffer, self.width, self.height, color)
self.framebuf = fb
# Provide methods for accessing FrameBuffer graphics primitives. This is a
# workround because inheritance from a native class is currently unsupported.
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
self.fill = fb.fill
self.pixel = fb.pixel
self.hline = fb.hline
self.vline = fb.vline
self.line = fb.line
self.rect = fb.rect
self.fill_rect = fb.fill_rect
self.text = fb.text
self.scroll = fb.scroll
self.blit = fb.blit
self.init_display()
def init_display(self):
for cmd in (
SET_DISP | 0x00, # off
# address setting
SET_MEM_ADDR, 0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
SET_MUX_RATIO, self.height - 1,
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
SET_DISP_OFFSET, 0x00,
SET_COM_PIN_CFG, 0x02 if self.height == 32 else 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,
SET_DISP | 0x01): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
def poweron(self):
self.write_cmd(SET_DISP | 0x01)
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):
x0 = 0
x1 = self.width - 1
if self.width == 64:
# displays with width of 64 pixels are shifted by 32
x0 += 32
x1 += 32
self.write_cmd(SET_COL_ADDR)
self.write_cmd(x0)
self.write_cmd(x1)
self.write_cmd(SET_PAGE_ADDR)
self.write_cmd(0)
self.write_cmd(self.pages - 1)
self.write_data(self.buffer)
#下面函数为添加的功能,根据pyboard板子厂商提供的例程修改
def show_hanzi(self, row, col, charlist1):
data = bytearray(charlist1)
fbuf = framebuf.FrameBuffer(data, 16, 16, framebuf.MONO_VLSB)
self.blit(fbuf,col,(row-1)*16)
del fbuf
def show_image(self, image_list):
data = bytearray(image_list)
fbuf = framebuf.FrameBuffer(data, 128, 96, framebuf.MONO_VLSB)
self.blit(fbuf, 0, 0)
del fbuf
class SSD1306_I2C(SSD1306):
def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False, color=framebuf.MONO_VLSB):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
super().__init__(width, height, external_vcc, color)
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_data(self, buf):
self.i2c.writeto(self.addr, b'\x40' + buf)
class SSD1306_SPI(SSD1306):
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False, color=framebuf.MONO_VLSB):
self.rate = 10 * 1024 * 1024
dc.init(dc.OUT, value=0)
res.init(res.OUT, value=0)
cs.init(cs.OUT, value=1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
import time
self.res(1)
time.sleep_ms(1)
self.res(0)
time.sleep_ms(10)
self.res(1)
super().__init__(width, height, external_vcc, color)
def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buf)
self.cs(1)
是不是,很简单!来看看效果:
也可以在网页上查看实际效果:
Wokwi Arduino and ESP32 Simulatorhttps://wokwi.com/projects/341771399848788563