RFM12 vs nrf24l01

Gast #2847453
Lesenswert?

Ich würde gerne zwischen 2 µC eine Funkverbindung aufbauen. Ich habe im 
Internet gesucht und 2 Funkmodule gefunden, die preislich ok wären: Das 
RFM12-433 und das nrf24l01. Welches dieser Funkmodule ist für Anfänger 
besser geeignet?
Wir haben in der Schule einen PIC18F45K22 programmiert, aber nur Timer, 
ADC, Komparatoren, Interrupt aber noch nie SPI oder I²C.
Gast #2847528
Lesenswert?

Ich hab bisher nur mit den RFM12 und RFM70 gearbeitet, aber ich würde 
dir zum Einstieg die RFM12 Module empfehlen.

Nach kurzem Überfliegen des Datasheets und einiger 
Produktbeschreibungen, scheint mir der nrf24l01 sehr ähnlich zum RFM70 
zu sein. Sehr viel mächtiger als der RFM12, mit Pipelines, ACK, 
retransmit, etc... Das ist alles sehr toll, wenn man es nutzen kann, 
aber das muss auch alles erstmal konfiguriert werden.

Ich denke der RFM12 ist schnell und einfacher zum Laufen zu bringen als 
der nrf24l01, dafür hat der nrf24l01 mehr Features und ist schneller.
#2847699
Lesenswert?

Verwirrter Anfänger schrieb:
> Nach kurzem Überfliegen des Datasheets und einiger
> Produktbeschreibungen, scheint mir der nrf24l01 sehr ähnlich zum RFM70
> zu sein.
Nahezu gleich, nur dass der nRF24L01 nur eine Bank hat und man fast gar 
nichts einstellen muss damit die Kommunikation funktioniert. Beim RFM70 
ist es etwas anders, aber das kann man 1:1 aus dem Beispielcode 
kopieren.

> Sehr viel mächtiger als der RFM12, mit Pipelines, ACK,
> retransmit, etc... Das ist alles sehr toll, wenn man es nutzen kann,
> aber das muss auch alles erstmal konfiguriert werden.

Und genau das ist beim nRF24L01 sehr einfach.
Hier mal ein Beispiel:
1
void nrf24l01_Initialize()
2
{
3
  uint8_t sta;
4
  
5
   
6
  SPI_Write_Reg(WRITE_REG + CONFIG, MASK_TX_DS | MASK_MAX_RT | 0x0C);
7
  CE_LOW();
8
  _delay_us(50);
9
    SPI_Write_Buf(WRITE_REG + TX_ADDR, RX0_Address, 5);    // Writes TX_Address to nRF24L01
10
    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX0_Address, 5); // RX_Addr0 same as TX_Adr for Auto.Ack
11
    SPI_Write_Reg(WRITE_REG + RX_PW_P0, sizeof(CONTROL_paket_t)); // Select same RX payload width as TX Payload width
12
    
13
    SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);  // Enable Pipe0
14
    
15
    SPI_Write_Reg(WRITE_REG + RF_CH, 40);        // Select RF channel 40
16
    SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x07);   // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
17
  SPI_Write_Reg(FLUSH_RX,0);//flush Tx
18
  SPI_Write_Reg(WRITE_REG + CONFIG, MASK_TX_DS | MASK_MAX_RT | 0x0F);
19
  
20
}
21

22
void SwitchToRxMode()
23
{
24
  CE_HIGH();
25
  _delay_us(150);
26
  SPI_Write_Reg(WRITE_REG + CONFIG, MASK_TX_DS | MASK_MAX_RT | 0x0f);     // Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT & TX_DS enabled..
27
}
28

29

30
void SwitchToTxMode()
31
{
32
  CE_LOW();
33
  _delay_us(150);
34
  SPI_Write_Reg(WRITE_REG + CONFIG, MASK_TX_DS | MASK_MAX_RT | 0x0e);     // Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT & TX_DS enabled..
35
}
36

37
void Send_Packet(uint8_t type,uint8_t* pbuf,uint8_t len)
38
{
39
  uint8_t fifo_sta;
40
  
41

42

43
  fifo_sta=SPI_Read_Reg(FIFO_STATUS);  // read register FIFO_STATUS's value
44
  if((fifo_sta&FIFO_STATUS_TX_FULL)==0)//if not full, send data (write buff)
45
  { 
46
    
47
    SPI_Write_Reg(FLUSH_TX,0);
48
    SPI_Write_Buf(type, pbuf, len); // Writes data to buffer
49
    CE_HIGH();
50
    _delay_us(20);
51
    CE_LOW();
52
    
53
  }         
54
}
55

56
uint8_t receive_paket(uint8_t *buffer){
57
  uint8_t sta,len, fifo_sta;
58
  
59
  len = 0;
60
  
61
  if(!nRF_data_available)
62
    return 0;
63
  
64
  nRF_data_available = 0;
65
  
66
  sta=SPI_Read_Reg(STATUS_REG);  // read register STATUS's value
67

68
  if((STATUS_RX_DR&sta) == 0x40)        // if receive data ready (RX_DR) interrupt
69
  {
70
    CE_LOW();
71
    do{
72
      len=SPI_Read_Reg(R_RX_PL_WID_CMD);  // read len
73
      if(len<=MAX_PACKET_LEN){
74
        SPI_Read_Buf(RD_RX_PLOAD,buffer,len);// read receive payload from RX_FIFO buffer
75
      }
76
      else{
77
        SPI_Write_Reg(FLUSH_RX,0);//flush Rx
78
      }
79
      fifo_sta=SPI_Read_Reg(FIFO_STATUS);  // read register FIFO_STATUS's value
80
          
81
    }while((fifo_sta&FIFO_STATUS_RX_EMPTY)==0); //while not empty
82
    
83
    SPI_Write_Reg(WRITE_REG|STATUS_REG,sta);// clear RX_DR or TX_DS or MAX_RT interrupt flag  
84
    //SwitchToRxMode();//switch to RX mode
85
    CE_HIGH();
86
  }  
87
    return len;
88
  
89
}

Mehr braucht es nicht.
Einfach "nrf24l01_Initialize"
und dann je nachdem was man machen will "SwitchToRxMode" oder 
"SwitchToTxMode"
und dann per "Send_Packet" bzw. "Receive_Paket" Senden/Empfangen.

Die Variable "nRF_data_available" in der "Receive_Paket"-Routine wird in 
einer Pin-Interrupt-Routine für den Int-Pin gesetzt.

Das reizt natürlich nicht die ganze Funktionalität aus, aber das ist ein 
Grundgerüst auf das man gut aufbauen kann.

Das RFM ist eigentlich nur bei der Initialisierung etwas komplizierter, 
aber ansonsten gleich. Das RFM70 hat jedoch auch mehr Reichweite als der 
nRF24l01 (5dBm vs 0dBm). Dafür kann der nRF24L01 noch 250 kbaud, was die 
Reichweite auch noch etwas erhöht.
Gast #2859233
Lesenswert?

Ich habe den Code gelesen, studiert und auch mehr oder weniger 
verstanden. Gehe ich richtig in der Annahme, dass die funktion 
SPI_transfer eine in Software realisierte SPI schnittstelle ist.
Könnte ich diese Funktion mit der Funktion SPI_Read ersetzen oder muss 
ich unterscheiden zwischen SPI_Write und SPI_Read?

SPI Bibliothek: 
http://www.mikroe.com/download/eng/documents/compilers/mikroc/pro/pic/help/spi_library.htm#spi1_read
#2859299
Lesenswert?

Lukas K. schrieb:
> Welche Reichweite kann ich mit dem nrf24l01 ungefähr erreichen?

Meine Testwerte: 0dbm (1mW Output Power) , 250kbps

Wenn der Sender in der 1. Etage liegt kann ich in einem Haus (ohne Stahl 
in den Wänden) der 1. zur 2. Etage gehen und verliere kein Paket, aber 
in der 3. Etage manchmal und je nach Lag ist das Signal auch weg.

Draußen: 100m waren kein Problem wenn man eine Sichtverbindung hat, mehr 
habe ich nicht getestet.
Wenn dar Empfänger im 100m Abstand dann hinter einem Gebäude verschwand 
war das Signal auch weg.

Meine Boards werden mit 3.0 oder 3.3V betrieben, eins war auch "defekt" 
bei mir angekommen. Nachdem ich das Center-pad (GND) des Chips von der 
Unterseite aus nachgelötet hatte funktionierte es.

http://www.mikrocontroller.net/articles/NRF24L01_Tutorial

http://www.tinkerer.eu/AVRLib/nRF24L01
#2860143
Lesenswert?

Lukas K. schrieb:
> Gehe ich richtig in der Annahme, dass die funktion
> SPI_transfer eine in Software realisierte SPI schnittstelle ist.
Ja.

> Könnte ich diese Funktion mit der Funktion SPI_Read ersetzen oder muss
> ich unterscheiden zwischen SPI_Write und SPI_Read?
Lediglich die SPI_Transfer und SPI_init ist Hardwareabhängig, daher 
brauchst du auch nur die anfassen.

Lukas K. schrieb:
> Noch eine kleine Frage: Wozu dienen diese zeilen?
>
1
#ifndef _nrf24l01_h_
2
>   #define _nrf24l01_h_
Das verhindert dass wenn du das Header-File in mehrere C-Files 
includierst, dass doppelte Definitionen/Deklarationen auftreten.
Das sollte man generell in jedes Header-File machen.
Schau dir mal die Header-Files deiner Toolchain an, du wirst keins 
finden wo diese Direktive nicht drin ist.
Vielleicht solltest du dir noch mal ein C-Buch anschauen bevor du dich 
an dein Projekt wagst.
#2860644
Lesenswert?

Lukas K. schrieb:
> Das eintige, was ich noch nicht verstanden habe ist, was ich der
> funktion Send_Packet als type übergeben soll...
>
>
1
void Send_Packet(uint8_t type,uint8_t* pbuf,uint8_t len)
Entweder W_TX_PAYLOAD_NOACK_CMD oder W_ACK_PAYLOAD_CMD, je nachdem ob 
AutoACK haben willst oder nicht.
Wie gesagt, lies die Examples, Datenblätter und Appnotes des 
Herstellers. Da steht alles drin. Ich bin nicht dazu da, dir das Denken 
abzunehmen.
Gast #2868851
Lesenswert?

