‘’’
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)<tem_Min:
tem_Min=int(temp)
if int(humi)>hum_Max:
hum_Max=int(humi)
if int(humi)<tem_Max:
hum_Min=int(humi)
def Print():
global i
oled.text(‘Temp:’+str(temp), 0, 12)
oled.text(‘Max:’+str(tem_Max), 0, 26) #空一段,最大最小
oled.text(‘Min:’+str(tem_Min), 64, 26)
oled.text(‘Humi:’+str(humi), 0,40)
oled.text(‘Max:’+str(hum_Max), 0, 57)
oled.text(‘Min:’+str(hum_Min), 64, 57)
oled.text(‘working’+point[i%4], 25, 0)
oled.show()
time.sleep(0.2)
oled.fill(0)
i=i+1
def Is_Int(Dir): #异常处理。整型
try:
int(Dir)
return True
except ValueError:
pass
def Is_Float(Dir): #异常处理。浮点型
try:
float(Dir)
return True
except ValueError:
pass
def twink():
L_Blue.value(1)
time.sleep(0.5)
L_Blue.value(0)
time.sleep(0.5)
L_Blue.value(1)
time.sleep(0.5)
L_Blue.value(0)
time.sleep(0.5)
oled.fill(0) #清屏
oled.text(‘Welcome!’, 10, 10) #欢迎界面
oled.show()
time.sleep(0.5)
oled.fill(0) #清屏
Open_Test(0) #先调用,才能全局改变下面的变量
Tim_S.init(period=space,mode=Timer.PERIODIC,callback=Open_Test)
#效果是到定义的时间就调用函数收集一下数据,但是程序依然在运行,到主函数后会因为未到指定时间
#而不启用收集函数,导致主函数出错,所以需要在定时器之前先调用一下函数,
#还有种办法,可以通过延时来达到等待函数运行后再去显示数据,但是因为后续会有自定义收集间隔
#所以如果通过延时来处理还需要让延时时间变量与间隔相同
#time.sleep(n)
tem_Max=int(temp) #控制空间,整数,大概
tem_Min=int(temp)
hum_Max=int(humi)
hum_Min=int(humi)
#主程序负责数据的对比,定时器外部中断优先,保障间隔的准确
while True: #循环获取温湿度
if Warn_tem_Min<temp<Warn_tem_Max and Warn_hum_Min<humi<Warn_hum_Max:
Voice_Off()
else:
Voice_On()
max_or_min()
Print()
#大概有几个口令:警报最大最小温度,湿度;采集时间间隔就这五个,
#注意判断类型,命令或类型不正确的不予理会,设置成功有闪灯提醒
if uart1.any()>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”, “
s
e
r
i
a
l
M
o
n
i
t
o
r
:
R
X
"
,
"
"
,
[
]
]
,
[
"
e
s
p
:
R
X
0
"
,
"
serialMonitor:RX", "", [] ], [ "esp:RX0", "
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