RFM12B | Willy's Desert Willy's Desert RFM12B | Willy's Desert

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 |
?

01
RF12Cmd(0x80d8);   // EL, EF, 433band, 12.5pF
02
RF12Cmd(0x8208);   // EX, DC
03
RF12Cmd(0xa640);   // 434MHz
04
RF12Cmd(0xc611);   // 19.2kbps
05
RF12Cmd(0x94a0);  // VDI, FAST, 137kHz, 0dBm, −103dBm
06
RF12Cmd(0xc2ac);   // AL, S, DQD4
07
RF12Cmd(0xca81);    // lress
08
RF12Cmd(0xced4);   // Synchro D4
09
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 |
?

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   &minus;  (RF12)nSEL
009
#define SPI_MOSI      5      // (uC)MOsi &minus;  (RF12)SDI
010
#define SPI_MISO      6      // (uC)MISO &minus;  (RF12)SDO
011
#define SPI_SCK       7      // (uC)SCK  &minus;  (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 &minus; (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);      //pb4
025
    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, DR
103
 
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);                       //pb7
121
    SPI_DDR |= _BV(SPI_SCK) | _BV(SPI_MOSI) | _BV(SPI_SS);        //pb7 pb5 pb4 out
122
    SPI_DDR &=~_BV(SPI_MISO);                                     //pb6 in
123
 
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.5pF
135
    RF12Cmd(0x8208);   // EX, DC         \\ NONE
136
    RF12Cmd(0xa640);   // 434MHz
137
    RF12Cmd(0xc611);   // 19.2kbps
138
    RF12Cmd(0x94a0);   // VDI, FAST, 137kHz, 0dBm, &minus;103dBm
139
    RF12Cmd(0xc2ac);   // AL, S, DQD4
140
    RF12Cmd(0xca81);   //
141
    RF12Cmd(0xced4);   // Synchro D4
142
    RF12Cmd(0xc483);   // A1, FI, OE, EN
143
    RF12Cmd(0x9850);   // 90kHz, 21db
144
    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:

 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   &minus;  (RF12)nSEL
009
#define SPI_MOSI      5      // (uC)MOsi &minus;  (RF12)SDI
010
#define SPI_MISO      6      // (uC)MISO &minus;  (RF12)SDO
011
#define SPI_SCK       7      // (uC)SCK  &minus;  (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 &minus; (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);    //pb4
025
    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, DR
103
 
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);                     //pb7
120
    SPI_DDR |= _BV(SPI_SCK) | _BV(SPI_MOSI) | _BV(SPI_SS);        //pb7 pb5 pb4 out
121
    SPI_DDR &=~_BV(SPI_MISO);                                     //pb6 in
122
 
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.5pF
134
    RF12Cmd(0x8208);   // EX, DC
135
    RF12Cmd(0xa640);   // 434MHz
136
    RF12Cmd(0xc611);   // 19.2kbps
137
    RF12Cmd(0x94A0);   // VDI, FAST, 137kHz, 0dBm, &minus;103dBm
138
    RF12Cmd(0xc2ac);   // AL, S, DQD4
139
    RF12Cmd(0xca82);   //
140
    RF12Cmd(0xced4);   // Synchro D4
141
    RF12Cmd(0xc483);   // A1, FI, OE, EN
142
    RF12Cmd(0x9850);   // 90kHz, 21db
143
    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

Kod żródłowy

Polecam również literature:

RFM QuickStart

RFM Calculator

Jeden komentarz

  1. Betty says:

    Nice blog, keep it going!