Урок 44. Контроллер элемента Пельтье. Другая версия программного обеспечения. Завершение проекта.

Основное окно

Окончание разработки контроллера (уроки 36 – 44). Доработаем программное обеспечение. Добавим функцию установки технологических параметров устройства с помощью программы верхнего уровня.

Предыдущий урок     Список уроков     Следующий урок

В предыдущих уроках (36 - 43) мы разработали Ардуино контроллер элемента Пельтье. Устройство получилось вполне работоспособное и может быть использовано в реальных системах охлаждения.

 

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

Эти параметры задаются в исходном тексте программы. Для загрузки параметров в контроллер требуется:

  • запустить программу Arduino IDE;
  • загрузить исходный код программы контроллера;
  • изменить параметры в тексте программы;
  • откомпилировать и загрузить программу в плату Ардуино.

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

За работой контроллера и состоянием системы охлаждения в целом мы можем наблюдать с помощью программы ”Монитор” из предыдущего урока. В главном окне этой программы отображаются нужные нам параметры. Так почему бы не устанавливать параметры в этой же программе без использования Arduino IDE. Такой способ будет гораздо практичнее и удобнее.

Что для этого надо сделать.

  • Хранить параметры в энергонезависимой памяти контроллера (EEPROM).
  • Реализовать протокол загрузки параметров через последовательный порт UART.
  • Добавить в программу верхнего уровня ”Монитор” функцию установки параметров.

В качестве устройства контроля и управления системой охлаждения можно будет использовать не только персональный компьютер, но и, например, Андроид совместимый планшет или сотовый телефон. Конечно, если написать для него функциональный аналог программы ”Монитор”.

 

Технологические параметры контроллера.

Я решил, дать возможность оперативно изменять следующие параметры:

Параметр Ед. измерения
Заданная температура в камере °C
Максимальная заданная мощность Вт
Интегральный коэффициент регулятора мощности ед. ШИМ / Вт * сек
Интегральный коэффициент регулятора температуры Вт / °C * сек
Пропорциональный коэффициент регулятора температуры Вт / °C
Дифференцирующий коэффициент регулятора температуры Вт / °C
Температура включения вентилятора °C
Температура выключения вентилятора °C
Температура перегрева радиатора °C

Остальные параметры ”привязаны” к аппаратной части устройства и изменять их в готовом контроллере нет необходимости. Например, если схема контроллера разработана для выходной мощности 50 Вт, то максимальную мощность 50 Вт можно задать один раз в исходном коде и затем загрузить программу в плату Ардуино. Изменять значение этого параметра в конкретном устройстве уже не допустимо.

 

Размещение параметров в EEPROM.

Раньше параметры были заданы как константы. Например:

#define koeffRegPwrInt 0.05 // интегральный коэффициент регулятора мощности

Теперь необходимо создать для каждого параметра переменную.

float koeffRegPwrInt;  // интегральный коэффициент регулятора мощности

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

Формат хранения данных в EEPROM мы уже выбрали в предыдущей версии программы для параметров ”заданная температура” и ”разрешенная мощность”. В новой версии будем использовать этот формат для всех параметров.

Напомню, что каждый параметр хранится в 5 байтах EEPROM. 4 байта это число типа float. И еще байт контрольного кода для контроля целостности данных.

Относительный адрес Содержимое Назначение
0 … 3 Число типа float Значение параметра
4 Сумма байтов 0 … 3 ^ 0xe5 Контрольный код

Для записи и чтения данных с таким форматом у нас уже есть функции writeFloatToEeprom() и readFloatToEeprom().

Выберем адреса хранения параметров в EEPROM.

Адрес EEPROM Переменная Ед. измерения Параметр
5 setTempRef °C Заданная температура в камере
10 maxSetPower Вт Максимальная заданная мощность
15 koeffRegPwrInt ед. ШИМ / Вт * сек Интегральный коэффициент регулятора мощности
20 koeffRegTmpInt Вт / °C * сек Интегральный коэффициент регулятора температуры
25 koeffRegTmpPr Вт / °C Пропорциональный коэффициент регулятора температуры
30 koeffRegTmpDif Вт / °C Дифференцирующий коэффициент регулятора температуры
35 tempOnVent °C Температура включения вентилятора
40 tempOffVent °C Температура выключения вентилятора
45 overHeatTemp °C Температура перегрева радиатора

Укажем их в программе:

