#include "PID_v1.h"
const int setPointPin = A0;
//Переменные для ПИД регулятора
double Setpoint, Input, Output;
//Параметры ПИД регулятора
double Kp = 40, Ki = 40, Kd = 0; // ПИ
//double Kp = 40, Ki = 40, Kd = 7; // ПИД
//Объект ПИД регулятора
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, P_ON_E, DIRECT);
void setup()
{
Serial.begin(115200);
myPID.SetOutputLimits(0, 255); //диапазон выхода
//индикаторы для отладки
Setpoint = 0; //начальное значение уставки - ноль
myPID.SetMode(AUTOMATIC); //включение регулятора
Input = simPlant(0.0,1.0); //внутренняя модель входного сигнала
Serial.println("Setpoint Input Output Watts");
}
void loop()
{
float heaterWatts = (int)Output * 20.0 / 255; //мощность нагревателя для модели
Input = simPlant(heaterWatts,Output>0?1.0:1-Output);//моделирование нагрева
if (myPID.Compute()) //ПИД регулятор
{
Setpoint = analogRead(setPointPin) / 4; // чтение уставки температуры (от 0 до 255)
}
report(); //вывод отладочных данных в com порт
}
/*Функция вывода результата работы ПИД-регулятора*/
void report(void)
{
static uint32_t last = 0;
const int interval = 100; //вывод раз в секунду
if (millis() - last > interval)
{
last += interval;
Serial.print("time:");
Serial.print((double)last/1000);
Serial.print(" SP:");
Serial.print(Setpoint);
Serial.print(" PV:");
Serial.print(Input);
Serial.print(" CV:");
Serial.print(Output);
Serial.print(' ');
Serial.println();
}
}
/*Функция модели нагрева
Q - мощность [Вт],
hfactor - относительный коэффициент теплопроводности*/
float simPlant(float Q,float hfactor)
{
//Имитация алюминиевого блока размером 1x1x2 см с нагревателем и пассивным охлаждением
float h = 5 *hfactor ; // Вт/м2K коэффициент конвекции
float Cps = 0.89; // теплоемкость Дж/грамм°C
float area = 1e-4; // площадь конвекции, м2
float mass = 1 ; // масса, граммы
float Tamb = 25; // температура окружающей среды °C
static float T = Tamb; // текущая температура °C
static uint32_t last = 0; // время для моделирования
uint32_t interval = 100; // период обновления данных, мс
if (millis() - last >= interval)
{
last += interval;
T = T + Q * interval / 1000 / mass / Cps - (T - Tamb) * area * h;
}
return T;
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
pot1:VCC
pot1:SIG
pot1:GND