from machine import Pin, PWM, I2C, Timer
import time
import dht
from ssd1306 import SSD1306_I2C
#########################初始化引脚定义#############################
# 舵机引脚定义
servo_pin = 15
# DHT22引脚定义
DHT_PIN = 32
# 初始化DHT22传感器
sensor = dht.DHT22(Pin(DHT_PIN))
# 初始化PWM
servo = PWM(Pin(servo_pin))
servo.freq(50) # 舵机频率50Hz
# 定义超声波引脚
PIN_TRIG = 26
PIN_ECHO = 25
# 初始化超声波引脚
trig = Pin(PIN_TRIG, Pin.OUT)
echo = Pin(PIN_ECHO, Pin.IN)
# 创建I2C对象
i2c = I2C(0, scl=Pin(14), sda=Pin(27)) # ESP32示例
# 创建OLED显示对象
oled = SSD1306_I2C(128, 64, i2c) # 128x64像素显示屏
# LED
led = Pin(2, Pin.OUT)
led_state = False
count=0
def toggle_led(timer):
global led_state
global count
count=count+1
if (temperature_state==1):
if(count%6==0):
led_state = not led_state
led.value(led_state)
elif(temperature_state==2):
if(count%2==0):
led_state = not led_state
led.value(led_state)
else:
led_state = not led_state
led.value(led_state)
if(count%6==0):
count=0
############################舵机部分################################
def servo_write(angle):
"""
设置舵机角度 (0-180度)
对应Arduino的servo.write()函数
"""
# 将角度转换为占空比
# 0度对应1ms脉宽(约占空比40),180度对应2ms脉宽(约占空比115)
# 公式:duty = (angle / 180) * (max_duty - min_duty) + min_duty
min_duty = 26 # 对应0.5ms脉宽
max_duty = 122 # 对应2.5ms脉宽
duty = int((angle / 180) * (max_duty - min_duty) + min_duty)
servo.duty(duty)
############################温湿度传感器##############################
def read_dht11():
global temperature, humidity
sensor.measure()
temperature = sensor.temperature()
humidity = sensor.humidity()
print("温度:", temperature)
print("湿度:", humidity)
############################超声波传感器##############################
def pulse_in(pin, level, timeout_us=30000):
start_time = time.ticks_us()
# 等待脉冲开始
while pin.value() != level:
if time.ticks_diff(time.ticks_us(), start_time) > timeout_us:
return 0 # 超时返回0
# 记录脉冲开始时间
pulse_start = time.ticks_us()
# 等待脉冲结束
while pin.value() == level:
if time.ticks_diff(time.ticks_us(), pulse_start) > timeout_us:
return 0 # 超时返回0
# 计算脉冲持续时间
pulse_end = time.ticks_us()
return time.ticks_diff(pulse_end, pulse_start)
def read_distance():
"""读取超声波距离"""
# 开始新的测量 - 对应digitalWrite(PIN_TRIG, HIGH)
global distance
trig.on()
# 等待10微秒 - 对应delayMicroseconds(10)
time.sleep_us(10)
# 结束触发脉冲 - 对应digitalWrite(PIN_TRIG, LOW)
trig.off()
# 读取回声脉冲持续时间 - 对应pulseIn(PIN_ECHO, HIGH)
duration = pulse_in(echo, 1)
distance = duration * 0.034 / 2
print("距离:", distance)
##################################################################
def main_loop():
"""主循环"""
timer0 = Timer(0)
timer0.init(period=500, mode=Timer.PERIODIC, callback=toggle_led)
global temperature_state
while True:
read_dht11()
read_distance()
if (temperature<20):
temperature_state=1
elif(temperature>20 and temperature<30):
temperature_state=2
else:
temperature_state=3
if (temperature<30):
servo_angle=0
else:
servo_angle=90
servo_write(servo_angle)
oled.fill(0) # 清屏
oled.text('temperature', 0, 0) # 在(0,0)位置显示文字
oled.text(str(temperature), 90, 0) # 在(0,0)位置显示文字
oled.text('humidity', 0, 10) # 在(0,10)位置显示文字
oled.text(str(humidity), 90, 10) # 在(0,10)位置显示文字
oled.text('distance', 0, 20) # 在(0,10)位置显示文字
oled.text(str(distance), 90, 20) # 在(0,10)位置显示文字
oled.show() # 更新显示
time.sleep(1)
# 程序入口
if __name__ == "__main__":
try:
main_loop()
except KeyboardInterrupt:
print("程序已停止")
servo.deinit() # 释放PWM资源
except Exception as e:
print("程序错误:", e)
servo.deinit()