Skip to Content

Нужен ли BAM vs ШИМ и как управлять светодиодами микроконтроллером.

Речь пойдёт об изготовлении каких-то больших "индикаторов" на базе микроконтроллера. Световой рекламы, например. Где принципиальной особенностью может быть необходимость плавного зажигания и гашения светодиодов.Есть разные методы это сделать, первый и очевидный -- широтно-импульсная модуляция. Причём реализуемая в таких случаях, как правило, полностью программно ввиду того, что число каналов (отдельных диодов или диодных лент) достаточно велико и практически сопоставимо с числом выводов микроконтроллера вообще (а может быть и больше, если используется SPI и регистры сдвига), а число аппаратных модулей ШИМ у дешёвых МК обычно весьма ограничено. Практически период ШИМ должен выбираться достаточно коротким, чтобы мерцание не было заметно. Где-то от 100Гц до 1КГц, чем выше, тем лучше. Но при большом числе каналов частоту сверху начинает ограничивать производительность микроконтроллера -- он просто не успеет с нужной частотой обсчитать состояние каждого вывода. А при низких частотах начинает слишком явно проявляться негативное свойство ШИМ, особенно хорошо заметное при коэффициенте заполнения близком к 0.5 -- на выходе практически меандр и мерцание становится особенно заметным.

С этим можно бороться осуществляя перестановку битов на выходе ШИМ. Например, было 11111111111111100000000000000, а стало 10010011011011001001001101101. Соотношение нулей и единиц то же самое, следовательно и яркость свечения диода. А мерцание уже практически не заметно.

Вопрос, как это сделать. Можно использовать алгоритм брезенхема для равномерного перемешивания нулей и единиц (легко найти в интернете). Но он требует слишком больших вычислительных расходов. А процессорного времени и так не хватает, иначе проще было поднять частоту ШИМ. Можно использовать свойство взаимо-простых чисел N и M, что вычисляя каждый раз i=(i+N)%M, для начального значения i=0, i пройдёт все значения от 0 до M-1, но не последовательно, а с каким-то шагом. Переменную i можно использовать как значение "счётчика" сравниваемое на каждом шаге с амплитудой сигнала и на основе сравнения выводится 0 или единица.

Ниже приведён пример для периода ШИМ равном 30, в левой колонке что получается при обычном алгоритме ШИМ (последовательность выводимых битовых значений), в правой то, что получается по описанному выше алгоритму:

0: 00000000000000000000000000000        00000000000000000000000000000
1: 10000000000000000000000000000        00000000000000000000000000001
2: 11000000000000000000000000000        00000000000010000000000000001
3: 11100000000000000000000000000        00000000000010000000000001001
4: 11110000000000000000000000000        00000000010010000000000001001
5: 11111000000000000000000000000        00000000010010000000001001001
6: 11111100000000000000000000000        00000010010010000000001001001
7: 11111110000000000000000000000        00000010010010000001001001001
8: 11111111000000000000000000000        00010010010010000001001001001
9: 11111111100000000000000000000        00010010010010001001001001001
10: 11111111110000000000000000000       10010010010010001001001001001
11: 11111111111000000000000000000       10010010010011001001001001001
12: 11111111111100000000000000000       10010010010011001001001001101
13: 11111111111110000000000000000       10010010011011001001001001101
14: 11111111111111000000000000000       10010010011011001001001101101
15: 11111111111111100000000000000       10010011011011001001001101101
16: 11111111111111110000000000000       10010011011011001001101101101
17: 11111111111111111000000000000       10011011011011001001101101101
18: 11111111111111111100000000000       10011011011011001101101101101
19: 11111111111111111110000000000       11011011011011001101101101101
20: 11111111111111111111000000000       11011011011011101101101101101
21: 11111111111111111111100000000       11011011011011101101101101111
22: 11111111111111111111110000000       11011011011111101101101101111
23: 11111111111111111111111000000       11011011011111101101101111111
24: 11111111111111111111111100000       11011011111111101101101111111
25: 11111111111111111111111110000       11011011111111101101111111111
26: 11111111111111111111111111000       11011111111111101101111111111
27: 11111111111111111111111111100       11011111111111101111111111111
28: 11111111111111111111111111110       11111111111111101111111111111
29: 11111111111111111111111111111       11111111111111111111111111111

Очевидно, что во втором случае (правая колонка) биты оказались перемешаны более равномерно и мерцание будет менее заметно. Данные получены с помощью представленной ниже программы. Взаимо-простые числа в данном случае 29 (период на единицу больше) и 9 (шаг).

for v=0:29
	printf("%u: ", v);
	for i=0:28
		if (v > i)
			printf("1");
		else
			printf("0");
		end
	end
	printf(" \t");
	j=0;
	for i=1:29
		j=mod(j+9, 29);
		if (v > j)
			printf("1");
		else
			printf("0");
		end
	end
	printf("\n");
