Skocz do zawartości

Open Radio - polskie radio internetowe na M5Stack Core2 (bez lutowania, bez kompilowania, bez konta)


Pomocna odpowiedź

Napisano (edytowany)

Cześć! Zanim doszedłem do tej kostki, swoje odbyłem z lutownicą - osobno ESP32, osobno ekrany, płytki i obudowy. Teraz biorę gotowy sprzęt ze sklepu i piszę do niego system, który wgrywacie z przeglądarki. Próg wejścia ma być jak najniższy. Projekt zacząłem rozwijać samodzielnie kilka miesięcy temu, a później nawiązałem współpracę z Botlandem, aby rozbudować system o nowe funkcje, a opis na Forbocie jest elementem naszych wspólnych działań.

00-kostka-zdjecie.thumb.jpg.1ba07ca687badf0c4eeaf52cfcdd853f.jpg

Open Radio na moim biurku, ekran wyboru stacji

Pierwszy taki system to Open Radio. Robi z M5Stack Core2 polskie radio internetowe. Kostka 54 na 54 milimetry stoi na biurku albo na kuchennej półce i gra RMF, Tok FM albo regionalną rozgłośnię, z własnego głośnika albo z głośnika Bluetooth. Dziewięć ulubionych stacji wybieracie spośród 236 w katalogu i przełączacie je dotknięciem ekranu. Strona projektu: esp32ai.me/pl/radio.

Tym razem lutownica zostaje zimna, a kompilatora nie trzeba nawet instalować. Kupujecie gotową płytkę, wpinacie ją kablem USB-C do komputera, klikacie przycisk na stronie instalacji i po dwóch minutach system jest na kostce. Cały start, razem z Wi-Fi i wyborem stacji, zajmuje kwadrans. Kod jest otwarty (GPL-3.0), źródła są na GitHubie.

Jak zrobić swoją wersję?

  1. Kupujecie M5Stack Core2 v1.3. W pudełku leży krótki kabel USB-C i w zupełności wystarczy. Inny kabel musi przenosić dane, bo przez taki „tylko do ładowania” komputer kostki nie zobaczy. Czujniki powietrza są opcjonalne, o nich niżej.
  2. Otwieracie stronę instalacji w Chrome, Edge albo Operze, klikacie „Zainstaluj Open Radio 0.4.4” i wybieracie port. Na liście kostka nazywa się „USB Single Serial”. Jeśli jej tam nie ma, komputerowi brakuje sterownika do układu CH9102.
  3. Po restarcie kostka pokazuje kod QR. Skanujecie go telefonem, telefon łapie sieć OpenRadio-Setup i zwykle sam otwiera stronę konfiguracji. Najpierw wybieracie stacje (gotowa dziewiątka albo własna), potem domowe Wi-Fi w paśmie 2,4 GHz. Kostka restartuje się jeszcze raz i gra.

01-kostka-radio.thumb.png.f6373adbe49d491983bef05a4d760dbe.png

Render ekranu głównego. Piksele rysuje ten sam kod C++, który działa na kostce

Kostka nie aktualizuje się sama i tak zostanie. Nie ma chmury ani konta, nikt jej zdalnie niczego nie podmieni. Nową wersję wgrywacie tak samo, z przeglądarki. Wgranie kasuje ustawienia, więc Wi-Fi i stacje podajecie od nowa.

Skąd pomysł?

Kostka powstała gdyż mojej żonie w pracy przestało działać wpierw radio FM / linia ścieżki radarowej poligonu czy coś innego. 😉 Praca jednak milej idzie jak coś w tle leci a nie zawsze to musi być lista Spotify. Gdy zacząłem grzebać przy temacie siostra w Niemczech też się okazało że by posłuchała po polsku coś w tle w pracy i potem dołączyli inni znajomi. 

Płatne aplikacje na smartfona z radiami internetowymi były płatne, a darmowe średnie i dodatkowo angażowały smartfon i wymagały dodatkowej uwagi. 

Radia internetowe jako sprzęty istnieją oczywiście ale cenowo nie zachęcają. I tak doszliśmy do Core2. 

03-telefon-wybor-stacji.thumb.png.89ef38d4e35ccd9269a74fda7aa1124f.png

