Уроки Ардуїно
Блог технічної підтримки моїх розробок
Головне меню
Урок 41. Розробка контролера елемента Пельтьє. ПІД регулятор температури.

Продовжимо розробку контролера елемента Пельтьє, розпочату в уроці 36. Додамо до проекту регулятор температури.
Регулятор температури виконує основну функцію холодильника – стабілізацію температури в камері. Саме він багато в чому визначає основні параметри пристрою: точність підтримки температури і швидкість реакції на впливи, що обурюють. Тому реалізовуватимемо регулятор температури згідно із законом ПІД регулювання.
Ще раз наведу структурну схему зв'язку регуляторів потужності та температури.

Регулятор температури отримує виміряне значення температури в камері, порівнює його із заданим та формує значення заданої потужності для регулятора потужності. Отже, у регуляторі температури:
- регульований параметр – температура у камері;
- регулюючий елемент – задана потужність регулятора потужності.
Для того щоб стабілізувати температуру треба її вимірювати. Тому перше, що додамо в програму, - це вимірювання температури в камері. Водночас реалізуємо вимірювання температури радіатора гарячої сторони елемента Пельтьє.
Реалізація вимірювання температури в камері та температури радіатора гарячої сторони модуля Пельтьє.
Температуру вимірюємо інтегральними датчиками DS18B20. Достатньо докладно про підключення датчиків такого типу до Ардуїно розказано в уроці 26. Для тих, хто не знає, як працювати з цими термодатчиками, слід уважно прочитати урок 26.
Підключимо датчики DS18B20 до плати Ардуїно за стандартною схемою. Ще на початку розробки мивирішили, що будемо використовувати аналогові висновки A2 та A3 у дискретному режимі.

Зібрана схема виглядає так.

Тепер допрацьовуватимемо програму.
Підключимо бібліотеку OneWire:
Додамо змінні для виміряних температур:
float measureTempRef; // Виміряна температура в камері (MEASURE_MAX_TEMP) measureTempRef = -300.; // помилка виміру > else measureTempRef=-300.; // помилка виміру >
if (cycle20mcCount == 46) // --------------------------- інтервал 46, читання датчика температури радіатора sensTempRad .reset(); // скидання шини 1-Wire sensTempRad.write(0xCC, 1); // пропуск ROM sensTempRad.write(0xBE, 1); // команда читання пам'яті датчика sensTempRad.read_bytes(bufData, 9); // Читання пам'яті датчика, 9 байтів
if ( OneWire::crc8(bufData, 8) == bufData[8] ) < // перевірка CRC // правильно measureTempRad= (float)((int)bufData[0] (((int)bufData[1]) MEASURE_MAX_TEMP)) measureTempRad= -300.; // помилка виміру > else measureTempRad=-300.; // помилка виміру >
Отримані результати перевіряються ще верхнє і нижнє максимальне значення. Якщо температура в нашій системі більша за 100 або нижче 40 °C це явна помилка.
Залишилося вивести виміряні температури на комп'ютер для перевірки.
Serial.print("t="); Serial.print(measureTempRef, 2); // температура в камері Serial.print("t="); Serial.print(measureTempRad, 2); //температура радіатора
Повністю скетч програми з вимірюванням температур у камері та радіатора можна завантажити за цим посиланням:
Зареєструйтесь та сплатіть. Усього 25 руб. на місяць за доступ до всіх ресурсів сайту!
Завантажуємо скетч у плату, відкриваємомонітор послідовного порту. Все працює.

