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

 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:

 C | 
 
 copy code |
?

  1. RF12Cmd(0x80d8);   // EL, EF, 433band, 12.5pF
  2. RF12Cmd(0x8208);   // EX, DC
  3. RF12Cmd(0xa640);   // 434MHz
  4. RF12Cmd(0xc611);   // 19.2kbps
  5. RF12Cmd(0x94a0);  // VDI, FAST, 137kHz, 0dBm, −103dBm
  6. RF12Cmd(0xc2ac);   // AL, S, DQD4
  7. RF12Cmd(0xca81);    // lress
  8. RF12Cmd(0xced4);   // Synchro D4
  9. RF12Cmd(0xc483);   // A1, FI, OE, EN
  10. RF12Cmd(0x9850);  // 90kHz, 21db
  11. RF12Cmd(0xCC17);   // Fast, 256kbps, dither
  12. 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:

 C | 
 
 copy code |
?

  1. #include <avr /io.h>
  2. #include <util /delay.h>
  3. #include "uart.h"
  4. // ustawienia SPI dla ATmega32
  5. #define SPI_PORT      PORTB
  6. #define SPI_DDR       DDRB
  7. #define SPI_SS        4      // (uC)SS   &minus;  (RF12)nSEL
  8. #define SPI_MOSI      5      // (uC)MOsi &minus;  (RF12)SDI
  9. #define SPI_MISO      6      // (uC)MISO &minus;  (RF12)SDO
  10. #define SPI_SCK       7      // (uC)SCK  &minus;  (RF12)SCK
  11. #define RF_IRQ_PORT     PORTD
  12. #define RF_IRQ_DDR      DDRD
  13. #define RF_IRQ_PIN      PIND
  14. #define RF_IRQ_BIT      2      // (uC)PD.2 &minus; (RF12)nIRQ
  15. #define PACK_SIZE      100     // dÅugoÅÄ pakietów testowych
  16. uint16_t RF12Cmd(uint16_t Cmd)
  17. {
  18.     uint16_t Data;
  19.     SPI_PORT &= ~_BV(SPI_SS);      //pb4
  20.     SPDR = Cmd >> 8;
  21.     while (!(SPSR & (1 < < SPIF)));
  22.     Data = SPDR << 8;
  23.     SPDR = Cmd & 0xff;
  24.     while (!(SPSR & (1 << SPIF)));
  25.     Data |= SPDR;
  26.     SPI_PORT |= _BV(SPI_SS);
  27.     return Data;
  28. }
  29. void RF12Send(uint8_t Data)
  30. {
  31.     while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
  32.     RF12Cmd(0xb800 | Data);
  33. }
  34. uint8_t RF12Recv(void)
  35. {
  36.     while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
  37.     return RF12Cmd(0xb000);
  38. }
  39. void RF12PacketSend(uint8_t Data[], uint8_t Len)
  40. {
  41.     uint16_t crc = 0;
  42.     uint8_t i, byte;
  43.     RF12Cmd(0x8228);
  44.     RF12Cmd(0x8238);
  45.     //Po osuniÄciu tego odczytu statusu RFM przestaje wysyÅaÄ
  46.     RF12Cmd(0x0000);
  47.     RF12Send(0xaa);
  48.     RF12Send(0xaa);
  49.     RF12Send(0xaa);
  50.     RF12Send(0x2D);
  51.     RF12Send(0xD4);
  52.     for (i = 0; i < Len; i++)
  53.     {
  54.       byte = Data[i];
  55.       RF12Send(byte);
  56.       crc += (i % 16) * byte;
  57.     }
  58.     RF12Send(crc >> 8);
  59.     RF12Send(crc & 0xff);
  60.     RF12Send(0xaa);
  61.     RF12Send(0xaa);
  62.     RF12Send(0xaa);
  63.     RF12Cmd(0x8200);
  64. }
  65. uint8_t RF12PacketRecv(uint8_t Data[])
  66. {
  67.     uint16_t crc = 0, pcrc;
  68.     uint8_t i = 0;//, byte;
  69.     RF12Cmd(0x0000);
  70.     RF12Cmd(0x8288);
  71.     RF12Cmd(0x82c8);
  72.     for (i=0; i < PACK_SIZE; i++)
  73.     {
  74.         Data[i] = RF12Recv();
  75.         crc += (i % 16) * Data[i];
  76.     }
  77.     pcrc = RF12Recv() << 8;
  78.     pcrc |= RF12Recv();
  79.     RF12Cmd(0xca81);   //
  80.     RF12Cmd(0xca83);   // FIFO8, DR
  81.     if (pcrc == crc)
  82.     {
  83.         return TRUE;
  84.     }
  85.     else
  86.     {
  87.         return FALSE;
  88.     }
  89.     return 0;
  90. }
  91. void RF12Init(void)
  92. {
  93.     /*
  94.     *inicjalizacja pinow SPI
  95.     */
  96.     SPI_PORT |= _BV(SPI_SCK) | _BV(SPI_SS);                       //pb7
  97.     SPI_DDR |= _BV(SPI_SCK) | _BV(SPI_MOSI) | _BV(SPI_SS);        //pb7 pb5 pb4 out
  98.     SPI_DDR &=~_BV(SPI_MISO);                                     //pb6 in
  99.     SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1);
  100.     /*
  101.     * inicjalizacja portów do obsÅugi RF
  102.     */  
  103.     RF_IRQ_PORT |= _BV(RF_IRQ_BIT);
  104.     RF_IRQ_DDR &= ~_BV(RF_IRQ_BIT);
  105.     _delay_ms(400);
  106.     RF12Cmd(0x80d8);   // EL, EF, 433band, 12.5pF
  107.     RF12Cmd(0x8208);   // EX, DC         \\ NONE
  108.     RF12Cmd(0xa640);   // 434MHz
  109.     RF12Cmd(0xc611);   // 19.2kbps
  110.     RF12Cmd(0x94a0);   // VDI, FAST, 137kHz, 0dBm, &minus;103dBm
  111.     RF12Cmd(0xc2ac);   // AL, S, DQD4
  112.     RF12Cmd(0xca81);   //
  113.     RF12Cmd(0xced4);   // Synchro D4
  114.     RF12Cmd(0xc483);   // A1, FI, OE, EN
  115.     RF12Cmd(0x9850);   // 90kHz, 21db
  116.     RF12Cmd(0xCC17);   //
  117.     RF12Cmd(0xe000);   //
  118.     RF12Cmd(0xc800);   //
  119.     RF12Cmd(0xc040);   //
  120. }
  121. int main(void)
  122. {
  123.     UART_init();
  124.     uint8_t BufWr[PACK_SIZE], i;
  125.     for (i = 0; i < PACK_SIZE; i++)
  126.     {
  127.         BufWr[i] = i + 1;
  128.     }
  129.     UART_putstr_P(PSTR("Start\r\n"));
  130.     RF12Init();
  131.     i=0;
  132.     UART_putstr_P(PSTR("\r\n"));
  133.     for ( ; ; )
  134.     {
  135.        _delay_ms(100);
  136.        UART_putstr_P(PSTR("WysyÅam\r\n"));
  137.        RF12PacketSend(BufWr,PACK_SIZE);
  138.        _delay_ms(2000);
  139.     }
  140. }