Pierwsze uruchomienie: telefon pyta o stacje, zanim zapyta o Wi-Fi

Wybrałem Core2, bo ma w obudowie ekran z dotykiem, głośnik, baterię, Wi-Fi i Bluetooth. yoRadio znam i cenię. To świetny kombajn – sami dobieracie ekran i przetwornik, lutujecie, kompilujecie, macie 65 tysięcy slotów na stacje, MQTT i Home Assistanta. Open Radio ma dziewięć stacji i trzy ekrany ustawień, gra na głośnik Bluetooth i można je postawić u mamy.

Pierwszą wersję wypuściłem 18 lipca. Kiedy cztery dni później wyszła 0.2, pierwsi użytkownicy w kilka godzin znaleźli dwa błędy, a poprawka 0.2.1 poszła jeszcze tego samego wieczoru. Od wersji 0.4 każde wydanie ma w dzienniku zmian rubrykę „czego nie sprawdziliśmy”.

Jak to działa? Co potrafi?

Stacje nadają w internecie publiczne strumienie MP3. Kostka łączy się z nimi bezpośrednio, tak jak przeglądarka, i dla nadawcy jest kolejnym słuchaczem. Poza serwerami nadawców, od których bierze strumienie i ikonki stacji, łączy się tylko z serwerem czasu (NTP). Telemetrii też nie ma.

Każdą stację, zanim trafiła do katalogu, zmierzyłem na żywym strumieniu. Pomiar trwa piętnaście sekund i kończy się jedną liczbą, czyli tym, o ile szybciej dane przychodzą, niż odtwarzacz je zużywa. Stacje, które nie nadążały, wyrzucałem.

04-stacje.png

 

Dziewiątka stacji, przełączana jednym dotknięciem

Poza radiem w kostce siedzi generator szumu – białego, różowego i brązowego. Szum powstaje w samej kostce, dlatego gra także bez internetu, w hotelu czy w samochodzie. Jest zegar, regulacja głośności i jasności, jasny i ciemny motyw, polski i angielski interfejs.

05-szum.thumb.png.7ece719cc66eec935413762c6d29cd3a.png

Szum w trzech kolorach, bez internetu

Pierwsze parowanie głośnika Bluetooth bywa uparte. Oba moje głośniki dały się znaleźć dopiero za trzecim podejściem. Potem kostka pamięta głośnik i po włączeniu łączy się z nim bez pytania. Na wbudowanej baterii gra około dwóch i pół godziny (zmierzony pobór to ok. 140 mA, w szczytach 190 mA), więc do drugiego pokoju przeniesiecie ją bez szukania gniazdka.

Dodatkowe czujniki

Z boku kostki jest gniazdo Grove (port A). Wpinacie w nie moduł, a kostka sama rozpoznaje, co dostała. Obsługuje trzy:

  • CO2L (SCD41): dwutlenek węgla, temperatura i wilgotność. Ten stoi u mnie.
  • CO2 (SCD40): tańszy wariant z węższym zakresem, do 2000 ppm.
  • ENV Pro (BME688): temperatura, wilgotność, ciśnienie i gaz.

Dwa moduły naraz wepniecie przez rozdzielacz 1 to 3 HUB. Uważajcie w koszyku: chodzi o zwykły HUB, a nie podobnie wyglądający PaHub, z którym kostka nie zagra.

06-kostka-powietrze-co2l.thumb.png.361b4a94d8e49b24ebed05f4501da846.png

Ekran powietrza z modułem CO2L: punkt rosy, tendencja ciśnienia, temperatura i CO₂

Ekran powietrza rysuje paski zamiast tabelki z liczbami, żeby dało się go odczytać z drugiego końca kanapy. Gruby pasek pokazuje, ile CO₂ zebrało się w pokoju, a kiedy zrobi się bursztynowy, pod spodem pojawia się napis „Wywietrz pokój”. Strzałka ciśnienia zdradza, że idzie zmiana pogody. Z ENV Pro dochodzi cienka kreska. Przez kilka pierwszych dni kostka uczy się, jak Wasz pokój pachnie normalnie, a potem pokazuje, że coś się zmieniło. Co dokładnie, tego nie powie. Czujnik gazu odpowiada jedną liczbą na perfumy, gotowanie i środki czystości, dlatego kostka nie jest czujnikiem czadu ani dymu i na te zagrożenia trzeba mieć certyfikowane czujki.

Na jakim sprzęcie?

Jeden plik działa na wszystkich trzech rewizjach Core2: v1.0 (układ zasilania AXP192), v1.1 (AXP2101) i v1.3. CoreS3 to inny procesor (ESP32-S3) i obraz od Core2 na nim nie ruszy. Core2 for AWS ani klonów nie sprawdzałem. A Tab5? Radia na nim nie będzie. Tab5 łączność dostaje od układu ESP32-C6, który zna tylko Bluetooth Low Energy, a głośniki muzyczne potrzebują klasycznego Bluetootha (A2DP). Mam na Tab5 osobny projekt ze starymi przygodówkami i o nim napiszę kiedy indziej.

Jak to się mieści w jednym ESP32? Szczegóły techniczne

Kto szukał, jak zrobić z ESP32 radio internetowe na głośnik Bluetooth, trafił pewnie na radę, żeby wziąć dwa ESP32 albo osobny nadajnik BT. Autor biblioteki ESP32-A2DP pisał wprost: „The ESP32 only supports either Bluetooth or WIFI, but not both at the same time”. Autor yoRadio Bluetootha nie planuje. W projektach, do których zajrzałem, obsługa A2DP leży zakomentowana albo radio i Bluetooth działają na zmianę, przełączane przyciskiem. Przekopałem GitHuba i fora ESP32, Arduino i M5Stack. Nie znalazłem nikogo, kto na jednym ESP32, w gotowej kostce czy na gołej płytce, gra stację prosto z internetu na głośnik Bluetooth i ma na to pomiary.

Najbliżej podeszło ESPuino – ma taki tryb od lipca, ale jego autorzy sami piszą, że jest słabo przetestowany i możliwe są crashe. Jest jeszcze squeezelite-esp32, który gra na Bluetooth, tyle że strumień dostaje z domowego serwera LMS, a ten bierze na siebie całą rozmowę z internetem.

W Core2 pracuje zwykły ESP32 z dwoma rdzeniami 240 MHz, 520 KB SRAM i 8 MB PSRAM. Kostka w tym samym czasie pobiera strumień przez Wi-Fi, dekoduje MP3, koduje SBC dla głośnika, wysyła go przez Bluetooth, rysuje ekran i pilnuje dotyku. Wi-Fi i Bluetooth mają na to jedno radio 2,4 GHz i jedną antenę, którą dzielą w czasie. Wszystko to naraz zjada prawie całą pamięć i czas procesora, więc większość pracy nad Open Radio polegała na szukaniu ustawień, w których jeszcze się mieści.

MP3 128 kb/s potrzebuje 15,6 KB/s. Przy grającym głośniku kostka pobiera 15,6–15,7 KB/s, czyli dokładnie tyle, ile trzeba, a w gorszych warunkach radiowych spada do 12–14 KB/s. Wi-Fi i Bluetooth dzielą radio w trybie zrównoważonym, bo tryb faworyzujący Wi-Fi słyszalnie dusił głośnik. Katalog kończy się na 128 kb/s. Jedynka nadaje tylko w 192 kb/s, przez Bluetooth brzmiała źle i do katalogu nie weszła. Popularna rada z forów, WiFi.setSleep(false) na szybsze Wi-Fi, kończy się tu abort() kontrolera Bluetooth i restartem co 26 sekund, w kółko. Modem-sleep zostaje włączony.

Z pamięcią jest jeszcze ciaśniej. Po starcie kostka ma 178 KB wolnej pamięci wewnętrznej. Stos Bluetooth (Bluedroid) zabiera z niej jednorazowo około 75 KB i kiedy radio gra, a głośnik jest połączony, zostaje 16–20 KB. Przy tym liczy się największy spójny blok – sama suma wolnej pamięci niewiele mówi. Kostka padła kiedyś na assercie Bluedroida, gdy największy wolny blok miał 1 588 bajtów. Wyłączenie mDNS na czas grania oddało 7 KB. Bluetooth startuje dziś tylko wtedy, gdy znajdzie blok co najmniej 16 KB. Próg schodził z 56 przez 32 do 16 KB, a przy 32 KB Bluetooth nie wystartował, bo zabrakło dwunastu bajtów.

Osobny kłopot to TLS. Sam handshake chce 30–40 KB, więc połączenia szyfrowane kostka załatwia przed startem Bluetootha, a od 0.4.2 pętla, która gra dźwięk, nie otwiera TLS wcale. Stacje dostępne tylko przez HTTPS mają przypięte zapasowe adresy HTTP.

Bufory mają razem około 20 sekund, ale to liczba na papierze. Po pierwszym zapasie od serwera strumień płynie w tempie odtwarzania i bufor nie urośnie ponad ok. 2,2 s. Wersja, która przed połączeniem z głośnikiem czekała na pełny bufor, łączyła się po sześciu minutach. Dziś progi zeszły do jednej, dwóch sekund.

Dekoder dostaje na jeden obieg pętli 8 192 ramki. Kiedy dostał trzy razy więcej, obieg trwał w medianie 784 ms i dotyk przestał reagować, a dźwięku nie przybyło ani trochę, bo wąskim gardłem była sieć. AAC nie obsługuję, bo dekoder, który mieści się w pamięci, ma licencję niezgodną z GPL, a zgodny z nią FAAD2 potrzebuje około 60 KB stosu, których przy grającym Bluetoothu nie ma.

Najdziwniejszy był błąd z routerem. Kostka dwa metry od niego tnie dźwięk, a w drugim pokoju gra czysto, bo nadajnik Wi-Fi zagłusza odbiornik Bluetooth. U mnie wystarczyło przestawić kostkę o trzy metry.

Każdą zmianę sprawdzam tak samo. Wgrywam ją, zbieram pięć minut zapisu z urządzenia i patrzę, czy bufor ani razu się nie opróżnił i czy watchdog ani razu nie zrestartował kostki. Dopiero potem słucham. Log i ucho mówią różne rzeczy – w dziesięciu minutach nagranych mikrofonem log pokazał 215 przerw w dopływie danych, a słychać było 25, najdłuższą 0,35 sekundy.

Binarkę możecie sprawdzić sami. Obok każdego pliku do pobrania leżą pełne źródła z instrukcją, jak je zbudować, a aplikacja 0.4.4 zbudowana z nich na czystej maszynie wychodzi identyczna co do bajtu.

Kod pisały ze mną dwa agenty AI, Codex i Claude Code. Ja decyduję, co radio ma robić, a czego nie, testuję na kostkach, słucham, jak gra, i zatrzymuję każde wydanie, które nie przeszło pomiarów.

Co nowego w 0.4.4

W 0.4.2 wyłączony i włączony głośnik Bluetooth wracał do kostki po kilkunastu sekundach, a czasem po kilku minutach. Radio czekało na pełny bufor wbudowanego głośnika, a przy strumieniu płynącym w tempie odtwarzania nie doczekało się nigdy – raz Bluetooth nie ruszył przez 460 sekund. Do tego, kiedy to głośnik dzwonił do kostki, Bluedroid zostawiał ją stroną podrzędną, łącze milkło i po 16 sekundach się zrywało. W 0.4.4 czekanie kończy się najpóźniej po 30 sekundach, a kostka zamyka łącze zestawione przez głośnik i sama do niego dzwoni. Na wydanym obrazie, na RMF FM, wyłączyłem i włączyłem głośnik dziesięć razy. Wracał po 3–16 sekundach, w dziewięciu próbach przed upływem dziesięciu, bez przerw w dźwięku i bez restartu kostki. Na tej wersji kończę linię 0.4. Wszystkie wersje radia pobrano dotąd ponad 500 razy.

Współpraca reklamowa: już w trakcie prac nad drugą wersją radia odezwał się Botland, który od tamtej pory pokrywa mi koszt kolejnych kostek i czujników.

Linki:

Jeśli Core2 kurzy się Wam w szufladzie, jeszcze dziś wieczorem może grać RMF. Pytania chętnie przyjmę w komentarzach 🙂

Edytowano przez iTomek
zona ;)
  • Lubię! 2

Podoba Ci się ten projekt? Zostaw pozytywny komentarz i daj znać autorowi, że zbudował coś fajnego!

Masz uwagi? Napisz kulturalnie co warto zmienić. Doceń pracę autora nad konstrukcją oraz opisem.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...