Решение проблемы постоянной составляющей, возникающей при регулировке мощности методом Брезенхема, оказалось до смешного простым. Модификация обычного алгоритма Брезенхема состоит буквально из одной строчки кода! Идея модификации: избежать накопления постоянной составляющей за счет переноса импульса на следующий полупериод, если на данном полупериоде подача импульса приведет к увеличению постоянной составляющей. Вот и все! Код маленькой тестовой программешки приведен ниже. Строка, устраняющая накопление постоянной составляющей, выделена красным. Результат работы модифицированного кода (и исходного для сравнения) показан на рисунке в приложении.
#include <stdio.h>
#define Nb 100
static int pp = 1; // Положительный (1) или отрицательный (-1) полупериод static int val; // Уровень модуляции в % static int err = 0; // Ошибка дискретизации static int ps = 0; // Текущая постоянная составляющая
//-------------------------------------------------------------------------- int beat() { // Выполняется один такт pdm-модуляции int ret = 0, lev = val + err; if(lev >= 50) ret = 1;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Коррекция постоянной составляющей: // если ret == 1 и это приведет к увеличению абсолютного значения // постоянной составляющей, то отложим подачу импульса на один // полупериод, где он будет "работать" уже на уменьшение постоянной // составляющей if(ps*ret*pp > 0) ret = 0; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(ret) err = lev - 100; // Считаем ошибку дискретизации else err = lev; return ret; } //-------------------------------------------------------------------------- int main() { for(val = 0; val < 101; val++) { int sum = 0; pp = 1; ps = 0; for(int i = 0; i < Nb; i++) { int pulse = beat(); sum += pulse; // Считаем сумму pdm-импульсов (для контроля) ps += pp*pulse; // Считаем постоянную составляющую pp = -pp; } printf("%d\t%d\n", sum, ps); } return 0; } //--------------------------------------------------------------------------
Ну вот, кажется, и все с Брезенхемом. Простенькая задачка оказалась. ;)
OldBean
Доцент
Красноярск
1K 1.4K
Отв.41 02 Нояб. 16, 19:17
Для завершения изготовления "обвязки" куба мне необходимо было проверить работоспособность всего "кубового хозяйства" вместе. Для этого я собрал небольшой стенд, блок-схема которого показана на рисунке.
Все управления работой куба осуществляет микрокомпьютер Raspberry Pi. В его ведении находится пока два датчика: датчик температуры куба и датчик среднеквадратичного (RMS) напряжения сети. Потом "подтянутся" другие датчики, связанные с колонной и дефлегматором с узлом отбора и сортировки проб.
Из исполнительных устройств пока одно - контроллер ТЭНа, который может регулировать мощность, поступающую от сети к ТЭНу. Метод регулировки - пропуск целых полупериодов по алгоритму диффузии ошибки (ака Брезенхем). Метод модифицирован так, чтобы избежать накопления постоянной составляющей в процессе модуляции сетевого напряжения (см.предыдущий пост).
Тестовая задача: обеспечить постоянную мощность нагрева при больших колебания напряжения сети. "Плохая" сеть моделируется при помощи ЛАТРа, от которого запитано все околокубное оборудование. В процессе тестирования напряжение ЛАТРА (т.е. как бы сеть) изменялось в диапазоне от 160 до 240 В.
Контроль нагрева осуществлялся при помощи датчика температуры. Если регулятор справляется с поддержкой постоянной мощности ТЭНа при колебаниях сети, то зависимость температуры от времени должна быть линейной (куб хорошо теплоизолирован, до кипения не доходим). По сути производная температуры по времени это и есть величина, пропорциональная вкладываемой мощности. Для тестирования в куб залита вода (около 21 л).
Общий вид собранного стенда (макет) показан на рисунке.
Программа, реализующая такой регулятор на Raspberry, очень проста. Скрипт написан на Python. Текст скрипта с комментариями - в приложении (файл regulator01.py увы, получилась только картинка).
Методика проведения испытаний очень проста - включаем оборудование, запускаем программу на малинке (я использую удаленную работу с малинкой по SSH) и все. Дальше крутим ручку ЛАТРа изображая колебания питающей сети. Вся необходимая информация (в том числе время и температура воды в кубе) пишется в лог-файл. В конце эксперимента по данным этого лога строим график.
График представлен на следующем рисунке.
Из него видно, что рост температуры воды в кубе при колебаниях сети от 160 до 240 вольт действительно сохраняет линейный характер. Для наглядности на этом же графике приведено среднеквадратичное напряжение сети (шкала для сети - справа). Т.е. малинка поддерживает постоянный уровень мощности, поступающей в куб, невзирая на достаточно сильные колебания сети. Ну вот вроде бы и все с "обвязкой" куба. На данный момент этот вариант меня вполне устраивает. С основными нюансами "прикубового хозяйства" вроде бы разобрался. Правда датчик RMS получился совсем не тот, который задумывался сначала. Ну да ладно. Лишь бы работал. Так что тему можно закрыть. PS Конечно, по-хорошему, в кубное хозяйство неплохо было бы добавить еще датчик уровня кубовой жидкости. Нормальный, не пороговый (защитные блокировки - это отдельная песня на потом). Но оставлю датчик уровня на следующие итерации. Впереди еще много другой работы: обвязка колонны и дефлегматора с узлом отбора. С колонной в общем-то ничего особенного не планируется: один датчик температуры и датчик давления. Как у всех - на 2/3 высоты. А вот с "верхом" все гораздо интереснее - куча совершенно разных решений. Есть над чем "почесать репу". Но это уже совсем другая история, как писали классики советской фантастики.
PS2 Заметил, что скрипт почему-то не прилепляется к посту. :(( Пристегнулся только в виде картинки.
Наверное, мне лучше было сразу выбрать формат блога, а не форума. Я подумаю.OldBean, 29 Окт. 16, 05:33
Вы продолжайте, читатели есть. Возможно кому то пригодиться в будущем, бывает спустя полгода люди интересоваться начинают. А Zapal, такой человек, не плохой, сарказма в избытке просто =)