RFM12B
Gdzieś na elektrodzie znalazłem opis modułów radiowych RFM01 i RFM02, zaciekawiony tym znaleziskiem, zacząłem szukać informacji o tych modułach i tak natrafiłem na układy RFM12B.
Po dłuższych poszukiwaniach, znalazłem opis ich uruchomienia i przykładowe programy. Postanowiłem zakupić sobie takowe dwa do badań :).
Moduły przyszły po tygodniu, ale na swoją kolej czekały aż znajdę czas po obronie. Jak już się obroniłem postanowiłem wrócić do tematu, lecz tu troszkę sie pośpieszyłem z kupnem modułów, gdyż zamówiłem RFM12B czyli wersje zasilaną 3.3V, choć czytałem, że co poniektórzy podłączali je do 5V. Nie zbyt chciało mi się eksperymentować i sprawdzać czy one wytrzymają takie napięcie, zrobiłem małą płytkę ze stabilizatorem 3.3V smd i kilkoma opornikami.
Środowisko testowe
Po uruchomieniu przejściówek i wlutowaniu RFM-ków, przystąpiłem do części programowej, tu się zaczęły schody. Utknąłem na co najmniej 2 tygodnie z tymi układami.
Jeden z nich miał pobór 1,8mA a drugi 0,8mA. Układy reagowały na wydawane komendy aby sprawdzić to wysyłałem komendę włączającą i wyłączająca zewnętrzną nóżkę oscylatora, ale tylko jeden z układów dawał oznaki i podawał sygnał na nóżkę, na drugim mój miernik pokazywał częstotliwość od 150-170KHz czasem 96KHz.
Po wydaniu komendy włączenia nadajnika i wysłaniu kilku bajtów pobór prądu przez układ był około 20mA, co świadczyło, że układy działają, ale za żadne skarby nie chciały sie komunikować.
Zacząłem więc modyfikować kod, i doszedłem do wniosku, że problemem jest linia nIRQ, która nie do końca sygnalizowała gotowość do nadawania/odbierania, gdzieś wyczytałem, że opróżnienie bufora FIFO sygnalizuje końcówka FFIT. Po podłączeniu wejścia procesora do FFIT układ zaczął wysyłać, ale było to złudzenie, musiałem przyjąć, że część elektroniczna jest dobra, gdyż inaczej moje próby z kodem nie miały by sensu.
Po około tygodniu zmian w kodzie, rfm-ki zaczęły się widzieć, przesyłały głupoty, ale już było widać światełko w tunelu.
Układy się “widziały”, ale miały problem z synchronizacją, zwiększyłem wiec ilość wysyłanych bajtów synchronizacji na 3
1 |
<!--wp_fromhtmlpreview_devfmt--> |
C |copy code |?
1 RF12Send(0xaa);2 RF12Send(0xaa);3 RF12Send(0xaa);4 RF12Send(0x2D);5 RF12Send(0xD4);
co poskutkowało tym, że pakiet zaczynał się bez błędów, ale kończyły błędami. Prędkość transmisji ustawiona była na 4700 na początku w bloku konfiguracji:
1 |
<!--wp_fromhtmlpreview_devfmt--> |
C |copy code |?
01 RF12Cmd(0x80d8); // EL, EF, 433band, 12.5pF02 RF12Cmd(0x8208); // EX, DC03 RF12Cmd(0xa640); // 434MHz04 RF12Cmd(0xc611); // 19.2kbps05 RF12Cmd(0x94a0); // VDI, FAST, 137kHz, 0dBm, −103dBm06 RF12Cmd(0xc2ac); // AL, S, DQD407 RF12Cmd(0xca81); // lress08 RF12Cmd(0xced4); // Synchro D409 RF12Cmd(0xc483); // A1, FI, OE, EN10 RF12Cmd(0x9850); // 90kHz, 21db11 RF12Cmd(0xCC17); // Fast, 256kbps, dither12 RF12Cmd(0xe000);13 RF12Cmd(0xc800);14 RF12Cmd(0xc040);
odległość między modułami wynosiła zaledwie pół metra, trochę mnie to podłamało, ale postanowiłem nadal mieszać kodem. Na końcu ramki (HOPE tak miał w swoich materiałach) był jeden bajt synchronizacji, zwiększyłem do 3-ch, układy zaczęły przesyłać 10 bajtowe ramki bez błędów.
Rozochocony postanowiłem rzucić układy na głęboką wodę , jeden układ został w pokoju podłączona do laptopa wysyłając 100 bajtowy bufor a na końcu sumę kontrolną pakietu w sumie 102 bajty, z drugim laptopem i podłączonym modułem w ręku schodziłem z 4 piętra sprawdzając zasięg. Prawdę powiedziawszy spodziewałem się, że nie dojdę do drzwi wyjściowych z mieszkania a zasięg się straci. Zszedłem z 4 piętra aż do warsztatu w piwnicy a układ nadal odbierał sygnał i wyświetlał ramki jakie odebrał, po uprzednim sprawdzeniu sumy kontrolnej.
Co pokazało, że mimo 5mW mocy układy są wstanie przebić się przez 5 kondygnacji. Po tym sukcesie zacząłem zwiększać stopniowo prędkość transmisji aż doszedłem do 19200 bitów/s przy 95% poprawnie odebranych pakietach.
Poniżej schemat przejściówki i rysunek płytki dla układów RFM12B, oraz kody źródłowe na których udało mi się dokonać transmisji.
Nadajnik:
1 |
<!--wp_fromhtmlpreview_devfmt--> |
C |copy code |?
001 #include <avr /io.h>
002 #include <util /delay.h>
003 #include "uart.h"
004 005 // ustawienia SPI dla ATmega32
006 #define SPI_PORT PORTB
007 #define SPI_DDR DDRB
008 #define SPI_SS 4 // (uC)SS − (RF12)nSEL
009 #define SPI_MOSI 5 // (uC)MOsi − (RF12)SDI
010 #define SPI_MISO 6 // (uC)MISO − (RF12)SDO
011 #define SPI_SCK 7 // (uC)SCK − (RF12)SCK
012 013 #define RF_IRQ_PORT PORTD
014 #define RF_IRQ_DDR DDRD
015 #define RF_IRQ_PIN PIND
016 #define RF_IRQ_BIT 2 // (uC)PD.2 − (RF12)nIRQ
017 018 #define PACK_SIZE 100 // długość pakietów testowych
019 020 uint16_t RF12Cmd(uint16_t Cmd)021 {
022 uint16_t Data;023 024 SPI_PORT &= ~_BV(SPI_SS); //pb4025 SPDR = Cmd >> 8;026 while (!(SPSR & (1 < < SPIF)));027 Data = SPDR << 8;028 SPDR = Cmd & 0xff;029 030 while (!(SPSR & (1 << SPIF)));031 Data |= SPDR;032 033 SPI_PORT |= _BV(SPI_SS);034 return Data;035 }
036 037 void RF12Send(uint8_t Data)038 {
039 while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));040 RF12Cmd(0xb800 | Data);041 }
042 043 uint8_t RF12Recv(void)044 {
045 while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));046 return RF12Cmd(0xb000);047 }
048 049 void RF12PacketSend(uint8_t Data[], uint8_t Len)050 {
051 uint16_t crc = 0;052 uint8_t i, byte;053 054 RF12Cmd(0x8228);055 RF12Cmd(0x8238);056 //Po osunięciu tego odczytu statusu RFM przestaje wysyłać
057 RF12Cmd(0x0000);058 059 RF12Send(0xaa);060 RF12Send(0xaa);061 RF12Send(0xaa);062 063 RF12Send(0x2D);064 RF12Send(0xD4);065 066 for (i = 0; i < Len; i++)067 {
068 byte = Data[i];069 RF12Send(byte);070 crc += (i % 16) * byte;071 }
072 073 RF12Send(crc >> 8);074 RF12Send(crc & 0xff);075 076 RF12Send(0xaa);077 RF12Send(0xaa);078 RF12Send(0xaa);079 080 RF12Cmd(0x8200);081 }
082 083 uint8_t RF12PacketRecv(uint8_t Data[])084 {
085 uint16_t crc = 0, pcrc;086 uint8_t i = 0;//, byte;087 088 RF12Cmd(0x0000);089 RF12Cmd(0x8288);090 RF12Cmd(0x82c8);091 092 for (i=0; i < PACK_SIZE; i++)093 {
094 Data[i] = RF12Recv();095 crc += (i % 16) * Data[i];096 }
097 098 pcrc = RF12Recv() << 8;099 pcrc |= RF12Recv();100 101 RF12Cmd(0xca81); //102 RF12Cmd(0xca83); // FIFO8, DR103 104 if (pcrc == crc)105 {
106 return TRUE;107 }
108 else
109 {
110 return FALSE;111 }
112 return 0;113 }
114 115 void RF12Init(void)116 {
117 /*
118 *inicjalizacja pinow SPI
119 */
120 SPI_PORT |= _BV(SPI_SCK) | _BV(SPI_SS); //pb7121 SPI_DDR |= _BV(SPI_SCK) | _BV(SPI_MOSI) | _BV(SPI_SS); //pb7 pb5 pb4 out122 SPI_DDR &=~_BV(SPI_MISO); //pb6 in123 124 SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1);125 126 /*
127 * inicjalizacja portów do obsługi RF
128 */
129 RF_IRQ_PORT |= _BV(RF_IRQ_BIT);130 RF_IRQ_DDR &= ~_BV(RF_IRQ_BIT);131 132 _delay_ms(400);133 134 RF12Cmd(0x80d8); // EL, EF, 433band, 12.5pF135 RF12Cmd(0x8208); // EX, DC \\ NONE136 RF12Cmd(0xa640); // 434MHz137 RF12Cmd(0xc611); // 19.2kbps138 RF12Cmd(0x94a0); // VDI, FAST, 137kHz, 0dBm, −103dBm139 RF12Cmd(0xc2ac); // AL, S, DQD4140 RF12Cmd(0xca81); //141 RF12Cmd(0xced4); // Synchro D4142 RF12Cmd(0xc483); // A1, FI, OE, EN143 RF12Cmd(0x9850); // 90kHz, 21db144 RF12Cmd(0xCC17); //145 RF12Cmd(0xe000); //146 RF12Cmd(0xc800); //147 RF12Cmd(0xc040); //148 }
149 150 int main(void)151 {
152 UART_init();153 uint8_t BufWr[PACK_SIZE], i;154 155 for (i = 0; i < PACK_SIZE; i++)156 {
157 BufWr[i] = i + 1;158 }
159 160 UART_putstr_P(PSTR("Start\r\n"));161 162 RF12Init();163 164 i=0;165 166 UART_putstr_P(PSTR("\r\n"));167 168 for ( ; ; )169 {
170 _delay_ms(100);171 UART_putstr_P(PSTR("Wysyłam\r\n"));172 RF12PacketSend(BufWr,PACK_SIZE);173 _delay_ms(2000);174 }
175 }
Odbiornik:
1 |
<!--wp_fromhtmlpreview_devfmt--> |
C |copy code |?
001 #include <avr /io.h>
002 #include <util /delay.h>
003 #include "uart.h"
004 005 // ustawienia SPI dla ATmega32
006 #define SPI_PORT PORTB
007 #define SPI_DDR DDRB
008 #define SPI_SS 4 // (uC)SS − (RF12)nSEL
009 #define SPI_MOSI 5 // (uC)MOsi − (RF12)SDI
010 #define SPI_MISO 6 // (uC)MISO − (RF12)SDO
011 #define SPI_SCK 7 // (uC)SCK − (RF12)SCK
012 013 #define RF_IRQ_PORT PORTD
014 #define RF_IRQ_DDR DDRD
015 #define RF_IRQ_PIN PIND
016 #define RF_IRQ_BIT 2 // (uC)PD.2 − (RF12)nIRQ
017 018 #define PACK_SIZE 100 // długość pakietów testowych
019 020 uint16_t RF12Cmd(uint16_t Cmd)021 {
022 uint16_t Data;023 024 SPI_PORT &= ~_BV(SPI_SS); //pb4025 SPDR = Cmd >> 8;026 while (!(SPSR & (1 < < SPIF)));027 Data = SPDR << 8;028 SPDR = Cmd & 0xff;029 030 while (!(SPSR & (1 << SPIF)));031 Data |= SPDR;032 033 SPI_PORT |= _BV(SPI_SS);034 return Data;035 }
036 037 void RF12Send(uint8_t Data)038 {
039 while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));040 RF12Cmd(0xb800 | Data);041 }
042 043 uint8_t RF12Recv(void)044 {
045 while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));046 return RF12Cmd(0xb000);047 }
048 049 void RF12PacketSend(uint8_t Data[], uint8_t Len)050 {
051 uint16_t crc = 0;052 uint8_t i, byte;053 054 RF12Cmd(0x8228);055 RF12Cmd(0x8238);056 //Po usunieciu tego odczytu statusu RFM przestaje wysylac
057 RF12Cmd(0x0000);058 059 RF12Send(0xaa);060 RF12Send(0xaa);061 RF12Send(0xaa);062 063 RF12Send(0x2D);064 RF12Send(0xD4);065 066 for (i = 0; i < Len; i++)067 {
068 byte = Data[i];069 RF12Send(byte);070 crc += (i % 16) * byte;071 }
072 073 RF12Send(crc >> 8);074 RF12Send(crc & 0xff);075 076 RF12Send(0xaa);077 RF12Send(0xaa);078 RF12Send(0xaa);079 080 RF12Cmd(0x8200);081 }
082 083 uint8_t RF12PacketRecv(uint8_t Data[])084 {
085 uint16_t crc = 0, pcrc;086 uint8_t i = 0;//, byte;087 088 RF12Cmd(0x0000);089 RF12Cmd(0x8288);090 RF12Cmd(0x82c8);091 092 for (i=0; i < PACK_SIZE; i++)093 {
094 Data[i] = RF12Recv();095 crc += (i % 16) * Data[i];096 }
097 098 pcrc = RF12Recv() << 8;099 pcrc |= RF12Recv();100 101 RF12Cmd(0xca81); //102 RF12Cmd(0xca83); // FIFO8, DR103 104 if (pcrc == crc)105 {
106 return TRUE;107 }
108 else
109 {
110 return FALSE;111 }
112 }
113 114 void RF12Init(void)115 {
116 /*
117 *inicjalizacja pinow SPI
118 */
119 SPI_PORT |= _BV(SPI_SCK) | _BV(SPI_SS); //pb7120 SPI_DDR |= _BV(SPI_SCK) | _BV(SPI_MOSI) | _BV(SPI_SS); //pb7 pb5 pb4 out121 SPI_DDR &=~_BV(SPI_MISO); //pb6 in122 123 SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1) ;124 125 /*
126 * inicjalizacja portów do obsługi RF
127 */
128 RF_IRQ_PORT |= _BV(RF_IRQ_BIT);129 RF_IRQ_DDR &= ~_BV(RF_IRQ_BIT);130 131 _delay_ms(400);132 133 RF12Cmd(0x80d8); // EL, EF, 433band, 12.5pF134 RF12Cmd(0x8208); // EX, DC135 RF12Cmd(0xa640); // 434MHz136 RF12Cmd(0xc611); // 19.2kbps137 RF12Cmd(0x94A0); // VDI, FAST, 137kHz, 0dBm, −103dBm138 RF12Cmd(0xc2ac); // AL, S, DQD4139 RF12Cmd(0xca82); //140 RF12Cmd(0xced4); // Synchro D4141 RF12Cmd(0xc483); // A1, FI, OE, EN142 RF12Cmd(0x9850); // 90kHz, 21db143 RF12Cmd(0xCC17); //144 RF12Cmd(0xe000); //145 RF12Cmd(0xc800); //146 RF12Cmd(0xc040); //147 }
148 149 int main(void)150 {
151 uint8_t BufWr[PACK_SIZE], i ;152 153 UART_init();154 155 for (i = 0; i < PACK_SIZE; i++)156 {
157 BufWr[i] = 0;158 }
159 160 UART_putstr_P(PSTR("Start\r\n"));161 _delay_ms(1500);162 163 RF12Init();164 165 i=0;166 167 UART_putstr_P(PSTR("\r\n"));168 169 for ( ; ; )170 {
171 if( RF12PacketRecv(BufWr) == TRUE )172 {
173 for (i = 0; i < PACK_SIZE; i++)174 {
175 UART_puthexU08( BufWr[i] );176 BufWr[i] = 0;177 }
178 UART_putstr_P(PSTR("\r\n"));179 }
180 else
181 {
182 UART_putstr_P(PSTR("Blad pakietu\r\n"));183 }
184 }
185 }
PDF z wydrukiem płytki do termotransferu
Polecam również literature: