Самодельный USB-свисток с микрофоном, STM32 и ESP8266 на борту
Хочу рассказать о своем небольшом проекте выходного дня, осветить трудности, с которыми пришлось столкнуться, дальнейших планах и получить консультацию более опытных Хабраюзеров. Формат статьи обзорный, так сказать, галопом по Европам. Если будет интерес, пройдусь подробнее по отдельным частям.
Коротко описать работу устройства можно так:
Электретный микрофон → Усилитель Max9812 → Микроконтроллер STM32F103 → Программное детектирование наличия звука → Кодирование звука в Speex → Отправка через ESP8266 на сервер → Скрипт PHP приема данных и оформления в звуковой контейнер Ogg. Кому интересно, прошу под кат.
Зачем все это надо?
Сама идея устройства у меня возникла после рождения дочки. В перспективе хочу сделать некое подобие радионяни: воткнул в розетку рядом с детской кроваткой, а сам в другой комнате сериальчик смотришь, тут хоп — на телефон пуш уведомление пришло и можно послушать что там происходит. Но по реализации последних пунктов у меня больше вопросов, нежели ответов. Об этом позже.
Возможно кто-то увидит другое применение такой поделке, но уверяю Вас, устройство не создается с целью негласного получения информации (ст.138.1 УК РФ) и любая такая попытка будет преследоваться по закону.
Попрошу сразу не критиковать саму идею, работа со звуком и Wi-Fi мне нужна в другом проекте, над которым я пока только думаю. А это — отдельный кусок, реализованный в самостоятельный девайс.
Корпус
По принципу «Design first» начал думать в каком конструктиве делать устройство. В поисках готовых корпусов на Ali наткнулся на корпуса для usb с отверстием под кабель и подумал про себя, что это идеальный вариант — дырку займет микрофон, а остальное как-нибудь впихнем.
Только вот заказывать 10шт за $5 я не хотел и начал искать варианты. В итоге заказал переходник USB-RS485 в точно таком корпусе за $0.84. А сам переходник пригодится на работе, а то Bolid«ы, стоимостью 1.5 тыс рублей, уходят как расходный материал.
Закупаем все необходимое
Во-первых, при ознакомлении с предметной областью предстоящей поделки, я наткнулся на статью Распознавание речи на STM32F4-Discovery. Там и прочитал про кодек Speex и его применение на микроконтроллерах. Признаюсь, это мой первый опыт работы с микроконтроллерами фирмы STM.
Итак, заказываем самую распространенную отладку с микроконтроллером STM32F103C8T6, к ней отладчик St-link v2, допиливаем его на коленке и уже можно жить. По приблизительным подсчетам ресурсов STM32F103C8T6 должно было хватить, но speex весьма прожорлив, да и сами драйвера HAL не такие уж компактные, в общем памяти для всех библиотек оказалось маловато. В конечном девайсе стоит STM32F103CBT6 с удвоенным количеством flash.
Во-вторых, нужен микрофон. Первой строчкой в поиске берем микрофонный модуль с усилителем max9812, а в довесок горстку более миниатюрных микрофонов типоразмера 6050 (ведь у нас уже есть корпус с отверстием, куда должен пролезть данный микрофон).
В-третьих, нужно подобрать модуль wi-fi, да такой, чтоб влез в купленный корпус. Выбор был сделан на миниатюрный ESP-03 с керамической антенной и несколько штук ESP-12 для макетирования.
Макетирование и программирование
В STM32CubeMX быстренько собираем необходимую периферию и идем дальше, в процессе работы все равно придется часто возвращаться к Кубу. Тут главное писать код в специально отведенных местах /* USER CODE */ и тогда новая генерация проекта никак не скажется на уже написанном.
Семплирование АЦП идет через DMA по триггеру таймера на частоте 8кГц в два кольцевых буфера размером 160 семплов, один буфер получается равен 20 мс. Столкнулся с таким моментом, который не знал и потерял на этом время: DMA продолжает работать на брейкпоинте отладчика, при этом оба флага HT (половина передачи) и TC (передача закончена) установлены, а буферы заполнены всегда полностью.
С библиотекой Speex разобрался не сразу, контроллер постоянно вылетал в HardFault. Оказалось просто не хватало размеров стека и кучи. Нашел Application Note от Silicon Labs с описание необходимых ресурсов для кодирования/декодирования, в конце статьи есть ссылка. Установил значения с небольшим запасом CSTACK 0×800 и HEAP 0×1600. На выходе кодирования получаем размер фрейма 20 байт. Собираем их в пакеты для отправки.
Модуль Esp8266 за раз может принять не более 2048 байт данных. Формат команды отправки: POST-заголовок + данные. Размер пакета данных я ограничил до 1800 байт (90 фреймов по 20 мс).
Прием данных сделал на PHP. Мне было стыдновато выкладывать код, тем более это мой первый опыт ООП в жизни. Прошу не хейтить, это не моя область, лучше научите как правильно. Суть скрипта в том, чтобы забрать данные из php://input, сформировать заголовок, посчитать необходимые контрольные суммы и сохранить все в файл Ogg (либо дописать старый, либо создать новый). Но у меня есть жуткое предчуствие, что принимать аудио через POST запросы очень глупо…
Вопрос к сообществу: что посоветуете для серверной части? В перспективе хочется получать стрим аудио в реальном времени. У меня лично есть небольшое желание познакомиться с Node.js.
А еще на github есть JS библиотека декодирования speex на лету, но пока не знаю как ей воспользоваться. Возможно кто-то подскажет, как с этим работать. Но тут еще вопрос: будет ли iOS это воспроизводить? Пример записанного звука есть в репозитории проекта на Github.
Принципиальная схема и разводка печатной платы
Схему и разводку нарисовал в бесплатной версии Eagle CAD, благо размер платы небольшой. Вот они. Без комментариев.
Заказ плат
Платы заказал в американском OSH Park. Чем примечателен данный сервис, так это тем, что цена формируется от размера платы ($5 за квадратный дюйм), а доставка бесплатная. Ко всему прочему на сайт можно грузить сам файл .brd из Орла и есть предпросмотр, не надо перегонять в Gerber.
Получилось 3 платы за $3.35. Для макетного образца это выгоднее, чем переплачивать китайцам $15 за ненужные 10шт. До сих пор дома валяются горы ненужных плат от других проектов. Да к тому же пришло все это в фирменном пакете с конфетками внутри. Мелочь, а приятно. Трек номера не было, дошло за 40 дней с момента заказа. В производстве были 10 дней (с 29 декабря по 9 января, возможно праздники как-то сказались на сроках).
Качеством плат я остался доволен. Дорожки 8 mil. Переходные 13 mil. Платы пришли с золочением, слой маски относительно площадок везде ровный.
Сборка и настройка
Пока не понял в чем дело, но модуль Esp-03 практически не ловит сигнал, что странно в условиях наличия керамической антенны и расстояния до телефона (который на работе выступает в качестве раздающего wi-fi) в пределах полуметра, при этом модуль ощутимо греется. При поднесении телефона вплотную начинает обнаруживать сеть и подключается к ней. Заказывать новый или в чем может быть дело?
Дальнейшие планы
1. Доработать алгоритм VAD (Voice Activity Detection, запись при обнаружении звука) до более адекватного.
2. Проверить возможность воспроизведения звука на телефоне.
3. Сделать возможность настройки удаленно. Сейчас это реализовано путем ответа сервера (Settings=40,2000,10,), где задается чувствительность нынешнего алгоритма VAD (сигнал должен 40 раз превысить 2000 бубок) и длительность записи в секундах.
Итоговый вариант
Калькуляция
$2.03 — модуль ESP-03
$2.13 — микроконтроллер STM32F103CBT6
$0.39 — микрофоны типоразмера 6050
$1.12 — микрофонный модуль с MAX9812 и обвязкой
$0.84 — преобразователь USB-RS485 (корпус + usb type A male)
$0.50 — стабилизатор NCP3335A на 3.3V
Итого: $7.01 (~420 руб) на один девайс.
Цены могут отличаться в связи с последними событиями на Ali. В стоимости не учтены программатор и рассыпуха.
Материалы
1. Репозиторий с проектом на Github https://github.com/oWartForHabr/AudioWiFi
Там есть проекты CubeMX, IAR, Eagle, PHP, а также пример записанного звука. Возможно, для воспроизведения понадобятся драйвера, но я уже не помню что и в какой последовательности ставил, поищите в интернете.
2. Speex Codec Manual https://speex.org/docs/manual/speex-manual.pdf
3. Application Note от Silicon Labs https://www.silabs.com/documents/public/application-notes/AN0055.pdf
Спасибо за внимание!
Вопросы и предложения пишите в комментарии.
Также допускается контакт или телеграмм, ник везде один.