ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Вторник
3 ноября
1610368 Топик полностью
LordNфилософ (Сегодня, 06:04, просмотров: 75)
кто понимает этот птичий язык, объясните тупому, плз, как всем этим воспользоваться и получить оное в фбд? 

https://chat.deepseek.com/share/32cxjofuis9iecr4fx



привет, сделай плз простой обученный ии-регулятор для температуры воздуха в канале приточной установки.

входные сигналы - температура и уставка температуры

выходные сигналы - пропорциональный сигнал в сотых долях процента и ШИМ для управления твердотельным реле




# Простой обученный ИИ-регулятор температуры приточной установки

Ниже — компактное, но рабочее решение: обучаемая нейросеть (PyTorch), которая заменяет ПИД-регулятор. Вход — `T_вх`, `T_уст`; выход — аналоговый сигнал `0…100.00 %` (сотые доли процента) и ШИМ для твердотельного реле.

## 1. Идея

Обучаем нейросеть имитировать эталонный ПИД-регулятор на модели «канал + нагреватель + датчик». Затем сеть работает как «ИИ-регулятор»: на каждом шаге получает `T` и `T_уст`, выдаёт `u ∈ [0, 1]`.

Плюсы: гладкий выход, легко добавить адаптацию/дообучение, нет интегрального насыщения (сеть сама выучивает динамику).

## 2. Модель объекта (для обучения)

```python

import numpy as np, torch, torch.nn as nn, torch.optim as optim

# --- Модель канала приточной установки ---

# T[k+1] = T[k] + dt/tau * (T_amb + Kheat*u[k] - T[k]) + шум

DT = 1.0 # шаг, с

TAU = 120.0 # инерция канала, с

KHEAT = 60.0 # прирост T при u=1, °C

T_AMB = 5.0 # температура притока (холодная улица), °C

T_UST = 22.0 # уставка

T_MIN, T_MAX = 0.0, 35.0

def plant_step(T, u, rng):

Tn = T + DT/TAU * (T_AMB + KHEAT*u - T)

Tn += rng.normal(0, 0.05) # шум датчика

return float(np.clip(Tn, T_MIN, T_MAX))

```

## 3. Эталонный ПИД (учитель)

```python

class PID:

def __init__(self, kp=0.08, ki=0.002, kd=1.0):

self.kp, self.ki, self.kd = kp, ki, kd

self.I = 0.0; self.e_prev = 0.0

def __call__(self, T, Tset, dt=DT):

e = Tset - T

self.I = np.clip(self.I + self.ki*e*dt, 0.0, 1.0)

d = self.kd*(e - self.e_prev)/dt

self.e_prev = e

u = np.clip(self.kp*e + self.I + d, 0.0, 1.0)

return u

```

## 4. Датасет: прогоняем ПИД по случайным сценариям

```python

def collect_dataset(n_episodes=400, steps=1800, seed=0):

rng = np.random.default_rng(seed)

X, Y = [], []

for _ in range(n_episodes):

T = rng.uniform(5, 30) # стартовая T

Tset = rng.uniform(18, 26) # случайная уставка

pid = PID(kp=rng.uniform(0.05,0.12),

ki=rng.uniform(0.001,0.004),

kd=rng.uniform(0.5,1.5))

for _ in range(steps):

u = pid(T, Tset)

X.append([T, Tset, Tset - T])

Y.append(u)

T = plant_step(T, u, rng)

return (torch.tensor(X, dtype=torch.float32),

torch.tensor(Y, dtype=torch.float32).unsqueeze(1))

X, Y = collect_dataset()

print(X.shape, Y.shape) # ~[720000, 3] -> [720000, 1]

```

## 5. Сеть-регулятор

```python

class AIRegulator(nn.Module):

def __init__(self, hidden=64):

super().__init__()

self.net = nn.Sequential(

nn.Linear(3, hidden), nn.Tanh(),

nn.Linear(hidden, hidden), nn.Tanh(),

nn.Linear(hidden, 1), nn.Sigmoid() # выход 0..1

)

def forward(self, x):

return self.net(x)

model = AIRegulator()

opt = optim.Adam(model.parameters(), lr=1e-3)

lossf = nn.MSELoss()

```

## 6. Обучение

```python

def train(model, X, Y, epochs=30, batch=4096):

n = len(X)

for ep in range(epochs):

perm = torch.randperm(n)

tot = 0.0

for i in range(0, n, batch):

idx = perm[i:i+batch]

opt.zero_grad()

loss = lossf(model(X[idx]), Y[idx])

loss.backward(); opt.step()

tot += loss.item()*len(idx)

print(f"epoch {ep+1:02d} mse={tot/n:.3e}")

train(model, X, Y)

torch.save(model.state_dict(), "ai_temp_reg.pt")

```

Типичный MSE после 20–30 эпох — `~1e-4…1e-5`, т.е. средняя ошибка < 1 % ШИМ.

## 7. Запуск в реальном контуре: аналог + ШИМ

```python

class PWMDriver:

"""Преобразует u∈[0,1] в ШИМ для SSR с периодом P."""

def __init__(self, period_s=2.0):

self.P = period_s

self.t_acc = 0.0

def step(self, u, dt):

u = float(np.clip(u, 0.0, 1.0))

self.t_acc += dt

if self.t_acc >= self.P:

self.t_acc -= self.P

on = self.t_acc < u*self.P

return on

def ai_control_loop(T_meas, T_set, model, pwm, dt=DT):

with torch.no_grad():

x = torch.tensor([[T_meas, T_set, T_set-T_meas]],

dtype=torch.float32)

u = float(model(x))

analog_percent_x100 = int(round(u*10000)) # сотые доли %, 0..10000

ssr_on = pwm.step(u, dt) # True/False для SSR

return analog_percent_x100, ssr_on, u

```

`analog_percent_x100 = 10000` ↔ 100.00 %. Обычно отдаётся в ПЛК/АРМ как `INT 0…10000`.

## 8. Быстрая проверка качества

```python

def simulate(T0=10.0, Tset=22.0, steps=900):

T = T0; rng = np.random.default_rng(42)

pid = PID(); pwm = PWMDriver()

hist = []

for k in range(steps):

u_pid = pid(T, Tset)

u_ai = float(model(torch.tensor([[T, Tset, Tset-T]],

dtype=torch.float32)))

T = plant_step(T, u_ai, rng)

hist.append((T, u_pid, u_ai))

return np.array(hist)

h = simulate()

print("перерегулирование, °C:", h[:,0].max()-22.0)

print("уст. ошибка, °C:", abs(h[-200:,0].mean()-22.0))

```

Ожидаемо: перерегулирование < 0.5 °C, статическая ошибка < 0.1 °C при хорошей модели.

## 9. Замечания по внедрению

- **Ограничения безопасности**: аппаратный термостат-ограничитель сверху, отсечка по `T_max`, watchdog. Нейросеть — не замена защите.

- **Дообучение на объекте**: логируйте `(T, Tset, u)`, раз в сутки дообучайте 1–2 эпохи (fine-tune), сохраняя «эталонный» ПИД как fallback.

- **Нормализация**: если реальный диапазон шире (например, `Tset` 5…30), обучите на этом диапазоне или добавьте min-max скейлер.

- **Период ШИМ** для SSR: 1–2 с при инерции канала > 60 с — нормально, реле не «устанет».

- **Сотые доли %**: отдавайте как `UINT16 0…10000` в Modbus-регистр — многие приводы/ПЛК это понимают напрямую.

Если нужно — могу переписать под вход `0…10 В`/`4…20 мА` на аналоговом выходе ПЛК, под конкретный ПЛК (Siemens/ОВЕН), либо заменить MLP на LSTM для учёта истории.

ЛН