Elektronikai és informatikai DIY projektek

Mikroelektronikai és informatikai bütykölések

Mikroelektronikai és informatikai bütykölések

Nano FM rádió

RDA5807M RRD-102V2.0 FM modullal és ATmega328P mikrovezérlővel

2018. július 27. - BTSoft

nano-radio-banner-atmel-inside.png

  Munka közben gyakran hallgatok zenét, azonban egy szerencsétlen eset kapcsán mindenféle zajkeltő eszközöm és lehetőségem megsemmisült. Gondoltam, hogy amíg pótlom a kütyüjeimet - pontosabban, amíg össze nem rakok egy BlueTooth-os, FM rádiós hordozható hangszórót - addig gyorsan elkészítek egy fejhallgató kimenettel rendelkező egyszerű FM rádiót. Természetesen ATmega328P processzorral, Arduino környezetben futó szoftverrel. A tervezgetés során - magam hatása alá kerülvén - mindenféle csodaszolgáltatást beleálmodtam a rádiómba, de a hardware szerény képességei nem tettek mindent megvalósíthatóvá.

Lássuk, hogy hogyan alakult az Arduino világába még éppen hogy csak beleszagolt lelkes amatőr rapid rádiója!

A nagyra törő tervek

Az elektronikus szakirodalom rengeteg megoldást kínál az Arduino-s FM rádiók építésére, én is jó néhányat átnéztem, néhány olyan munkát sorolok fel az alábbiakban, amelyek valamilyen szempontból felkeltették a figyelmemet.

  Sajnos mindegyiknek volt vagy épp hiányzott olyan komponense, amely miatt végül is a saját megoldás mellett döntöttem, eggyel növelve a már így is igen nagyszámú FM rádió implementációkat. Viszont mindegyikből merítettem egy-egy ötletes megoldást, ihletet. A tervezgetés elején még úgy gondoltam, hogy majd jól felokosítom a saját rádiómat. Lesz benne RTC (Real Time Clock), amely bónuszként még a hőmérséklet mérését is (pl.: a DS32301 modul egy nem túl pontos hőmérő szenzort is tartalmaz); lesz majd jó sok memóriahely a kedvenc adók tárolására; automatikus csatornahangolás, klassz RDS szolgáltatása is lesz, és persze az RDS infókból az alternatív frekvenciákat is fogja kezelni, stb. 

  De sajnos az élet - bár inkább a processzor kevés RAM-ja - ezt nem tette lehetővé, még az egyes "gyári" library-k lecsupaszítását követően is a fejlesztés alatt sokszor elfogyott a stack, lefagyott a kütyüm, így sok mindenről le kellett mondanom. 

Mindenesetre az alapelvárásokat sikerült teljesíteni, ezek az alábbiak:

  • Alap rádió funkciók + RDS adó név, szöveg és idő kezelése
  • Csak fejhallgató kimenete van, nem kellett hangszóró.
  • Az LCD kijelzőjének háttér világítása igazodik a környezethez (sötétben ne vakítson, de nappal lehessen azért látni)
  • Kicsi, könnyű, hordozható, USB-ről tölthető akkumulátoros megoldással
  • Mivel akkumulátoros, így méri annak a feszültségét, és alacsony feszültségnél kikapcsolja magát.
  • Készenléti állapotban keveset fogyaszt.
  • Környezeti hőmérsékletet méri (standby állapotban).
  • Nem funkcionális tulajdonság, de: igen-igen jó a hangja és olcsó.

 

A komponensek kiválasztása

 

ATmega328P mikrovezérlő

  A kettős impulzusszámlálós ponthegesztőm építése során megismert mikrokontroller számomra nagyon jól bevált, így nem is volt kérdés, hogy mi lesz a "lelke" a rádiómnak. Bár ez a második ilyen munkám, de már most megmutatkoztak a mikrovezérlő korlátai. Elsősorban a RAM miatt tört bele a bicskám néhány szolgáltatás implementálásába, emiatt többről le is kellett mondanom. Többször kellett "megnyirbálnom" némely library-t, mert a flash memória is kevésnek bizonyult. Jelenleg az Adafruit GFX/PCD8544 LCD könyvtárat alkalmazom, amit közel sem használok ki, de jó sok tárhelyet foglal. Bár próbáltam néhány más LCD könyvtárat bevetni, de nem igazán akartam már a lelki világukat feltárni, gyorsan kellett a kütyü, szóval maradt az Adafruit. Így - valószínűleg - a V0.0.3-as verzióban már hozzá fogok/kénytelen vagyok hozzányúlni a képernyőkezeléshez és nyerek némi tárterületet és remélhetőleg bár byte RAM-ot is. Én korábban itt szereztem be a mikrovezérlőimet 380Ft/db áron, most (2018.07 vége felé) úgy látom, hogy kissé (bár inkább nagyon) meglódult az ára....

Nokia 5110 LCD + KY040 Rotary Encoder

lcd-modulok.png  A ponthegesztőnél már jól bevált eszközök, itt is ezeket választottam. Az elején még gondolkodtam az OLED kijelzőkön, de túl kicsiknek bizonyultak (0.96"-osaim vannak), úgy gondoltam, hogy az RDS szövegeket nem lenne kényelmes nagyítóval nézegetni rajtuk. Nemrég a kezembe akadt egy olyan LCD modul (kék) amelynek a háttérvilágítása pont fordítva működik azokhoz képest, amikkel eddig dolgom volt, így a programot felkészítettem az ilyen modul kezelésére is (részletek a firmware ismertetésénél) Az LCD modulokat korábban innen szereztem be, 530Ft/db áron

A rotary encoder-en túl nem terveztem egyéb kezelőszervet a rádiómba, így a firmware úgy lett kialakítva, hogy mindent a tekergetéssel és kattintgatással lehet elérni. (Egy dolgot nem terveztem bele: nem lehet reset-elni a kütyüt, de erre igen ritkán van szükség, arra meg ott az elem ki-be módszer). A KY-040-et korábban innen vásároltam, 165Ft/DB áron.

RDA5807M FM rádió modul

fm_modulok.png  A különböző írások áttanulmányozását követően természetesen nem tudtam egyértelműen eldönteni, hogy mely modul lesz a számomra megfelelő, így rendeltem néhányat a gyakoribb típusokból és kipróbáltam őket. Sokat kísérletezgettem velük, az eredmény számomra elég meglepő lett. Mint a mesében: a legkisebb, a legegyszerűbb, a legolcsóbb vált be, de az nagyon! Na jó, nem annyira nagyon-nagyon, csak nagyon... (Így most van egy raklap egyéb típusú FM modulom, de majd ráállok a nagyüzemi rádió gyártásra és eldolgozom őket...)

Szóval az RDA5807M vált be nekem a legjobban, elég könnyű a programozása az igazán jó implementációjú Radio Arduino könyvtár segítségével. Bár pont ezt a könyvtárat kellett megnyirbálnom, hogy beleférjek a RAM-ba (no és a flash területbe). Rendelkezik bassboost mély hang kiemeléssel, melynek következtében eszetlen jó hangzása van!! Valamint zavarba ejtően olcsó...

rda5807m_modul.png rda5807m_modul_bekotese.png

  Tehát ez a modul minden olyat tud, ami nekem kell (gyors I²C kommunikáció, egyszerű API, RDS, kiváló hangzás), de azért van baja is... Az RDS mondhatni csapnivaló. Ahol lakom - ott elég gyengék az FM adók térereje - ott szinte használhatatlan. Nagyon nehezen szinkronizálja rá magát az RDS adásra, sokáig kell rá várni. Emiatt is módosítottam a fenti Radio könyvtár RDS dekóderének környékén a  kódot. Viszont, ahol dolgozom, ahol használom, ott elég jó a térerő, így az RDS is jó, tehát ez pipa. Viszont a munkahelyem környékén két helyi rádió  adó is van, amik meg kihozzák a modul gyenge szelektivitását, sok adóba belezavarnak a helyi adások.
De mindezeket a nyűgöket annulálja a többi kipróbált FM modulhoz képesti hangzás: döbbenetesen jól szól ez a kis modul és még illesztő kondik sem kellenek a kimenetre. A modult én itt szereztem be, 138Ft/db áron. Az itt található leírásból lestem el, hogy a kényelmetlen raszterű lábkiosztását hogyan lehet egyszerűen "konvertálni".

Kétirányú I²C szintillesztő

i2c_szintillesztok.png  Az FM modulok némelyike 3.3V-ról működik. Bár láttam megoldásokat, hogy a modulokat simán 5V-ra kötve hajtották, de nem nagyon tudtam, hogy a kipróbálandó FM modulok hogy viselik ezt el. Így a biztonság kedvéért beszereztem a szükséges 5V↔3.3V szintillesztőket is. Igen olcsók (106Ft/db), én itt szereztem be. Elég egyszerű a bekötésük és a használatuk, a biztonság kedvéért szerintem megéri beépíteni.

DS18B20 digitális hőszenzor

   Mint azt a korábbiakban már említettem, elég grandiózus tervekkel estem neki a rádiómnak, de már jóval szerényebb lettem a projekt vége felé. A memória szűkössége miatt elvetettem a DS3231 alapú RTC beépítését, így most ez a modul megmarad egy következő projektre. De hogy legalább valami értelmeset műveljen a kütyüm a standby állapotban, egy DS18B20 hőmérő kódját préseltem még be a mikrovezérlőbe. Mivel a rádió akkumulátoros táplálású, így az amúgy általam messze elkerült LM335-ös analóg szenzor alkalmazását minden lelkiismeret furdalás nélkül elvetettem. A Dallas DS18B20-at én itt szereztem be, arcpirítóan olcsón jutottam hozzájuk egy szerencsés aukción (150Ft/db), de többnyire 230-250Ft-ért már meg lehet venni.

USB 1S 3.7V li-ion töltő

 1s-li-ion-tolto.jpg Egy korábbi projekt kapcsán szereztem be ezt a töltőt. Elég olcsók (150-200Ft), és nagyon sokoldalúan fel lehet őket használni. Jelen esetben kifejezetten jól jön, hogy van USB csatlakozási lehetősége, így akár egy PC-ről is lehet tölteni a rádiót.

GL5516 foto ellenállás

 foto-szenzor.jpg Ebben a leírásban láttam azt az ötletet, hogy az LCD modul háttérvilágítását a környezet fényerejéhez képest változtatja a szerző. Mivel elég sok kezdeti tervről lemondtam, így arra gondoltam, hogy - a kód nem túl bonyolult és nem foglal sok helyet - szépségtapasznak jó lesz az én rádiómra is ez a trükk. A fotoellenállást én itt szereztem be, 12Ft/db áron.

 Egyebek

A 18650-es akku egy kivénhedt laptopból származik. Maga az akku meglepően jól érzi még magát. Az akkutartót itt vásároltam 85Ft/db áron. A 12x7x5cm méretű műanyag  dobozt már jó régen vettem valahol, ha minden igaz, akkor kb 750Ft volt. Szintén egy korábbi beszerzésből származik a 78L33-as 3.3V-os feszültség stabilizátor IC is, én itt vettem 26Ft-ért.

 

 A kapcsolási rajz

deszkamodell.pngA fejlesztést és így a kapcsolást deszkamodellen végeztem el egy Arduino Nano-val. A Nano lábkiosztása - a dolog természetéből adódóan - más, mint a sima ATmega328P mikrovezérlőé, a deszkamodell rajzát itt lehet megtekinteni.  

nano-fm-radio_barebones_v0_0_1.png

 *A kapcsolási rajzhoz sajnos nem találtam két csatornás I²C szintillesztő szimbólumot, így egy 4 csatornás modul látható a rajzon (M1), de "képzeljük le" a +2 csatornát róla :) 

  Néhány szót a kapcsolásról. Az LCD modul, az I²C szintillesztő és az FM modul 3.3V-ról jár, amit a deszkamodellen a Nano biztosít, a "csupasz" mikrokontrolleres (barebones)  verzióban viszont az IC1 78L33-as stabilizátor.  

   A li-ion-os táplálás miatt fontos az akku feszültségének mérése, pontosabban a túlmerítés elkerülése érdekében az alacsony feszültség detektálása. Mivel a firmware a mikrovezérlő belső 1.1V-os referenciafeszültségét használja az analóg bemenetein mérhető feszültségszintek meghatározására, így az akku-feszültségmérést az R1-R2 feszültségosztó segítségével kell hogy végezzük, le kell osztani a maximális akkufeszültséget 1.1V alá. A korrektebb mérés miatt érdemes R1/R2 feszültségosztót 1%-os tűrésű ellenállásokból felépíteni.

Alacsony akkufesz esetén a rádió kikapcsolja magát, "PowerDown" állapotba kerül. Hogy ebből az állapotból ki lehessen billenteni (mert már töltőre dugtuk a kütyüt), a rotary encoder SW lába rá van kötve a mikrovezérlő INT1 lábára (Nano: D3, ATmega328P: pin5). Így a rotary encoder megnyomására egy külső interrupt keletkezik, ami kilöki a processzort a "kikapcsolt" módból.

Az LCD háttérvilágításának szabályozásához szolgáltat információt az R3-R4 alkotta feszültségosztó. R3 optoellenállás nappali fény esetén x100Ω, míg este x10kΩ ellenállása a környezet fényerejével arányos feszültséget szolgáltat a mikrokontroller A2 analóg bemenetére. A firmware ezt a feszültséget méri, és a D11-es lábára kötött LCD háttérvilágítás LED-et a mért feszültségtől fordított arányban függő PWM-el hajtja meg, ami végső soron a LED fényerejét szabályozza.

A kész rádió felprogramozása az AVR ISP portján keresztül történik, ez a csatlakozó (J1) ki is van vezetve a rádió oldalán.

 

A firmware

A rádió forráskódja a github-ról tölthető le. A C++ projekt egy Eclipse IDE Arduino projekt, erről a fejlesztői környezetről a digitális ponthegesztőmnél már kitértem. A kód elég jól kommentezett, így nem térnék ki a részletes ismertetésére, csak néhány érdekességre térek ki.

Mint azt korábban már említettem, helyszűke miatt le kellett csupaszítanom (ill. a modul gyenge RDS tulajdonsága miatt módosítanom) a Radio Arduino library-t, az eredmény a  BTRDA5807M állományokban található. 

Az akkufesz mérését a belső 1.1V-os referencia feszültség segítségével oldja meg a program. A feszültségméréssel kapcsolatos konstansok a NanoFmRadio.cpp állomány elején találhatóak. 

feszmeres-konstansok.png

A firmware a mért tápfeszültég értékét az üzemi képernyő jobb felső sarkában elhelyezett telep (bár jobban emlékeztet egy szódás szifon patronjára, de így sikerült...) szimbólummal, pontosabban annak "tartalmának" változtatásával  jelzi. Amennyiben a tápfesz 4.2V (BATT_VOLTAGE_HIGH) vagy annál nagyobb, a szimbólum teljesen kitöltött, míg 3.2V-os  (BATT_VOLTAGE_LOW) akkufesz esetén a szimbólum nincs kitöltve. Amennyiben R1-R2 értékét a kapcsolási rajzon feltüntetett értékekhez képest módosítanánk, úgy a BATT_VOLTAGE_ATT_VALUE preproceszor konstans értékét is változtassuk meg, ez a konstans definiálja az aktuális osztási értéket.

Az alacsony akkufesz esetén (3.2V) a kikapcsolást, valamint a standby állapotban a PowerDown módból történő időzített feléledést a LowPower könyvtár segítségével oldottam meg. low-voltage-powerdown.png

 A háttérvilágítás szempontjából kétféle viselkedésű LCD modul támogatására az LcdBackLightAdjuster osztály konstruktorát 3 paraméterrel láttam el, a 3. paraméter határozza meg a háttérvilágítás LED-jének működését. Default esetben (alacsony szintre aktív az LCD LED-je) nem kell a kódot módosítani, a 3. paraméter default értéke  LOW.

lcd-bl-low.pngMíg egy "kék" LCD modul esetén az LcdBackLightAdjuster  konstruktorának 3. paraméterét HIGH értékkel kell megadni, a kódnak tehát az alábbiak szerint kell alakulnia.

lcd-bl-high.png

Low-Batt állapot 

low-batt.pngAlacsony akkufesz (3.2V) esetén a program 'kikapcsolja' a processzort, csak egy külső megszakítás tudja visszabillenteni (a rotary encoderen egy klikk). Ebben az állapotban az LCD sincs frissítve, az áramkör csak néhány μA-t fogyaszt. A képernyőn a figyelmeztető üzeneten túl megjelenik az tápfesz utolsó mért értéke (a képen egy a programból előidézett állapot látható, nyilván a kijelzett feszültség nem indokolná a kikapcsolást).

Készenléti állapot

Készenléti állapotban a program az idő döntő többségét PowerDown állapotban tölti, csak 500msec-enként éled fel a rotary encoder valamint a DS18B20 olvasásának idejére. Az 500msec amiatt van, mert nagyobb időegység választása esetén - bár nyilván a fogyasztás szempontjából kedvezőbb lenne - a kész kütyüm több másodperc után kapcsolódott csak be, az okát még nem találtam meg. Ennél az értéknél még elég keveset fogyaszt a rádió, és elfogadható időn belül veszi észre, hogy be kell kapcsolódnia. Ahogy ezeket a sorokat írtam eszembe jutott, hogy valójában a fogyasztáson még mindig lehetne nyerni, ha az R1-R2 valamint R3-R4 feszültségosztókat nem közvetlenül a tápfeszre, hanem egy szabad digitális kimenetre (pl.: D9 vagy D10) kötném, és csak a mérések idejére kapnának az osztók feszültséget a kimenetről.

Készenléti állapotban a képernyő az alábbiak szerint néz ki.

standby.png

Készenléti állapotba hozni, kikapcsolni úgy tudjuk a rádiót, ha a rotary encoder gombját ~2mp-ig nyomva tartjuk ("hosszú klikk").

Bekapcsolt állapot

Bekapcsolt állapotban a képernyő az alábbiakban látható.

display.png

A képernyő felső szekciója a vételre, valamint az akkufeszre vonatkozó információkat jelenít meg. Ezek rendre a következők:

  • Az RSSI-vel (Recieved Signal Strength Indicator, vételi térerő) arányos magasságú térerő háromszög szimbólum
  • Az RSSI aktuális értéke
  • Sztereó szimbólum, csak akkor látható, ha sztereó a vétel
  • RDS vétel, csak akkor látszik ha szinkronizált az RDS vevő
  • Az akku feszültségével arányosan kitöltött/feltöltött telep szimbólum

Az "információs sáv" alatt elhelyezkedő "Menü" (szándékosan idézőjelbe téve) sora azt mutatja, hogy a rotary encoder tekergetése mit fog okozni. A fenti kép szerint a "Seek" felirat azt jelenti, hogy a tekergetésre az FM modul a tekerés irányával egyező frekvencia "irányban" keres egy adóállomást. A menü - ott ahol annak értelme van - érték vagy egy funkció ki bekapcsolás választásakor az aktuális értéket ki is írja.

A "menüben" egy klikkel lehet "lépkedni", a menü cirkulárisan szervezett. A teljes menütérkép az alábbiak szerint néz ki:

  • Seek: állomásra hangolás
  • Volume: hangerőállítás, értékkészlet: 0-15
  • BassBoost: mély hang kiemelés, értékkészlet: on/off
  • SoftMute: adó nélküli frekvencián némítás, értékkészlet: on/off
  • LCD BLight: LCD háttérvilágítás be- kikapcsolása, értékkészlet: on/off
  • Frequency: 100kHz-es lépésekben hangolás

A rotary encoder támogatja a sebességfüggő érték változtatást, így ha gyorsabban tekergetjük, akkor az állított érték is gyorsabban változik, ami elsősorban a frekvencia hangolás esetén jön jól.

display-1.png display-2.png display-3.png

A képernyőn az RDS-ből származó adatok törlődnek, ha új frekvenciára hangolunk, ill. RDS vétel esetén folyamatosan frissülnek. Mint azt korábban említettem, ennek az FM modulnak az RDS vevője nem egy világbajnok, így elég nehézkesen birkózik meg az RDS adatokkal: ha "nem támasztjuk az antennáját az adónak", akkor többnyire az RDS adatokban csacsiságok jelennek meg :( 

Diagnosztikai képernyő

   A fejlesztés során kialakítottam egy "diagnosztikai"/belső állapot képernyőt is, de végül is a kész kütyü kódjában benne hagytam. A diagnosztikai képet bekapcsolt állapotban a rotary encoder dupla klikkjével lehet előcsalni. Itt a mért akkufesz, a hőmérséklet, a szabad RAM byte-okban valamint az FM modul vételi térerejének értéke (RSSI) látható. A képernyőből egy klikkel lehet kilépni.

internal-state.png

 

Néhány kép a kész rádióról

kutyu-1.png kutyu-2.png kutyu-3.png
kutyu-4.png kutyu-5.png kutyu-6.png


Az antenna

antenna.pngAntennaként jó vételi körülmények között tulajdonképpen bármilyen "drót" megteszi, de nem nagy baj, ha mondjuk ennek a hossza méretezve is van. Én kétféle antennával próbálkoztam, egy a 88-108MHz sávközépre hangolt negyedhullámú botantennával (~77cm a hossza), ill. gyengébb vétel esetén egy dipól antennával, melynek "ágai" ugyan ilyen hosszúak (az egyik antennavég a földre, a másik az FM modul antenna bemenetére kötve). Az képen a dipól látható. Csak a kép kedvéért van ilyen csinosan elrendezve, üzemszerűen az antenna ágai ki vannak feszítve. Az antenna egy kéteres, szimpla szigetelésű, ø1mm-es rézvezetékből lett kialakítva, ha minden igaz ez a vezeték valamikor egy telefonkábel volt.

 

Mi mennyibe került? 

 A blog vége felé jöjjön a szokásos kérdés: mennyi is volt mindez? Nos, most nem sorolom fel tételesen az egyes alkatrészek árát - néhány helyen már utaltam az árakra - csak a végösszeget írom le (az akku nélkül, hiszen az bontásból származik): ~2.500Ft-ból kijött a kütyü !! :)
 

Összefoglalásként

   A könnyfakasztóan szűkös memóriaproblémák ellenére nagyon élveztem a projektet, és mindezek ellenére igen hamar összeállt a rádió. Bizonyára, ha vettem volna a fáradságot és komolyabban nekiestem volna egy-két igen csak felhízott library lecserélésének, úgy a többszintes UI menü, a tárolható állomások, az RTC (ezt nagyon sajnálom, hogy ki kellett dobnom :( ) is talán belefért volna a dobozka tudásába. De nem ez volt a cél. Talán majd legközelebb, a V0.0.3-as verzióban összekalapálok valamit :) 

Mindenesetre így is egy igen csak kiváló hangzású rádióm lett (az RDS tudását most leplezze az elnézően nagyvonalú hallgatás), és közben tovább reszelgettem a már megkopott C++ ismereteimet. Szóval pozitív az egyenleg!

 

breadboard-barebones.png

 

A bejegyzés trackback címe:

https://electrodiy.blog.hu/api/trackback/id/tr3214145183

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.
süti beállítások módosítása