Температура вимірюється правильно.
Реалізація ПІД регулятора температури.
Під час розробки регулятора потужності (урок 39) я зробив невелику помилку. Для швидкого вимикання регулятора використовував умову setPower == 0. Тобто. при заданій потужності, що дорівнює 0, регулятор миттєво вимикався, інтегральне ланка скидалося. Швидке вимкнення потрібне для реалізації в майбутньому аварійних режимів.
Але задана потужність може на короткий час стати рівною 0 під дією складової, що диференціює. Я змінив умову аварійного вимкнення регулятора потужності:
Тепер вимкнення регулятора відбувається за будь-якого негативного значення заданої потужності.
Отже. Створюємо всі змінні та константи, необхідні для регулятора температури.
#define koeffRegTmpInt 0.002 // інтегральний коефіцієнт регулятора температури #define koeffRegTmpPr 0.5 // пропорційний коефіцієнт регулятора температури #define koeffRegTmpDif 50 // коефіцієнт коефіцієнта регулятора температури, що диференціює
#define MAX_POWER 5. // максимальна вихідна потужність контролера
float regPwrInt=0; // інтегральна ланка регулятора потужності float maxSetPower = MAX_POWER; // максимальна задана потужність float regTmpInt=0; // інтегральна ланка регулятора температури float regTmpPr; // пропорційна ланка регулятора температури float regTmpDif; // диференціальна ланка регулятора температури float regTmpErr; // помилка неузгодженості температури float regTmpErrPrev; // Попередня помилка неузгодженості температури float setTempRef; // задана температура у камері
Поясню лише параметри обмеження потужності.
Константа MAX_POWERвизначає максимальну потужність, яку здатний створити контролер. Це апаратні обмеження на блок живлення, ключовий стабілізатор, модуль Пельтьє тощо.
Змінна maxSetPower визначається користувачем і в будь-який момент може бути змінена кнопками контролера. Вона запроваджує додаткове обмеження на вихідну потужність. Наприклад, хтось хоче обмежити споживану потужність для економії електроенергії.
Сам регулятор виконаємо в циклі 20 мс на інтервалі 47 відразу після отримання результатів вимірювання температури.
if (cycle20mcCount == 47) // --------------------------- інтервал 47, регулятор температури в камері
setTempRef = 20.; // тимчасово задана температура regTmpErr = measureTempRef - setTempRef; // Обчислення помилки неузгодженості
При різкому зменшенні сигналу неузгодженості диференціальна складова повинна зменшувати вихідний сигнал регулятора. Тобто. диференціююча складова повинна відніматися з інших складових. Уважно подивіться на показання монітора послідовного порту. При наближенні (зниженні) реальної температури до заданої складова, що диференціює, зменшує задану потужність.
Едуард з нетерпінням чекаю завершення проекту. Я збираю таку саму штуку, але ось загвоздка у мене буде стояти кілька елементів пельтьє т.к. мені необхідно сильніше охолодження і стояти вони будуть з різних боків корпусу, а точніше сам корпус буде алюмінієвим радіатором, і зверху закритий термоізоляцією. І у зв'язку з цим питання чи не можна зробити контроль температури та керування потужністю для декількох елементів пельтьє від ардуїно та відстежувати навантаження. Сам у програмуванні я не селен. а збирати кілька контролерів на один пристрій не доцільно.
Можливо простішепідключити кілька елементів Пельтьє паралельно і зробити потужніший регулятор.
Мені необхідно контролювати пельтьє від перегріву, якщо вони запараленні, то контроль відсутня, і велика ймовірність, що один буде більше нагріватися, ніж інший, в результаті ккд нижче ніж з контролем, а у мене працюють вони на граничних навантаженнях і велика ймовірність виходу з ладу пельтьє .
Контроль температури гарячої сторони це найпростіше завдання. Вимірюйте температуру кількома датчиками і відпрацьовуйте захист. У наступному уроці зроблю захист від перегріву. До речі, може відкрити тему на форумі сайту. Хтось поділиться своїм досвідом.
Привіт Едуард. Скажіть, а чому підключили датчики за схемою паразитного живлення, а не стандартним, 3-х провідним способом?
Вітаю! Провід заощаджував. Але ви можете легко змінити.
Вітаю. Питання щодо програми. Для чого спочатку обмежувати інтегральну складову значенням maxPower, а потім сам вихідний сигнал тим же значенням? Чи не краще інтегральну складову обмежувати максимальним позитивним значенням змінної, щоб не було перескоку на негативні?
Вітаю! Якщо обмежити тільки вихідне значення регулятора, то при негативних значеннях пропорційної або диференціальної складових інтегральна складова може стати вищою за максимально-допустиму.
Вітаю. Переглянув весь скетч, але так і не зрозумів: у цьому рядку regTmpDif= (regTmpErr - regTmpErrPrev) * koeffRegTmpDif; використовується regTmpErrPrev, але хоч якесь значення їй надається тільки в наступному рядку regTmpErrPrev=regTmpErr; Як тоді проводитися обчислення в попередньому рядку, якщо regTmpErrPrev не має початкового значення?
Вітаю! У цьому сенс. З помилки неузгодженості поточної температури віднімається її попереднє значення. Тільки при запуску програми в перший момент використовуватиметься значення 0. А далі все працює логічно.
При ініціалізації змінних компілятор встановлює у яких 0. Диференціальний регулятор немає пам'яті більше як один такт.
Щоб зайвий раз наголосити, що початкове значення для цих змінних має важливе значення.