from machine import Pin, PWM, I2C
import time
import dht
import ssd1306
# ===================== 硬件引脚配置 =====================
# 1. 楼层按钮(输入,上拉电阻,按下时为低电平)
btn_1 = Pin(0, Pin.IN, Pin.PULL_UP)
btn_2 = Pin(1, Pin.IN, Pin.PULL_UP)
btn_3 = Pin(2, Pin.IN, Pin.PULL_UP)
# 2. 楼层指示灯(输出,高电平点亮)
led_1 = Pin(10, Pin.OUT)
led_2 = Pin(11, Pin.OUT)
led_3 = Pin(12, Pin.OUT)
# 3. 方向指示灯(输出)
led_up = Pin(13, Pin.OUT)
led_down = Pin(14, Pin.OUT)
# 4. 门状态灯(输出)
led_door = Pin(15, Pin.OUT)
# 5. 数码管(输出,共阴极,连接 GP3 ~ GP9)
seg_pins =[Pin(i, Pin.OUT) for i in range(3, 10)]
DIGITS = {
1:[0, 1, 1, 0, 0, 0, 0],
2:[1, 1, 0, 1, 1, 0, 1],
3:[1, 1, 1, 1, 0, 0, 1]
}
# 6. 门控舵机(PWM控制,连接 GP16)
servo = PWM(Pin(16))
servo.freq(50)
# 7. 温湿度传感器 (DHT22, 连接 GP17)
dht_sensor = dht.DHT22(Pin(17))
# 8. OLED屏幕 (I2C1通信, SCL=GP19, SDA=GP18)
i2c = I2C(1, scl=Pin(19), sda=Pin(18), freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# ===================== 电梯状态初始化 =====================
current_floor = 1
target_floor = 1
direction = 0
# 温湿度全局缓存(防止频繁读取阻塞或报错)
last_dht_time = 0
curr_temp = 0.0
curr_hum = 0.0
# 屏幕刷新函数
def update_oled():
global last_dht_time, curr_temp, curr_hum
current_time = time.ticks_ms()
# 限制 DHT22 读取频率(至少间隔2秒)
if time.ticks_diff(current_time, last_dht_time) > 2000 or last_dht_time == 0:
try:
dht_sensor.measure()
curr_temp = dht_sensor.temperature()
curr_hum = dht_sensor.humidity()
last_dht_time = current_time
except Exception:
pass # 传感器读取失败时保留上一次的值
oled.fill(0) # 清屏
# 1. 顶部:显示当前楼层与运行方向
dir_str = "Stay"
if direction == 1: dir_str = "Up ^"
elif direction == -1: dir_str = "Down v"
oled.text(f"Floor:{current_floor} Dir:{dir_str}", 0, 0)
# 2. 第二行:显示电梯内的温湿度
oled.text(f"T:{curr_temp}C H:{curr_hum}%", 0, 15)
# 3. 底部:根据当前所在楼层,动态显示该层功能
oled.text("--- Function ---", 0, 35)
if current_floor == 1:
oled.text("1F: Lobby", 0, 50) # 大堂
elif current_floor == 2:
oled.text("2F: Office", 0, 50) # 办公室
elif current_floor == 3:
oled.text("3F: Canteen", 0, 50) # 餐厅
oled.show()
# 数码管显示函数
def display_floor(floor):
if floor in DIGITS:
pattern = DIGITS[floor]
for i in range(7):
seg_pins[i].value(pattern[i])
# 舵机角度控制函数
def set_servo_angle(angle):
min_duty = 1638
max_duty = 8192
duty = int(min_duty + (angle / 180.0) * (max_duty - min_duty))
servo.duty_u16(duty)
# 系统硬件初始化
def init_system():
led_1.value(1); led_2.value(0); led_3.value(0)
led_up.value(0); led_down.value(0); led_door.value(0)
display_floor(1)
set_servo_angle(0)
update_oled()
# ===================== 核心功能函数 =====================
def check_buttons():
if btn_1.value() == 0:
time.sleep_ms(20)
if btn_1.value() == 0: return 1
elif btn_2.value() == 0:
time.sleep_ms(20)
if btn_2.value() == 0: return 2
elif btn_3.value() == 0:
time.sleep_ms(20)
if btn_3.value() == 0: return 3
return 0
def update_direction():
global direction
if current_floor < target_floor: direction = 1
elif current_floor > target_floor: direction = -1
else: direction = 0
def update_floor_led():
led_1.value(0); led_2.value(0); led_3.value(0)
if current_floor == 1: led_1.value(1)
elif current_floor == 2: led_2.value(1)
elif current_floor == 3: led_3.value(1)
# 模拟电梯运行
def run_elevator():
global current_floor
# 闪烁循环:总计3秒
for _ in range(6):
if direction == 1: led_up.value(1)
elif direction == -1: led_down.value(1)
update_oled() # 运动时刷新屏幕
time.sleep(0.25)
led_up.value(0)
led_down.value(0)
update_oled()
time.sleep(0.25)
# 达到下一个楼层
current_floor += direction
update_floor_led()
display_floor(current_floor)
update_oled()
# 模拟开关门
def door_control():
led_door.value(1)
set_servo_angle(90)
time.sleep(3)
led_door.value(0)
set_servo_angle(0)
time.sleep(1)
# ===================== 主循环 =====================
def main():
global target_floor
init_system()
print("电梯仿真系统启动,初始楼层:1楼")
while True:
pressed_floor = check_buttons()
if pressed_floor != 0 and pressed_floor != target_floor:
target_floor = pressed_floor
print(f"接收到指令:前往{pressed_floor}楼")
update_direction()
if direction != 0:
run_elevator()
if current_floor == target_floor:
print(f"到达{current_floor}楼,开门...")
update_oled()
door_control()
print("关门,等待新指令...")
# 持续刷新屏幕状态
update_oled()
time.sleep_ms(100)
if __name__ == "__main__":
main()