Светомузыка с Arduino. Сезон 2 Часть 2

Часть 1 https://pikabu.ru/story/svetomuzyika_s_arduino_sezon_2_chast...

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

Как работает ШИМ на ардуино? А очень просто:

Что бы это понять расскажу о таймерах и как оно устроено:

Таймер - это такая штука, которая тикает с определенным временным промежутком, который задается генератором частоты (или резонатором, хер его знает как это правильно назвать - нам это не важно), у Ардуины нано он составляет 16МГц, т.е. тикает 16 млн. раз в секунду.

Счетчик таймера - это такая своего рода переменная, которую таймер увеличивает на 1 с каждым тактом (тиком). Для каждого таймера свой счетчик, - таким образом имеем 3 счетчика и 3 таймера. Каждый счетчик имеет свою разрядность (то максимальное число, до которого можно досчитать). Счетчик таймера 0 может сосчитать от 0 до 255. Счетчик таймера 1 от 0 до 1023, Счетчик таймера 2 от 0 до 255.

Так же для каждого таймера есть две переменные для сравнения, называется она - а хер его знает как они правильно называются, назову их канал А и Б.

На практике оно обзывается так:

TCNT0, TCNT1, TCNT2 - Счетчики таймеров 0, 1, 2.

OCR0A, OCR0B, OCR1A, OCR1B, OCR2A, OCR2B - каналы А и Б для каждого счетчика таймера.

Когда счетчик досчитывает до максимального своего значения - он обнуляется.

Теперь о ШИМ:

Когда передаешь в функцию analogWtite значение ШИМ, то запускается такой вот механизм:

(Канал таймера выбирается кодом функции analogWtite)

На примере таймера 2

Светомузыка с Arduino. Сезон 2 Часть 2 Arduino, Таймер, Прерывания, Совет, Длиннопост, Шим

Допустим записываем в D3 значение 93 - analogWrite(3, 93), если посмотреть в код функции, то там можно увидеть что этому пину ШИМ соответствует Счетчик таймера 2, канал B.

Счетчик таймера 2 может считать до 255, что отображено на шкале. С каждым тактом таймера, счетчик TCNT2 увеличивает свое значение на 1, И до тех пор пока счетчик не досчитает до 93, на выходе D3 будет 5 вольт (вкл, высокий уровень). Как только счетчик досчитает до 93, то на выходе D3 будет 0 (выкл, низкий уровень). Досчитав до 255, счетчик обнулится, и все начинается сначала.

Аналогично с пином D11 - это Счетчик таймера 2, канал А.


Таким образом, как можно сделать задуманное не повредив работу ШИМ? Можно использовать прерывание, но никаких манипуляций со Счетчиками или каналами делать нельзя. Хорошо, попробуем:

В блоке setup поставим разрешение на прерывание

TIMSK2 |= (1 << OCIE2B);

, где:

TIMSK2 - Это Выбор Таймера 2, (выбор из : TIMSK0, TIMSK1, TIMSK2 - собсно таймеры)

OCIE2B - Прерывание по счетчику таймера 2 на канал В (Выбор из: OCIE0A,OCIE0B, OCIE1A, OCIE1B, OCIE2A, OCIE2B - Думаю объяснять не надо, что тут к чему относится).

А функция которая будет вызываться - это


ISR (TIMER2_COMPB_vect) {

... тут код

}

, где

ISR - это грубо говоря тип функций для прерываний, а в скобках описывается что за прерывание.

TIMER2 - Ну таймер 2,

COMPB - Сокращение от COMPARE B, сравнение с каналом В, Есть другие, читаем гугл.

Собственно если надо другое - меняем номер таймера или канала.

Теперь это выглядит так:

Светомузыка с Arduino. Сезон 2 Часть 2 Arduino, Таймер, Прерывания, Совет, Длиннопост, Шим

Да, оно работает, - прерывание вызывается, ШИМ работает. То есть имеем что то типа 2 потоков, один работает самостоятельно в цикле LOOP, второй на выбранном прерывании. правда есть две небольших особенности:

1. В цикле по прерыванию, НЕЛЬЗЯ просто так использовать задержки и вообще нагружать цикл чем-то тяжелым, Но например помигать светодиодом, или дернуть микруху стробом или считать значение - можно.

2. Это прерывание, в рамках таймингов микросхемы вызывается не так часто как хотелось бы, т.е. если померить промежуток времени между прерываниями, то получается что-то порядка 2 миллисекунд.... а тайминги микросхемы идут в микросекундах.


Итого, 1 особенность - мне не мешает, да и при умении, она легко обходится.

2 особенность связана с тем что помимо частоты работы есть еще так называемые делители частоты, которые используются в этих таймерах. - От этого и есть много интересных статей по увеличению частоты ШИМ и прочие радости. А значит решить эту проблемку можно подняв частоту ШИМ.


Почему я использую таймер 2, а не другие:

Во первых, он 8 разрядный, т.е. считает до 255, - т.е. прерывание будет вызываться чаще чем таймер 1, который считает до 1023.

Во вторых, Таймер 0 - он хоть и тоже 8 разрядный, но на нём работают помимо ШИМ еще функции delay, micros и тому подобные, а функция micros мне нужна. То есть, если я буду поднимать чатоту ШИМ на таймере 0, то функция micros и другие тоже начнут работать не корректно.


Итак имеем. Понятие как работает ШИМ, что такое Таймеры, счетчики и прерывания, Запустили дополнительный цикл параллельно основному, но пока медленный.

Можно конечно все рассказать в одном посте - но будет слишком много информации, поэтому разбиваю на несколько частей примерно по темам.


Далее я кратко расскажу что такое делители частоты, как ими пользоваться, и немного о режиме счетчика CLC (сброс при совпадении). Продолжение следует.