Найти тему
Terrabyte

Синтез музыки на микроконтроллере ATtiny13: вызов для программиста - 5

Оглавление

Друзья, привет!

Вообще, решение музыкальных задач для меня имеет особую привлекательность. Не имея музыкального образования и не умея играть на чем либо, мне всегда нравилось подбирать мелодии, тыкая пальцем в клавиши фортепиано, когда никто не видел, разумеется! Формальную сторону музыки я более или менее представляю, и даже отличаю диезы от бемолей (а еще бекары есть). Будем считать, что этого хватит для реализации программных алгоритмов.

Итак, задача - научить нашу минималистичную игровую консоль на ATtiny13 воспроизводить мелодии по нотам.

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

Доработка консоли на ATtiny13

Напомню, что изначально консоль состояла из микроконтроллера (ATtiny13), OLED-дисплея с диагональю 0,96 дюйма и двух кнопок.

Игровая консоль на ATtiny13: базовая версия
Игровая консоль на ATtiny13: базовая версия

Соответственно, схема имела вид.

Схема базового варианта консоли
Схема базового варианта консоли

Если внимательно присмотреться, то можно обнаружить, что 5-й вывод микроконтроллера остался неподключенным. Это было сделано умышленно. Я не стал использовать его не вполне понимая целесообразность того или иного решения. Про звук я уже тогда думал, поэтому оставил именно 5-й вывод. Ведь к нему подключен 0-й канал встроенного в контроллер таймера (OC0A). Кроме того, его можно использовать и как обычный вывод общего назначения, например, для подключения кнопки. Тогда мне и необходимость кнопки представлялась не вполне обоснованной. Однако, чем больше я увлекался программированием этой занятной игрушки, тем больше кнопок мне захотелось! Например, для тетриса или какого-либо скроллера точно нужно более 2-х кнопок. А как-же звук?

Тогда я не смог принять решения. Самое время это сделать теперь! Не желая терять в функциональности я решил сделать этот вывод аппаратно конфигурируемым. То есть переключать его назначение при помощи джампера. Появляется возможность можно менять функциональность вывода простой перестановкой перемычки.

В результате проработки схема приобрела вот такой вид.

Доработанная схема игровой консоли на ATtiny13
Доработанная схема игровой консоли на ATtiny13

По разному соединяя контакты на джампере J1 можно менять периферию, подключенную к контроллеру. При замыкании контактов 1-2 к выводу 5 подключается внешний динамик BUZ1. При замыкании контактов 2-3 к контроллеру подключается еще одна кнопка - LEFT2. Кнопка специально подключается через резистор R4. Поскольку вывод может конфигурироваться и как вход и как выход, то во избежании случайного выхода из строя при неправильном положении джампера, кнопка подключена через резистор. Тогда даже при подаче высокого потенциала на выход, резистор ограничит максимальный ток.

На транзисторе Q1 собран силовой ключ, управляющий 16-омным динамиком. Чтобы слишком сильный ток через динамик (более 150 мА) не просаживал напряжение питания, динамик подключен через балластный резистор R3. Такое решение конечно же уменьшает громкость, но зато продляет срок службы батарейки и предохраняет ее от слишком сильного тока.

Защитный конденсатор C1 по питанию (защита от скачков тока при звучании динамика) я сначала предусмотрел, но на практике необходимость в нем не возникла.

Начинаем доработку. Вот так выглядит консоль со стороны монтажа до доработки.

Консоль со стороны монтажа
Консоль со стороны монтажа

Первое, что мы сделаем - отпаяем земляную шину снизу. Вот так.

Шина "земли" отпаяна
Шина "земли" отпаяна

Далее, подготовим новую кнопку. Места для ее установки чуть меньше, поэтому мы отогнем выводы кнопки как можно более вертикально.

Формование выводов кнопки
Формование выводов кнопки

Теперь устанавливаем кнопку слева.

Установка кнопки
Установка кнопки

И хорошенько прижимаем ее к монтажной плате.

Кнопка установлена
Кнопка установлена

Теперь ее можно припаять с обратной стороны. Результат получился вот таким.

Результат установки кнопки
Результат установки кнопки

Следующий шаг - установка группы из 3-х контактов с шагом 2,54 мм. Это и есть тот самый джампер, при помощи которого мы будем переключать функциональность 5-го вывода.

3-пиновый джампер
3-пиновый джампер

Сзади припаянный джампер и кнопка выглядят так.

Подпаянный джампер и кнопка со стороны монтажа
Подпаянный джампер и кнопка со стороны монтажа

Обратите внимание - справа выводы старой и новой кнопки спаяны между собой. Это "земля". Кроме того, средний вывод джампера подпаян к 5-му контакту панельки контроллера.

Устанавливаем динамик. Это обычная пассивная 16-омная пищалка, которую обычно используют для озвучивания приборов и проектов на Ардуино.

Установленный динамик
Установленный динамик

Слева "+" динамика, справа "-". Вдоль правой кромки платы в 3 соседние отверстия (у меня получилась линия "T") устанавливается "народный" транзистор 2N2222. Срезом внутрь.

Установленный транзистор 2N2222
Установленный транзистор 2N2222