Odbiornik:

 C | 
 
 copy code |
?

  1. #include <avr /io.h>
  2. #include <util /delay.h>
  3. #include "uart.h"
  4. // ustawienia SPI dla ATmega32
  5. #define SPI_PORT      PORTB
  6. #define SPI_DDR       DDRB
  7. #define SPI_SS        4      // (uC)SS   &minus;  (RF12)nSEL
  8. #define SPI_MOSI      5      // (uC)MOsi &minus;  (RF12)SDI
  9. #define SPI_MISO      6      // (uC)MISO &minus;  (RF12)SDO
  10. #define SPI_SCK       7      // (uC)SCK  &minus;  (RF12)SCK
  11. #define RF_IRQ_PORT     PORTD
  12. #define RF_IRQ_DDR      DDRD
  13. #define RF_IRQ_PIN      PIND
  14. #define RF_IRQ_BIT      2      // (uC)PD.2 &minus; (RF12)nIRQ
  15. #define PACK_SIZE      100      // dÅugoÅÄ pakietów testowych
  16. uint16_t RF12Cmd(uint16_t Cmd)
  17. {
  18.     uint16_t Data;
  19.     SPI_PORT &= ~_BV(SPI_SS);    //pb4
  20.     SPDR = Cmd >> 8;
  21.     while (!(SPSR & (1 < < SPIF)));
  22.     Data = SPDR << 8;
  23.     SPDR = Cmd & 0xff;
  24.     while (!(SPSR & (1 << SPIF)));
  25.     Data |= SPDR;
  26.     SPI_PORT |= _BV(SPI_SS);
  27.     return Data;
  28. }
  29. void RF12Send(uint8_t Data)
  30. {
  31.     while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
  32.     RF12Cmd(0xb800 | Data);
  33. }
  34. uint8_t RF12Recv(void)
  35. {
  36.     while (RF_IRQ_PIN & (1 << RF_IRQ_BIT));
  37.     return RF12Cmd(0xb000);
  38. }
  39. void RF12PacketSend(uint8_t Data[], uint8_t Len)
  40. {
  41.     uint16_t crc = 0;
  42.     uint8_t i, byte;
  43.     RF12Cmd(0x8228);
  44.     RF12Cmd(0x8238);
  45.     //Po usunieciu tego odczytu statusu RFM przestaje wysylac
  46.     RF12Cmd(0x0000);
  47.     RF12Send(0xaa);
  48.     RF12Send(0xaa);
  49.     RF12Send(0xaa);
  50.     RF12Send(0x2D);
  51.     RF12Send(0xD4);
  52.     for (i = 0; i < Len; i++)
  53.     {
  54.       byte = Data[i];
  55.       RF12Send(byte);
  56.       crc += (i % 16) * byte;
  57.     }
  58.     RF12Send(crc >> 8);
  59.     RF12Send(crc & 0xff);
  60.     RF12Send(0xaa);
  61.     RF12Send(0xaa);
  62.     RF12Send(0xaa);
  63.     RF12Cmd(0x8200);
  64. }
  65. uint8_t RF12PacketRecv(uint8_t Data[])
  66. {
  67.     uint16_t crc = 0, pcrc;
  68.     uint8_t i = 0;//, byte;
  69.     RF12Cmd(0x0000);
  70.     RF12Cmd(0x8288);
  71.     RF12Cmd(0x82c8);
  72.     for (i=0; i < PACK_SIZE; i++)
  73.     {
  74.         Data[i] = RF12Recv();
  75.         crc += (i % 16) * Data[i];
  76.     }
  77.     pcrc = RF12Recv() << 8;
  78.     pcrc |= RF12Recv();
  79.     RF12Cmd(0xca81);   //
  80.     RF12Cmd(0xca83);   // FIFO8, DR
  81.     if (pcrc == crc)
  82.     {
  83.         return TRUE;
  84.     }
  85.     else
  86.     {
  87.         return FALSE;
  88.     }
  89. }
  90. void RF12Init(void)
  91. {
  92.     /*
  93.     *inicjalizacja pinow SPI
  94.     */
  95.     SPI_PORT |= _BV(SPI_SCK) | _BV(SPI_SS);                     //pb7
  96.     SPI_DDR |= _BV(SPI_SCK) | _BV(SPI_MOSI) | _BV(SPI_SS);        //pb7 pb5 pb4 out
  97.     SPI_DDR &=~_BV(SPI_MISO);                                     //pb6 in
  98.     SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR1) ;
  99.     /*
  100.     * inicjalizacja portów do obsÅugi RF
  101.     */  
  102.     RF_IRQ_PORT |= _BV(RF_IRQ_BIT);
  103.     RF_IRQ_DDR &= ~_BV(RF_IRQ_BIT);
  104.     _delay_ms(400);    
  105.     RF12Cmd(0x80d8);   // EL, EF, 433band, 12.5pF
  106.     RF12Cmd(0x8208);   // EX, DC
  107.     RF12Cmd(0xa640);   // 434MHz
  108.     RF12Cmd(0xc611);   // 19.2kbps
  109.     RF12Cmd(0x94A0);   // VDI, FAST, 137kHz, 0dBm, &minus;103dBm
  110.     RF12Cmd(0xc2ac);   // AL, S, DQD4
  111.     RF12Cmd(0xca82);   //
  112.     RF12Cmd(0xced4);   // Synchro D4
  113.     RF12Cmd(0xc483);   // A1, FI, OE, EN
  114.     RF12Cmd(0x9850);   // 90kHz, 21db
  115.     RF12Cmd(0xCC17);   //
  116.     RF12Cmd(0xe000);   //
  117.     RF12Cmd(0xc800);   //
  118.     RF12Cmd(0xc040);   //
  119. }
  120. int main(void)
  121. {
  122.     uint8_t BufWr[PACK_SIZE], i ;
  123.     UART_init();
  124.     for (i = 0; i < PACK_SIZE; i++)
  125.     {
  126.         BufWr[i] = 0;
  127.     }
  128.     UART_putstr_P(PSTR("Start\r\n"));
  129.     _delay_ms(1500);
  130.     RF12Init();
  131.     i=0;
  132.     UART_putstr_P(PSTR("\r\n"));
  133.     for ( ; ; )
  134.     {    
  135.         if( RF12PacketRecv(BufWr) == TRUE )
  136.         {
  137.             for (i = 0; i < PACK_SIZE; i++)
  138.             {
  139.                 UART_puthexU08( BufWr[i] );
  140.                 BufWr[i] = 0;
  141.             }
  142.             UART_putstr_P(PSTR("\r\n"));
  143.         }
  144.         else
  145.         {
  146.             UART_putstr_P(PSTR("Blad pakietu\r\n"));
  147.         }
  148.     }
  149. }

PDF z wydrukiem płytki do termotransferu

Kod żródłowy

Polecam również literature:

RFM QuickStart

RFM Calculator

1 komentarz

  1. Betty says:

    Nice blog, keep it going!

Dodaj komentarz