Ich habe erste versuceh mit dem Modul und dem Code von Timmo H. 
(masterfx) gemacht. Ich habe leider keine daten empfangen.
Wo sollte ich bei der fehlersuche anfangen?
Ich habe 2 PIC18F45K22 mit jeweils einem Modul verbunden und folgende 
Quellcodes geschreiben:

Rx:
1
#include "nrf24l01.c"
2

3
void interrupt(void)
4
{
5
  nRF_data_available = 1;
6
  PORTD=0xFF;
7
  INTCON.INT0IF=0;
8
}
9

10
void Interrupt_Init(void);
11
void main()
12
{
13
  char rxbuf[10];
14
  rxbuf[0]=0;
15

16
  ANSELD=0x00;
17
  PORTD=0x00;
18
  TRISD=0x00;
19

20
  ANSELC=0x00;
21
  TRISC=0x00;
22
  PORTC=0x00;
23

24
  ANSELB=0x00;
25
  TRISB=0xFF;
26

27
  Interrupt_Init();
28
  SPI_init();
29
  nrf24l01_Initialize();
30
  
31
  SwitchToRxMode();
32

33
  while(1)
34
  {
35
    Receive_Paket(rxbuf);
36
    PORTD=rxbuf[0];
37
    Delay_ms(1000);
38
  }
39

40

41
}
42

43
void Interrupt_Init(void)
44
{
45
  RCON.IPEN=0;
46
  INTCON.GIE=1;
47
  INTCON.PEIE=1;
48
  INTCON.INT0IE=1;              // Enabel INT0 (RB0)
49
  INTCON2.INTEDG0=0;            // INT0 on falling edge
50
}
Tx:
1
#include "nrf24l01.c"
2

3
void interrupt(void)
4
{
5
  nRF_data_available = 1;
6
  INTCON.INT0IF=0;
7
}
8

9
void Interrupt_Init(void);
10
void main() 
11
{
12
  char tx[10];
13
  tx[0]=0;
14
  
15
  ANSELD=0x00;
16
  TRISD=0x00;
17

18
  ANSELC=0x00;
19
  TRISC=0x00;
20
  PORTC=0x00;
21
  
22
  ANSELB=0x00;
23
  TRISB=0xFF;
24
  
25
  Interrupt_Init();
26
  SPI_init();
27
  nrf24l01_Initialize();
28
  
29
  SwitchToTxMode();
30
  
31
  while(1)
32
  {
33
    Send_Packet(W_ACK_PAYLOAD_CMD,tx,1);
34
    tx[0]++;
35
    Delay_ms(1000);
36
  }
37
  
38
}
39

40
void Interrupt_Init(void)
41
{
42
  RCON.IPEN=0;
43
  INTCON.GIE=1;
44
  INTCON.PEIE=1;
45
  INTCON.INT0IE=1;              // Enabel INT0 (RB0)
46
  INTCON2.INTEDG0=0;            // INT0 on falling edge
47
}

Die bibliothek habe ich ein bisschen an meine PIC angepasst.
Angehängte Dateien:
#2871315
Lesenswert?

Vermutlich liegt es daran, dass du "nRF_data_available" nicht als 
volatile deklariert hast.
Schlecht kopiert würde ich sagen :D in meinem Code wars ja drin.

Achja und "#include "nrf24l01.c" solltest du auch nicht machen. Includen 
tut man eigentlich das entsprechende header-file, da stehen ja die 
Funktiosprototypen drin, die du in deiner "main.c" brauchst.
Gast #2880836
Lesenswert?

Ist es normal, dass die Reichweite im Freien nur ca. 15m beträgt?
Habe ich etwas falsch konfiguriert?
1
void nRF24L01_Init(void)
2
{
3
  SPI_Init();
4
  CSN_HIGH();
5
  CE_LOW();
6

7
  SPI_Write_Reg(WRITE+CONFIG,0b01111000);
8

9
  SPI_Write_Reg(WRITE+RF_CH,125);
10

11
  SPI_Write_Buf(WRITE+TX_ADDR, Adress, 5);
12

13
  SPI_Write_Buf(WRITE+RX_ADDR_P0, Adress, 5);
14

15
  SPI_Write_Reg(WRITE+RX_PW_P0, 5);                   // RX Payload with: 5
16

17
  SPI_Write_Reg(WRITE+EN_RXADDR, 0x01);
18

19
  SPI_Write_Reg(WRITE+RF_SETUP, 0b00101011);
20

21
  SPI_Write_Reg(WRITE+EN_AA, 0b00000001);
22

23
  SPI_Write_Reg(FLUSH_RX,0);
24

25
  SPI_Write_Reg(WRITE+CONFIG,0b01001010);             // TX
26
  //SPI_Write_Reg(WRITE+CONFIG,0b00111011);             // RX
27
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren