Forum: Mikrocontroller und Digitale Elektronik RFM 01 empfängt Daten sehr verzöger


von ArduStemmi (Gast)


Lesenswert?

Ich beobachte bei einer Funkverbindung ein sehr seltsames Verhalten.

Der Sender (RFM02, betrieben mit der Bibliothek vom Benedikt, aber 
umgestellt auf 866 Mhz) sendet jede Sekunde 32 Byte.

Der Empfänger (RFM01, betrieben mit der Bibliothek vom Benedikt, aber 
umgestellt auf 866 Mhz) fragt permanent den FIFO ab und schaltet LED's 
an oder aus.

Das Kuriose ist, dass das funktioniert. Nur leider nicht gleich. Der 
Empfänger braucht zwischen 3 Sekunden und 3 Minuten um die Daten richtig 
zu empfangen! (Was ich daran erkenne, dass die gewünschten LEDs nach 
dieser Wartezeit angehen! Danach reagiert das System sofort! Jede 
Änderung am Sender wird unmittelbar am Empfänger wiedergegeben!) Es 
hilft auch nicht, den µC zu resetten, oder den RFM01 zu resetten. Es ist 
für mich nicht nachvollziehbar!

Kann das jemand erklären?

PS: Im Übrigen verwende ich die Module, weil ich mich eben nicht 
tiefgreifend mit HF-Technik befassen möchte! Ich hatte die Hoffnung, die 
Dinger mit dem µC anzusteuern und gut. Den Rest sollten die Module 
erledigen. Vielleicht ist das zu naiv, aber ich habe es trotzdem 
versucht!

von P. F. (pfuhsy)


Lesenswert?

ArduStemmi schrieb:
> Ich hatte die Hoffnung, die
> Dinger mit dem µC anzusteuern und gut. Den Rest sollten die Module
> erledigen. Vielleicht ist das zu naiv, aber ich habe es trotzdem
> versucht!

Das Problem hab ich jeden mal.

Zeig doch mal den Code, vielleicht kann man da was sehen !

von ArduStemmi (Gast)


Lesenswert?

Das mache ich!

von Christian K. (the_kirsch)


Lesenswert?

Ich hatte meine Ansteuerung für den RFM01/02/12 selbst geschrieben.
Wichtig ist nur des der Sender eine Präambel vor der Startbedingung 
sendet.

Startbedingung ist 0x2DD4, als Präambel eignet sich 0xAAAA oder 0x5555
A    A    A    A    2    D    D    4
1010 1010 1010 1010 0010 1101 1101 0100

Ohne Präambel kann sich der Empfänger nicht auf den Takt einschwingen 
und übersieht das Startbyte.

Und du meinst wahrscheinlich 868Mhz

Der genaue Bereich den man verwenden kann, geht von 868.0 bis 868.6Mhz
Daher am besten genau die Mitte nehmen. Dafür musst du die Formel im 
Datenblatt nachschlagen, kann dir aber sagen das man für 868.3 Mhz das 
'f' mit 1660 gesetzt werden muss, und das macht man indem man 0xA67C an 
das Modul sendet.

Das zweite ist der Frequenzhub, den kann man zwischen 15 und 240 kHz 
einstellen, Standard ist 90 und sollte man erstmal so lassen.
Es wird eine  2-FSK verwendet, dass bedeutet bei einer '0'  sendet er 
auf 868.21Mhz und bei einer Logischen '1' auf 686,39 MHz.

Außerdem muss Transferrate eingestellt werden dazu muss 'r' gesetzt 
werden. In meinem Code hatte ich das nur für zwei werte ausgerechnet:
0xC647 => Data Rate: r=71 ; cs=0 => 4,79 kbps
0xC67F => Data Rate: r=127 ; cs=0 => 2,7 kbps

Kleine Transferrate => geringere Bitfehlerwahrscheinlichkeit => größere 
Reichweite



PS. Als ich das hier am schreiben bin, ist mir eingefallen das der RFM01 
gar kein EmpfangsFIFO hat, sondern nur der RFM12. Oder war es der 
SendeFIFO im RFM02. Bin mir aber nicht sicher.

von ArduStemmi (Gast)


Angehängte Dateien:

Lesenswert?

Hier die Dateien für den Sender!

von ArduStemmi (Gast)


Angehängte Dateien:

Lesenswert?

Und hier die Dateien für den Empfaenger!

von Christian K. (the_kirsch)


Lesenswert?

OK, rf02_txdata sendet automatisch am Anfang  AA AA AA 2D D4

was mich jetzt stutzig macht ist:
rf02_setfreq(RF02FREQ(830.25));          // Sende/Empfangsfrequenz auf 
830,25 MHz einstellen

Das ist die unterste Grenze was das Modul unterstützt, aber die 
Antennenschaltung ist auf eine Frequenz Optimiert, bei der sie die beste 
Efferenz hat. und das wird wohl 868Mhz sein.

Des weiteren ist wie gesagt in Deutschland nur der Bereich 868.0 bis 
868.6 erlaubt. Und das auch nur mit 1% Zeitnuzung. Sendet man am Stück 
10ms muss man 990ms pause machen.

Deine 32 + 5 Bytes brauchen schon 15,42ms

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Christian K. schrieb:
> das der RFM01
> gar kein EmpfangsFIFO hat

Doch klar, hat er. Und es ist wirklich sinnvoll, den vor einem Paket zu 
reinitialisieren. Nach erfolgreichem Empfang dann gleich wieder 
reinitialisieren. Dann läuft das alles recht solide. Ich lasse immer 
einen Timer als Timeout mitlaufen, wenn da innerhalb einiger Sekunden 
nichts kommt, wird einfach mal der Fifo neu gestartet.
Allerdings strahlt mein Sender auch alle paar Sekunden ein Bakensignal 
aus, der für regelmässige Updates in den Empfängern sorgt.

von Christian K. (the_kirsch)


Lesenswert?

Ich hab noch mal nachgeschaut, der RFM02 hat kein Sendepuffer der RFM12 
schon, das war der unterschied denn ich noch im Kopf hatte.

von ArduStemmi (Gast)


Lesenswert?

Christian K. schrieb:
> Ich hatte meine Ansteuerung für den RFM01/02/12 selbst geschrieben.
> Wichtig ist nur des der Sender eine Präambel vor der Startbedingung
> sendet.
>
> Startbedingung ist 0x2DD4, als Präambel eignet sich 0xAAAA oder 0x5555
> A    A    A    A    2    D    D    4
> 1010 1010 1010 1010 0010 1101 1101 0100

Das passiert bei mir in der Prozedur rf02_txdata:
1
    rf02_shiftout(0xAA);
2
    rf02_shiftout(0xAA);
3
    rf02_shiftout(0xAA);
4
    rf02_shiftout(0x2D);
5
    rf02_shiftout(0xD4);

Christian K. schrieb:
> Und du meinst wahrscheinlich 868Mhz
>
> Der genaue Bereich den man verwenden kann, geht von 868.0 bis 868.6Mhz
> Daher am besten genau die Mitte nehmen. Dafür musst du die Formel im
> Datenblatt nachschlagen, kann dir aber sagen das man für 868.3 Mhz das
> 'f' mit 1660 gesetzt werden muss, und das macht man indem man 0xA67C an
> das Modul sendet.

Dazu habe ich folgende Änderungen in der Bibliothek vorgenommen:
1
#define RF02FREQ(freq)  ((freq-860.0)/0.0025)    //früher stand hier: ((freq-430.0)/0.0025)

Mit diesem Makro in der Header-Datei wird der so genannte f-Wert 
berechnet! Des Weiteren habe ich die Prozedur rf02_setmodfreq angepasst.
1
void rf02_setmodfreq(unsigned char bandwidth)
2
{
3
  rf02_trans(0x9780|(bandwidth&7));      //früher stand hier rf02_trans(0x8F80|(bandwidth&7));
4
}
Hier habe entsprechend Datenblatt die bits b0 und b1 im Configuration 
Setting Command an 868 Mhz angepasst!

In meinem Quelltext habe ich mich für 830.25 MHz entschieden, warum weiß 
ich aber nicht mehr!
1
  rf02_init();                  // ein paar Register setzen (z.B. CLK auf 10MHz)
2
  rf02_setfreq(RF02FREQ(830.25));          // Sende/Empfangsfrequenz auf 830,25 MHz einstellen
3
  rf02_setpower(4);                // -12dBm Ausgangangsleistung
4
  rf02_setmodfreq(3);                // 120kHz Frequenzshift
5
  rf02_setbaud(19200);              // 19200 Baud

Ich sehe gerade: die 830,25 sind vollkommener Blödsinn! Die Prozedur 
korrigiert aber den Wert auf 860.24 Mhz(entspricht dem f-Wert von 96!)

Christian K. schrieb:
> Der genaue Bereich den man verwenden kann, geht von 868.0 bis 868.6Mhz
> Daher am besten genau die Mitte nehmen. Dafür musst du die Formel im
> Datenblatt nachschlagen, kann dir aber sagen das man für 868.3 Mhz das
> 'f' mit 1660 gesetzt werden muss, und das macht man indem man 0xA67C an
> das Modul sendet.

Damit komme ich nicht ganz klar: Meiner Meinung nach Ergibt 868,3 MHz 
einen f Wert von freq = (868,3 - 860) / 0,0025 = 3.320! Das ergibt nach 
meinem Verständnis 0xA000 | freq = 0xA000 | 0x0CF8 = 0xACF8 für das 
Frequency Setting Command! Oder?

von ArduStemmi (Gast)


Lesenswert?

Matthias Sch. schrieb:
> Ich lasse immer
> einen Timer als Timeout mitlaufen, wenn da innerhalb einiger Sekunden
> nichts kommt, wird einfach mal der Fifo neu gestartet.
> Allerdings strahlt mein Sender auch alle paar Sekunden ein Bakensignal
> aus, der für regelmässige Updates in den Empfängern sorgt.

Das würde mich interessieren, wie Du das realisierst!

von Christian K. (the_kirsch)


Lesenswert?

RTFM

f0 = 10 x c1 x ( c2 + F / 40000 ) [MHz]

Band C1 C2
315  1  31
433  1  43
868  2  43
915  3  30


868.3 = 10 x 2 ( 43 + F / 40000)
43,415 = 43 + F / 40000
0,415 = F / 40000
1660 = F

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Angehängte Dateien:

Lesenswert?

ArduStemmi schrieb:
> Das würde mich interessieren, wie Du das realisierst!

Der Code ist schon ein wenig älter und sollte für den Arduino sein, wenn 
ich mich recht erinnere. Allerdings komplett in Assembler und nur für 
die Hardware des Due Milanove und nichts mit Arduino Bibliotheken.

Da das für ein Wireless DMX Empfänger ist, wunder dich nicht über die 
'DMX' Bezeichnung des Empfangsbuffers.
Die Pinbelegung steht drin. Ich benutze übrigens ziemlich genau die 
Bandmitte bei 865,12 MHz.

von ArduStemmi (Gast)


Lesenswert?

Christian K. schrieb:
> RTFM
>
> f0 = 10 x c1 x ( c2 + F / 40000 ) [MHz]
>
> Band C1 C2
> 315  1  31
> 433  1  43
> 868  2  43
> 915  3  30
>
> 868.3 = 10 x 2 ( 43 + F / 40000)
> 43,415 = 43 + F / 40000
> 0,415 = F / 40000
> 1660 = F

Ja, das ist die Formel aus dem Datenblatt! In Benidikt's Headerdatei 
steht aber Freq = (F - 430)/0,0025. Ich geh' mal davon aus, dass das die 
gekürzte Formel für 433 Mhz ist. Muss ich also anpassen:

für 868 MHz gilt dann also:
f0 = 10 * 2 *(43 +F/4000)
f0 = 860 + F/200
f0-860 = F/200
F = (f0 - 860) * 200 oder (f0 - 860) / 0,005

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

ArduStemmi schrieb:
> Ich geh' mal davon aus, dass das die
> gekürzte Formel für 433 Mhz ist. Muss ich also anpassen

So isses. Bei den 865 Mhz Modulen hast du als Basis 860Mhz und die 
Rasterfrequenz ist 5kHz.
Es ist also Frx = 860+(PLLWert * 0,005)
Für 865,12 Mhz ist also PLL = 1024.

von ArduStemmi (Gast)


Lesenswert?

Ich habe jetzt die Frequenzen angepasst. Seitdem funktioniert das 
einwandfrei! Danke für Eure Bemühungen!

Eine Frage hätte ich jedoch noch!
1
for (;;)
2
  {  rf01_rxdata(data, 32);    // 32Bytes empfangen
3
    // hier die Daten verarbeiten
4
    
5
6
      PORTD = data[0];
7
      _delay_ms(250);
8
  
9
    }

hier wird ja bei jedem Durchlauf abgefragt, ob Daten (genau 32 Byte) da 
sind. Bleibt das Programm da stehen, wenn keine Daten da sind? Wenn ja: 
Wie kann ich das umgehen?

von ArduStemmi (Gast)


Lesenswert?

Und er sendet jetzt nur noch auf Knopfdruck, womit auch das Problem 
Zeitnutzung gelöst ist!

von Christian K. (the_kirsch)


