Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.
Obě strany předchozí revize Předchozí verze Následující verze | Předchozí verze | ||
2015:si4703-radio [2016/01/17 14:55] Adam Štěpánek [Závěr] |
2015:si4703-radio [2016/01/17 16:07] (aktuální) Adam Štěpánek |
||
---|---|---|---|
Řádek 5: | Řádek 5: | ||
* Použijte vývojový kit [[http://developer.mbed.org/platforms/KL25Z/|FRDM-KL25Z]] | * Použijte vývojový kit [[http://developer.mbed.org/platforms/KL25Z/|FRDM-KL25Z]] | ||
=====Integrované rádiové moduly===== | =====Integrované rádiové moduly===== | ||
- | Většina mobilních telefonů a MP3 přehrávačů mají v sobě automaticky radiový přijímač. Není se čemu divit, výrobci je integrovali do velmi malých pouzder a při jejich masové výrobě je cena příznivá. Všechny potřebné funkce mají již v sobě (RDS, potlačení šumu, AGC, automatické vyhledávání stanic, atd.), takže stačí pouze přidat výstupní zesilovač, nebo využít digitálních audio výstupů. Nejvíce mě zaujala nabídka [[http://www.silabs.com/products/audio/Pages/default.aspx|Silicon Labs.]] Nabízí mimo přijímačů i vysílače nebo kombinace obojího. Vysílače umožňují velmi jednoduše spojit MP3 přehrávač nebo mobilní telefon přímo s autorádiem. (pozn.: Česká legislativa něco takového neumožňuje) | + | Většina mobilních telefonů a MP3 přehrávačů mají v sobě automaticky radiový přijímač. Není se čemu divit, výrobci je integrovali do velmi malých pouzder a při jejich masové výrobě je cena příznivá. Všechny potřebné funkce mají již v sobě (RDS, potlačení šumu, AGC, automatické vyhledávání stanic, atd.), takže stačí pouze přidat výstupní zesilovač nebo využít digitálních audio výstupů. Nejvíce mě zaujala nabídka [[http://www.silabs.com/products/audio/Pages/default.aspx|Silicon Labs.]] Nabízí mimo přijímačů i vysílače nebo kombinace obojího. Vysílače umožňují velmi jednoduše spojit MP3 přehrávač nebo mobilní telefon přímo s autorádiem. (pozn.: Česká legislativa něco takového neumožňuje) |
=====Hardware===== | =====Hardware===== | ||
Vybral jsem si modul FM rádia [[https://www.sparkfun.com/datasheets/BreakoutBoards/Si4702-03-C19-1.pdf|Si4703]]. Ten má v sobě zabudovaný i RDS procesor a další funkce. Zapsáním hodnoty do příslušného registru ovládáme VCO (oscilátor řízený napětím), s pomocí kterého obvod naladí frekvenci. Modul již má audiozesilovač, takže stačí jen připojit sluchátka, které slouží zároveň i jako anténa. | Vybral jsem si modul FM rádia [[https://www.sparkfun.com/datasheets/BreakoutBoards/Si4702-03-C19-1.pdf|Si4703]]. Ten má v sobě zabudovaný i RDS procesor a další funkce. Zapsáním hodnoty do příslušného registru ovládáme VCO (oscilátor řízený napětím), s pomocí kterého obvod naladí frekvenci. Modul již má audiozesilovač, takže stačí jen připojit sluchátka, které slouží zároveň i jako anténa. | ||
Řádek 15: | Řádek 15: | ||
Budeme ho ovládat pomocí vývojového kitu [[http://www.nxp.com/products/software-and-tools/hardware-development-tools/freedom-development-boards/freedom-development-platform-for-kinetis-kl14-kl15-kl24-kl25-mcus:FRDM-KL25Z|FRDM-KL25Z.]] | Budeme ho ovládat pomocí vývojového kitu [[http://www.nxp.com/products/software-and-tools/hardware-development-tools/freedom-development-boards/freedom-development-platform-for-kinetis-kl14-kl15-kl24-kl25-mcus:FRDM-KL25Z|FRDM-KL25Z.]] | ||
=====Software===== | =====Software===== | ||
- | Vývojové prostředí [[mbed.org]] umožňuje vyhledat a importovat knihovny, které vytvořili ostatní uživatelé. Takto se podařilo získat knihovny pro FM modul i displej. Následující vytvořený kód má za úkol zobrazit hlavní obrazovku, na které bude zobrazena aktuálně naladěná frekvence, možnost manuálního i automatického ladění, nastavení hlasitosti a dat z RDS. | + | Vývojové prostředí www.mbed.org umožňuje vyhledat a importovat knihovny, které vytvořili ostatní uživatelé. Takto se podařilo získat knihovny pro FM modul i displej. Následující vytvořený kód má za úkol zobrazit hlavní obrazovku, na které bude zobrazena aktuálně naladěná frekvence, možnost manuálního i automatického ladění, nastavení hlasitosti a dat z RDS. |
---- | ---- | ||
- | **Velký počet proměnných, které jsou třeba například pro uložení nastavení mě pomohly zpřehlednit struktury** | + | **Velký počet proměnných, které jsou třeba například pro uložení nastavení mně pomohly zpřehlednit struktury** |
- | <code> | + | <code cpp> |
+ | /* | ||
+ | +-----------------------------------------------------+ | ||
+ | | | | ||
+ | | | | ||
+ | | FM radio s Si4703 | | ||
+ | | | | ||
+ | | | | ||
+ | +-----------------------------------------------------+ | ||
+ | */ | ||
+ | // Autor: Adam Stepanek | ||
+ | // Vytvoreno v ramci projektu MPOA 2016 | ||
+ | |||
+ | |||
+ | // Inkluze knihoven | ||
+ | #include "mbed.h" | ||
+ | #include "SparkFun-Si4703.h" | ||
+ | #include "SSD1306.h" | ||
+ | #include "millis.h" | ||
+ | |||
+ | // Definice pro tlacitka | ||
+ | #define LEFT 0x01 | ||
+ | #define CENTER 0x02 | ||
+ | #define RIGHT 0x03 | ||
+ | |||
+ | // Definice pro displej | ||
+ | #define MAIN 0x01 | ||
+ | #define MENU 0x02 | ||
+ | #define ONOFF 0x04 | ||
+ | #define VOLUME 0x05 | ||
+ | |||
+ | // Konstruktory | ||
+ | Serial pc(USBTX, USBRX); // tx, rx | ||
+ | Si4703_Breakout radio(I2C_SDA, I2C_SCL, PTA1, &pc); | ||
+ | |||
+ | // Nastaveni I/O | ||
+ | DigitalIn btn_left(PTA5); | ||
+ | DigitalIn btn_center(PTC8); | ||
+ | DigitalIn btn_right(PTC9); | ||
+ | |||
+ | // Definice funkci | ||
+ | int button_pressed(void); | ||
+ | void show_frequency(void); | ||
+ | void show_screen(int screen, int position); | ||
+ | |||
// Prostor pro ulozeni nastaveni | // Prostor pro ulozeni nastaveni | ||
typedef struct{ | typedef struct{ | ||
Řádek 37: | Řádek 82: | ||
Frequency_Info frequency; | Frequency_Info frequency; | ||
+ | |||
+ | // Nezbytne promenne | ||
+ | char rds[8]; // Zde se uklada vysledek cteni RDS | ||
+ | char volume_char[2]; // Aktualni hlasitost prevedena na text | ||
+ | char channel_char[4]; // Aktualni frekvence prevedena na text | ||
+ | int btn_pressed = false; // Bylo v minulosti zmacknuto tlacitko? | ||
+ | bool exit_menu = false; // Navrat z menu | ||
+ | bool exit_submenu = false; // Navrat z menu druhe urovne | ||
+ | int menu_position = 0; // Ulozeni aktualni pozice sipky v menu | ||
+ | int submenu_position = 0; // Ulozeni aktualni pozice sipky v submenu | ||
</code> | </code> | ||
---- | ---- | ||
- | **** | + | **Hlavní funkce programu** |
- | <code> | + | <code cpp> |
+ | // HLAVNI FUNKCE | ||
+ | int main() { | ||
+ | init(); // Inicializace displeje SSD1306 | ||
+ | cls(); // Smazani obrazovky | ||
+ | startMillis(); // Zapnuti pocitani milisekund | ||
+ | radio.powerOn(); // Zapnuti radia | ||
+ | setup.volume = 2; | ||
+ | radio.setVolume(setup.volume); // Nastaveni vychozi hlasitosti | ||
+ | frequency.current = 760; // Naladeni vychozi frekvence | ||
+ | radio.setChannel(frequency.current); | ||
+ | |||
+ | show_screen(MAIN, 0); // Zobrazeni hlavni obrazovky | ||
+ | show_frequency(); // Zobrazeni aktualni frekvence | ||
+ | |||
+ | |||
+ | // HLAVNI SMYCKA | ||
+ | while(true){ | ||
+ | if(setup.rds){ // Cti RDS pokud je tato funkce zapnuta | ||
+ | radio.readRDS(rds, 1500); // Cteni RDS s timeoutem 1.5 sekundy | ||
+ | OLED_ShowStr(50, 5, rds, 1);// Zobrazeni vysledku RDS, pokud byla prijata | ||
+ | } | ||
+ | |||
+ | switch(button_pressed()){ // Ceka, dokud nebude zmacknuto tlacitko | ||
+ | case LEFT: // Zmacknuto leve tlacitko | ||
+ | if(setup.tuning) // Je zapnuto manualni ladeni? | ||
+ | radio.setChannel(--frequency.current); // Manualni ladeni | ||
+ | else | ||
+ | frequency.current = radio.seekDown(); // Automaticke ladeni | ||
+ | if(frequency.current < 760){ // Pokud dosahneme pod minimalni frekvenci, | ||
+ | frequency.current = 1080; // bude naladena nejvyssi | ||
+ | radio.setChannel(frequency.current); | ||
+ | } | ||
+ | show_frequency(); | ||
+ | break; | ||
+ | |||
+ | case RIGHT: // Zmacknuto prave tlacitko | ||
+ | if(setup.tuning) // Je zapnuto manualni ladeni? | ||
+ | radio.setChannel(++frequency.current); // Manualni ladeni | ||
+ | else | ||
+ | frequency.current = radio.seekUp(); // Automaticke ladeni | ||
+ | if(frequency.current < 760) // Ochrana proti naladeni neplatne frekvence | ||
+ | frequency.current = radio.seekUp(); | ||
+ | show_frequency(); | ||
+ | break; | ||
+ | |||
+ | |||
+ | |||
+ | case CENTER: // Vstup do MENU | ||
+ | while(!exit_menu){ | ||
+ | |||
+ | show_screen(MENU, menu_position+2); // Ukaze sipku v menu | ||
+ | |||
+ | switch(button_pressed()){ // Ceka dokud nebude zmacknuto tlacitko | ||
+ | |||
+ | case LEFT: // Zmacknuto leve tlacitko, | ||
+ | if(menu_position == 0) // provede se posunuti sipky | ||
+ | menu_position = 3; | ||
+ | else | ||
+ | menu_position--; | ||
+ | break; | ||
+ | |||
+ | case RIGHT: // Zmacknuto leve tlacitko, | ||
+ | if(menu_position == 3) // provede se posunuti sipky | ||
+ | menu_position = 0; | ||
+ | else | ||
+ | menu_position++; | ||
+ | break; | ||
+ | |||
+ | case CENTER: // Vstup do dalsi urovne MENU | ||
+ | exit_submenu = false; | ||
+ | switch(menu_position){ | ||
+ | case 0: // SUBMENU Nastaveni Hlasitosti | ||
+ | exit_submenu = false; | ||
+ | while(!exit_submenu){ | ||
+ | radio.setVolume(setup.volume); | ||
+ | show_screen(VOLUME, 0); | ||
+ | switch(button_pressed()){ // Pridat volume | ||
+ | case LEFT: | ||
+ | if(setup.volume == 0); | ||
+ | else | ||
+ | setup.volume--; | ||
+ | break; | ||
+ | case RIGHT: // Ubrat volume | ||
+ | if(setup.volume == 15); | ||
+ | else | ||
+ | setup.volume++; | ||
+ | break; | ||
+ | case CENTER: // Navrat do hlavniho menu | ||
+ | exit_submenu = true; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | break; | ||
+ | case 1: // SUBMENU Manualni ladeni | ||
+ | exit_submenu = false; | ||
+ | while(!exit_submenu){ | ||
+ | cls(); | ||
+ | show_screen(ONOFF, setup.tuning+3); | ||
+ | if(button_pressed() == CENTER) | ||
+ | exit_submenu = true; | ||
+ | else | ||
+ | setup.tuning = !setup.tuning; // Zapnuti nebo vypnuti | ||
+ | } // manualniho ladeni | ||
+ | break; | ||
+ | case 2: // SUBMENU Nastaveni RDS | ||
+ | exit_submenu = false; | ||
+ | while(!exit_submenu){ | ||
+ | cls(); | ||
+ | show_screen(ONOFF, setup.rds+3); | ||
+ | if(button_pressed() == CENTER) | ||
+ | exit_submenu = true; | ||
+ | else | ||
+ | setup.rds = !setup.rds; // Zapnuti nebo vypnuti RDS | ||
+ | } | ||
+ | break; | ||
+ | case 3: // Navrat z menu | ||
+ | show_screen(MAIN, 0); | ||
+ | show_frequency(); | ||
+ | exit_menu = true; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | break; | ||
+ | } | ||
+ | exit_menu = false; | ||
+ | menu_position = 0; | ||
+ | |||
+ | OLED_ShowStr(0, 5, "Staince: ", 1); // Smazani informaci z RDS, pokud dojde k preladeni | ||
+ | } | ||
+ | } | ||
</code> | </code> | ||
---- | ---- | ||
- | **** | + | **Funkce pro zobrazováni na displeji** |
- | <code> | + | <code cpp> |
+ | // FUNKCE | ||
+ | |||
+ | // Funkce pro zjisteni, ktere tlacitko bylo stisknuto | ||
+ | int button_pressed(void){ | ||
+ | btn_pressed = false; | ||
+ | while(!btn_pressed){ | ||
+ | |||
+ | if (btn_left) | ||
+ | btn_pressed = LEFT; // Indikace zmacknuteho leveho tlacitka | ||
+ | |||
+ | if (btn_center) | ||
+ | btn_pressed = CENTER; // Indikace zmacknuteho prostredniho tlacitka | ||
+ | |||
+ | if (btn_right) | ||
+ | btn_pressed = RIGHT; // Indikace zmacknuteho praveho tlacitka | ||
+ | } | ||
+ | while(btn_left || btn_center || btn_right); // Dokud je tlacitko zmacknute, ceka | ||
+ | wait_ms(200); // Jednoduche odstraneni zakmitu | ||
+ | return btn_pressed; | ||
+ | } | ||
+ | |||
+ | // Funkce pro zobrazeni aktualni frekvence | ||
+ | void show_frequency(void){ | ||
+ | frequency.high = frequency.current / 10; | ||
+ | frequency.low = frequency.current % 10; | ||
+ | OLED_ShowStr(38, 2, " ", 2); | ||
+ | sprintf(channel_char, "%d.%d",frequency.high, frequency.low); | ||
+ | OLED_ShowStr(38, 2, channel_char, 2); | ||
+ | } | ||
+ | |||
+ | //Funkce pro zobrazeni displeje (menu, hlavni obrazovka...) | ||
+ | void show_screen(int screen, int position){ | ||
+ | switch(screen){ | ||
+ | |||
+ | case MAIN: // Zobrazeni hlavni obrazovky | ||
+ | cls(); | ||
+ | locate(0, 0); | ||
+ | OLED_ShowStr(0, 0, " FM Radio", 2); | ||
+ | OLED_ShowStr(0, 2, "< MHz >", 2); | ||
+ | OLED_ShowStr(0, 5, "Staince:", 1); | ||
+ | OLED_ShowStr(0, 7, " [MENU] ", 1); | ||
+ | show_frequency(); | ||
+ | break; | ||
+ | |||
+ | case MENU: // Zobrazeni menu | ||
+ | cls(); | ||
+ | OLED_ShowStr(0, 0, " MENU", 2); | ||
+ | OLED_ShowStr(0, 2, " Hlasitost", 1); | ||
+ | OLED_ShowStr(0, 3, " Manualni ladeni", 1); | ||
+ | OLED_ShowStr(0, 4, " RDS", 1); | ||
+ | OLED_ShowStr(0, 5, " Zpet", 1); | ||
+ | OLED_ShowStr(0, 7, " [VYBRAT] ", 1); | ||
+ | OLED_ShowStr(0, position, "->", 1); // Zobrazeni sipky na spravne pozici | ||
+ | break; | ||
+ | |||
+ | case ONOFF: // Zobrazeni submenu volby On/Off | ||
+ | cls(); | ||
+ | OLED_ShowStr(0, 3, " Off", 1); | ||
+ | OLED_ShowStr(0, 4, " On", 1); | ||
+ | OLED_ShowStr(0, position, "->", 1); // Zobrazeni sipky na spravne pozici | ||
+ | OLED_ShowStr(0, 7, " [OK] ", 1); | ||
+ | |||
+ | break; | ||
+ | |||
+ | case VOLUME: // Volba hlasitosti | ||
+ | cls(); | ||
+ | sprintf(volume_char, "%d",setup.volume); // Zobrazeni aktualni hlasitosti | ||
+ | OLED_ShowStr(60, 3, volume_char, 2); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
</code> | </code> | ||
+ | |||
+ | ---- | ||
+ | **Zapojení** | ||
+ | |||
+ | {{ :2015:si4703-radio:dsc4343.jpg?direct500 |}} | ||
---- | ---- | ||
Řádek 56: | Řádek 321: | ||
Výsledkem projektu je vytvoření aplikace, které spojuje modul rádia, displeje a tři tlačítka v použitelný radiopřijímač. Kromě automatického ladění je možné frekvenci zadat i ručně, je zde i možnost ovládání hlasitosti. Pomocí dat z RDS se podařilo zobrazit jen název u jedné stanice, a to u EVROPY 2. Lepšího výsledku by šlo dosáhnout pouze s vlastní knihovnou pro ovládání FM modulu. Programování mi zpříjemňoval poslech částečně naprogramovaného rádia. | Výsledkem projektu je vytvoření aplikace, které spojuje modul rádia, displeje a tři tlačítka v použitelný radiopřijímač. Kromě automatického ladění je možné frekvenci zadat i ručně, je zde i možnost ovládání hlasitosti. Pomocí dat z RDS se podařilo zobrazit jen název u jedné stanice, a to u EVROPY 2. Lepšího výsledku by šlo dosáhnout pouze s vlastní knihovnou pro ovládání FM modulu. Programování mi zpříjemňoval poslech částečně naprogramovaného rádia. | ||
- | Kromě tohoto modulu FM přijímače mě zaujal i modul pro vysílání FM signálu, například [[https://learn.adafruit.com/adafruit-si4713-fm-radio-transmitter-with-rds-rdbs-support/overview|Si4713]]. Existují i integrované obvody, které slučují obě funkce (příjem i vysílání). Daly by se použít k bezdrátovému přenosu zvuku například z mp3 přehrávače nebo PC. | + | Kromě tohoto modulu FM přijímače mě zaujal i modul pro vysílání FM, například [[https://learn.adafruit.com/adafruit-si4713-fm-radio-transmitter-with-rds-rdbs-support/overview|Si4713]]. Existují i integrované obvody, které slučují obě funkce (příjem i vysílání). Daly by se použít k bezdrátovému přenosu zvuku například z mp3 přehrávače nebo PC. Nebo k bezdrátovému přenosu dat, protože mají implementovanou funkci RDS. Dále modul [[http://www.silabs.com/products/audio/fm-am-receiver/Pages/si4707.aspx|Si4707]] pro příjem zpráv o počasí. |
- | Celý zdrojový kód je uveřejněný na stránkách mbed [[https://developer.mbed.org/users/vodavprasku/code/projekt_Si4703/| Projekt MPOA Si4703 ]]. | + | Celý zdrojový kód je uveřejněný na stránkách mbed.org: [[https://developer.mbed.org/users/vodavprasku/code/projekt_Si4703/| Projekt MPOA Si4703 ]]. |