Например TDA7294

РадиоКот > Конкурс: Поздравь Кота по-человечески 2014!

MIDI плейер для AVR2.

Автор: nHz
Опубликовано 16.09.2014.
Создано при помощи КотоРед.

 

Присоединяюсь к общим поздравлениям Радиокота и желаю ему положительного развития и процветания!!!


У постоянных читателей сайта, возможно, возникнет дежа вю,по поводу названия статьи, ведь в прошлом году уже была статья "MIDI плейер для AVR". Я решил продолжить начинание её автора, так как несколько раз повторив конструкцию, возникло желание её улучшить. В итоге, родился мой вариант MISICBOX'а , который я вам и представляю. Не умаляя заслуг автора оригинальной статьи, считаю, что мои изменения достойны отдельной конкурсной оценки.

Железо.

Коробочки и шкатулки иногда бывают очень маленькими, соответственно требуется, в первую очередь, разработать миниатюрную печатную плату. Однако, есть еще батарейки и динамик, так что сильно мельчить я не стал и остановился на размере платы 1x5 см, как раз под размер батарейки ААА.

Микроконтроллер я взял attiny25 с 2 килобайтами флеш, нарочно отказавшись от более жирных attinу45 и attinу85. Доступность и цена тут ни при чем, просто захотелось немного оптимизировать программу, чтобы без мелодии она занимала < 1килобайта, такой вот челлендж. Можно было бы взять и еще более слабый attinу13, но звук с его ЦАПа был просто ужасен, и места под мелодию от килобайтного флеша почти не оставалось. Хотя, если переписать программу под ассемблер, немного оптимизировать... В общем, это я сделаю как нибудь в другой раз, если захочу.

Схема подключения микроконтроллера получилась самая обычная.


На 2-х ногах (PWM1 и PWM2)висит усилитель.Схему я взял из оригинальной статьи, убрав лишние детали, оставив только транзисторы.

На 2 свободные ноги контроллера я повесил резисторы по 300 Ом, на них я подключил светодиоды, чтобы они мигали в такт музыки. Получилось довольно интересно, особенно с трехцветным светодиодом.

Питает всю конструкцию батарейка ААА. Она недорогая, легко доставаемая и весьма маленькая. Так как микроконтроллеру 1.5 вольта питания мало я сделал преобразователь 1.5 в 5 вольт на ncp1402. Схема подключения примерно по даташиту.

Выключателем у меня служит геркон, чтобы, просто встроив в крышку магнит, можно было включать музыку, открывая коробку.Но нормально замкнутого геркона у меня не нашлось, решил приколхозить небольшой полевичок для инвертирования сигнала с геркона. Воткнул я его между преобразователем и схемой, поэтому преобразователь оказался всегда включен. Так как ток потребления от батарейки при выключенной схеме всего 100мкА, то в дежурном режиме её хватает примерно на полгода и дольше, в зависимости от качества батарейки. Если найти нормально замкнутый геркон(или переключающий) этот недостаток можно устранить. А пока, схема выключателя питания такая.

Пусть немного топорно, но работает. Резистор в затворе на 1-2 мегаома, транзистор IRLML0100 или любой в SOT23 на ток более 1А, управляемый логическим уровнем.

После запайки компонентов имеем следующий вид.



По железу вроде все, далее рассказ про софт.

Программа.

Програмную часть я написал с нуля, чтобы оптимизировать размер кода. У меня компилятор GCC, поэтому тем кто будет использовать другой компилятор или другой микроконтроллер придется немножко подправить код. А конкретно изменить обращение к массивам констант и подправить аппаратную инициализацию. Основной код(файл midiplayer.c) содержит примерно 100 строк, так что разобраться в нем не составит труда.

Чтобы стало еще понятнее для начинающих и тех, кто не "в теме" расскажу как можно получить звук на микроконтроллере. Берете любую ногу контроллера и начинаете ей по таймеру ритмично дрыгать вверх-вниз, вверх-вниз и т.д. Повесив на неё усилитель, в динамике вы услышите звук(если будете дрыгать 16-20000 раз в секунду). Вот только звук будет не "чистым", а содержащим множество гармоник основной частоты. Можно, конечно, и так, но чтобы получить настоящие гармонические колебания нам понадобится ЦАП, на вход которого мы будем ритмично подавать значения из таблицы синуса. Если таймер будет срабатывать, например, 64000 раз в секунду и, в момент срабатывания  выдавать очередное значение из таблицы синуса размером 64 байта, то из динамика мы услышим звук 1000 Гц. Если инкрементировать индекс таблицы на 2, то получим колебания 2000 Гц. Для синтеза определенной частоты инкремент индекса таблицы будет равен inc=F*(64/64000).