Lesenswert?

Nach dem Erkennen der Startbedingung werden 32 Bytes eingelesen.

Hört der Sender vorher auf, kommt danach halt nur zufälliges rauschen 
an.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

ArduStemmi schrieb:
> Bleibt das Programm da stehen, wenn keine Daten da sind?
Jo, wird weiter auf die kompletten 32 Bytes warten
> Wenn ja:
> Wie kann ich das umgehen?
Du könntest bspw. einen Endemarker definieren, der das Ende eines 
Paketes markiert. Wenn dieser Marker empfangen wird, betrachtet die 
Empfangsroutine die Übertragung als beendet. Auch eine bestimmte Folge 
von Bytes wäre geeignet.

von Stefan B. (sibbl) Benutzerseite


Lesenswert?

Beitrag "rfm22b Empfänger läuft nicht"

In diesem Thread ist ein funktionierendes Programm drin....

von Christian K. (the_kirsch)


Lesenswert?

rf01_rxdata() blockiert solange bis die Startbedingung kommt.
das delay danach kannst du weglassen.


Die Lib von Benedikt ist ziemlich einfach gestickt, benutzt weder 
Interrupts noch Hardware SPI.

Benutzt man beides kann man die Kommunikation wunderbar im Hintergrund 
laufen lassen und das Hauptprogramm kann was anderes tun.

von ArduStemmi (Gast)


Lesenswert?

Christian K. schrieb:
> rf01_rxdata() blockiert solange bis die Startbedingung kommt.
> das delay danach kannst du weglassen.
>
> Die Lib von Benedikt ist ziemlich einfach gestickt, benutzt weder
> Interrupts noch Hardware SPI.
>
> Benutzt man beides kann man die Kommunikation wunderbar im Hintergrund
> laufen lassen und das Hauptprogramm kann was anderes tun.

Klingt gut! Gibt es dazu bereits funktionierenden Code?

von Christian K. (the_kirsch)


Lesenswert?

ArduStemmi schrieb:
> Gibt es dazu bereits funktionierenden Code?

Ja.
Aber mein Programm will ich nicht veröffentlichen.

So schwer ist es aber nicht.
Sieh es als Herausforderung an, es selbst zu probieren.

von ArduStemmi (Gast)


Lesenswert?

Christian K. schrieb:
> ArduStemmi schrieb:
>> Gibt es dazu bereits funktionierenden Code?
>
> Ja.
> Aber mein Programm will ich nicht veröffentlichen.
>
> So schwer ist es aber nicht.
> Sieh es als Herausforderung an, es selbst zu probieren.

Würde ich gern! Eine Frage kannst Du mir aber sicher beantworten: wie 
bringe ich den Rfm02 dazu, mir zu sagen, dass er Daten hat, die 
abgefragt werden sollten? Das habe ich noch nicht begriffen! Diese 
Botschaft könnte ich als Trigger für einen Interupt zu nehmen.

von ArduStemmi (Gast)


Lesenswert?

ArduStemmi schrieb:
> Christian K. schrieb:
>> ArduStemmi schrieb:
>>> Gibt es dazu bereits funktionierenden Code?
>>
>> Ja.
>> Aber mein Programm will ich nicht veröffentlichen.
>>
>> So schwer ist es aber nicht.
>> Sieh es als Herausforderung an, es selbst zu probieren.
>
> Würde ich gern! Eine Frage kannst Du mir aber sicher beantworten: wie
> bringe ich den Rfm02 dazu, mir zu sagen, dass er Daten hat, die
> abgefragt werden sollten? Das habe ich noch nicht begriffen! Diese
> Botschaft könnte ich als Trigger für einen Interupt zu nehmen.

Ich meine den RFM01, den Empfänger!

von Christian K. (the_kirsch)


Lesenswert?

RFM01/02/12 sind von der Ansteuerung identisch.

Es reichen 5 Leitungen 4 für SPI und eine für den Interrupt.

Die Interrupt Leitung wird immer Aktiv wenn sich ein Bit im 
Statusregister ändert. Und erlöscht wenn das Statusregister ausgelesen 
wird.

Das heißt immer wenn der Interrupt aktiv wird, das Statusregister 
auslesen und nachschauen was sich geändert hat.

Beim Sender, z. B. ob der Sendepuffer bereit ist, das nächste Byte 
entgegen zu nehmen.
Beim Empfänger ob was neues im Empfangspuffer ist.

Es gibt einige Fehlerflägs auf die man reagieren könnte.

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.