BAM: Альтернатива ШИМу
Наверняка, каждому попадалась задача, в которой нужно управлять яркостью огромного количества светодиодов. Аппаратных ШИМ-каналов никак не хватает, а если посчитать, сколько нужно вычислительных мощностей для программного ШИМ’а, то отпадает всякое желание с этим всем связываться.
Выход из этой ситуации называется BAM (Binary Angle Modulation).
Смысл очень прост — яркость кодируется двоичным числом, каждый бит которого соответствует
включенному состоянию светодиода. Чем старше бит числа, тем больше у него "вес".
положение бита | вес |
0 | 1 |
1 | 2 |
2 | 4 |
3 | 8 |
4 | 16 |
5 | 32 |
6 | 64 |
7 | 128 |
“Вес” соответствует длительности включения светодиода. К примеру, если мы хотим зажечь диод с яркостью 0b00101111, то нужно будет пропустить промежутки в 128 и 64, потом включить диод на промежуток 32 тика, потом снова отключить на 16 тиков и включить на 8, 4, 2, 1. Надеюсь, следующая картинка расставит все на свои места:
Чем BAM лучше, чем ШИМ ?
- Для его реализации нужно значительно меньше вычислительной мощности, чем для реализации ШИМ’а.
Если для одного прохода 8битного ШИМ’а должно произойти 256 прерываний (для 100Гц ШИМ’а по прерыванию каждые 39мкс), то для BAM той-же глубины и частоты нужно всего 8 прерываний: каждые 5000мкс, 2500мкс, 1250мкс, 625мкс, 312мкс, 156мкс, 78мкс, 39мкс.
- Мерцание диодов, модулированных BAM немного менее заметно, так как включения и выключения диодов происходят с большей чем несущая частотой. (исключение — ровно половина яркости, при таком положении, BAM и ШИМ будут одинаковы).
Почему такое хитрое название? Каждый бит занимает некий кусок фазы включённого состояния светодиода — отсюда слово Angle. Эти куски распределены как степени двойки, вот и получается слово Binary. Ну, то, что это вид модуляции догадаться не сложно. Вот и получается Binare Angle Modulation.
Используя такой подход, народ делает совершенно сумасшедшие вещи, к примеру — https://www.elcojacobs.com/shiftpwm/ Вы только вдумайтесь – регулировать яркость у 768 светодиодов на обычной атмеге! Потрясающе!
Круто. Я потом задам пару вопросов по ШИМ.
Кстати, MEMS сенсор для цифрового микрофона дают бесплатно тут: https://www.st.com/internet/analog/product/250941.jsp
А почему для 8-битного ШИМа надо 256 прерываний? Поясните, пожалуйста.
2^8 = 256. На каждом тике нужно увеличить счетчик и сравнить его значение с регистром.
К сожалению, с ШИМ ещё не разбирался, не было в нём нужды.
Но в ШИМ я вижу пока только один (два) прерывания, необходимых для работы:
1. Прерывание на основной частоте (включение сигнала). Для 100Гц ШИМ’а прерывание каждые 10мс). Здесь производятся все вычисления широты импульса.
2. Время прерывания вычисленное и заданное в п. 1 (отключение сигнала). Для 100Гц ШИМ’а прерывание от 0 до 10мс).
То, что вы написали справедливо для одного канала ШИМа. Если каналов больше, прерываний будет уже много и они будут накладываться друг на друга, из-за этого получится куча побочных эффектов.
Справедливо было бы указать и недостатки BAM.
Так увидел навскидку:
1.Большее (в разы) число переключений за «период» (Важно для коммутирующих элементов, ведь они греются (разрушаются) именно в это время).
2.Невозможность фильтрации основной гармоники.
Расскажите, плиз, и о других недостатках, если таковые имеются.
1. Да, переключений больше, не спорю.
2. А вот тут не правда. Минимальная частота у БАМа есть, тоесть фильтрация с помощью ФНЧ вполне себе возможна.
«для BAM той-же глубины и частоты нужно всего 8 прерываний: каждые 5000мкс, 2500мкс, 1250мкс, 625мкс, 312мкс, 156мкс, 78мкс, 39мкс»
Правильно понимаю:
Делаем первое прерывание через 39мкс, затем в нём выставляем следующее срабатывание через 78-39мкс, в следующем 156-78мкс … 2500-1250мкс, а затем через 36мкс и по новой.
Так?
Ага, именно так.
Дочитал до этого места и думал, что все понял, но теперь не понимаю идею VBMart.
Первое прерывание через 39us
Второе — через … опять 39us? (78-39=39)
Третье — через 78us
…
Седьмое — через 1250us (2500-1250)
Восьмое — через 36us
Ерунда какая-то выходит.
Мое понимание:
0. Если нулевой бит яркости равен единице, включаем порт, запускаем таймер на 39us
1. Первое прерывание через 39us. Смотрим на первый бит. Ставим таймер на 78us
2. Смотрим на второй бит, ставим таймер на 156us.
…
7. Смотрим на 7-й бит, ставим таймер на 5000us
8. Переходим на шаг 0.
Не так?
Реализовал, работает просто замечательно! Спасибо за идею.
Можно более подробно расписать алгоритм по пунктам? Хочу на асме реализовать, Си читаю плохо, поэтому пример не понимаю.
И еще вопрос, каким образом используется один таймер на такое количество каналом BAM, ведь он каждый раз перезаводится на разное время или просто по кругу он так по ступенькам перезаводится для всех каналов?
Спасибо.
Считаю что идея очень неплохая, а с некоторыми доработками, та и вообще замечательная.
Вот мои реализации алгоритмов: https://vitaliy-rudik.blogspot.com/2012/04/bit-angle-modulation.html
Старая песня о главном)
https://electronix.ru/forum/index.php?s=&showtopic=37510&view=findpost&p=310533