Контуры управления

Ответить
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
Контуры управления

Сообщение Oleg »

Хотя эти уроки посвящены в основном исполнительным устройствам (двигателям, нагревателям, источникам света и прочим «выходным приспособлениям»), во многих схемах, использующих исполнительные устройства, также находят применение и датчики для отслеживания поведения исполнительных устройств. В качестве характерного примера можно привести термостатический управляемый нагреватель, где управление мощностью нагревательного элемента осуществляется на основе считывания показателей температурного датчика. Такое управление может осуществляться простым включением/выключением элемента, или же быть основано на более совершенной технологии, например, на так называемом пропорционально- интегрально-дифференциальном управлении (от англ. proportional-integral-deriva- tive, PID),

В этой главе рассматриваются вопросы объединения датчиков и исполнительных устройств с целью создания системы управления - эта технология будет применена для доработки проекта охладителя напитков, реализованного ранее.
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
Простой термостат

Сообщение Oleg »

Наверное, для понимания принципов объединения в единую систему управления датчика и исполнительного устройства, лучше всего начать с попытки поддержания постоянного температурного режима за счет использования температурного датчика и нагревательного элемента. Принципы, усвоенные при рассмотрении этого примера, могут с таким же успехом применяться для управления позицией двигателя, или уровнем воды в резервуаре, или в любой другой сфере, допускающей как измерение существующего состояния, так и управление его изменением с применением электронных устройств.

На рисунке показано, почему такие системы называются контурами управления.

В случае с термостатом в доме устанавливается желаемая температура - назовем ее контрольной, или заданной, температурой. Температурный датчик измеряет фактическую температуру. Вычитанием фактической температуры из заданной определяется величина рассогласования. Затем контроллер получает эту величину для вычисления мощности, подаваемой на нагреватель.
Контур управления (на примере термостата)
Контур управления (на примере термостата)
В самом простом варианте нагреватель только включается и выключается. Если рассогласование температур имеет положительную величину (т. е. заданная темпе ратура выше фактической), значит, в доме достаточно холодно, чтобы включить нагреватель. Или же, если фактическая температура стала выше заданной, значит, в доме достаточно жарко, чтобы снова отключить нагреватель.

В разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?» для создания простого термостата мы воспользуемся Arduino в сочетании с резистором в качестве нагревателя и цифровым температурным датчиком. Это же оборудование будет использовано при изучении более точных способов управления исполнительным устройством.
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?

Сообщение Oleg »

В этом эксперименте для реализации простой системы температурного регулирования путем включения/выключения нагревателя используется плата Arduino и интегральная микросхема цифрового температурного датчика DS18B20. Роль нагревательного элемента исполнит резистор сопротивлением 100 Ом, физически прикрепленный к микросхеме DS18B20, измеряющей его температуру.

Для установки заданной температуры через окно монитора порта будут подаваться соответствующие команды, считываемая температура будет также отображаться на этом мониторе. Считанные температурные показатели можно копировать и вставлять в электронную таблицу, создавая затем с ее помощью графики, показывающие качество регулирования температуры.

Небольшие габариты и близкое расположение компонентов позволяют проводить эксперименты с температурным регулятором, не прибегая к использованию крупных (и в силу этого медленно поддающихся изменениям) объектов. Схема этого эксперимента показана на рисунке ниже - обратите внимание на прищепку, крепко прижимающую резистор к микросхеме температурного датчика.
Схема эксперимента по созданию термостатической системы регулирования на основе включения/выключения нагревателя с использованием Arduino в сборе
Схема эксперимента по созданию термостатической системы регулирования на основе включения/выключения нагревателя с использованием Arduino в сборе
Комплектующие

В этом эксперименте для работы с Arduino или Raspberry Pi (независимо от того, какая именно плата используется) понадобятся следующие комплектующие:
IC1 - Микросхема цифрового термометра DS18B20
R1 - Резистор 4,7 ком
R2 - Резистор 1 ком
R3 - Резистор 100 Ом 0,25 Вт
Q1 - Составной транзистор МРЅА14
400-точечная беспаечная макетная плата
Перемычки
Небольшая прищепка

Если нет небольшой прищепки, можно взять обычную, но обязательно пластмассовую, - чтобы не закоротить ненароком выводы резистора или микросхемы.

Иногда микросхема DS18B20 предлагается совместно с резистором на 4,7 ком Кроме того, ее часто продают в водонепроницаемом корпусе. Для эксперимента желательно использовать «голую» микросхему (выглядящую как обычный транзистор), но если есть стремление продолжить работу и создать настоящий термостат, то для проекта из рассматриваемого далее разд. «Проект: термостатический охладитель напитков» идеально подойдет как раз се вариант в виде водонепроницаемого датчика.

Принципиальная схема эксперимента

Принципиальная схема для нашего эксперимента показана на рисунке ниже. Она фактически состоит из двух частей: температурного датчика DS18B20, которому требуется гасящий резистор R1 номиналом 4,7 кОм, и нагревательной части, в центре которой установлен транзистор Q1. Резистор R2 ограничивает ток, поступающий на базу транзистора, а резистор R3 служит в качестве нагревательного элемента.
Принципиальная схема эксперимента с термостатом на основе включения/выключения
Принципиальная схема эксперимента с термостатом на основе включения/выключения
МИКРОСХЕМА DS18B20
Микросхема DS18B20 - весьма полезное малогабаритное устройство. И дело не только в ее точности (±0,5 градуса по Цельсию), но и в том, что она допускает создание цепочки из подобных устройств с использованием только одного контакта Arduino или Raspberry Рі.


Инструкцию по подключению нескольких датчиков DS18B20 и отдельному обращению к ним можно найти в программе для Arduino от Майлза Бартона (Miles Burton) по адресу: https://milesburton.com/Dallas_Temperat ... ol_Library

При извлечении данных из нескольких устройств на Raspberry Pi при открытии файлов устройств нужно использовать для этих устройств разные идентификаторы.

Макетная схема эксперимента

Схема, собранная для проведения эксперимента на макетной плате, показана на рисунке ниже.
Собранная на макетной плате схема для термостата на основе включения/выключения
Собранная на макетной плате схема для термостата на основе включения/выключения
Резистор нагревателя R3 размещается сразу же за плоской стороной датчика DЅ18В20 - чтобы их можно было крепко прижать друг к другу небольшой прищепкой.

В схеме задействованы два контакта Arduino: контакт D9 служит для управления транзистором, включая и выключая с его помощью питание резистора, выступающего в роли нагревателя, а контакт D2 является входом сигнала от цифрового датчика.

Размещайте транзистор и микросхему DS18B20 правильно- к правому краю макетной платы.
Резистор и датчик DS18B20 прижаты друг к другу небольшой прищепкой
Резистор и датчик DS18B20 прижаты друг к другу небольшой прищепкой
Программа

Микросхема DВ18B20 работает на шине под названием 1-Wire («один провод»). Чтобы использовать эту микросхему в качестве датчика для Arduino, нужно загрузить две библиотеки Arduino и установить их в среду Arduino IDE.

Сначала загрузите библиотеку OneWire (http://www.pjrc.com/teensy/arduino libraries/OneWire.zip). Распакуйте загруженный архив и каталог с именем OneWire и установите в вашу среду Arduino.

Для загрузки второй библиотеки непосредственно для самой микросхемы DS18B20 зайдите на страницу

https://github.com/milesburton/Arduino- ... ol-Library и щелкните там по кнопке Download ZIP (Загрузить ZIP-файл). После распаковки архива у вас образуется папка с именем dallas-temperature-control, которую, перед тем как переместить ее в ваш каталог libraries, нужно переименовать в Dallas Temperature.

УСТАНОВКА БИБЛИОТЕК ARDUINO
Среда Arduino IDE включает множество предустановленных библиотек, но иногда возникает необходимость загрузить библиотеку, не включенную в IDE-среду из Интернета. Делается это весьма просто: обычно библиотека загружается в виде ZIP-архива, который нужно распаковать в отдельный каталог. Имя этого каталога должно совпадать с именем библиотеки, но случается, что загруженный каталог не будет иметь точно такое же имя, особенно когда загрузка ведется из GitHub.

После переименования каталога (при необходимости) его нужно переместить в ваш, предназначенный для Arduino, каталог libraries, который находится в вашем же каталоге arduino. Среда Arduino IDE должна была автоматически создать каталог arduino внутри вашего каталога. Documents - именно в нем Arduino хранит свои небольшие программы.

Создавая самую первую библиотеку, прежде чем перемещать загруженную библиотеку в каталог libraries (его пока еще нет), в каталогe arduino/ нужно создать каталог с этим именем: libraries.

Чтобы после установки новой библиотеки она была распознана, понадобится провести перезапуск среды Arduino IDE.

Скетч Arduino для этого проекта:

Код: Выделить всё

#include <OneWire.h>
#include <DallasTemperature.h>

const int tempPin = 2;     // (1)
const int heatPin = 9;
const long period = 1000;  // (2)

OneWire oneWire(tempPin);  // (3)
DallasTemperature sensors(&oneWire);

float setTemp = 0.0;       // (4)
long lastSampleTime = 0;

void setup() {  
  pinMode(heatPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("t30 - sets the temperature to 30");
  sensors.begin();        // (5)
}

void loop() { 
  if (Serial.available()) {     // (6)
    char command = Serial.read();
    if (command == 't') {
      setTemp = Serial.parseInt();
      Serial.print("Set Temp=");
      Serial.println(setTemp);
    }
  }
  long now = millis();         // (7)
  if (now > lastSampleTime + period) {
    lastSampleTime = now;
    float measuredTemp = readTemp();    // (8)
    float error = setTemp - measuredTemp;
    Serial.print(measuredTemp);
    Serial.print(", ");
    Serial.print(setTemp);
    if (error > 0) {                    // (9)
        digitalWrite(heatPin, HIGH);
        Serial.println(", 1");
    }
    else {
      digitalWrite(heatPin, LOW);
      Serial.println(", 0");
    }
  }
}

float readTemp() {     // (10)
  sensors.requestTemperatures(); 
  return sensors.getTempCByIndex(0);  
}
Уточним некоторые моменты скетча по пунктам, воспользовавшись разметкой строк, сделанной в комментариях:

1. Код начинается с определения констант для контакта считывания температуры (tempPin) и контакта управления нагревателем (neatPin).
2. Константа реriod используется для установки интервала времени между последовательными считываниями температуры. Микросхема DS18B20 не обладает особо высоким быстродействием, и этот интервал может составлять до 750 мс, поэтому для period лучше выбрать значение не меньше, чем 750.
3. Обеим библиотекам, DallasTemperature И ОneWire, нужны переменные, определяемые для получения доступа к ним.
4. Переменная setTemp содержит текущую заданную температуру, а переменная lastSampleTimе используется для показателя времени съема последнего значения температуры.
5. Инициализация библиотеки DallasTemperature.
6. Первая часть функции loop() проверяет последовательные команды, поступающие из окна монитора порта. Фактически, имеется только одна возможная команда ('t'), за которой следует желаемая устанавливаемая температура в градусах Цельсия. После установки нового значения setTemp, оно возвращается эхом в окно монитора порта для подтверждения.
7. Вторая половина looр() сначала проверяет, не настало ли время для нового считывания, т. е. не истек ли период, указанный в миллисекундах
8. Температура измеряется, и вычисляется рассогласование, после чего значения measuredTemp и setTemp записываются в окне монитора порта.
9. Если рассогласование больше нуля, нагреватель включается, и в конце строки на мониторе появляется цифра 1, означающая включение питания нагревателя. В противном случае нагреватель выключается, и на экран отправляется цифра 0.
10. Всю цепочку, состоящую из датчиков DS18B20, можно подключать к одному и тому же входному контакту, поэтому команда геquestTemperature просит все подключенные микросхемы DS18B20 (в нашем случае, только одну микросхему) провести измерение температуры и отправить результат. Затем для возвращения считанного результата с первой и единственной подключенной микросхемы DЅ18B20 используется вызов функции getTempCByIndex.

Загружаем и выполняем программу

Загрузите программу и откройте окно монитора порта в нем должен появиться постоянный поток считанных температурных данных (учтите, что микросхема DS18B20 разработана для работы по температурной шкале Цельсия, и, поскольку этой главе присуща некая научная составляющая, я на всем ее протяжении придерживаюсь температурных единиц, выраженных в градусах Цельсия):

Код: Выделить всё

t30 - устанавливает температуру на 30
21.75, 0.00, 0
21.69, 0.00, 0
21.75, 0.00, 0 
21.69, 0.00, 0
21.75, 0.00, 0
В трех выводимых столбцах показываются: измеренная температура, заданная температура (в данном случае 0) и индикатор включения электропитания нагревателя (0 или 1).

Введите команду t30, чтобы установить желаемую температуру равной 30°С. Температура тут же начнет подниматься, поскольку нагреватель сразу включится, о чем будет свидетельствовать цифра в третьем столбце:

21.75, 0.00, 0
21.75, 0.00, 0
Установленная температура 30.00
21.75, 30.00, 1
21.75, 30.00, 1
21.81, 30.00, 1
21.94, 30.00, 1
22.06, 30.00, 1

Когда температура достигнет 30°С, нагреватель должен будет отключиться, и вы должны увидеть цикл включения/выключения нагревателя при колебании температуры возле значения 30 °С:

29.87, 30.00, 1
29.94, 30.00, 1
29.94, 30.00. 1
30.00, 30.00, 0
30.06, 30.00, 0
30.12, 30.00, 0
30.06, 30.00, 0.
29.94, 30.00, 1
29.81, 30.00, 1
29.75, 30.00, 1

Получилось! Вы создали термостат, и он вполне может пригодиться для решения многих задач. Но не трудно заметить, что температура «рыскает» вокруг заданного значения в 30 градусов. Размах этого рысканья можно увидеть, скопировав фрагмент данных, вставив его в файл, используя текстовый редактор, и задав для имени файла расширение csv. Затем этот файл можно импортировать в удобную для вас программу электронной таблицы и создать из данных файла график, получив в ре зультате изображение, один из вариантов которого показан на рисунке ниже.
построение графика температуры простого термостата, работающего на основе включения/выключения
построение графика температуры простого термостата, работающего на основе включения/выключения
Как видите, температура колеблется выше-ниже заданной почти на полградуса. Существенно улучшить наши результаты можно за счет использования уже упомянутой ранее технологии управления, называемой пропорционально-интегрально- дифференциальным регулированием (ПИД). И хотя само название ПИД - наводит на мысль о применении сложных математических выкладок, всю работу можно упростить, следуя нескольким основным правилам.
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
Гистерезис

Сообщение Oleg »

Использование транзистора для включения/выключения питания позволяет добиться высокой скорости этого процесса и воспользоваться технологией ШИМ. Но для некоторых систем очень частое включение/выключение электропитания устройства крайне нежелательно. Это может относиться и к бытовому нагревателю, которому нужно время для начала выработки тепла после его включения в сеть. К тому же, управление им с использованием электромеханических выключателей и других подобных устройств в режиме постоянного включения/выключения сократит срок службы нагревателя.

Чтобы предотвратить слишком быстрое переключение, нужно установить ему минимальное время, не позволяющее устройству отключаться, пока оно не истечет, или же ввести гистерезис.
Гистерезис в термостате
Гистерезис в термостате
Применительно к термостату, гистерезис означает наличие не одного, а двух температурных порогов, один из которых выше другого на определенную фиксированную величину. Если температура падает ниже нижнего порога, нагреватель включается, но выключается он только при превышении температурой верхнего

порога. Таким образом, для введения задержки в процесс переключения используется естественная инерционность системы.
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
ПИД-управление

Сообщение Oleg »

Выключение нагревателя в тот момент, когда температурный датчик показывает, что нагреватель горячее заданной температуры, и его включение, когда он холоднее ее, приводит к созданию системы, где температура «рыскает» вокруг заданного значения.

Для более точного поддержания температуры следует воспользоваться пропорционально-интегрально-дифференциальным (ПИД) регулированием.

Вместо простого включения/выключения нагревателя, ПИД-контроллер регулирует выходную мощность нагревателя (или другого исполнительного устройства), принимая в расчет три фактора: пропорциональность, интегральность и дифференциальность.

Предупреждение
В этом разделе нам предстоит более глубокое погружение в теорию. Вопросы по ПИД управлению мне задавались весьма часто, и в качестве одной из основных целей я выбрал рассмотрение принципов работы и применения ПИД-регулирования.

Пропорциональность (П)

Используя одну лишь П-часть ПИД-контроллера и игнорируя две остальные - И и Д. можно на многих системах добиться весьма неплохих результатов. части- Поэтому на каждой новой системе в любом случае следует начинать с одной только части П. и смотреть, насколько приемлемым окажется результат.

Пропорциональное управление означает, что подаваемая на нагреватель мощность пропорциональна рассогласованию. Чем больше рассогласование, т. е. чем ниже фактическая температура от заданной, тем больше мощности подается на нагрева тель. Как только фактическая температура близко подходит к заданной, мощность снижается, и получается, что фактическая температура не настолько сильно пре- вышает заданную, как показано на рисунке "построение графика температуры простого термостата, работающего на основе включения/выключения". В зависимости от системы, она, скорее всего, все же превысит заданную, но совсем не настолько, как это происходит при простом управлении на основе включения/выключения. Этот процесс отчасти напоминает приближение на машине к знаку СТОП подъезжая к нему, вы начинаете тормозить заранее, а не непосредственно у самого знака.

Если фактическая температура выше заданной, рассогласование будет отрицательным, и это должно выразиться в отъеме мощности от нагревателя. Если нагреватель был бы элементом Пельтье, то можно было бы, используя Н-мост, пустить ток через него в обратном направлении и превратить его из нагревателя в охладитель. Впрочем на практике, если только окружающая температура не сильно отличается от заданной, так делать не приходится. Вместо этого можно просто дать системе остыть (или нагреться) естественным образом.

Рассогласование, на котором основывается вычисление подаваемой выходной мощности в случае с термостатом, - это разница температур. Выражая его в градусах Цельсия, получим, что если заданная температура равна 30°С, а измеренная - 25°С, то рассогласование равно 5°С (30°C 25°С). Если для установки выходной мощности используется ШИМ-схема Arduino, то выход будет иметь значение в диапазоне от 0° до 255°С. Поэтому непосредственная установка на величину рассогласования (5) приведет к подаче на нагреватель слишком малой мощности, которой, скорее всего, не хватит, чтобы он нагрелся до 30°С. Следовательно, чтобы получить значение подаваемой выходной мощности, рассогласование умножается на число, называемое kp (которое иногда называют также увеличением, от англ. gain). Изменение kp определит, насколько быстро температура станет подниматься до заданной. При низком значении kp температура может никогда не дойти до за- данной, но при слишком высоком значении kp система будет вести себя точно так же, как контроллер температуры на основе включения/выключения, и фактическая температура станет колебаться вокруг заданной температуры. На рисунке ниже показано, как различные значения к меняют поведение идеализированной системы.
Влияние величины кр (gain) на выход в пропорциональном контроллере
Влияние величины кр (gain) на выход в пропорциональном контроллере
Здесь видно, что если значение к недостаточно высоко, температура может никогда не подняться до заданной, или же на это может уйти слишком много времени. С другой стороны, если значение ко слишком велико, на выходе начнутся колебания, и их величина не станет уменьшаться. Подходящее значение kp будет быстро подгонять выход до заданного уровня, возможно, с небольшим превышением, а затем колебания быстро сойдут (успокоятся) на приемлемо низкий уровень.

Поиск подходящего значения kp называется настройкой системы. Настройка ПИД-регулирования будет рассмотрена далее.

Вернемся к примеру с заданной температурой, равной 30°С, но при фактической температуре 25°С. В этом случае по-прежнему желательно, чтобы на нагревателе рассеивалась максимальная мощность, т. е. для ШИМ был бы установлен коэффициент заполнения 255 (100%). Если в качестве значения kp выбрать 50, то рассогласование в 5 единиц приведет к подаче следующей выходной мощности:

Выход = рассогласование х kp=5 х 50 = 250

Как только система окажется всего в 1°С от заданной температуры, выходная мощность упадет до следующего значения:

Выход = рассогласование х kp=1 х 50= 50

Этой мощности может хватить, а может и не хватить для достижения системой заданной температуры. Системы отличаются друг от друга, поэтому контроллер нуждается в настройке.

Интегральность (И)

Если предположить, что от пропорционального управления мощностью нужной точности добиться не удается, в вычисления может понадобиться добавить некое значение I, чтобы выходная мощность вычислялась по следующей формуле:

Выход = рассогласование х kp+I x ki

Здесь присутствует новая константа ki, масштабирующая наше новое загадочное свойство по имени I (откроем секрет- это как раз и есть Интегральность), и выходная мощность будет вычисляться путем сложения этой интегральной составляющей с уже рассмотренной нами ранее пропорциональной составляющей. Такой тип контроллера называется ПИ-контроллером (PI, или иногда Р + I, не путайте с Рі в названии Raspberry Pi). Как применение чисто пропорционального контроллера, так и применение ПИ-контроллера, иногда приводит к получению вполне приемлемых результатов, исключая необходимость добавления третьей составляющей ПИД-регулятора, Д.

Интегральная составляющая вычисляется путем сохранения текущей суммы рассогласований при каждом измерении температуры. Когда рассогласование имеет положительное значение (разогрев), I-составляющая будет становиться все больше и больше, превышая значение первоначального ответа. Уменьшение начнется только тогда, когда рассогласование станет отрицательным после превышения заданной температуры.

Как только фактическая температура достигнет заданной, I-составляющая окажет успокаивающее воздействие, сглаживая температурные изменения, чтобы температура лучше закреплялась на желаемом значении.

Единственная проблема, связанная с I-составляющей, заключается в том, что она дает большой прирост по мере подъема температуры, это приводит к возможному большему превышению температуры, после чего требуется время на то, чтобы она снизилась до заданной и стабилизировалась.

Дифференциальность (Д)

На практике D-составляющая зачастую в реальных системах управления не используется, потому что преимущества от ее использования для снижения промахов перевешиваются усложнением настройки.

При добавлении к программе управления D-составляющей, противодействующей эффекту промахов, выходная мощность вычисляется по следующей формуле:

Выход = рассогласование х kp+I x ki+D x kd.

D-составляющая является мерой того, насколько быстро меняется рассогласование между каждыми замерами температуры, и поэтому она в некотором смысле предсказывает, куда пойдет температура.

Настройка ПИД-регулятора

Настройка ПИД-контроллера означает поиск значений kp, ki и kd, заставляющих систему вести себя подобающим образом. Я рекомендую не усложнять себе жизнь, и использовать только ПИ-регулировку, устанавливая для ка нулевое значение, тогда останется настроить только два параметра. Фактически, это упрощение об легчает настройку большинства систем, однако несколько увеличивает затрачиваемое на нее время.

Далее в разд. «Эксперимент: термостатический ПИД-регулятор», я проведу вас через метод проб и ошибок, который неплохо подходит для тех температур, с которыми работает контроллер. Остальная часть раздела будет посвящена наиболее популярному способу ПИД-настройки, носящему название метод Циглера-Никольса (Ziegler-Nichols). Этот метод существенно сокращает процесс получения значений kp, ki и kd, сводя его к серии экспериментов с последующими простыми вычислениями.

Настройка Циглера-Никольса начинается с установки нулевых значений для ki и kd, чтобы контроллер стал работать в пропорциональном режиме. Значение kp затем постепенно увеличивается, пока выходная мощность не начнет колебаться. Значение kp, при котором это происходит, называется ku

После определения значения ко нужно измерить количество колебаний в секунду (период колебаний, называемый здесь pu).
]определение количества колебаний в секунду (периода колебаний)
]определение количества колебаний в секунду (периода колебаний)
Чтобы его получить, нужно нанести на график показания мощности на нагрузке, как это делалось в эксперименте из разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?».

