Komunikace modulů RFM12B/868D

Martin Králíček, Pavel Kopeček
xkrali02stud.feec.vutbr.cz, xkopec01stud.feec.vutbr.cz 

Obsah:

  1. Úvod
  2. Realizace
  3. Závěr
  4. Soubory
  5. Literatura

Úvod

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ů.

Pouzdro

Obr.1: Modul RFM12B/868D [1].

Realizace

Důležité prametry modulu jsou uvedeny v následující tabulce:

Parametry RFM12B/868D
Napájecí napětí2,2 - 3,8V
Komunikační frekvence868MHz
Citlivost-102dBm
Maximální výkon7dBm

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.

Schéma

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ů:

BytePopis
1Adresa přijímače
2Adresa výsílače
3Byt s nastavením
4Rezervovaný byte
5-16Datové byty
17CRC

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.

Závěr

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.

Soubory

Kód hlavního programu (main.c)
Kód transceiveru (transceiver.c)
Kompletní kód pro přípravek

Literatura

[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