ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
23 ноября
398954
Связанные сообщения
Bam Шим
См. пример по ссылке. Брезенхем трудно сдвинуть нельзя, т.к. в отличии от ШИМа (с перепутанными битами) у него нет фазы (которая...2020-09-24
fk0, легенда (02.04.2013 11:45, просмотров: 24885)
Нужен ли 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 (http://en.wikipedi …/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 не в полной мере является таковым). Либо можно поступить проще, с помощью того же макро-ассемблера, из псевдоинструкций ("установить яркость", "пауза", "конец") генерировать сразу непосредственно машинный код вызывающий нужные функции. Это будет основной цикл программы. А обработка ШИМ может вестись исключительно в прерываниях.
[ZX]