Затем можно вычислить значения для kp, ki и kd

kp=0.6 x ku
ki = (2 х кр) / pu
kd (kp х pu) / 8


Если у вас используется ПИ-контроллер, то лучше воспользоваться следующими

вычислениями:

кр = 0.45 * ku
ki = (1.2 x kp) / pu
kd = 0

Статью, посвященную методу Циглера-Никольса, можно найти в Википедии (http://ru.wikipedia.org/wiki/ПИД-регулятор).
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
Эксперимент: термостатический ПИД-регулятор

Сообщение Oleg »

В этом эксперименте мы исследуем работу ПИД-регулятора с использованием как Arduino, так и Raspberry Pi. Программа для ПИД-контроллера с использованием Arduino берется из библиотеки, а программу для ПИД-контроллера с использованием Raspberry Pi придется набирать вручную.

Оборудование

В этом эксперименте используется точно то же самое оборудование, что и в экспе рименте из разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?». Но при подключении его к Raspberry Pi, нужно про- явить особое внимание, поскольку микросхему DS18B20 и нагреватель из резистора следует запитать на Рі отдельно: микросхему DS18B20 от напряжения 3,3 В, а резисторный нагреватель от напряжения 5 В. Дело в том, что цифровой выход из DS18B20 должен повышаться до 3,3 В, а не до 5 В, чтобы не повредить входные цепи Raspberry Рі.

Программа для Arduino

В этом эксперименте используется готовая к использованию ПИД-библиотека

(https://github.com/br3ttb/Arduino-PID-Library/), которую можно загрузить и установить. Полную документацию по этой библиотеке можно найти на веб-сайте Arduino (http://playground.arduino.cc/Code/PIDLibrary).

Скетч, используемый в эксперименте с Arduino:

Код: Выделить всё

#include <OneWire.h>
#include <DallasTemperature.h>
#include <PID_v1.h>

const int tempPin = 2;
const int heatPin = 9;
const long period = 1000; // >750

double kp = 0.0;     // (1)
double ki = 0.0;
double kd = 0.0;


OneWire oneWire(tempPin);
DallasTemperature sensors(&oneWire);

double setTemp = 0.0;
double measuredTemp = 0.0;
double outputPower = 0.0;     // (2)
long lastSampleTime = 0;

PID myPID(&measuredTemp, &outputPower, &setTemp, kp, ki, kd, DIRECT); // (3)

void setup() {
  pinMode(heatPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("t30 - sets the temperature to 30");
  Serial.println("k50 20 10 - sets kp, ki and kd respectively");
  sensors.begin();
  myPID.SetSampleTime(1000); // (4)
  myPID.SetMode(AUTOMATIC);  
}

void loop() { 
  checkForSerialCommands();  // (5)
  
  long now = millis();
  if (now > lastSampleTime + period) { // (6)
    lastSampleTime = now;
    measuredTemp = readTemp();
    myPID.Compute();
    analogWrite(heatPin, outputPower);
  
    Serial.print(measuredTemp);  // (7)
    Serial.print(", ");
    Serial.print(setTemp);
    Serial.print(", ");
    Serial.println(outputPower);
  }
}

void checkForSerialCommands() {  // (8)
    if (Serial.available()) {
    char command = Serial.read();
    if (command == 't') {
      setTemp = Serial.parseFloat();
      Serial.print("Set Temp=");
      Serial.println(setTemp);
    }
    if (command == 'k') {
      kp = Serial.parseFloat();
      ki = Serial.parseFloat();
      kd = Serial.parseFloat();
      myPID.SetTunings(kp, ki, kd);
      Serial.print("Set Constants kp=");
      Serial.print(kp);
      Serial.print(" ki=");
      Serial.print(ki);
      Serial.print(" kd=");
      Serial.println(kd);
    }
  }
}

double readTemp() {
  sensors.requestTemperatures(); 
  return sensors.getTempCByIndex(0);  
}

Уточним некоторые моменты скетча по пунктам, воспользовавшись разметкой строк, сделанной в комментариях.

ПРИМЕЧАНИЕ
Код, относящийся к считыванию температурных данных с DS18B20, ничем не отличается от кода для эксперимента из разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?», поэтому здесь мы сосредоточим внимание на коде, относящемся к ПИД-регулированию.


1. В качестве коэффициентов масштабирования для Р-, I- и D-компонентов выхода определяются три переменные: кр, ki и kd. Использование переменных обу- словлено тем, что они могут изменяться с помощью команд в окне монитора порта в ходе выполнения программы. Тип double использован вместо типа float отчасти потому, что он позволяет работать с более точными числами, чем floats, а также потому, что именно этот тип ожидается библиотекой.

2. Переменная outputPower будет содержать коэффициент заполнения ШИМ в пределах от 0 до 255.

3. Для обращения к коду ПИД-библиотеки определена переменная myPID. Заметьте, что первые три параметра при создании переменной для обращения к ПИД-библиотеке являются именами переменных measuredTemp, outputPower и setTemp, перед которыми стоит префикс &. Это прием языка С, позволяющий ПИД-библиотеке изменять значения этих переменных, даже если они не явля-ются частью библиотеки. Если вас интересуют дополнительные сведения об этой технологии (указателях языка С), обратитесь к материалу Tutorials Point (http://www.tutorialspoint.com/cprogramm ... inters.htm). Последний параметр (DIRECT) устанавливает для ПИД-операции прямой режим, который в случае применения этой библиотеки означает, что выход будет пропорционален рассогласованию, и не будет инвертирован. Для удобства по умолчанию диапазон выходных значений для ШИМ устанавливается от 0 до 255.

4. Время периодичности снятия показаний нужно установить равным 1 секунде (1000 мс). ПИД-вычисления запускаются установкой режима на AUTOMATIC.

5. Теперь проверка поступления последовательных команд находится в своей собственной функции, останавливающей цикл looр(), что облегчает чтение кода. который ранее был слишком многословен.

6. Как только наступает время очередного замера температуры, происходит ее считывание в переменную measuredTemp, а затем ПИД-библиотека получает предписание на обновление своих вычислений (myРID.Compute). При этом автоматически производится обновление значения outputPower , которое затем используется для установки коэффициента заполнения ШИМ на контакте, используемом для управления резисторным нагревателем.

7. Все значения выводятся в окне монитора порта, поскольку они нужны нам для построения графиков и отслеживания работы контроллера.

8. Функция checkForSerialCommands проверяет выдачу команды для задания температуры, как и в эксперименте из разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?», но также проверяет и наличие команды k, за которой следуют три числа: kp, ki kd, устанавливая параметры настройки в случае получения команды.

Загружаем и выполняем программу

Оборудование и программа, предназначенные для этого эксперимента, дают нам все необходимое, чтобы провести эксперимент с ПИД-контроллером. Мы можем изменить заданную температуру и три значения kp, ki и kd- и записать влияние, оказываемое ими на выходе. В нашем случае вполне приемлемые результаты будут получены с ПИ-регулятором, поэтому для kd может быть просто установлено значение 0.

Итак, загрузите программу в Arduino и откройте окно монитора порта.
Использование окна монитора порта для тестирования ПИД-регулирования
Использование окна монитора порта для тестирования ПИД-регулирования
Настройка контроллера требует времени. Нужно будет записать данные и построить на их основе график, чтобы увидеть, насколько приемлемо поведение системы. Сначала следует подобрать подходящее значение для кр. Давайте просто попробу ем значения 50, 500 и 5000, чтобы получить представление о системе.

Прежде всего установим параметры настройки, введя в окне монитора порта следующие значения: k50 0 0

В результате для kp будет установлено значение 50, а для kі и kd- значения, равные нулю. Если хотите, можете ввести значения с указанием десятичной части (например, k30.0 0.0 0.0). В обоих случаях, числа будут преобразованы в формат чисел с плавающей точкой.

Теперь давайте установим заданную температуру на 30°С (это значение я выбрал как наиболее подходящее, превышающее значение температуры окружающей среды примерно на 7 или 8 градусов):
t30

Температура должна начать подниматься, что станет отображаться на экране, где появятся три столбца, показывающие фактическую температуру, заданную температуру и значение на выходе ШИМ (в диапазоне от 0 до 255);

25.06, 30.00, 246.88
25.19, 30:00, 240.63
25.31, 30.00, 234.38
25.44, 30.00, 228.13

Заметьте, что значение на ШИМ-выходе сохранено в виде числа с плавающей точкой, поэтому у него имеются цифры после десятичной точки. При вызове функции analogWrite это значение должно быть усечено до целого числа в диапазоне от 0 до 255.

Как можно видеть, значение коэффициента заполнения ШИМ в последнем столбце при заданном для kp значении 50 начинает почти сразу же снижаться. Это означает, что значение kp выбрано слишком низким, но вы продолжайте собирать данные еще несколько минут, а затем перенесите их в текстовый файл и импортируйте этот файл в программу электронной таблицы. Я начал копировать данные, когда температура достигла 25°С. Постройте по показателям температуры график и получите примерно такую же картину, что изображена на рисунке ниже.
График изменения температуры с течением времени для кр= 50
График изменения температуры с течением времени для кр= 50
Похоже, что при значении kp, равном 50, температура никогда не поднимется до 30°С. Задайте температуру 0°С (t0 - в окне монитора порта) и подождите, пока система не остынет, после чего повторите процедуру сначала для kp со значением 500, а потом со значением 5000. Результаты, полученные при этих трех значениях kp. показаны на рисунке ниже.

Как мы и предполагали, для kp значение 50 слишком мало, 500 уже больше подходит, но при нем значение заданной температуры все еще не достигается, а при значении 5000 система ведет себя как термостат, работающий по принципу включение/выключение. Можно выдвинуть предположение, что для kp вполне подойдет значение 700, особенно, если система получит ускорение в подъеме температуры за счет добавления значения для I-составляющей.

В методе настройки ПИ-контроллера от Циглера-Никольса предлагается вычислять значение ki по следующей формуле:

ki = (1,2 × kр)/pu

Мы прикинули, что для kp вполне подойдет значение 700, а из рисунка следует, что значение pu составляет приблизительно 15 секунд, из чего для ка предлагается значение 56.
График изменения температуры с течением времени для трех значений kp
График изменения температуры с течением времени для трех значений kp
График изменения температуры с течением времени для П и ПИ-регулирования
График изменения температуры с течением времени для П и ПИ-регулирования
Задайте Arduino еще один набор данных: с kp= 700 и k = 56. Результаты, полученные на его основе, показаны на рисунке выше, где они даны в сравнении с результатами для чисто пропорционального регулирования при значении kp равном 700. Ось Y здесь несколько растянута, чтобы можно было увидеть, насколько хороши результаты для ПИ-регулирования.

Как только кривая ПИ-графика достигнет заданной температуры, она будет изме няться на величину, слегка превышающую 0,1 градуса. Температура изменяется ступенчато, а не плавно, поскольку микросхема DS18B20 является цифровым уст ройством с фиксированным шагом.

Потратив дополнительные усилия на проведение экспериментов, можно, наверное, еще улучшить результат, но вряд ли этим стоит заниматься.

Подключение Raspberry Pi

Схема, собранная на макетной плате для Raspberry Pi, немного отличается от того, что было собрано для Arduino. Разница в том, что нам нужно, чтобы резисторный нагреватель по-прежнему работал от 5 В, а датчику температуры DЅ18В20, чтобы быть совместимым с GPIO-контактами Raspberry Pі, нужно работать от 3,3 В.
Компоновка макетной платы для подключения к Raspberry Pi
Компоновка макетной платы для подключения к Raspberry Pi
Программа для Raspberry Pi

Чтобы микросхема DS18B20 работала с Raspberry Pi, требуется небольшая подготовка. Сначала нужно включить шину 1-Wire. Для этого отредактируйте файл /boot/config.txt, воспользовавшись следующей командой:
$ sudo nano /boot/config.txt

Добавьте к концу файла следующую строку:
dtoverlay=w1-gpio

Теперь нужно перезапустить Raspberry Pi, чтобы изменения вступили в силу. В микросхеме DS18B20 используется интерфейс в стиле текстового файла, значит, программе на языке Python придется считывать файл, а затем извлекать из него температурные измерения. Можно попытаться сделать это до запуска всей программы и посмотреть, как выглядит формат сообщения, изменив с помощью следующей команды текущий каталог на /sys/bus/w1/devices:

$ cd /sys/bus/w1/devices

Затем нужно получить список каталогов, находящихся в этой папке, воспользовавшись следующей командой:
$ 1s
28-000002ecba60 w1_bus_master1
pi@raspberrypi /sys/bus/w1/devices $


Сделайте текущим каталог, чье имя начинается с 28. В нашем случае это каталог 28-000002ecba60 (учтите, что у вас, скорее всего, он будет иметь другое имя):
$ cd 28-000002ecba60

И, наконец, запустите следующую команду для извлечения последних считанных значений температуры:

$ cat w1_slave

Ответ приходит в двух строках:
53 01 4b 46 7f ff Od 10 e9 : crc=e9 YES
53 01 46 46 71 ff od 10 e9 t=21187
pi@raspberrypi /sys/bus/w1/devices/28-000002ecba60 $


Первая часть каждой строки представляет собой уникальный идентификатор для датчика температуры, а первая строка заканчивается словом YES, показывающим, что чтение прошло успешно. Вторая же строка заканчивается показанием температуры, выраженным в тысячных долях градуса Цельсия. В данном случае это 21 187 (или 21,187°С).

Хотя для ПИД-регулирования имеются доступные библиотеки на языке Python, использовать их сложнее, чем их двойников для Arduino, и поэтому для версии Raspberry Pi ПИД-алгоритм будет реализован с чистого листа (хотя и не совсем код был написан с оглядкой на библиотеку Arduino и с попыткой сделать две версии как можно более похожими друг на друга).

Код: Выделить всё

import os
import glob
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

heat_pin = 18 
base_dir = '/sys/bus/w1/devices/'   # (1)
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
 
GPIO.setup(heat_pin, GPIO.OUT)
heat_pwm = GPIO.PWM(heat_pin, 500)
heat_pwm.start(0)

old_error = 0 # (2)
old_time = 0
measured_temp = 0
p_term = 0
i_term = 0 
d_term = 0

def read_temp_raw():  # (3)
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
 
def read_temp():  # (4)
    lines = read_temp_raw()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        return temp_c
        
def constrain(value, min, max): # (5)
    if value < min :
        return min
    if value > max :
        return max
    else: 
        return value

def update_pid():   # (6)
    global old_time, old_error, measured_temp, set_temp
    global p_term, i_term, d_term
    now = time.time()               
    dt = now - old_time # (7)
    error = set_temp - measured_temp # (8)
    de = error - old_error       # (9)

    p_term = kp * error                     # (10)
    i_term += ki * error                    # (11)
    i_term = constrain(i_term, 0, 100)      # (12)
    d_term = (de / dt) * kd                 # (13)
                                
    old_error = error     
    # print((measured_temp, p_term, i_term, d_term))  
    output = p_term + i_term + d_term      # (14)
    output = constrain(output, 0, 100)       
    return output

set_temp = input('Enter set temperature in C ')  # (15)
kp = input('kp: ')
ki = input('ki: ')
kd = input('kd: ')

old_time = time.time() # (16)
try:
    while True:
        now = time.time()
        if  now > old_time + 1 : # ()17)
            old_time = now 
            measured_temp = read_temp()
            duty = update_pid()
            heat_pwm.ChangeDutyCycle(duty)
        
            print(str(measured_temp) + ', ' + str(set_temp) + ', ' + str(duty))
finally:
    GPIO.cleanup()
Уточним некоторые моменты программы по пунктам, воспользовавшись разметкой строк, сделанной в комментариях:

1. Этот код определяет каталог, в котором находится файл для DS18B20. Это делается практически так же, как и в ранее рассмотренном методе с использованием команды glob для нахождения первого каталога, начинающегося с 28.

2. Эти глобальные переменные используются ПИД-алгоритмом. Переменная old_error служит для вычисления изменения рассогласования для D-составляющей.

3. Функция read_temp там считывает в виде двух строк текста показания микросхемы DS18820

4. Функция read_temp отвечает за фактическое извлечение показателя температуры с конца второй строки после проверки, что в первой строке получен ответ YES.

5. Эта вспомогательная функция ограничивает значение первого параметра, чтобы оно всегда находилось внутри диапазона, указанного вторым и третьим параметрами.

6. Функция update_pid содержит код ПИД-вычислений.

7. Вычисление dt (сколько времени прошло с последнего вызова функции update_pid).

8. Вычисление рассогласования.

9. Вычисление изменения в рассогласовании de.

10. Вычисление пропорциональной составляющей.

11. Добавление к i_term текущего значения error*ki.

12. Ограничение интервала значений: i_term тем же диапазоном, что и на выходе (от 0 до 100).

13. Вычисление d_term.

14. Сложение всех составляющих и ограничение интервала значений в диапазоне выходных значений от 0 до 100.

15. В отличие от версии Arduino, позволяющей корректировать настроечные переменные при работе контроллера, программа на языке Python делает однократный запрос на ввод температуры, kp, ki и kd

16. Переменная old_time инициализируется текущим временем непосредственно перед началом основного управляющего цикла.

17. Если со времени предыдущего замера прошла 1 секунда, производится измерение температуры, а затем получение нового значения на выходе (duty) и соответствующее изменение коэффициента заполнения ШИМ-канала.

Загружаем и выполняем программу

Одно из отличий версии программы для Arduino от версии программы для Raspberry Pi заключается в том, что у Raspberry Pi выход в диапазоне от 0 до 100, а у Arduino - от 0 до 255. Поэтому параметры kp и ki, найденные при настройке Arduino, нуждаются в корректировке под Raspberry Рі. По сути, чтобы подогнать выход под интервал от 0 до 100, можно просто разделить значения kp и ki на 2,5. Это приведет к тому, что у kp будет значение 280, а у ki - 22.

Запустите программу, задайте температуру 30, подключите эти числа, и в результате должны быть получены данные, сходные с теми, что были при использовании версии под Arduino:

$ sudo python ex_11_pid_thermostat.py
Введите заданную температуру в градусах Цельсия 30
kp: 280
ki: 22
kd: 0
23.437, 30, 100 23.437, 30, 100
23.5, 30, 100 23.562, 30, 100
23.687, 30, 100


Построив по этим показателям с помощью электронной таблицы график, я получил результаты, показанные на рисунке. Здесь также используется растянутое представление температуры, которая регулируется довольно точно.
Результаты ПИД-регулирования с использованием Raspberry Pi
Результаты ПИД-регулирования с использованием Raspberry Pi
Oleg
Сообщения: 186
Зарегистрирован: 12 июл 2023, 12:09
Проект: термостатический охладитель напитков

Сообщение Oleg »

В этом проекте мы добавим термостатическое регулирование к проекту из разд. «Проект: охладитель напитков», чтобы напитки могли более точно охлаждаться до нужной температуры (рисунок ниже). В дальнейшем, проект получит свое Дальнейшее развитие - к нему будет добавлен дисплей, показывающий заданную и фактическую температуры. Как уже было сказано, этот проект реализуется с использованием Arduinо, но учитывая, что вы уже научились использовать Raspberry Pi совместно с микросхемой DЅ18B20, у вас не должно возникнуть проблем и по изменению проекта под работу c Raspberry Pi.
Термостатический охладитель напитков в сборе
Термостатический охладитель напитков в сборе
Оборудование

Этот проект основывается на проекте из разд. «Проект: охладитель напитков», но с добавлением в рабочий цикл платы Arduino и датчика температуры DЅ18B20, поэтому, если вы еще не проработали тот проект, следуйте инструкциям по его реализации, имеющимся в разделе.

Комплектующие

В этом проекте для работы с Arduino понадобятся следующие комплектующие:

R1 - Резистор 4,7 Ом;
R2 - Резистор 1 ком;
R3 - Резистор 270 Ом;
R4 - Подстроечный резистор на 10 ком;
Герметичный температурный датчик DS18B20;
Q1 - МОП-транзистор FQP30N06L;
LED1 - Зеленый светодиод;
Термоэлектрическое охлаждающее устройство на элементах Пельтье с двумя вентиляторами и с током потребления не более 4 А;
Переходник с круглым гнездом и винтовыми зажимами;
Источник питания (12 В 5 А);
Двунаправленная клеммная колодка;
Большая емкость из под сока;

Герметичный температурный датчик DS18B20 содержит точно такую же микросхему, что использовалась в экспериментах из разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?» и из разд. «Эксперимент: термостатический ПИД-регулятор», за исключением того, что он поставляется в удобной водонепроницаемой капсуле с длинными проводами, которые могут быть подключены непосредственно к макетной плате.

Если потребуется задействовать более мощный элемент Пельтье, чем тот, что указан в перечне, следует воспользоваться более мощным блоком питания, чтобы его максимально допустимый ток наверняка превышал ток, потребляемый элементом. Предусмотрите, как минимум, превышение в половину ампера для вентиляторов и еще в половину ампера на всякий случай.

Схема проекта

Принципиальная схема этого проекта изображена на рисунке ниже. В левой части схемы показан подстроечный резистор R4, который также называют потенциометром. Подвижный контакт потенциометра подключен к контакту А0, представляющему собой аналоговый вход Arduino. Положением ручки потенциометра на контакте АО устанавливается напряжение, которое замеряется Arduino, а затем используется для установки нужной температуры охладителя.

Потенциометры

Компонент под названием потенциометр должен быть вам известен по регуляторам громкости радиоприемника или усилителя. У него есть ручка, вращающаяся почти на полный оборот.

Область на рисунке выше вокруг R4 показывает, как потенциометр используется в качестве устройства ввода данных в Arduino: верхний контакт потенциометра подключен к линии 5 В, а нижний - к заземлению, при этом на среднем контакте потенциометра напряжение в зависимости от положения ручки будет изменяться в диапазоне от 0 до 5 В

Правая часть схемы на рисунке ниже очень похожа на схему эксперимента из разд «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?», за исключением того, что вместо маломощного транзистора МРЅА14 используется мощный МОП-транзистор FQP30N06L. Этот транзистор способен коммутировать подводимый к охладителю ток силой 4 А и более, при этом степень его нагрева позволяет обойтись без радиатора.
Принципиальная схема термостатического охладителя
Принципиальная схема термостатического охладителя
Сборка проекта

Предполагая, что вы уже реализовали проект из разд. «Проект: охладитель напитков», для реализации этого проекта нужно выполнить лишь следующие дополнительные действия.

Шаг 1. Добавление температурного датчика

Физическая конструкция охладителя остается точно такой же, что и в проекте из разд. «Проект: охладитель напитков», но теперь к ней добавляется температурный датчик, который следует разместить на дне контейнера - под ставящиеся на него охлаждаемые стаканы или бутылки (рисунок ниже). В данном случае я просто прикрепил датчик ко дну контейнера клейкой лентой, но лучше его все же основательно приклеить.
Добавление температурного датчика
Добавление температурного датчика
Шаг 2. Сборка схемы на макетной плате

На рисунке ниже изображена собранная на макетной плате схема, используемая для проекта, а также показаны соединения различных деталей проекта.

Расположите компоненты на макетной плате, убедившись в правильном подключении МОП-транзистора и светодиода. Температурный датчик имеет в своем кабеле четыре провода. Провода с красной и черной изоляцией подключаются соответст венно к общей линии питания (VCC) и к заземлению (GND), а провод с желтой изоляцией является цифровым выходом зонда. Четвертый провод никуда подключать не нужно.

На ручку потенциометра я наколол небольшой клочок бумаги, соорудив из него примитивную шкалу с рисками, позволяющими увидеть задаваемую температуру охладителя.
Схема проекта, собранная на макетной плате
Схема проекта, собранная на макетной плате
Шаг 3. Подключение охладителя

У охладителя имеются три пары проводов: две для вентиляторов и одна для самого элемента Пельтье. Чтобы упростить подключение охладителя, используется двунаправленная клеммная колодка, позволяющая подключить охладитель к макетной плате всего двумя проводами (рисунок ниже).
Подключение охладителя
Подключение охладителя
Шаг 4. Подключение блока питания

Переходник с круглым гнездом и винтовыми зажимами, конечно, может быть подключен к макетной плате перемычками «папа-папа». С этим вариантом можно согласиться в случае использования высококачественных проводов-перемычек относительно большого поперечного сечения, однако многие соединительные провода содержат слишком тонкие проводники, которые могут сильно нагреваться от про- ходящего по ним тока силой в несколько ампер. Само по себе это не создает про- блем до тех пор, пока эти провода не станут сильно греться, вместо того, чтобы быть просто теплыми. Но это означает, что из 12 В на элемент Пельтье станет попадать не все напряжение, и на то, чтобы войти в рабочий режим, охладителю потребуется больше времени.

Для подключения макетной платы к переходнику питания можно вместо простых соединительных проводов-перемычек воспользоваться каким-нибудь одножильным изолированным проводом большого сечения. То же самое касается и соединительных проводов, подводимых к охладителю.

Программа для Arduino

Использование ПИД-регулятора для охладителя напитков можно посчитать излишеством. Но вопрос в данном случае упирается только в программу, поэтому на использование «крутого» алгоритма поддержки напитков в охлажденном состоянии дополнительных затрат не предвидится.

Программа этого проекта во многом похожа на ту, что использовалась в экспериментах из разд. «Эксперимент: насколько хорош терморегулятор, основанный на включении и выключении?» и из разд. «Эксперимент: термостатический ПИД-регулятор», включая весь код для создания интерфейса с температурным датчиком

DS18B20, поэтому, чтобы разобраться в этом коде, следует вернуться к описанию упомянутых экспериментов:

Код: Выделить всё

#include <OneWire.h>
#include <DallasTemperature.h>
#include <PID_v1.h>

const double minTemp = 0.0;  //1
const double maxTemp = 20.0;
const float tempOKMargin = 0.5; 

double kp = 1500;     //2
double ki = 50.0;
double kd = 0.0;

const int tempPin = 2;
const int coolPin = 9;
const int ledPin = 10;   //3    
const int potPin = A0;
const long period = 1000; // >750

OneWire oneWire(tempPin);
DallasTemperature sensors(&oneWire);

double setTemp = 0.0;
double measuredTemp = 0.0;
double outputPower = 0.0;     
long lastSampleTime = 0;

PID myPID(&measuredTemp, &outputPower, &setTemp, kp, ki, kd, REVERSE); //4

void setup() {
  pinMode(coolPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  sensors.begin();
  myPID.SetSampleTime(1000); // (4)
  myPID.SetMode(AUTOMATIC);  
}

void loop() { //5
  long now = millis();         
  if (now > lastSampleTime + period) {
      checkTemperature();
      lastSampleTime = now;
  }
  setTemp = readSetTempFromPot(); //6
}

void checkTemperature() {      //7
  measuredTemp = readTemp();  
  Serial.print(measuredTemp);
  Serial.print(", ");
  Serial.print(setTemp);
  Serial.print(", ");
  Serial.println(outputPower);
  myPID.Compute();
  analogWrite(coolPin, outputPower);
  float error = setTemp - measuredTemp;//8
  if (abs(error) < tempOKMargin) {        
    digitalWrite(ledPin, HIGH);
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

double readSetTempFromPot() {   //9
  int raw = analogRead(potPin);
  double temp = map(raw, 0, 1023, minTemp, maxTemp);
  return temp;
} 

double readTemp() {
  sensors.requestTemperatures(); 
  return sensors.getTempCByIndex(0);  
}
Уточним некоторые моменты программы по пунктам, воспользовавшись разметкой строк, сделанной в комментариях:

1. Диапазон температур, задаваемых с помощью потенциометра, устанавливается двумя константами: minTemp и msxTemp. Переменная tempOKMargin определяет значение выше или ниже заданной температуры, которое может иметь фактическая температура до того, как погаснет зеленый светодиод.
2. Для kp установлено довольно высокое значение, чтобы включение и выключение охладителя происходило более четко. Сделано это в основном с тем, чтобы избавиться от унылого звучания моторов вентиляторов, когда они питаются в режиме низкого уровня выходной мощности. Вместо этого вентиляторы можно запитать отдельно, чтобы они постоянно работали, и заниматься только регулировкой мощности на элементе Пельтье
3. Определение дополнительных контактов для светодиода и потенциометра.
4. ПИД-регулятор инициализируется в режиме REVERSE, а не DIRECT (как ранее).
поскольку добавление выходной мощности будет снижать, а не повышать температуру.
5. В основном цикле проверяется истечение секундного интервала, после чего для включения и выключения охладителя по мере надобности вызывается функция checkTemperature.
6. При каждом прохождении цикла (которое должно осуществляться несколько раз
в секунду), для установки значения переменной setTemp на основании позиции
ручки потенциометра вызывается функция readsetTempFromPot.
7. Функция checkTemperature производит измерение температуры, считывает полученные данные, а затем производит обновление ПИД-контроллера. Эта функция также записывает прочитанные данные в окно монитора порта, позволяя настроить охладитель или отследить его работу. Arduino не нуждается в подключении через порт USB, поскольку получает электропитание через свой контакт Vin, но если его подключить через порт USB, выводимые данные можно будет увидеть на экране в окне монитора порта.
8. Остальная часть этой функции включает светодиод, если измеренная температура находится в пределах допустимого отклонения от заданной температуры, определяемого с помощью константы tempOKMargin. Функция abs (абсолютное значение) удаляет знак минуса перед числом.

9. Код превращения позиции потенциометра в значение между minTemp и maxTemp. Необработанное аналоговое считывание (значения в диапазоне от 0 до 1023) производится в переменную гам. Затем для преобразования считанного значения в желаемый диапазон температур вызывается функция map(см. далее врезку «Функция тар, используемая в Arduino»).

ФУНКЦИЯ МАР, ИСПОЛЬЗУЕМАЯ В ARDUINO
При управлении какими-либо устройствами с помощью Arduino или Raspberry Pi часто возникает проблема преобразования числа, имеющего один диапазон значений, в число в каком-нибудь другом диапазоне значений.

Например, на аналоговом входе Arduino установлен диапазон значений от 0 до 1023, и если нужно отобразить этот диапазон на температуру, например, между 0 и 20, можно просто разделить число на 51,15 (т. е. на 1023 /20). Тогда 1023 превратится в 1023/51,15=20.

Задача усложняется, если оба диапазона начинаются не с нуля. И тут может пригодиться имеющаяся в Arduino функция map. Как далее показано, она получает пять параметров, которые преобразуют число в диапазоне от 0 до 1023 в число в диапазоне от 20 до 40
map(value, 0, 1023, 20, 40);
Первый параметр представлен здесь значением, которое нужно преобразовать, второй и третий параметры задают диапазон имеющегося значения, а четвертый и пятый - диапазон, в котором нужно получить соответствующее значение (в данном случае, это диапазон от 20 до 40).

В языке Python отсутствует встроенная функция диапазона, но ее довольно просто создать, а затем использовать в своей программе. Она должна выглядеть примерно так:

Код: Выделить всё

def map(value, from_low, from_high, to_low, to_high):
    from_range = from_high - from_low
    to_range = to_high - to_low 
    scale_factor = from / to_range
    return to_low + (value / scale_factor)
Затем эту функцию на языке Python можно будет вызвать с такими же параметрами, что и у ее двойника в Arduino. Например: map(510, 0, 1023, 20, 40)

В результате будет возвращено значение 30, которое является средним значением для диапазона от 20 до 40, точно так же, как и значение 510, которое расположено примерно посредине между значениями в диапазоне от 0 до 1023

Ответить