// адреса EEPROM
#define EEPROM_SET_TEMP_REF 5 // заданная температура в камере
#define EEPROM_MAX_SET_POWER 10 // заданная максимальная мощность
#define EEPROM_KOEFF_REG_PWR_INT 15 // интегральный коэффициент регулятора мощности
#define EEPROM_KOEFF_REG_TMP_INT 20 // интегральный коэффициент регулятора температуры
#define EEPROM_KOEFF_REG_TMP_PR 25 // пропорциональный коэффициент регулятора температуры
#define EEPROM_KOEFF_REG_TMP_DIF 30 // дифференцирующий коэффициент регулятора температуры
#define EEPROM_TEMP_ON_VENT 35 // температура включения вентилятора
#define EEPROM_TEMP_OFF_VENT 40 // температура выключения вентилятора
#define EEPROM_OVER_HEAT_TEMP 45 // температура перегрева радиатора

В принципе, у нас в программе уже есть 2 параметра, которые хранятся в EEPROM: ”заданная температура” и ”разрешенная мощность”. Для остальных параметров надо сделать то же самое – загрузку их из EEPROM в интервале 1. Например:

        // интегральный коэффициент регулятора мощности
        if ( readFloatFromEeprom(EEPROM_KOEFF_REG_PWR_INT, & koeffRegPwrInt) == false ) {
          if ( readFloatFromEeprom(EEPROM_KOEFF_REG_PWR_INT, & koeffRegPwrInt) == false ) {
            fatalError= true; // признак фатальной ошибки
            errors |= 1;  // признак ошибки EEPROM
            koeffRegPwrInt= 0; // если ошибка, то 0
          }       
        }

Теперь параметры:

  • хранятся в EEPROM;
  • на первом интервале раз в секунду загружаются в соответствующие переменные;
  • в алгоритме программы используются параметры-переменные, а не константы.

Только, если первые два параметра можно изменять кнопками контроллера, то остальные пока задать невозможно.

 

Протокол загрузки параметров.

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

Я затрагивал вопросы о протоколе обмена через UART в уроке 31. Повторяться не буду. Возможно, кому-то стоит просмотреть второй раздел этого урока. Там даны самые общие понятия о протоколах.

Загрузка параметров в EEPROM – ответственная операция. Случайные данные пришедшие из последовательного порта не должны вызывать загрузку EEPROM. Это сразу приведет к неработоспособности контроллера. Контрольный код при чтении EEPROM не совпадет, замигает светодиод ”Ошибка” и устройство отключится.

Значит, данные должны сопровождаться контрольным кодом.

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

Т.е. мы будем передавать информацию не в виде текста (кодов символов), а в виде двоичных чисел. Если надо передать, например число 12.34567, то мы будем передавать не коды символов ”1”, ”2”, ”.”, ”3”… Мы будем передавать 4 байта числа формата float.

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

Я выбрал такой протокол.

Номер байта в пакете Назначение
0 Адрес EEPROM
1 – 4 Значение параметра (4 байта числа формата float)
5 Контрольный код (сумма байтов 0…4 ^ e5h)

Протокол простой. Всего 6 байтов. Ответа об успешном завершении операции нет. Т.е. после записи параметра необходимо убедиться, что он загрузился правильно. Думаю, для данной задачи этого вполне достаточно.

 

Реализация загрузки параметров в контроллер.

Реализовал я алгоритм загрузки параметров очень просто.

Один раз в секунду на интервале 25 проверяется, есть ли данные в приемном буфере последовательного порта. Если  данные есть, то взводится признак serialDataPresent.

    if (cycle20mcCount == 25) {
      //--------------------------- интервал 25, запись параметра в EEPROM
      // проверка есть ли данные
      if (Serial.available() == 0) serialDataPresent= false;
      else serialDataPresent= true;
    }