end

Шаг стоит выбирать примерно равным от четверти до половины периода. Список взаимо-простых чисел можно найти в интернете или вычислить по алгоритму приведённому в Wikipedia (en.wikipedia.org/wiki/Coprime_integers).

Другой специфической проблемой может стать источник питания. Если множество диодов переключаются синхронно, то пики потребления приводят к сильному падению напряжения в момент включения, что может быть заметно визуально и влиять на электронную схему в целом. Либо следует применять более качественный источник питания, либо начало периода ШИМ для разных каналов разнести во времени. Что в описываемом выше случае можно реализовать добавлением к i некоторой константы n*P/N, где n -- номер канала, P -- период, N -- общее число каналов.

Есть также известный способ управления светодиодами называемый ВАМ (Bit Angle Modulation). У него есть преимущество, применительно к микроконтроллерам: требуется меньшее время на вычисления. Так для шим с периодом P нужно, соответственно, P раз вычислять выводимые значения. А для BAM только log2(P).
Но есть и недостатки:

  • во-первых для BAM невозможно выбирать период не кратный 2^N. Например, известно, что ШИМ не успевает отрабатывать с периодом 64, но успевает с периодом 50. А в случае с BAM останется ограничиться периодом 32. В последнем случае плавность зажигания уже под вопросом, видно ступенчатое изменения яркости.
  • Во-вторых BAM не позволит более равномерно перемешать биты на выходе как показано выше и получить меньшее мерцание, при выводе амплитуд близким к 0.5 периода мерцание при использовании BAM будет максимально.

Кроме того, BAM хоть и требует, суммарно, меньше времени на вычисления, в пике он требует такой же производительности как ШИМ: прерывания при выводе младших битов учащаются каждый раз в 2 раза и при выводе самого младшего бита идут с такой же частотой как у ШИМ. Но если микроконтроллер успевает их обслужить в этом случае, почему он не успеет для всех остальных выводимых значений ШИМ? То преимущество BAM, что требуется меньше вычислений, по сравнению с ШИМ на самом деле весьма эфемерно и является преимуществом только в случае, например, если кроме управления светодиодами микроконтроллер занят какими-то другими задачами, требующими тоже большого количества процессорного времени, что вряд ли.

Нужно рассмотреть ещё один вопрос. Алгоритм непосредственно управления индикацией. Допустим, есть программа которая для N каналов выводит заданные для каждого канала интенсивности методом ШИМ. Но как из этого получить динамичную картинку? Нужна "программа" по которой будут включаться те или иные сегменты изображения. И нужен интерпретатор этой программы. Интерпретатор на самом деле не сложный, он может оперировать функциями "включить такую-то яркость на таком-то канале с такой-то скоростью перехода (плавно)", "пауза столько-то миллисекунд" и "конец или переход на начало программы". Это, наверное, минимум. Возможен и более сложный язык, но это отдельная история. Можно сделать интерпретатор байткода (скорей, слов в ПЗУ), очевидно как. И какую-либо программу для перевода описания "программы" из текста в "байткод". Для последнего подойдёт, наприме, макроассемблер (встроенный в AVR-studio не в полной мере является таковым). Либо можно поступить проще, с помощью того же макро-ассемблера, из псевдоинструкций ("установить яркость", "пауза", "конец") генерировать сразу непосредственно машинный код вызывающий нужные функции. Это будет основной цикл программы. А обработка ШИМ может вестись исключительно в прерываниях.

Комментарии

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".

BAM

BAM можно использовать с периодами не 2^N, точнее не 2^N−1, если корректировать число при установленном старшем бите.

BAM можно использовать для управления большим количеством каналов, если разнести начала периодов.


Реализовал этот принцип. Был

Реализовал этот принцип. Был впечатлён. В эксель придумал расчёт для получения массива равномерно перемешанных чисел. Позже удалось срастить этот принцип с аппаратным 8-ми битным ШИМ, виртуально увеличив битность до 10 бит. Без снижения частоты! Результат получился ещё более впечатляющим. Причём 10 бит это далеко не предел для програмного расширения битности стандартного 8-ми битного аппаратного ШИМ.

Огромное спасибо автору изобретения сего приципа и автору сей публикации!

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Доступны HTML теги: <a> <p> <span> <s> <strike> <div> <h1> <h2> <h3> <h4> <h5> <h6> <img> <map> <area> <hr> <br> <br /> <ul> <ol> <li> <dl> <dt> <dd> <table> <caption> <tbody> <tr> <td> <em> <b> <u> <i> <strong> <del> <ins> <sub> <sup> <quote> <blockquote> <pre> <address> <code> <cite> <embed> <object> <param> <strike>
  • Использовать как разделитель страниц.

Подробнее о форматировании

CAPTCHA
Введите текст что Вы видите на картинке. Регистр букв не важен.