Если перестраивать выходную частоту с определенным шагом равным полутону(минимальный интервал между 2 нотами), то можно синтезировать все ноты от До до Си. Для каждой частоты будет свой инкремент, который следует занести в таблицу. В такой таблице будет всего 12 значений. Остальные возможно получить умножением на 2 имеющихся значений требуемое число раз, получая частоты в 2,4,8,16 раз больше исходных. Так можно менять октаву. Кроме высоты тона(частоты) требуется знать и продолжительность звучания нот, чтобы играть мелодии. Я воспользовался программой из оригинальной статьи, чтобы получить  нотную запись мелодии в фомате, удобном для микроконтроллера. У меня это 2 массива, храняших номер ноты и задержку до включения следующей ноты. Я не стал хранить номер канала, так как посчитал это лишней информацией. Просто, поступающую ноту, я вывожу в текуший канал и меняю номер текущего канала.

Да, кстати, о каналах. Для воспроизведения полифонии их требуется как минимум 2. Т.е. в программе мы получаем 2 и больше потоков данных, которые нужно выводить на ЦАП. А ЦАП у нас один. Хотя может быть и несколько, но аппаратное смешивание я не рассматриваю. Как же их смиксовать програмно? Можно в лоб нормировать сигналы нескольких каналов и складывать их. Или можно просто выводить данные каналов поочередно на один ЦАП. И, как не странно, слух почти ничего не замечает, воспринимая это как одновременное звучание нескольких нот. Главное частоту вывода данных задрать повыше, чтобы меньше звуковых артефактов получалось. В моей программе именно этот способ и реализован. Это экономит такты работы МК и позволяет на 16 мегагерцах(штатная частота для attiny25) получить 4-х канальную полифонию. Напомню, что в оригинальной статье автор применил разгон кристалла, что, помимо уменьшения надежности, повлекло необходимость применения кварцевого резонатора с обвязкой.

Для придания естественности звучанию необходимо ограничить амплитуду синусоидальных колебаний оберткой(envelope), чтобы они затухали. Это можно сделать, умножая текущие значения синуса на табличные данные затухания. Я отказался от такого способа, поскольку жалко памяти МК и ресурсов на умножение. Напомню, что attiny25 не имеет аппаратного умножения, а значит будет тратить на это драгоценные такты процессора и флеш память. Уменьшать амплитуду колебаний в  канале для вывода на ЦАП, я решил с помощью сдвига влево. Получается почти деление, только с делителями 2,4,8 и т.д. Так можно получить неплохое затухание.

Все эти уловки не прошли даром, и сама программа плеера без мелодии уместилась в 700 байт, что неплохо. Т.е. для хранения мелодии остается еще примерно 1300 байт. Это 650 нот, или около одной-двух минут звучания средней мелодии. Если хочется еще больше, то можно взять камень пожирнее или применить какое нибудь сжатие. Так как большинство мелодий имеют повторяющиеся фрагменты, то можно неплохо сэкономить, если применить не очень прожорливый алгоритм сжатия. Но в этой статье я не буду рассказывать про сжатие, сишком это объемная тема. Однако, несколько прошивок, с простым алгоритмом сжатия я положу в архив с исходниками. 

Если залить прошивки из архива в новый микроконтроллер, то звучать они будут очень  странно и медленно, поэтому надо поменять фьюзы, чтобы МК работал на полную скорость, т.е. 16 МГц от внутреннего генератора. Для этого лучше воспользоваться каким нибудь калькулятором фьюзов. У меня получился младший байт фьзов 0xC1, а старший 0xDE. Но лучше свериться, так как можно случайно запороть МК.

Итог.

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

И на всякий случай ссылка на видео

Всем пока, всем удачи, а кота еще раз с днем рождения!

 

 

 


Файлы:
Архив ZIP


Все вопросы в Форум.


ID: 1977