Через 20 мс (на следующем интервале) в случае, если на предыдущем интервале появились данные, проверяется, сколько данных в приемном буфере. Если все правильно, то должно быть ровно 6 байтов. Времени 20 мс хватит, на передачу всех байтов. Если передача затянулась, значит это ошибка. Лишние байты – тоже ошибка.

    if ((cycle20mcCount == 26) && (serialDataPresent == true)) {
      //--------------------------- интервал 26, запись параметра в EEPROM

      if (Serial.available() == 6) {
        // данных ровно столько, сколько надо

        // чтение данных из порта в буфер с вычислением контрольного кода
        unsigned int sum=0;
        for (int i=0; i < 5; i++) {
          bufData[i] = Serial.read();
          sum = sum + (unsigned int)bufData[i];
        }
       
        // проверка контрольного кода
        if ( (byte)sum == ((byte)Serial.read() ^ 0xe5)) {

          // все правильно, надо записывать в EEPROM
          EEPROM.write(bufData[0], bufData[1]);
          EEPROM.write(bufData[0]+1, bufData[2]);
          EEPROM.write(bufData[0]+2, bufData[3]);
          EEPROM.write(bufData[0]+3, bufData[4]);
          EEPROM.write(bufData[0]+4, (byte)(bufData[1]+bufData[2]+bufData[3]+bufData[4]) ^ 0xe5);                             
        }
        else {
          // ошибка контрольного кода 
          while (true) { if (Serial.read() == 0xffff) break;} // сброс порта
        }
       
      }
      else {
        // число данных неправильное
        while (true) { if (Serial.read() == 0xffff) break;} // сброс порта         
      }     
    }

  • Если принято ровно 6 байтов, то все данные считываются в массив bufData[] и проверяется контрольный код.
    • При правильном контрольном коде происходит запись данных в EEPROM.
  • При любой ошибке все данные удаляются из последовательного порта.

К недостаткам такого алгоритма следует отнести то, что параметры для загрузки в EEPROM можно передавать не чаще, чем 1 раз в сек. Но я не заметил на практике каких-то проблем, связанных с этим ограничением.

При желании можно коды для интервалов 26 и 27 повторить еще на нескольких интервалах. Тогда данные последовательного порта будут проверяться чаще. Чаще их можно будет и передавать.

Загрузить окончательный вариант скетча можно по этой ссылке.

 

Небольшая доработка программы.

C LCD индикатором FDCC0801 FLYYBW-51LR у меня все работало  безукоризненно. Когда я поставил другой индикатор фирмы Winstar, то появилась проблема. Изображение на дисплее помигивало раз в секунду, а в режиме установки все так мелькало, что с трудом можно было различить символы.

Это произошло из-за того, что при каждом выводе информации я очищал экран функцией

disp.begin(8, 1);  // инициализация дисплея 1 строка, 8 символов

В принципе эта функция предназначена для инициализации дисплея. Одновременно она очищает содержимое экрана. Я решил ее использовать для очистки. Инициализация лишний раз не помешает. Но с другим индикатором Winstar это привело к неприятностям.

Поэтому я изменил способ очистки экрана на традиционный, с помощью функции clear(). Каждую строку в тексте цикла loop() (2 строки)

disp.begin(8, 1);  // инициализация дисплея 1 строка, 8 символов

я заменил  на строку

disp.clear();  // очистка дисплея

В результате скетч программы стал таким  ArduinoPelteContr_2_2.ino. Я обозначил его как новую версию программы. Если будут еще изменения и доработки, то я создам на форуме сайта тему, в которой буду информировать о новых версиях программы.

 

Программа верхнего уровня.

Я назвал программу ”Монитор Ардуино контроллера элемента Пельтье, версия 2.1”.  Установка, первый запуск абсолютно такие же, как и для предыдущей версии программы (урок 43). Загрузить приложение можно по этой ссылке.

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

Основное окно

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

После записи окно редактирования параметра автоматически закроется и в основном окне отобразится значение параметров уже считанных из EEPROM.

Окна редактирования параметров выглядят так.

Редактирование заданной температуры

Редактирование разрешенной мощности

Редактирование темп. перегрева радиатора

Режим включения вентилятора

Режим выключения вентилятора

Пропорциональный коэффициент

Интегральный коэффициент

Дифференцирующий коэффициент

Интегральный коэффициент

Пояснять здесь особенно нечего.

После загрузки скетча программы в плату Ардуино в EEPROM окажутся случайные, неправильные данные. Будет мигать светодиод ”Ошибка”, контроллер отключит напряжение с нагрузки.

Все заработает только после того, как с помощью программы ”Монитор” будут загружены все технологические параметры.

 

Я закончил разработку контроллера элемента Пельтье. Она длилась целую вечность - 9 уроков. Я даже перестал думать, о чем писать в следующих уроках. Мне теперь чего-то не хватает.

 

Разработка будет поддерживаться. Если найдутся ошибки – буду исправлять. На форуме сайта можно обсудить, каких функций или режимов не хватает в проекте. Если устройство вызовет большой интерес, доработаю. Может быть, программу монитор под Андроид напишу.

Предыдущий урок     Список уроков     Следующий урок

