Hallo Ihr RFM12 Experten,
ich habe bei mir einen RFM12 Sender und Empfänger laufen.
Der Sender funktioniert soweit schonmal fehlerfrei.
Leider macht der Empfänger noch ein Problem. Im Forum habe ich leider
noch nichts passendes gefunden...
Ich kann leider nur die ersten beiden gesendeten Bytes (16bit) aus dem
FIFO lesen.
Ich habe folgenden Ablauf:
Sender:
RFM12_write(0x8228);
delay_us(4);
RFM12_write(0x8238);
RFM12_SendByte(0xAA);
RFM12_SendByte(0xAA);
RFM12_SendByte(0xAA);
RFM12_SendByte(0x2D);
RFM12_SendByte(0xD4);
RFM12_SendByte(0x3A);
RFM12_SendByte(0x5A);
RFM12_SendByte(0x6A);
RFM12_SendByte(0x7A);
RFM12_SendByte(0x8A);
... usw.
Der Sender sendet alle 5 sec. diese Daten.
Empfänger:
Empfang wird über einen Interrupt ausgelöst.
Beim Auslesen des FIFOs bekomme ich folgende Werte zurück:
nIRQReceive
rfm12_GetStatus()= A0E0
rfm12_read_data(): data[0]: 3a --> Byte i.O.
rfm12_GetStatus()= 80FF
rfm12_read_data(): data[1]: 5a --> Byte i.O.
rfm12_GetStatus()= 0287 // FIFO leer
rfm12_read_data(): data[2]: 00 --> Byte n.i.O.
rfm12_GetStatus()= 02A7 // FIFO leer
rfm12_read_data(): data[3]: 00 --> Byte n.i.O.
Die Funktion RFM12_read_fifo() sieht wie folgt aus:
int16 RFM12_read_fifo(){
int i;
int16 data;
disable_interrupts(GLOBAL);
while(input(SDO==1));
RFM12_GetStatus();
data=rfm12_read_data(0xB000);
delay_us(2);
enable_interrupts(GLOBAL);
return(data);
}
Jetzt stellt sich mir die Frage, warum ich nur die ersten zwei
gesendeten Bytes empfangen kann.
Ich vermute, dass der RFM12 16bit in den FIFO überträgt und di nächsten
16bit können nicht in den FIFO geschrieben werden.
Kann es evtl. noch ein Timing Thema sein, dass ich den FIFO schon zu
früh abfrage?
Kann es möglicherweise an der SPI Frequenz von nur 271KHz liegen? Ich
habe die SPI Schnittstelle (PIC 18F2550) softwareseitig realisiert.
Hallo,
mich verwirren 2 Dinge:
Du liest im Interrupt des RFM12?
Warum dann auf SD0 testen, hast Du noch andere Interruptquellen des
RFM12 aktiv? Falls nicht, kann ja nur der FIFO-IRQ aktiv geworden sein
und dann ist SD0 definitiv 1, sonst wäre er ja nicht in die ISR
gegangen.
Du liest den Status und wertest ihn ohnehin nicht aus? Wozu also erst
lesen?
Du schreibst 271kHz SPI-Frequenz, ich hoffe, Deine Baudrate ist auch
klein genug, Du brauchst ja 32 SPI-Takte für ein Byte, mehr als 4800
Baud sins also sowieso nicht drin, weil die Bytes, die nicht in den FIFO
passen (alles nach dem 2.) schon lange gesendet wurden, bevor Du Platz
im FIFO geschaffen hast...
1
ISR(INT0_vect)
2
{
3
staticuint8_tdaten[32];
4
staticuint8_tchecksum=0;
5
staticuint8_tbytecount=0;
6
uint8_ti,sensor_nr,byte;
7
8
RFM12_PORT&=~(1<<RFM12_CS);// CS auf L
9
10
byte=0xB0;// Receive FIFO
11
12
for(i=0;i<8;i++)// Kommando senden
13
{
14
if(byte&0x80)
15
{
16
RFM12_PORT|=(1<<RFM12_SDI);// DATA auf H
17
}
18
else
19
{
20
RFM12_PORT&=~(1<<RFM12_SDI);// DATA auf L
21
}
22
RFM12_PORT|=(1<<RFM12_SCK);// CLK auf H
23
24
byte=(byte<<1);// nächstes Bit nach oben
25
26
RFM12_PORT&=~(1<<RFM12_SCK);// CLK auf L
27
}
28
29
byte=0;
30
31
for(i=0;i<8;i++)// FIFO Daten lesen
32
{
33
byte=(byte<<1);// eins höher schieben
34
if((RFM12_PIN&(1<<RFM12_SDO)))// Bit 1?
35
{
36
byte=(byte|0x01);// ja
37
}
38
RFM12_PORT|=(1<<RFM12_SCK);// CLK auf H
39
asm("nop");
40
RFM12_PORT&=~(1<<RFM12_SCK);// CLK auf L
41
}
42
43
RFM12_PORT|=(1<<RFM12_CS);// CS auf H
44
45
daten[bytecount]=byte;// Daten speichern
46
bytecount++;
47
checksum^=byte;// XOR-Prüfsumme
48
49
if(bytecount==PAKET_LEN)// fertig?
50
{
51
rfm12_send_cmd(0xCA81);// set FIFO mode
52
rfm12_send_cmd(0xCA83);// enable FIFO
53
54
if(checksum==0)// Checksumme ok?
55
{
56
sensor_nr=(daten[0]&0x0F)-1;// jetzt ab 0
57
if(sensor_nr<SENSOR_ANZ)// im gültigen Beeich?
58
{
59
daten[bytecount-1]=1;// 1 ins letzte Byte (Checksumme) für neue Daten
ist zwar AVR, empfängt bei mir im IRQ mit 38400 "nebenbei", SPI ist
Software.
Die Anzahl Bytes eines Telegramms werden mitgezählt, eine simple
XOR-Prüfsumme liegt über den Daten. Wenn alles passt, werden sie in das
passende Sensor-Array kopiert und der Empfänger wieder scharf gemacht,
ich empafange hier allerdings nur, der Sender ist unbenutzt.
Gruß aus Berlin
Michael
Danke schonmal für Eure Antworten:
Die Init Routine sieht wie folgt aus:
1
voidRFM12_INIT(void){
2
RFM12_GetStatus();
3
rfm12_write(0x80D7);
4
rfm12_write(0x82C9);
5
rfm12_write(0xC4A7);
6
rfm12_write(0xA640);
7
rfm12_write(0xC647);
8
rfm12_write(0x94A0);
9
rfm12_write(0xC2AC);
10
rfm12_write(0xCA81);
11
rfm12_write(0xCA83);
12
rfm12_write(0x9850);
13
rfm12_write(0xE000);
14
rfm12_write(0xC800);
15
rfm12_write(0xC000);
16
}
Zum Interrupt: Ich habe es so verstanden und auch so gemessen, dass der
Interrupt ausgelöst wird, wenn nach den Syncron Pattern ein Byte im FIFO
liegt. Dann lese ich den 4 mal FIFO aus. Am Ende mache ich einen FIFO
Reset. Wenn ich mir Deinen Code anschaue, scheint es ja so zu sein, dass
der INT bei jedem einzelnen Byte ausgelöst wird?
Das Emfangen funktioniert ja auch bei den ersten zwei Bytes. Ich
versuche jetzt nochmal die Baudrate runterzusetzten um zu prüfen ob das
noch Verbesserung bringt. Die Interruptroutine sieht wie folgt aus:
Hallo,
Du legst ja per Register fest, bei wieviel Bit im Fifo der IRQ ausgelöst
wird. Der RFM12 und auch der FIFO kennen nur Bits, dem ist egal, ob
Deine Daten ein Byte-Format haben oder aus 3er oder 16er Bitgruppen
bestehen.
Bei Bytes also IRQ-Trigger auf FIFO 8 Bit und wenn der IRQ kommt dann
dieses Byte abholen. Dann auf den nächsten IRQ warten, also darauf, daß
eben die nächsten 8Bit eingetroffen sind.
Gerade mal geschaut: 0xCAxy ist das Kommando, x legt die Anzahl Bits
fest.
Das die ersten beiden Bytes bei Dir ankommen, dürfte daran liegen, daß
die empfangen sind, bevor Du was sinnvoll abgeholt hast. Danach wird
dann nichts mehr eingelesen (FIFO voll, passen ja genau 2 Byte rein) und
wenn Du es endlich abgeholt hast, sind die anderen Bytes vorbei...
Gruß aus Berlin
Michael
Hallo Michael,
das ist nochmal ein super Tip. Ich glaube ich weiß schon woran es dann
hängt.
Ich sperre im Moment während des Auslesen den Interrupt. Ich darf also
bei (FIFO Level = 8) nur schnell das Byte auslesen und muss dann den INT
wieder freigeben.
Ich werds heute abend gleich mal testen und mich dann wieder melden...
Ich denke, dass ich auch nochmal die SPI Frequenz etwas tunen muss,
damit alles etwas schneller wird.
Grüße
Hallo Michael,
danke für den Tip. Ich habe die Interruptroutine umgeschrieben, so dass
jetzt jedes Byte einzeln ausgelesen wird. Jetzt klappts.
Allerdings lasst die Reichweite noch etwas zu wünschen...
Im Moment nur ca. 10cm nur mit dem RFM1 Modul ohne Antenne.
Hast Du noch einen Tip? Ich werd auch nochmal das Forum durchsuchen...
Schönen Abend noch...
Grüße
Hallo,
meine "Antennen" sind ca. 16cm Schaltdraht an den 433MHz Modulen,
möglichst senkrecht, allerdings teilweise auch ungünstig abgewinkelt.
Reichweiten hier zwischen 3-4m aus dem Gefrierfach (2 Altbauwände
dazwischen) und ca. 10m aus dem Keller in das 1. Obergeschoß.
Der Sensor aus dem Keller wird auch reltiv stabil empfangen wenn am
Empfänger nur ca. 2cm dran sind.
http://www.avr.roehres-home.de/
habe zwar ewig nicht weiter gemacht, alle Sensoren laufen seit April
2009.
Die überlagerten Pollin-Batterien laufen alle noch, die 2032 im
Gefrierfach mußte ich Mitte 2010 wechseln.
Die Sourcen auf meiner Webseite dürften die alten ASM-Versionen sein,
ich habe aber fast alles nach C als Einsteigerübung für mich
übertragen...
Der AVR-Webserver hängt zur Zeit nicht dran, es läuft unter
http://roehre.homeip.net
user: test
pass: test
ein Apache auf einer Seagate Dockstar mit dem USB-Modul dran.
Gruß aus Berlin
Michael
Hallo Michael,
tolles Webserverprojekt. :-)
Meine Funkübertragung läuft letzt auch stabil.
Die Reichweite hab ich jetzt bis 2m schon getestet (Länger sind meine
USB Leitungen nicht).
Danke nochmal für Deine Unterstüzung.
Grüße...
Andre Müller schrieb:> Die Reichweite hab ich jetzt bis 2m schon getestet
Mach einen Draht dran mit Lamda/4 der Wellenlänge Deiner Frequenz, da
machste im Haus locker 30m und im Freien über 100m. Die Baudrate sollte
dafür allerdings unter 4kbit/s liegen und der Empfänger auf maximale
Empfindlichkeit gesetzt werden. Ebenso sollte TX-Power auf maximal
stehen.