После того, как все остальные компоненты установлены можно соединить их, используя провода и выводные резисторы между собой. некоторые провода в изоляции, во избежание короткого замыкания. Общий вид монтажа показан на следующей фотографии.

Монтаж компонентов
Монтаж компонентов

Левый нижний резистор, расположенный горизонтально - 100 Ом, остальные (вновь установленные по 1 килоому).

Общий вид устройства с установленной перемычкой джампера.

Игровая консоль на ATtiny13, версия №2.
Игровая консоль на ATtiny13, версия №2.

Если перемычка соединяет центральный контакт с правым (как на фото) - подключен динамик, если с левым - подключена кнопка.

На этом модернизация консоли завершена. Начинаем разбираться с программированием музыки.

Программная поддержка синтезатора музыки

Для воспроизведения нот различной частоты я решил воспользоваться тем же режимом таймера CTC (Clear Timer on Compare), что и в случае игр "Пинг-понг" и "Змейка".

Только, если ранее я не задействовал аппаратные возможности управления пином OC0A, то теперь самое время.

Общая логика управления частотой на выходе таймера заключается в использовании регистра переполнения для управления переключением состояния пина. При синхронизации микроконтроллера от внутреннего генератора на частоте 4,8 МГц и использовании предделителя на 64, получается частота, с которой тикает таймер: 4800000 / 64 = 75000 Гц. Это ультразвук, конечно, но его нам слушать не придется! Далее, устанавливая регистр переполнения (разрядность - 8 бит) мы можем получить самую низкую частоту переключения пина: 75000 / 256 = 293 Герца. Но, следует учесть, что с этой частотой пин будет менять свое состояние на противоположное. Для формирования звука необходимо изменить состояние два раза (сначала от нуля к единице, а затем обратно). Значит, результирующая частота будет в 2 раза ниже, то есть около 146 Герц. Это примерно соответствует ноте РЕ малой октавы. Зная соотношение частот соседних нот (корень 12-й степени из 2-х) я получил таблицу коэффициентов деления 31-й ноты.

Коэффициенты деления для нот разной частоты.
Коэффициенты деления для нот разной частоты.

Получившийся диапазон - от ФА малой октавы до СИ второй октавы. Можно было бы и больше нот получить, но очень важно было уложится именно в 31 ноту, и вот почему. Ноты нужно как-то хранить в памяти. Каждая нота характеризуется своей частотой и длительностью (про выразительность я молчу вообще). Для минимизации объема хранения я решил на каждую ноту отвести 1 байт. Причем 5 старших битов использовать для хранения порядкового номера ноты, который будет указывать на коэффициент деления, хранящийся в отдельном массиве, а 3 младших бита для задания длительности ноты (8 вариантов). 5 битов как раз позволяют хранить 32 ноты (точнее - 31 ноту и паузу, когда нота не воспроизводится).

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

Программа с массивом музыки заняла в памяти 644 байта.

Результат компиляции скетча
Результат компиляции скетча

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

Отдельного упоминания заслуживает задача определения длительности ноты. Дело в том, что таймер-то работает с разной частотой в зависимости от звучащей ноты и чтобы использовать его для подсчета интервалов, приходится для каждой ноты вычислять количество периодов ее звучания. Счетчик периодов декрементируется в прерывании и когда достигает 0, начинается следующая нота. Так вот здесь возникла проблема с которой я до конца разобраться не смог. Дело в том, что значение количества периодов требует 16-битного представления (uint16_t). Вычисляется оно в основном теле программы, а декрементируется в прерывании таймера. Несмотря на то, что переменная была объявлена глобально (то есть, считай статически) и с модификатором прямого доступа к ячейке памяти - volatile, при обращении к переменной из прерывания иногда терялся старший байт. Почему так происходило - не ясно!Пришлось отсчитывать длительность при помощи только 8-битной переменной, используя фиксированный множитель (TICKS_CYCLE), который циклически декрементируется в прерывании.

Больше проблем с реализацией алгоритма не возникало. В результате получился одноголосный музыкальный синтезатор с диапазоном в 2,5 октавы.

Заключение

Конечно сделать игру на ATtiny13 с полноценным музыкальным сопровождением будет тот еще адов труд, но, минимальные звуки, оживляющие приложения, издавать пожалуй можно.

Для тех, кто упорно продолжает спрашивать - зачем все это нужно, я сразу скажу - МНЕ ИНТЕРЕСНО! Всем, кому еще интересно - присоединяйтесь! Делитесь идеями, вашими приложениями или решениями для этого экстремально слабенького чипа ATtiny13. Можно делиться в комментариях, можно в нашей группе ВК.

А впереди у меня еще очень много задумок относительно различных приложений и игр. Всех кому это интересно приглашаю в наше сообщество!

Ссылка на архив со схемой устройства и скетчем музыкального синтезатора: https://disk.yandex.ru/d/oHHa9SIyfxvKug

Спасибо, что читаете-смотрите Terrabyte! Подписывайтесь, если вам интересна радиолюбительская тематика, микроконтроллеры, мини-ПК, необычные компьютерные решения и инновационные разработки! Спасибо всем, кто нас поддерживает своими комментариями и лайками!

Наша группа ВК: https://vk.com/terrabyte

Наш канал на VK-Video: https://vk.com/video/@terrabyte/all

Наши разработки: