Martin Králíček, Pavel Kopeček
xkrali02stud.feec.vutbr.cz,
xkopec01
stud.feec.vutbr.cz
V tomto projektu se budeme zabývat komunikací mezi dvěma moduly RFM12B/868D. Pomocí těchto modulů budou komunikovat mikrokontroléry ATMega16 a to v obousměrné komunikaci. Tyto moduly komunikují v pásmu ISM, lze s nimi na volném prostranství dosáhnout spojení až do vzdálenosti cca 200m a jejich využití je všestrané od dálkového řízení po sběr dat ze senzorů.
Obr.1: Modul RFM12B/868D [1].
Důležité prametry modulu jsou uvedeny v následující tabulce:
Napájecí napětí | 2,2 - 3,8V |
---|---|
Komunikační frekvence | 868MHz |
Citlivost | -102dBm |
Maximální výkon | 7dBm |
Modul komunikuje s mikrokontrolérem pomocí SPI. Je použita softwareová verze SPI pro jeho větší kompatibilitu. Samotné moduly mezi sebou komunikují v pásmu ISM a to na jedné frekvenci, tím vzniká problém při použití více než dvou zařízení. Teoreticky je možné nastavovat vysílací kanály, nisméně tato varianta je komplikovaná. Jednodušší je při vysílání odeslat s daty také adresu koncového modulu a tu porovnávat při příjmů. Pro komunikaci s ATMega16 vzniká problém s použitím 5V napájení procesoru. Je nutné vložit mezi modul a procesor redukci na převod 5V -> 3,3V a zpět. Redukce dále zabezpečuje převod z metrické rozteče lišty na palcovou (2mm -> 2,54mm). Modul i s rozměry je zobrazen na obr. 1. Schéma zapojení redukce pak na obr. 2.
Obr.2: Schéma regukce
Redukce se na vývojové desce zapojuje na port B. A to jak je vyznačeno ve schématu - lišta JP1, nejdříve 5V napájení, následuje nezapojený pin, pak dva zemnící piny a poté již PB0-PB7. Jednotlivé vstupy/výstupy lze nastavit v header souboru transceiver.h.
Vyslaný paket má následující pořadí bytů:
Byte | Popis |
---|---|
1 | Adresa přijímače |
2 | Adresa výsílače |
3 | Byt s nastavením |
4 | Rezervovaný byte |
5-16 | Datové byty |
17 | CRC |
Daná struktura paketu není určena žádnou normou, nicméně její použití se osvědčilo. A to jak při rozlišení, zda je zpráva opravdu určena danému modulu, tak i pro detekci chyb v přenosu radiovou částí spoje. Po přijetí prvního bytu zprávy se rozhoduje, zda je zpráva určena danému přijímači. Při shodě se přijme celá zpráva, spočte se CRC a porovná se s přijatým. Pokud CRC odpovídá tak je zpráva přijata za platnou.
Strukturu hlavního programu main.c lze popsat následujícím způsobem. Po spuštění mikrokontroleru se před samotným zacyklením v nekonečné smyčce provede několik inicializačních procedur. Nejdříve se nastaví a povolí přerušení INT1, které se využívá pro vyslání zkušebního paketu. Následuje inicializace lcd a transceiveru a vyslání paketu náhodných dat, bez kterého transceiver nepracuje správně. Poté už pouze nastavíme RX a TX adresu a povolíme přerušení. Po těchto krocích se program zacyklí v nekonečné smyčce, kde se už pouze kontroluje zda se nepřijala nějaká platná data. Jejich přijetí je indikováno nastavením Receiv_int do "1". Po přijetí jsou data zobrazena na lcd, vynulován Receiv_int a povoleno přerušení pro příjem dalších dat. Hlavní program dále obsahuje vektor přerušení INT1, na tento vstup je připojeno tlačítko TL1. Po jeho stisknutí se aktivuje kontrolní led dioda, nastaví se do Paket_out.Data_buf, což je buffer výstupních dat, řetězec "Hello!!!:)" a pomocí funkce Send_paket se paket vyšle. Po jeho odeslání je led dioda opět zhasnuta.
#include <avr/io.h> // Hlavickovy soubor popisujici microcontroler #include <avr/interrupt.h> // Soubor popisujici preruseni microcontroleru #include <stdio.h> #include <util/delay.h> #include "Transceiver.h" #include "lcd_h.h" #define F_CPU 16000000UL int main (void){ extern volatile N_ROTE_paket Paket_in; extern unsigned char ID_RX, my_ID; extern volatile unsigned char Receiv_int; MCUCR |= (1<<ISC11); //nastaveni preruseni INT1 na tlacitko GICR |= (1<<INT1); Receiv_int = 0; //nastaveni neprijatych dat lcd_init(); //inicializace lcd lcd_clrscr(); //smazani lcd Init_Transceiver(); //inicializace transceiveru Send_paket(); //odeslani zkusebniho prazdneho paketu ID_RX = 0xB0; //nastaveni adresy prijimace my_ID = 0xA0; //nastaveni vlastni adresy sei(); //povoleni preruseni while(1) { if(Receiv_int == 1) //podminka prijatych dat { lcd_clrscr(); //smazani lcd lcd_gotoxy(0,0); //nastaveni kurzoru do nuly lcd_putc(Paket_in.Data_buf[1]); //vypsani datoveho paketu lcd_putc(Paket_in.Data_buf[2]); lcd_putc(Paket_in.Data_buf[3]); lcd_putc(Paket_in.Data_buf[4]); lcd_putc(Paket_in.Data_buf[5]); lcd_putc(Paket_in.Data_buf[6]); lcd_putc(Paket_in.Data_buf[7]); lcd_putc(Paket_in.Data_buf[8]); lcd_putc(Paket_in.Data_buf[9]); lcd_putc(Paket_in.Data_buf[10]); Receiv_int = 0; //nastaveni prazdnych dat REC_on; //povoleni preruceni } } } ISR(INT1_vect) { extern volatile N_ROTE_paket Paket_out, Paket_in; LED_1; //aktivace led delay(65000); delay(65000); sprintf(Paket_out.Data_buf,"Hello!!!:)"); //zapis dat do vysilaciho bufferu Send_paket(); //odeslani paketu delay(65000); delay(65000); LED_0; //deaktivace led }
Všechny funkce pro komunikaci s transceiverem jsou umístěny v transceiver.c. Vysílání paketu probíhá pomocí funkce Send_paket. Po spuštění funkce se provede vypnutí přerušení, aby funkce proběhla naráz a reset FIFO registru a CRC. Posledním krokem před vysláním samotných dat je přepojit modul do módu vysílání (transmit_mode). Následuje přímé odeslání dat pomocí funkce Write_FSK, nejdříve synchronizačních dat a následně všech bytů paketu a to podle schématu naznačeného v tabulce výše. Funkci Write_FSK voláme s argumentem, ve kterém jsou přímo data, které se mají vyslat. Na závěr přepneme modul do módu přijímaní (receive_mode) a povolíme přerušení.
Příjem dat se uskutečňuje automaticky bez zásahu uživatele. Při přijetí je modulem vyvoláno vnější přerušení INT2. Povolení tohoto přerušení probíhá v inicializaci transceiveru. V přerušení probíhá příjem paketu a kontrola zda se jedná o platný paket. Příjem zajišťuje funkce Receiv_paket. V té se nejdříve vypne přerušení, aby nebyl průběh ničím rušen, poté se postupně byte po bytu naplní paměťový prostor pro vstupní data. Vyčítání jednotlivých bytů se provádí pomocí funkce RX_FIFO. V té se nejdříve odesílají samé "0", dokud nepřijdou data 1XXX XXXX XXXX XXXX, které signalizují přijetí platných dat. Poté se vyšle číslo paměťového místa v modulu, odkud se budou data číst (0xB000). Příchozí data se následně už pouze vymaskují na 1 byte platných dat a jsou funkcí vrácena.
Po nahrání kódu do mikrokontrolérů a spuštění se provede inicializace. Poté jsou již obě zařízení ve stavu přijímání. Po stisku tlačítka TL1 na přípravku je daným modulem vyslána zpráva obsahující řetězec ASCII znaků: "Hello!!!:)" (bez "). Druhý modul zprávu přijme, porovná adresu a CRC a následně zobrazí zprávu na LCD displeji. Je nutné pamatovat na to, že při nahrávání kódu do mikrokontroleru, je nutné pro každý modul zadat svou adresu. Celá komunikace je funkční a program je připraven na implementaci do zařízení využívající komunikaci pomocí modulů RFM12B.
Kód hlavního programu (main.c)
Kód transceiveru (transceiver.c)
Kompletní kód pro přípravek
[1] HOPE RF. Universal ISM band FSK tranciever modula RFM12b [online]. [citováno 26.5.2010]. Dostupný z WWW: www.hoperf.com/upfile/RFM12B.pdf