Смысл и формула, которую я вкладывал в этот блок:
https://youtu.be/qJt-AtaccJE
Сниму ещё одно видео и выложу файл Flprog полностью
Phazz, в Flprog ПИД находится в Блоке пользователя (см. скриншоты):
DeclareSection
float TIMER_PID; // Внутренний таймер ПИД
float E_1; // Текущее рассогласование
float E_2; // Рассогласование на -1 шаг
float E_3; // Рассогласование на -2 шага
float D_T; // Время воздействия на текущем шагу регулирования
float SUM_D_T; // Накопленное время воздействия
float TIMER_PID_UP; // Накопленное время открытия
float TIMER_PID_DOWN; // Накопленное время закрытия
boolean PID_PULSE; // Шаг выполнения 1 цикла
LoopSection
E_1 = SET_VALUE - PRESENT_VALUE; // Текущее рассогласование температуры
if (K_I == 0.0) // Деление на 0
{
K_I = 9999.0;
}
if (CYCLE == 0.0) // Деление на 0
{
CYCLE = 1.0;
}
// Расчет управляющего воздействия
if (PULSE_100MS & TIMER_PID == 0.0 & ! PID_PULSE)
{
PID_PULSE = 1; // Присвоить шаг
D_T = K_P * (E_1 - E_2 + CYCLE * E_2 / K_I + K_D * (E_1 - 2 * E_2 + E_3) / CYCLE) * VALVE / 100; // Время воздействия на текущем шагу регулирования
E_3 = E_2; // Запись рассогласования -2 шага назад
E_2 = E_1; // Запись рассогласования -1 шаг назад
SUM_D_T = SUM_D_T + D_T; // Накопленное время воздействия
if (SUM_D_T >= 0.5) // Сброс накопленного времени закрытия
{
TIMER_PID_DOWN = 0.0;
}
if (SUM_D_T <= -0.5) // Сброс накопленного времени открытия
{
TIMER_PID_UP = 0.0;
}
if ( E_1 < DEAD_ZONE & E_1 > - DEAD_ZONE) // Зона нечувствительности
{
D_T = 0.0;
SUM_D_T = 0.0;
}
}
if (PULSE_100MS)
{
TIMER_PID = TIMER_PID + 0.1; // Внутренний таймер ПИД ВОТ ТУТ БЫЛА ОШИБКА
}
if (ON_OFF & AUTO_HAND)
{
if (TIMER_PID >= CYCLE) // Сброс таймера при окончание цикла регулирования
{
PID_PULSE = 0; // Сбросить шаг
TIMER_PID = 0.0;
if (SUM_D_T>=0.5 || SUM_D_T<=-0.5) // Сброс накопленного времени воздействия
{
SUM_D_T = 0.0;
}
}
}
else
{
PID_PULSE = 0;
D_T = 0.0;
SUM_D_T = 0.0;
TIMER_PID = 0.0;
E_3 = E_1;
E_2 = E_1;
TIMER_PID_UP = 0.0;
TIMER_PID_DOWN = 0.0;
}
// Управление
UP = ((((SUM_D_T >= TIMER_PID & SUM_D_T >= 0.5) || D_T >= CYCLE - 0.5 || TIMER_PID_UP >= VALVE) & AUTO_HAND) || (HAND_UP & ! AUTO_HAND)) & ON_OFF & ! DOWN; // Открытие клапана
if ( PULSE_100MS & UP & TIMER_PID_UP < VALVE) // Накопленное время открытия
{
TIMER_PID_UP = TIMER_PID_UP + 0.1;
}
DOWN = ((((SUM_D_T <= - TIMER_PID & SUM_D_T <= - 0.5) || D_T <= - CYCLE + 0.5 || TIMER_PID_DOWN >= VALVE) & AUTO_HAND) || ( HAND_DOWN & ! AUTO_HAND)) & ON_OFF & ! UP; // Закрытие клапана
if ( PULSE_100MS & DOWN & TIMER_PID_DOWN < VALVE) // Накопленное время закрытия
{
TIMER_PID_DOWN = TIMER_PID_DOWN + 0.1;
}