Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Это самая долгосрочная поделка в моей жизни. От идеи до конечной реализации, так чтобы ей можно было пользоваться, прошло 12 лет! За это время произошло колоссальное количество событий: переезды, рождения, смерти, но идея была со мной и ни смотря ни на что, я её доделал. И хочу рассказать о путях, терниях, чаяниях, которые сопровождали данную поделку и что из этого в результате получилось.
Идея
Саму идею Wi-Fi радио на базе маршрутизатора я увидел давным-давно вот в этом проекте. Если что — это 2009 год. Это было радио на базе роутера, Linux и mpd-демона. Тогда это были не совсем понятные для меня термины, но очень хотелось иметь подобное радио. И я загорелся этой идеей. Плюс меня очень вдохновляла любая ламповая техника: усилительные лампы, индикаторные лампы (6Е1П, которая у меня на аватарке), ЭЛТ-экраны. И так же очень радуют VFD-дисплеи (VFD — Vacuum Fluorescent Display или по-русски Вакуумно-люминесцентный индикатор (ВЛИ), или катодолюминесцентный индикатор (КЛИ).
Поэтому я принял решение использовать кассовый дисплей. Тогда я даже не знал, что он называется дисплей покупателя.
Итак идея: дисплей покупателя, некоторый одноплатный компьютер или роутер, Linux+mpd, вакуумно-люминесцентный индикатор и какие-то органы управления этим добром. Примерно по аналогии с проектом, который меня вдохновил.
Понимаю, что с этой поделкой сильно опоздал, так как есть куча различных вариантов Wi-Fi радио. Но всё же оно отличается концептуально, даже сегодня, от остальных и думаю будет интересно почитать о создании такого устройства. Тем более, что делал я его для души, а не для продажи.
Основной концепт и дизайн
У этого радио в те годы (примерно 2010 год) была и другая проектная цель. В те годы я изучал сербский язык и мне хотелось иметь простое устройство, где «щелкнув тумблером» получал сербскую радиостанцию. Телефоны, компьютеры были не вариант, так как они меня сами по себе сильно отвлекали: пока откроешь уже забудешь что делал. Второе, мне очень хотелось чтобы железяка оставалась максимально похожей на обычное привычное радио и им смог бы пользоваться даже пожилой человек. И последнее, хотелось чтобы управление было в минималистичном стиле: одна кнопка.
Меня очень вдохновляли дизайнерские решения 30-40-х годов 20 века в архитектуре, интерьере и в частности в дизайне радиоприемников. Этот стиль зовется Арт-деко. В нашей стране яркий представитель этого стиля здание Ленинской библиотеки, станция метро Аэропорт, Маяковская, Красносельская (точнее будет сказать имеет влияние этого стиля). Если говорить о приемниках (дизайн которых они получили уже из архитектуры), то наиболее интересные варианты были тех, у кого шкала находится сверху.
Дизайнерские решения, которые сильно вдохновляли
Конечно, изначально корпус данного радио планировал делать из ценных пород дерева, наподобие приемника сверху. И даже когда-то тут на хабре познакомился с дизайнером, который делал аналогичный проект (не помню какой, простите); и мы даже сделали какие-то наброски, прикидывали проект, но все же тогда я не решился пойти по столь серьезному пути, а зря… В общем было много всяких странных мечтаний и желаний. Но все упиралось в жестокую реальность.
Первые шаги реализации
Основой всего Wi-Fi радио стал дисплей покупателя. Дисплей я подбирал очень долго, тупо ходил по магазинам и смотрел что мне больше всего нравится. Больше всего мне понравился дисплей Posiflex PD-2700. На нем я и остановился.
Первое включение, и вывод изображения на экран
По работе с данными дисплеями я писал отдельную статью. Можете почитать вот тут. Поэтому подробно останавливаться на принципе их работы я не буду.
В качестве «мозгов» этого радио себя примеряли роутер TP-Link 3020, Nokia N800 (да-да, не удивляйтесь, именно N800), различные ноутбуки, промышленные компьютеры всех мастей, кассовые компьютеры, Raspberry Pi различных поколений, одноплатники и многое другое. Все говорит об универсальности принятых решений. И забегая вперед, некоторые решения были сделаны в угоду переносимости, а не удешевления конструкции.
Но в целом, все эти решения мне не нравились, либо были чрезмерными по возможностям для такой задачи, либо наоборот были слишком низкой производительности и имели проблемы с воспроизведением звука (например роутеры). Далее я расскажу основные пути, по которым шел в реализации проекта. Без тупиковых ответвлений, типа Nokia N800 (при всей романтичности данного подхода).
Рабочий прототип
Первый рабочий прототип, который был автономен и даже играл радио и стоял на кухне, я реализовал на базе роутера TP-Link 3020 и китайской USB-звуковой карте за 100 рублей. Этот роутер отличная штука для таких поделок, его главное преимущество, что можно купить в ближайшем компьютерном магазине, в отличии от любого другого одноплатника. Основная ОС была OpenWRT, звук воспроизводился через самые дешманские колонки, за 500 что ли рублей с питанием от USB. В общем, все по нижней планке. И оно даже работало! Короче, лучше один раз увидеть, чем тысячу раз прочитать.
После чего, стало понятно что как в видео управлять с планшета ну не вариант. Теряется смысл радио, когда можно использовать тот же самый планшет. Поэтому принял решение добавить управление с помощью энкодера. Изначально энкодер подключался к GPIO данного роутера (да, у него есть GPIO на борту), но мне не очень понравилась его работа и такое решение не было переносимо, поэтому в будущем сделал отдельный контроллер энкодера на базе arduino, которая подключается по UART.
Энкодер подключен к GPIO TP-Link 3020
После чего надо было сделать «настройку» радиостанции, и хотелось ее сделать так, чтобы она выглядела как в старых радиоприемниках, когда крутишь ручку, а ползунок бегает по экрану. Для этого был реализован шрифт вертикальной палки, пять штук. И перегружал ее каждый раз, о том как загружать шрифты читайте в моей статье. В результате получилось такое решение.
Ну осталось скрестить само радио с этими опытами и в результате получаем удобное управление. Сказал в двух словах, а на деле прошло несколько месяцев, но мне важен результат.
Вроде все, но как обычно у всех моих знакомых радиолюбителей — у устройства нет корпуса, и начал думать, что же делать. Меня очень вдохновили открытые старинные приемники 30-х годов, где просто уголок с щитком и ручками, и все кишочки на свободе.
Вариант прототипа
И решил повторить. Для этого раздербанил колонку, снял с нее размеры и сделал прототип из картонки.
Потрошу колонки, достаю усилитель и делаю замеры размеров
После того как разобрал колонку, вынул от туда усилитель, затем снял все размеры корпуса, крутилки усилителя и энкодера, и все разметил на картонке как это будет выглядеть.
Разметка размеров
Подумал, а чем черт ни шутит, дай посмотрю как это будет выглядеть в картоне, этакий картонный прототип.
Картонное радио
И оно даже работает!
После чего срисовал все размеры, начертил и отправил в лазерную резку.
Размеры
После пришел порезанный акрил, и вот как это выглядит после сборки.
На передней панели кнопка включения, энкодер, ручка громкости. Внутри можно заметить, что есть самостоятельный блок питания, куча хабов, ну и будем честны, выглядит не очень.
Как многие могут заметить, акрил прозрачный. Изначально я хотел дисплей разместить за него, чтобы он просвечивал сквозь него (дисплей и так белый, светит через зеленый светофильтр). Но мне не понравился цвет и контрастность.
На фото свет через оранжевый акрил, честный цвет дисплея (в жизни он белый), и синий светофильтр одного из дисплеев (у меня в радио сейчас стоит зеленый).
Результирующая конструкция конечно прикольная, но не буду врать самому себе, не практичная. Конечно, это работало и даже некоторое время это изделие я слушал, однако вскрылся ряд проблем. Во-первых, пользоваться в таком виде было совершенно невозможно: собирает пыль, нельзя ничего поставить сверху, занимает много место. Во-вторых, TP-Link 3020 оказался слабоват для радио, и многие сталкивались с проблемой реализации на нем. В OpenWRT нет аппаратной поддержки плавающий точки, и поэтому mpd на 100% грузит процессор и это слышно в звуке (идут неприятные цифровые щелчки). Что в общем-то поставило крест на вот такой реализации. Плюс ряд обстоятельств в моей жизни не позволил больше заниматься данным проектом, и это радио было разобрано и убрано в буквальном смысле в ящик.
Окончательное решение
Но не стоит думать, что вот так просто я сдался. Нет, идея продолжала жить. И вот спустя некоторое время, решил все же добить это радио. И так удачно получилось, что у меня завалялся корпус, купленный в Китае. В качестве мозгов я взял beaglebone black, с которым работал в одном проекте и знаю его хорошие и плохие стороны. Платка конечно старая, но для данной задачи подходит отлично. Изначально качестве основной ОС хотел поставить OpenWRT, но получил там кучу проблем с драйверами Wi-Fi. Звуковую карту взял на популярном ЦАП PCM2704. Она легко ищется по данному запросу на популярном аукционе, белая такая платка. Звуковой картой очень доволен, но в целом можно было поставить любую, хоть SoundBlaster.
Этапы прототипирования, пробуем разные звуковые карты, одноплатники, образы Linux, Wi-Fi-адаптеры и подбираем наиболее оптимальное решение
В прошлой своей статье я говорил о том, что нужно потратить время на выбор компонентов, иначе будет головная боль. Тут случилось так же, я хотел USB-Wi-Fi-карту с поддержкой Linux. И не очень долго думая взял себе TP-Link N150. Если кратко, не делайте так. Она выпила у меня тонны крови, потратил на нее неделю. Под OpenWRT завести мне ее не удалось, на Ubuntu завел с какими-то лютейшими танцами с бубном. Если совсем кратко, то устанавливал ее вот по данному мануалу (там инструкция где-то в серединке). Стартовый скрипт (/etc/rc.local) у меня выглядит примерно вот так (после кучи экспериментов).
#!/bin/sh
PATH="/sbin:/bin:/usr/bin"
ps -ef|grep wpa|awk '{print $2}' |xargs -i kill {}
#in case you want to test the script
ifdown wlan0
sleep 0.1
ifup wlan0
sleep 0.1
ifup wlan0
sleep 0.1
ifup wlan0
sleep 0.1
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
#END
sleep 30
#тут ниже запуск моих сервисов
В общем, после всех мытарств все это завелось и все это было скомпоновано и убрано в корпус. Всех деталей не буду описывать, ибо у каждого будут свои. Но изготовил новые втулки для ножек, снизу основание из фанеры и к нему же все крепил. Дисплей крепил на деревянных рамках.
Передняя панель
Управление все осуществляется с помощью энкодера. Влево-вправо — выбор станции, нажатие на кнопку энкодера — пауза; двойное краткое нажатие на кнопку — вывод времени и даты (работает как часы).
Задняя панель
Не смотря на то, что это именно Wi-Fi радио, оставил возможность подключения по Ethernet для диагностики и отладки. Так же, как можете заметить усилителя теперь в корпусе нет. Только линейный выход, что, на мой взгляд даже удобнее. Давайте заглянем внутрь.
Внутри слева видим блок питания, снизу на морде дисплей в деревянной рамке, справа на морде энкодер. В верху USB-хаб, в который воткнуто питание, от него же питается дисплей, в хаб также вставлена звуковуха; сам одноплатник стоит на алюминиевом уголке на стойках, прикрученный к фанере. Справа спрятан контроллер энкодера, он выглядит вот так.
Контроллер энкодера
Это обычная ардуинка, которая подключена по UART к Beaglebone.
Пару слов об исходном коде и настройках
Заметил, что если в статью добавляется описание кода, то ее читаемость снижается сразу вдвое. Поэтому в данной статье кода будет очень мало, хотя только описанию кода можно посвятить две статьи. Настройку mpd-демона описывать не буду, тысячи статей в том числе и на хабре, да и сам мануал обычно исчерпывающий на него. Настройку Linux на Beaglebone опущу. Разве что пришлось включить UART, для подключения Arduino. Но это тоже легко гуглится. Исходный код всего проекта обитает на гитхабе и доступен всем.
Не буду разбирать все моменты кода. Работу с дисплеем ранее осветил в статье. Пробегусь по файлам.
В папке arduino_encoder лежит проект энкодера для ардуины. Там все интуитивно понятно и не вижу смысла это как-то разбирать. В папке Linux исходные коды самого радио, именно этот код кочевал из проекта в проект.
- Makefile
Это сборка самого проекта, тут ничего нового.
- control.c
Это головная программа, где и творится вся магия.
- uart.c
- uart.h
Тут готовый код инициализации UART. Вот всем кто работает на си с UART в Linux, рекомендую заглянуть в эти два файла. Ну и так же всем кто смотрел мои вебинары по работе с UART под линукс раз и два тоже рекомендую в них заглянуть.
- display.c
- display.h
- output.h
Как можно догадаться — это код работы с дисплеем. Плюс к нему пришлось прикрутить код конвертации символов.
- charset_coverter.c
- charset_coverter.h
Дисплей работает в кодировке CP866. И даже, чтобы вывести на него сообщение на русском из консоли приходится применять вот такой трюк:
echo -en "Привет Хабру\nот dlinyj" | iconv -f UTF-8 -t CP866 > /dev/ttyACM0
Но, есть нюанс: букв «ё» нет, твердый знак «ъ» и мягкий знак «ь» перепутаны местами. Так что после декодировки надо додекодировать.
- mpc.c
- mpc.h
Работа с mpd-демоном. Вообще есть библиотеки для работы с ним, но так как мне нужно не очень большое количество функций, то решил написать все с нуля на сокетах. Быть может кому-то будет полезно.
- term.c
- term.h
О, а это замечательная часть. Так как код отлаживать иногда приходилось без дисплея, то сделал себе «симулятор» дисплея, с управлением с клавиатуры вместо энкодера. Выглядит это вот так: на первой картинке дата и часы, на второй мелодия и станция.
Подробнее, как такое писать рассказывал в статье «Терминальная графика».
Добавление радиостанций у меня происходит следующим скриптом.
#! /bin/sh -
# Some configuration settings
VOLUME=60
#mpc volume $VOLUME # adjust this to suit your speakers/amplifier
mpc clear # clear current playlist
mpc add http://relay3.slayradio.org:8000/ #*Slay Radio
mpc add http://fr1.streamhosting.ch:8080 #*lounge-radio.com
mpc add http://us-tx1.streams.bassdrive.com:9000/ #*DnBHeaven.com
mpc add http://uk2.internet-radio.com:31491 #*AmbientRadio.org
mpc add http://www.partyvibe.com:8010/ #*PARTY VIBE RADIO
mpc add http://streamer.psyradio.org:8120 #*psyradio chillout
mpc add http://live.coolradio.rs/cool128
mpc add http://big2.bigportal.ba:8100/big2
Если у вас есть какие-то потоковые радиостанции которые вы можете порекомендовать, особенно по электронной музыке, то пишите в комментариях :)
Еще для удобства управления и настройки, добавил себе web-интерфейс из проекта ympd. Выглядит это вот так.
В результате файл /etc/rc.local в конце выглядит вот так:
sleep 30
/home/ubuntu/addradio.sh > /dev/null 2>&1 &
/home/ubuntu/wifi-radio/Linux/control > /dev/null 2>&1 &
/home/ubuntu/ympd --webport 80 > /dev/null 2>&1 &
Да, да, я знаю, что на Ubuntu systemd и rc.local использовать плохо и другие бла, бла, бла. Но я использую, потому что хочу и могу.
Итог
Конечно, радио получилось не таким красивым и пафосным, как задумывалось вначале, но я решил, что лучше синица в руке, чем журавль в небе. Лучше сделать так, чем растягивать удовольствие еще на несколько лет с неясным результатом. Тем не менее, хоть и неказисто, но очень меня радует. Ну и что читать кучу текста, пора смотреть видео, как это все выглядит и функционирует.
Видео чуть старое, сейчас антенна и Ethernet подключены и вполне себе даже работают.
Куда расти?
А расти есть куда. Один из ответвлений этого проекта, который я долго эксплуатировал — это проект Volumio. Это восхитительный плеер-агрегатор, который позволяет слушать радиостанции со всего мира, потоковые вещания и т.п. Всем хорош, прекрасно состыковался с моим проектом и выводил все станции на экран. Разве что органы управления были совершенно бесполезны. Еще можно добавить голосовое управление, есть чудесный проект Rhasspy, о котором даже была статья на Хабре. Он позволяет делать голосовое управление без связи с внешним сервером!
Единственное, что стоит отказываться от mpd — это бутылочное горлышко. Если станции нет, он зависает в ожидании нее. Нет предбуферизации других станций и т.п. То есть, почва для роста есть. И тема безумно интересная, с кучей идей. Спасибо, что дочитали!