21

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

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

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


Продолжаем ковырять прерывания и таймеры.

Поговорим о делителях частоты и зачем они нужны. Делители - тупо уменьшают системную частоту, зачем - да фиг его знает, но зачем то нужны. В прошлом посте я пришёл к тому, что цикл прерывания работает, и не мешают работе ШИМ, но вот чот не так быстро как хотелось бы. Напомню, что время между тактами составляло порядка 2 миллисекунд, а надо микросекунды. Будем отключать делитель.

У адруины нано есть вот такие варианты:

1. таймер/Счетчик выключен;

2. Тактовый генератор;

3. Делитель на 8;

4. Делитель на 64;

5. Делитель на 256;

6. Делитель на 1024.

По умолчанию, в частности на таймере 2, делитель установлен на 64. Посчитаем:

Ардуина работает на 16 МГц, следовательно 16 000 000 / 64 = 250 000, т.е. 250 кГц, т.е. 250 000 раз в секунду.

Далее посмотрим, сколько времени требуется на такт: 1 / 250 000 = 0, 000004 сек, или 4 микросекунды. Счетчик таймеры 2 считает до 255, а значит прерывание срабатывает 1 раз за 256 тактов (0 - 255), значит прерывание срабатывает каждые 4 * 256 = 1024 мкс, или 1,024 миллисекунды,...


Отступление: многие мануалы, которые я прочитал,пытаются заставить работать прерывание со сбросом при совпадении, и настраивают его на работу в 1 миллисекунду, но при выборе режима работы допускают маленькую ошибку, и получают время 1,024 - на практике это особо не заметно, и их светодиоды работают вроде бы как надо, но отличить глазом разницу в 24 мкс - не реально, и типа ок. А когда я стал с этим разбираться, тайминги не совпадали, и ничего не работало как надо.


Ок, вернемся к нашим баранам.

1,024 миллисекунды - слишком медленно,... будем выключать делители. Посмотрим как это делать: (картинка с видео)

Как видим, какие-то мутные регистры, но ничего сложного:

Все настройки делаются в блоке setup!

CS00, CS01, CS02 - Разбираемся: CS - Регистры, просто запоминаем. первая цифра - номер таймера, Нам нужен 2. Вторая цифра - управляющий бит. Итак, нам надо тактовый генератор на канале B таймера 2, а значит надо установить регистры CS20 = 1, CS21 = 0, CS22 = 0 в регистр таймера 2 канал B

В программном виде это выглядит так:

TCCR2B |= 1<<CS20;

TCCR2B &= ~((1<<CS22)|(1<<CS21));

, где

TCCR2B - Регистр таймера 2, канал B (Соответственно может быть TCCR0А, TCCR0B, TCCR1A, TCCR1B, TCCR2A, TCCR2B - Думаю понятно что тут и где).

Первой строчкой через оператор OR устанавливаю 1 на регистр CS20, второй строчкой устанавливаю нули в регистры CS21 и CS22 используя операторы AND и Инвертирование от OR.

Для тех кто не знает:

| - это оператор OR (логиеское или). Принцип работы: имеем биты А и Б, Про себя проговариваем: Если А или Б = 1, то на выходе 1. т.е. если хотя бы один из битов = 1, то на выходе 1. Соответственно, если оба = 0, то на выходе 0.

& - это оператор AND (логическое и). Принцип работы: имеем биты А и Б, Про себя проговариваем: Если А и Б = 1, то на выходе 1. т.е. если хотя бы один из битов = 0, то на выходе 0. Соответственно, если оба = 0, то на выходе тоже 0. Чуишь разницу?

~ - это оператор NOT (логическое не). Принцип работы: Имеем бит А. Про себя проговариваем: Если А = 0, то на выходе не 0, и наоборот. Грубо говоря, просто инвертируем значение.

<< - Операция побитового смещения влево, То есть, было у нас 3 бита = 001, смещаем их влево на 1 знак, получаем 010, Еще разок сместим - 100, еще разок сместим 000. ну и вправо смещать тоже можно аналогично.


