Forum: HF, Funk und Felder RFM12 FIFO Empfangsproblem


von Andre M. (gluehwein)


Lesenswert?

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.

: Verschoben durch Moderator
von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Poste mal bitte Deine kompletten Einstellungen, wie Du das RFM vor dem 
Empfang konfigurierst.

von Michael U. (amiga)


Lesenswert?

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
  static uint8_t daten[32];
4
  static uint8_t checksum = 0;
5
  static uint8_t bytecount = 0;
6
  uint8_t i, 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
60
              memcpy((void *) sensor[sensor_nr], (void const *) daten, PAKET_LEN);
61
            }
62
        }  
63
      checksum = 0;
64
      bytecount = 0;     
65
    }
66
67
}

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

von Andre M. (gluehwein)


Lesenswert?

Danke schonmal für Eure Antworten:
Die Init Routine sieht wie folgt aus:
1
void RFM12_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:
1
#INT_EXT2
2
void nIRQReceive()
3
{
4
 disable_interrupts(INT_EXT2);   
5
 i++;
6
 printf("nIRQReceive\r\n");
7
  for (i=0;i<4;i++) { 
8
        data[i]=RFM12_read_fifo();
9
        printf("rfm12_read_data(): data[%i]: %lx\r\n",i,data[i]);
10
  }
11
    rfm12_write(0xCA81);      // FIFO Reset
12
    delay_us(2);
13
    rfm12_write(0xCA83);
14
    RFM12_GetStatus();
15
    enable_interrupts(INT_EXT2);  
16
}

von Michael U. (amiga)


Lesenswert?

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

von Andre M. (gluehwein)


Lesenswert?

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

von Andre M. (gluehwein)


Lesenswert?

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

von Michael U. (amiga)


Lesenswert?

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

von Andre M. (gluehwein)


Lesenswert?

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

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.