17 комментариев на «Урок 44. Контроллер элемента Пельтье. Другая версия программного обеспечения. Завершение проекта.»

  1. Спасибо Вам огромное! Так все толково, грамотно, без трепотни. Хоть это пока последняя статья в цикле, но я решил написать комментарий сюда. Восхищаюсь Вами. Жаль, что мне не суждено быть таким же крутым… Остается брать готовое и пытаться хоть чему-то научиться… Хотя большинство людей живет может даже и не зная обо всей этой науке. Наверно, у каждого свое место. Спасибо!

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

  3. Эдуард, большое спасибо за такое подробное описание программирования плат. В процессе изучения по этой теме для меня остался один пробел в знаниях: как программа верхнего уровня запрашивает/передает данные плате? Понятно, что обмен идет через UART. Но каким способом это описано в программе верхнего уровня? Может быть дадите урок на эту тему для любого простого примера?

    • Сам протокол я описывал. Ближайший урок будет посвящен связи платы Ардуино с контроллером и в нем я опять затрону тему протоколов.
      Что касается разработки программы верхнего уровня это совершенно другая обширная тема. Одним уроком здесь не обойтись. У меня появляются мысли написать инфопродукт на эту тему. Но не знаю, дойдет ли до этого.

  4. Ваш форум — единственное хранилище знаний и практических навыков в работе с пельтье. Я сам — однажды купил готовый заводской холодильник на пельтье, но на нем нет никаких регулировок по температуре/мощности и нет индикации параметров. Теперь, буду собирать весь предложенный вами модуль, дабы пользоваться с удовольствием. Единственное, чего не хватает в вашем решении — это контроля падения напряжения (отключать при падении напряжения ниже 9,8 Вольт). Ведь, изначально — это автомобильный холодильник, и в нем стоит аккумулятор.

    • Спасибо за добрые слова. Контроллер на Ардуино хорош тем, что в него легко добавить новые функции.

    • Рад, если помог. Все библиотеки есть на сайте. Наверное, надо сделать отдельную страницу с ссылками.

  5. Добрый день! Эдуард, спасибо за интересный проект, специально искал именно это для повторения (хочу собрать маленький чиллер для охлаждения рубашки бродильного чана (занимаюсь пивоварением). У меня есть платы Ардуино нано и дисплеи 1602 с шиной i2c, сложно ли изменить скетч под этот дисплей? Можно ли в параллель соединить 2 элемента 12706?
    Они будут расположены не каскадно, а рядом (на водоблоках 40*80 с холодной и с горячей стороны)

    • Здравствуйте!
      Для I2C дисплея надо другую библиотеку использовать. Два элемента Пельтье поставить можно, только импульсный стабилизатор (ключ, дроссель…) должен соответствовать по мощности.

  6. Здравствуйте! Хочу поблагодарить Вас за уроки Ардуино. Великолепный материал, очень подробные объяснения. Я учусь по Вашим урокам. Спасибо. Есть просьба. В 44 уроке по указанной ссылке загружается скетч с комментариями. Но комментарии (на русском) отображаются в виде «крякозябр». Можете дать другую ссылку или объяснить как поставить нужную кодировку. У меня браузер Хром. Спасибо.

    • Здравствуйте!
      Спасибо за добрые слова.
      Это браузер открывает, как текстовый файл. Буду выкладывать в zip архиве. Просто думал так проще просматривать.
      Нажмите на странице в браузере правой кнопкой мыши. Дальше СОХРАНИТЬ КАК и укажите путь. Сохранится исходный файл .ino.

      • Спасибо. Я открыл скетч в Notepad, всё стало понятно. У меня следующий вопрос: запись в EEPROM ограничена, а чтение нет? Вы в программе читаете EEPROM каждую секунду. Не испортит ли это память? Второй вопрос: я храню в EEPROM только 2 уставки (макс и мин). Достаточно ли читать EEPROM только в setup? Или раз в час считать контр. сумму уставок и сранивать её с такой же в EEPROM? Вобщем я что-то запутался. Собираю автополив для растений.

        • Здравствуйте!
          Чтение из EEPROM не ограничено ни по частоте, ни по количеству. При чтении не происходит перезаряд емкости ячеек памяти.
          С какой частотой проверять целостность данных — решать вам. Почему бы не проверять при каждом чтении, если время позволяет?
          В некоторых моих разработках я проверяю отдельно операцией в цикле с периодом несколько мс.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *