Теперь в нашем онлайн-магазине доступна уникальная книга «BEAM-робототехника. От азов до создания практических устройств», идеально подходящая как для кружков робототехники, так и для самообучения дома. Вы можете приобрести её по привлекательной цене в 699 рублей. Дополнительная информация о книге доступна на нашем сайте. Также в ассортименте нашего онлайн-магазина представлены готовые наборы для сборки роботов, с помощью которых ваш ребенок сможет легко собрать своего первого робота, следуя нашим подробным инструкциям. Перейти в магазин
Наверняка, каждому попадалась задача, в которой нужно управлять яркостью огромного количества светодиодов. Аппаратных ШИМ-каналов никак не хватает, а если посчитать, сколько нужно вычислительных мощностей для программного ШИМ’а, то отпадает всякое желание с этим всем связываться.
Выход из этой ситуации называется 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.
Используя такой подход, народ делает совершенно сумасшедшие вещи, к примеру – http://www.elcojacobs.com/shiftpwm/ Вы только вдумайтесь – регулировать яркость у 768 светодиодов на обычной атмеге! Потрясающе!
// define the processor speed if it's not been defined at the compilers command line. #ifndef F_CPU #define F_CPU 1000000 #endif
volatile uint8_t g_timeslice[8] ; // one byte for each bit-position being displayed on a port. volatile uint8_t g_tick = 0; volatile uint8_t g_bitpos = 0; // which bit position is currently being shown
// now a (simple) demonstration... // In the real-world, you'd probably want to decouple the // animation speed from the LED flicker-rate. uint8_t slowtick = 30; uint8_t position = 0 ; while(1) { while(g_tick==0){ /*wait for g_tick to be non-zero*/ } g_tick = 0 ; //consume the tick // make each of the LEDs slightly dimmer... for ( uint8_t index = 0 ; index < 8 ; index++ ) { if (brightness[ index ] > 0) brightness[ index ]-- ; } // once every 50 ticks, advance the head of the sweep... slowtick-- ; if (slowtick==0) { slowtick = 30; position++ ; position &= 7 ; brightness[ position ] = 100 ; } // and now re-encode all the timeslices... led_encode_timeslices( brightness ) ; } return(0); }
// simple initialisation of the port and timer void led_init( void ) { PORTD = 0x00 ; // All outputs to 0. DDRD = 0xff ; // All outputs.
TCCR2 |= (1<<WGM21) ; // set the timer to CTC mode. TCCR2 |= ((1<<CS21)|(1<<CS20)) ; // use clock/32 tickrate g_bitpos = 0 ; OCR2 = 1 ; // initial delay. TIMSK |= (1 << OCIE2) ; // Enable the Compare Match interrupt }
// encode an array of 8 LED brightness bytes into the pattern // to be shown on the port for each of the 8 timeslices. void led_encode_timeslices( uint8_t intensity[] ) { uint8_t portbits = 0; uint8_t bitvalue ;
// Timer interrupt handler - called once per bit position. ISR( TIMER2_COMP_vect ) { g_bitpos ++ ; g_bitpos &= 7; PORTD = g_timeslice[ g_bitpos ] ; // now set the delay... TCNT2 = 0; OCR2 <<= 1 ; if (g_bitpos == 0) OCR2 = 1 ; // reset the compare match value. if (g_bitpos == 7) g_tick = 1 ; // give the main loop a kick. }
Общайтесь с друзьями в нашем Online-чате по робототехнике
Мы рады, что в России открывается все больше кружков по робототехнике и мы стараемся прикладывать к этому свои усилия начиная с 2008 года :) Мы будем очень рады видеть в чате живое общение, обмен опытом между учащимися в робототехнике и просто увлеченными в этом направлении людей. Мы всегда онлайн, приходите, спрашивайте, помогайте другим - давайте сделаем Мир чуточку лучше!
Чтобы не потерять чат и быть всегда с нами на связи - откройте окно чата в новом окне браузера и добавьте его в заколадки. Открыть в новом окне