Как работает вся эта конструкция в целом - да не особо важно, если будет ты туда залез, и тебе это нужно - разобраться будет не сложно.


Итак. Делители выключили, посчитаем: 1 секунда / 16 000 000 Гц = 0,0625 мкс, * 256 = 16 мкс. Во, уже просто супер! Теперь можно хреначить цикл работы с микрухой анализатора.

Изменение частоты делителя, никак не влияет на работу ШИМ, - так как подняв частоту ШИМ, мы не меняем скважность сигнала (процентное соотношение времени вкл и выкл) - это как частоту на мониторе поднять, просто мерцать меньше будет.


В общем и целом,что можно сделать на ардуине:

7 типа параллельных потоков:

один цикл - Основной LOOP, - очень шустрый, менее 1 мкс на круг.

еще два цикла - на таймере 2 каналы A и B - довольно шустрые по 16 мкс на круг.

еще два цикла - на таймере 1 каналы A и B - помедленнее, так как они до 1024 считаю, т.е. 64 мкс на круг.

и еще два - на таймере 0, но тут частоту менять не надо, то есть 1024 мкс на круг.


Далее, если нам не надо ШИМ или всякие Delay, micros, millis, и прочие (в зависимости от таймеров и каналов), можно поставить в прерывании по таймеру сброс счетчика, и в регистр сравнения записать 1, таким образом, прерывание будет вызываться в каждый такт: т.е. получим скорость как у основного цикла LOOP, = 0,0625 мкс.

Посмотрим как это делать:

Видим, что надо задавать регистры WGM, где первая цифра - это номер таймера, вторая - задающий бит (У таймера 1 немного иначе - имейте ввиду). То есть надо сделать так:

TCCR2B = 1<<WGM21;

По умолчанию установлен режим Нормальный, то есть биты стоят в 0. поэтому дополнительных манипуляций не требуется, просто берем и устанавливаем единицу в нужный регистр.

Обращаю внимание что оператор | (OR) перед знаком равенства не используется! Я фиг знает почему так, - логично что надо бы, но если его поставить, то нифига не работает. Ну и соответственно, эту строчку надо бы размещать перед другими настройками этого бита (TCCR2B в данном случае).

Если надо установить в оба бита, то делаем так: TCCR2B = ((1<<WGM21)|(1<<WGM20));

Итак: в конечном виде это выглядит так:

TCCR2B = 1<<WGM21;  Режим Сброс при совпадении

TCCR2B |= 1<<CS20;  Режим работы по генератору 16 МГц

TCCR2B &= ~((1<<CS22)|(1<<CS21));  Делители выключаем.

OCR2B = 1;  Число для сравнения с счетчиком, пущай каждый такт прерывание фигачит

TIMSK2 |= (1 << OCIE2B);  Разрешаем прерывание при совпадении

В коде функции прерывания, напишем немного кода, что бы посчитать время. И на мониторе порта посмотрим результат: 30 мкс... Сабака, так быстро тикает, что пропускает такты, или micros не успевает считать. Ок,.. поставим Счетчик подальше, OCR2B = 127 и... 15 мкс

Вывод: Без делителей, смысла использовать режим Сброса при совпадении - особо нет. Да и ШИМ перестает работать - нахер эту ерунду. Оставляем режим в "нормальном", вырубаем делители, и получаем и ШИМ и 16 мкс на круг. Всё, можно писать прошивку для Светомузыки с  микросхемой анализатора.


Продолжение следует.... со скоростью китайско-русской почты. Жду посылку с микрухой.

Arduino & Pi

1.5K постов20.9K подписчик

Правила сообщества

В нашем сообществе запрещается:

• Добавлять посты не относящиеся к тематике сообщества, либо не несущие какой-либо полезной нагрузки (флуд)

• Задавать очевидные вопросы в виде постов, не воспользовавшись перед этим поиском

• Выкладывать код прямо в посте - используйте для этого сервисы ideone.com, gist.github.com или схожие ресурсы (pastebin запрещен)

• Рассуждать на темы политики

• Нарушать установленные правила Пикабу

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества