PID + AC = какая-то фигня. Подскажите, где ошибка.
- Войдите на сайт для отправки комментариев
Ср, 28/09/2022 - 12:24
Всем привет!
Пытаюсь настроить ПИД-регулятор на поддержку заданной температуры. В качестве нагревателя использую лампочку 220в через модуль с симистром.
Начинаю с настройки коэффициента на "P", но рост температуры ни то чтобы не образует волны, а даже не доходит до заданной и останавливается не доходя процентов 10. Коэф "P" поднимал до 100, результат ближе к заданному, но все равно не доходит до него и вообще никакого колебания нет.
График и фото прилагаю.
В чем моя ошибка?
01 | #include <GyverPID.h> |
02 | #include <PIDtuner.h> |
03 | #include <PIDtuner2.h> |
04 | GyverPID pid; |
05 |
06 | #include <DS_raw.h> |
07 | #include <microDS18B20.h> |
08 | #include <microOneWire.h> |
09 |
10 | MicroDS18B20 <A5> ds; |
11 |
12 | #define ZERO_PIN 2 // пин детектора нуля |
13 | #define INT_NUM 0 // соответствующий ему номер прерывания |
14 | #define DIMMER_PIN 4 // управляющий пин симистора |
15 | #include <GyverTimers.h> // библиотека таймера |
16 | float dimmer; // переменная диммера |
17 | int dt = 100; // помоему, нужен только для Ki |
18 |
19 | void setup () { |
20 | pid.Kp = 1; |
21 | pid.Ki = 0; |
22 | pid.Kd = 0; |
23 | pid.setDt(dt); //частота опроса с датчика |
24 | pid.setDirection(NORMAL); //работа на увеличение |
25 | pid.setpoint = 60; //нужная температура |
26 |
27 | pinMode(ZERO_PIN, INPUT_PULLUP); |
28 | pinMode(DIMMER_PIN, OUTPUT); |
29 | attachInterrupt(INT_NUM, isr, RISING); // для самодельной схемы ставь FALLING |
30 | Timer2.enableISR(); |
31 | Serial .begin(9600); |
32 | } |
33 |
34 | void loop () { |
35 | temp(); |
36 | pidControl(); |
37 |
38 | } |
39 |
40 | void temp() { |
41 | static uint32_t timer = millis(); |
42 | if (millis() - timer >= 1000) { |
43 | timer = millis(); |
44 | if (ds.readTemp()) { |
45 | Serial .println(ds.getTemp()); |
46 | } |
47 | ds.requestTemp(); |
48 | } |
49 | } |
50 |
51 | void pidControl() { |
52 | static uint32_t tmr; |
53 | if (millis() - tmr > dt) { |
54 | tmr = millis(); |
55 | pid.input = ds.getTemp(); // передаем новый измеренный сигнал с датчика |
56 | pid.getResult(); //делает рассчеты, ее нужно вызывать по таймеру с периодом dt |
57 | pid.output; //принимает значение управляющего сигнала |
58 | dimmer = map(pid.output, 0, 125, 9300, 500); |
59 | } |
60 | } |
61 |
62 | // прерывание детектора нуля |
63 | void isr() { |
64 | static int lastDim; |
65 | digitalWrite(DIMMER_PIN, 0); // выключаем симистор |
66 | // если значение изменилось, устанавливаем новый период |
67 | // если нет, то просто перезапускаем со старым |
68 | if (lastDim != dimmer) Timer2.setPeriod(lastDim = dimmer); |
69 | else Timer2.restart(); |
70 | } |
71 | // прерывание таймера |
72 | ISR(TIMER2_A) { |
73 | digitalWrite(DIMMER_PIN, 1); // включаем симистор |
74 | Timer2.stop(); // останавливаем таймер |
75 | } |
а прямо к лампочке прислонить?
или поставь -
pid.setpoint = 50;
//нужная температура
Лампочка осиливает температуру в 60 градусов. И 80 осиливает.
Если поставить 50 градусов, то будет доходить до ~45 и там останавливаться.
У тебя система настолько медленная, а опросы настолько частые, что колебаний ты не увидишь
Тут даже фазное регулирование ни к чему.
Тупо ШИМ организуй с периодом 0,1Гц и скважность регулируй с дискретностью 10мс.
как я понял, датчик температуры 18D20 чаще чем каждые 0,85 сек опрашивать бесполезно. Поэтому выставлено на 1 сек.
но какое-то решение должно же быть? как его найти?
как я понял, датчик температуры 18D20 чаще чем каждые 0,85 сек опрашивать бесполезно. Поэтому выставлено на 1 сек.
но какое-то решение должно же быть? как его найти?
Я же говорю, система медленная, а опросы слишком частые.
Пересчитыйвай, значение хотя бы раз в 10сек, а не каждую секунду.
Понял. Спасибо! Буду пробовать