PID + AC = какая-то фигня. Подскажите, где ошибка.

David_Kh

✩✩✩✩✩✩✩
28 Сен 2022
3
0
Всем привет!
Пытаюсь настроить ПИД-регулятор на поддержку заданной температуры. В качестве нагревателя использую лампочку 220в через модуль с симистром.
Начинаю с настройки коэффициента на "P", но рост температуры ни то чтобы не образует волны, а даже не доходит до заданной и останавливается не доходя процентов 10.
График и фото прилагаю.
Где моя ошибка?

C++:
#include <GyverPID.h>
#include <PIDtuner.h>
#include <PIDtuner2.h>
GyverPID pid;

#include <DS_raw.h>
#include <microDS18B20.h>
#include <microOneWire.h>

MicroDS18B20 <A5> ds;

#define ZERO_PIN 2    // пин детектора нуля
#define INT_NUM 0     // соответствующий ему номер прерывания
#define DIMMER_PIN 4  // управляющий пин симистора
#include <GyverTimers.h>  // библиотека таймера
float dimmer;               // переменная диммера
int dt = 100; // помоему, нужен только для Ki

void setup() {
  pid.Kp = 1;
  pid.Ki = 0;
  pid.Kd = 0;
  pid.setDt(dt); //частота опроса с датчика
  pid.setDirection(NORMAL); //работа на увеличение
  pid.setpoint = 60; //нужная температура

  pinMode(ZERO_PIN, INPUT_PULLUP);
  pinMode(DIMMER_PIN, OUTPUT);
  attachInterrupt(INT_NUM, isr, RISING);  // для самодельной схемы ставь FALLING
  Timer2.enableISR();
  Serial.begin(9600);
}

void loop() {
  temp();
  pidControl();

}

void temp() {
  static uint32_t timer = millis();
  if (millis() - timer >= 1000) {
    timer = millis();
    if (ds.readTemp()) {
      Serial.println(ds.getTemp());
    }
    ds.requestTemp();
  }
}

void pidControl() {
  static uint32_t tmr;
  if (millis() - tmr > dt) {
    tmr = millis();
    pid.input = ds.getTemp(); // передаем новый измеренный сигнал с датчика
    pid.getResult(); //делает рассчеты, ее нужно вызывать по таймеру с периодом dt
    pid.output; //принимает значение управляющего сигнала
    dimmer = map(pid.output, 0, 125, 9300, 500);
  }
}

// прерывание детектора нуля
void isr() {
  static int lastDim;
  digitalWrite(DIMMER_PIN, 0);  // выключаем симистор
  // если значение изменилось, устанавливаем новый период
  // если нет, то просто перезапускаем со старым
  if (lastDim != dimmer) Timer2.setPeriod(lastDim = dimmer);
  else Timer2.restart();
}
// прерывание таймера
ISR(TIMER2_A) {
  digitalWrite(DIMMER_PIN, 1);  // включаем симистор
  Timer2.stop();                // останавливаем таймер
}
 

Вложения

David_Kh

✩✩✩✩✩✩✩
28 Сен 2022
3
0
@Геннадий П, т.е. в коде нет ошибки?

То что касается коэффициентов. Как я понял из видео от AlexGever, надо вначале настроить "P". Чтобы быстро набиралась температура, перескакивала заданный уровень и уходила на снижение. И такие колебания должны быть постоянно, с медленным затуханием. А в дальнейшем, с помощью остальных коэффициентов подбирать так, чтобы колебания затихали как можно быстрей.
Так вот коэф "P" я поднимал до 100. Но ни при каком не доходило до заданного значения и колебаний вообще не было. Поэтому я и решил, может я в коде что-то напутал?..