print("Hello, RP2040!")
from machine import Pin, PWM, ADC, I2C
import utime
import math
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
# Параметры 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()
class NTC10K:
def __init__(self, pin_num, r_ref=10000, beta=3950, ntc_r=10000, t_nominal=25):
self.adc = ADC(pin_num)
# На RP2040 нельзя задать atten — диапазон всегда ~0–3.3V
self.r_ref = r_ref # Опорный резистор (10K)
self.beta = beta # Коэффициент Бета
self.ntc_r = ntc_r # Сопротивление NTC при 25°C
self.t_nominal = t_nominal # Номинальная температура
def read_temp(self):
adc_value = self.adc.read_u16() # 16-битное значение (0–65535), но ADC 12 бит → масштабируем
adc_value_12bit = adc_value >> 4 # Приводим к 12 битам (0–4095)
if adc_value_12bit == 0:
return float('inf') # Избегаем деления на ноль
# Напряжение на выходе делителя
v_out = 3.3 * adc_value_12bit / 4095
# Вычисляем сопротивление NTC
ntc_resistance = self.r_ref * v_out / (3.3 - v_out)
# Формула Стейнхарта-Харта через Beta
steinhart = math.log(ntc_resistance / self.ntc_r) / self.beta
steinhart += 1.0 / (self.t_nominal + 273.15)
temp_k = 1.0 / steinhart
temp_c = temp_k - 273.15
return temp_c
# === Инициализация устройств (выбираем пины, совместимые с 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()
# Пороги
NORMAL_ON = 15
NORMAL_OFF = 10
FAST_ON = 20
FAST_OFF = 10
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
# Скорость нагрева
dt = current_utime - last_utime
if dt > 0:
heating_rate = (temp1 - prev_temp) / dt
else:
heating_rate = 0
# Режим работы
if heating_rate >= 1:
on_threshold = FAST_ON
off_threshold = FAST_OFF
mode = "БЫСТРЫЙ"
else:
on_threshold = NORMAL_ON
off_threshold = NORMAL_OFF
mode = "НОРМАЛЬНЫЙ"
# Управление мотором
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} | Нагрев: {heating_rate:.2f}°C/сек")
print(f"Температуры: {temp1:.1f}°C / {temp2:.1f}°C")
print(f"Разница: {temp_diff:.1f}°C | Пороги: ВКЛ>{on_threshold}°C, ВЫКЛ<={off_threshold}°C")
print(f"Мотор: {'ВКЛ' if motor_state else 'ВЫКЛ'}")
print(f"Тревога: {'АКТИВНА' if alarm else '---'}")
print("="*50)
# Обновление
prev_temp = temp1
last_utime = current_utime
utime.sleep(1)