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.
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.
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:
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_treceive_paket(uint8_t*buffer){
57
uint8_tsta,len,fifo_sta;
58
59
len=0;
60
61
if(!nRF_data_available)
62
return0;
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
returnlen;
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.
Hallo
Ich habe auch Module mit dem 24L01+ verwendet. Diese sind einfach
einzustellen und recht verständlich. Wenn ich den Einstellmaraton der
RFM12 sehe, habe ich mich richtig entschieden
Gruß
@Timmo H. (masterfx): Fehlen bei deinem Code nicht noch die ganzen
Includes, Deklarationen,...
Wenn ja, wäre es möglich, dass du mir diese auch postest?
Lukas K. schrieb:> @Timmo H. (masterfx): Fehlen bei deinem Code nicht noch die ganzen> Includes, Deklarationen,...> Wenn ja, wäre es möglich, dass du mir diese auch postest?
Klar hier meine Sources
Damit dürftest du freifeld etwa 30-50m kommen. Es gibt aber auch noch
das nRF24L01 + PA + LNA (20dBm) damit kommst du dann bis ca. 1km. Oder
das rfm70 das schafft etwa 100m da 5dBm. Oder das rfm70p ebenfalls 20
dBm und nur etwa 7€.
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
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_Tutorialhttp://www.tinkerer.eu/AVRLib/nRF24L01
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.
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.
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
voidinterrupt(void)
4
{
5
nRF_data_available=1;
6
PORTD=0xFF;
7
INTCON.INT0IF=0;
8
}
9
10
voidInterrupt_Init(void);
11
voidmain()
12
{
13
charrxbuf[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
voidInterrupt_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
voidinterrupt(void)
4
{
5
nRF_data_available=1;
6
INTCON.INT0IF=0;
7
}
8
9
voidInterrupt_Init(void);
10
voidmain()
11
{
12
chartx[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
voidInterrupt_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.
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.
Was ist das Problem, wenn ich "#include "nrf24l01.c"?
Das mit der volatile ist es auch nicht, nicht mal ein Interrupt
ausgelöst wird. Ich habe auch die Interrupt Leitung mit dem Oszi
gemessen.
Hast du diese bereits verwendet?
Wo kann ich diese kaufen? Wenn ich mich auf dieser Website registrieren
will, muss ich Company und Job Title eingeben, bin aber
Privatkäufer/Student.
Lukas K. schrieb:> Ist es normal, dass die Reichweite im Freien nur ca. 15m beträgt?
Na wenn man so wie du auf -12 dBm stellt denke ich schon dass es normal
ist. (Bit 0 hat keine Funktion im RF_SETUP)