print("Hello, RP2040!")
from machine import Pin, PWM, ADC, I2C
import utime
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
from klass_ntc import NTC10K
# Параметры LCD
I2C_ADDR = 0x27
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16
# Инициализация шины I2C (на GPIO 4 = SDA, GPIO 5 = SCL)
i2c = I2C(0, sda=machine.Pin(4), scl=machine.Pin(5), freq=400000)
# Создание объекта LCD
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
# Определение пользовательского символа — градус
degree_symbol = [
0b00110,
0b01001,
0b01001,
0b00110,
0b00000,
0b00000,
0b00000,
0b00000
]
# Загрузка символа градуса в CGRAM по индексу 0
lcd.custom_char(0, degree_symbol)
utime.sleep(1)
print("Starting LCD test")
# Вывод названия устройства
lcd.move_to(3, 0)
lcd.putstr("Kontr_ temp")
lcd.move_to(7,1)
lcd.putstr("v1.0")
utime.sleep(2)
lcd.clear()
# === Инициализация устройств (выбираем пины, совместимые с RP2040) ===
# Датчики температуры (аналоговые пины: GP26, GP27, GP28 → ADC0, ADC1, ADC2)
sensor1 = NTC10K(26) # GP26 = ADC0
sensor2 = NTC10K(27) # GP27 = ADC1
# Мотор (простое управление GPIO)
motor = Pin(9, Pin.OUT) # GP9
# LED (индикатор тревоги)
led = Pin(10, Pin.OUT) # GP10
# Buzzer (ШИМ на GP21)
buzzer_pin = Pin(21, Pin.OUT)
buzzer = PWM(buzzer_pin)
buzzer.freq(2000) # Частота 2 кГц
# Параметры управления
motor_state = False
prev_temp = sensor1.read_temp()
last_utime = utime.time()
# Параметры плавного алгоритма
BASE_THRESHOLD = 15
SENSITIVITY = 2
MIN_ON_THRESHOLD = 5
MAX_ON_THRESHOLD = 20
MIN_OFF_THRESHOLD = 2
ALARM_TEMP = 79
# === Основной цикл ===
while True:
current_utime = utime.time()
temp1 = sensor1.read_temp()
lcd.move_to(0,0)
lcd.putstr(f"Tk:{temp1:.1f}{chr(0)}")
temp2 = sensor2.read_temp()
lcd.move_to(0,1)
lcd.putstr(f"Tb:{temp2:.1f}{chr(0)}")
temp_diff = temp1 - temp2
lcd.move_to(9,0)
# Используем фиксированную ширину в 3 символа для числа
lcd.putstr(f"Dif:{temp_diff:2.0f}{chr(0)}") # :2.0f - минимум 2 символа)
# Скорость нагрева
dt = current_utime - last_utime
if dt > 0:
heating_rate = (temp1 - prev_temp) / dt
else:
heating_rate = 0
# === ПЛАВНЫЙ АЛГОРИТМ УПРАВЛЕНИЯ ===
# Расчет динамического порога включения
on_threshold = BASE_THRESHOLD - (heating_rate * SENSITIVITY)
on_threshold = max(MIN_ON_THRESHOLD, min(MAX_ON_THRESHOLD, on_threshold))
# Динамический порог выключения (всегда на 5°C ниже порога включения)
off_threshold = max(MIN_OFF_THRESHOLD, on_threshold - 5)
# Отображение режима на LCD
lcd.move_to(9,1)
if heating_rate > 2:
mode_str = "Fast "
elif heating_rate > 0.5:
mode_str = "Medium"
else:
mode_str = "Slow "
lcd.putstr(mode_str)
# Управление мотором
if not motor_state and temp_diff > on_threshold:
motor.on()
motor_state = True
elif motor_state and temp_diff <= off_threshold:
motor.off()
motor_state = False
# Тревога
alarm = temp1 >= ALARM_TEMP
led.value(alarm)
buzzer.duty_u16(32768 if alarm else 0) # 50% duty при тревоге (32768 ≈ 50% от 65535)
# Вывод
print("\n" + "="*50)
print(f"Режим: {mode_str} | Нагрев: {heating_rate:.2f}°C/сек")
print(f"Температуры: {temp1:.1f}°C / {temp2:.1f}°C")
print(f"Разница: {temp_diff:.1f}°C | Пороги: ВКЛ>{on_threshold:.1f}°C, ВЫКЛ<={off_threshold:.1f}°C")
print(f"Мотор: {'ВКЛ' if motor_state else 'ВЫКЛ'}")
print(f"Тревога: {'АКТИВНА' if alarm else '---'}")
print("="*50)
# Обновление
prev_temp = temp1
last_utime = current_utime
utime.sleep(1)