Forum: Mikrocontroller und Digitale Elektronik RFM12 868MHz


von Matthias S. (lecorde)


Lesenswert?

Moin,

ich sitz schon seit einer geraumen Zeit an meinen ATMega32 Board (10MHz 
Quarz) und dem RFM12 herum und bekomm das trotz etlicher Recherchen im 
Forum nicht zum laufen.

Das Programm baut auf das Beispiel von Pollin auf. Ich hab dabei nur bei 
dem Übertragen von den Registereinstellungen lediglich ein paar Delays 
eingebaut (Hatte ich mal im Forum geslesen).

Ich hab dabei nen Sender der alle 10sek nur ein Byte überträgt (Nach 
Synchronisation et.) und den Empfänger, der auf Tastendruck was 
empfangen soll und anschließend den Statusregister an einem Display 
anzeigt.

Hier meine Fragen:

1.) Wenn ich das Statusregister auslese bekomm ich zwei Widersprüchliche 
Aussagen vom Empfänger:

x2 -> Der RX-FIFO ist übergelaufen

und

x6 -> Der FIFO-Puffer ist leer/EMpty

Gelegendlich kommt auch der LowBat Status, obwohl ich die 
Schwellspannung des LowBattery Detector auf der Mind.Spannung gesetzt 
hab und die 5V Betriebsspannung stabil sind.

Weis da jemand vielleicht einen Rat?

2.) Wenn ich ein 868MHz Modul hab, muss ich da nur das Configuration 
Setting Command Register ändern?

MfG
Matthias

von Matthias S. (lecorde)


Lesenswert?

Mein IRQ-Ausgang ist auch ständig auf HI gesetzt und beim Auslesen des 
FIFO kommt immer nur 0x00 heraus.

Wär nett wenn da jemand Rat weiss

von Gast (Gast)


Lesenswert?

hmm genau das gleiche problem habe ich bei meinen rfm12 auch. könntet 
ihr mal eure initialisierung des moduls posten? nutzt ihr hardware oder 
software spi?

von Matthias S. (lecorde)


Lesenswert?

1.) Also die Initialisierung für beide ist:
  //Configuration Setting
  RF12_WRT_CMD(0x80EF);  //EL,EF,868band,12.0pF
  //Frequency Setting
  RF12_WRT_CMD(0xA000+1500);//868MHz
  //Data Rate
  RF12_WRT_CMD(0xC60B);    //32kbps
  //Data Filter
  RF12_WRT_CMD(0xC2AC);    //AL,!ml,DIG,DQD4
  //FIFO/Reset Mode
  RF12_WRT_CMD(0xCA81);    //FIFO8,SYNC,!ff,DR
  //Automatic Frequency Control
  RF12_WRT_CMD(0xC483);    //@PWR,NO RSTRIC,!st,!fi,OE,EN
  //Wake Up Timer
  RF12_WRT_CMD(0xE000);    //NOT USE
  //Low Duty Cycle
  RF12_WRT_CMD(0xC800);/    //NOT USE
  RF12_WRT_CMD(0xC0E0);

2.) Dann nochmal für den Sender:
  RF12_WRT_CMD(0x8239);    //!er,!ebb,ET,ES,EX,!eb,!ew,DC
  //TX Configuration Control
  RF12_WRT_CMD(0x9855);    //!mp,9810=30kHz,MAX OUT
  //RX Control
  RF12_WRT_CMD(0x95C8);    //VDI,FAST,134kHz,-20dBm,-103dBm

3.) Dann nochmal für den Empfänger:
  //Powermanagement
  RF12_WRT_CMD(0x82D9);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
  //TX Configuration Control
  RF12_WRT_CMD(0x9850);//!mp,9810=30kHz,MAX OUT
  //RX Control
  RF12_WRT_CMD(0x95C8);

4.) Bei Senden mach ich folgendes:
  RF12_SEND(0xAA);  //PREAMBLE
  RF12_SEND(0xAA);  //PREAMBLE
  RF12_SEND(0xAA);  //PREAMBLE
  RF12_SEND(0x2D);  //SYNC HI BYTE
  RF12_SEND(0xD4);  //SYNC LOW BYTE

  while(PINB&(1<<2));//wait for previously TX over
  {
    RF12_WRT_CMD(0xB800+Byte);  //B8xx: Daten (0xAA) senden
  }

  RF12_SEND(0xAA);  //DUMMY BYTE
  RF12_SEND(0xAA);  //DUMMY BYTE
  RF12_SEND(0xAA);  //DUMMY BYTE

5.) Und Empfangen geht bei mir so:
  RF12_WRT_CMD(0x82C8);
  RF12_WRT_CMD(0xCA81);
  RF12_WRT_CMD(0xCA83);
  RF12_WRT_CMD(0x0000);
  FIFO_data=RF12_WRT_CMD(0xB000);  //B0xx: FIFO Daten auslesen

von Matthias S. (lecorde)


Lesenswert?

Und hier noch ne Frage (und damit mein Threat nicht ganz nach unten 
verrutscht ;-) )

Sind die Präamble vor dem Senden wirklich notwendig oder konnte man da 
auch ein Delay einfügen?

von R. W. (quakeman)


Lesenswert?

Meine Initialisierung sieht ähnlich aber nicht genauso aus. Ich benutze 
die 433MHz Module, aber das sollte sich eigentlich nur auf die 
Frequenzeinstellung auswirken.
Mit meinen selbstgeschriebenen Sende- und Empfangsroutinen funktionieren 
die Module sehr stabil und zuverlässig. Ich benutze SDO zum Prüfen ob 
das RFM12 Modul bereit ist da ich mit dem IRQ des Moduls bisher 
schlechte Erfahrungen gemacht habe.

Bei der Senderoutine übergebe ich die Anzahl der zu übertragenden Bytes 
und ein Array mit den Nutzdaten. Bei der Empfangsroutine ist es genauso, 
nur daß in dem übergebenen Array anschließend die empfangenen Daten 
drinstehen. Diese Methoden sind nicht mehr die Endgültigen die ich 
momentan benutze, aber für Testzwecke haben sie sehr gut funktioniert.

Sie sind zwar für einen LPC935 (8051er), aber da es C Code ist sollte 
man schon die Zusammenhänge sehen können. :)

1
// RFM12 initialisieren
2
// Grundfrequenz = 434,00MHz
3
// Eine 1 wird mit positivem Hub gesendet (bei mp=0, FSK=1) -> Tx-Freq = 434,00MHz + 45kHz =434,045MHz
4
// Eine 0 wird mit negativem Hub gesendet (bei mp=0, FSK=1) -> Tx-Freq = 434,00MHz - 45kHz =433,955MHz
5
void init_rfm12() {
6
  v_Write_rfm12(0x0000);  // Status auslesen da die Module ansonsten manchmal etwas spinnen
7
  v_Write_rfm12(0x80D7);  // el , ef , 11.5pf, 433 MHz band
8
  v_Write_rfm12(0x82C9);  // er , ebb , !et , !es , ex , !eb , !ew , dc
9
  
10
  // Frequenz einstellen
11
  set_freq_rfm12(434000);  // 434,00 MHz / 868,00 MHz
12
13
  v_Write_rfm12(0xC647);  // 4.8kbps
14
  v_Write_rfm12(0x94C4);  // Vdi , Fast , 67 kHz Bandbreite, 0db , -79dbm
15
  v_Write_rfm12(0xC2AC);  // al , !ml , Dig , Dqd4
16
  v_Write_rfm12(0xCA81);  // Fifo8 , Sync , !ff , dr
17
  v_Write_rfm12(0xC493);  // @pwr , +15/-16 f(res) , !st , !fi , oe , en
18
  v_Write_rfm12(0x9827);  // 45 kHz Frequenzhub, tx-power -21 dB, !mp
19
  v_Write_rfm12(0xE000);
20
  v_Write_rfm12(0xC800);
21
  v_Write_rfm12(0xC000);  // 1 MHz , 2.2V
22
}
23
24
// Einen 16Bit Wert senden
25
void v_Write_rfm12(unsigned int uiDaten) {
26
  // Slave aktivieren
27
  NSEL = 0;
28
  
29
  // Erstes Datenbyte senden
30
  SPDAT = uiDaten >> 8;
31
  
32
  // Warten bis Byte gesendet
33
  while ((SPSTAT & 0x80) == 0);
34
  // Flags zurücksetzen
35
  SPSTAT = 0xFF;
36
37
  // Zweites Daten Byte senden
38
  SPDAT = uiDaten & 0xFF;
39
  
40
  // Warten bis Byte gesendet
41
  while ((SPSTAT & 0x80) == 0);
42
  // Flags zurücksetzen
43
  SPSTAT = 0xFF;
44
45
  NSEL = 1;
46
}
47
48
// Einen 16Bit Wert senden und gleichzeitig 16 Bit empfangen
49
unsigned int ui_RW_rfm12(unsigned int uiDaten) {
50
  unsigned int temp;
51
52
  // Slave aktivieren
53
  NSEL = 0;
54
  
55
  // Erstes Datenbyte senden
56
  SPDAT = uiDaten >> 8;
57
  
58
  // Warten bis Byte gesendet
59
  while ((SPSTAT & 0x80) == 0);
60
  // empfangenes High-Byte laden
61
  temp = SPDAT;
62
63
  // Flags zurücksetzen
64
  SPSTAT = 0xFF;
65
66
  // Zweites Daten Byte senden
67
  SPDAT = uiDaten & 0xFF;
68
69
  // High-Byte an richtige Position bringen
70
  temp = temp * 256;
71
  
72
  // Warten bis Byte gesendet
73
  while ((SPSTAT & 0x80) == 0);
74
  // empfangenes Low-Byte laden
75
  temp += SPDAT;
76
77
  // Flags zurücksetzen
78
  SPSTAT = 0xFF;
79
80
  NSEL = 1;
81
  
82
  return temp;
83
}
84
85
// Warten bis RFM12 bereit
86
void wait_rfm12() {
87
  NSEL = 0;              // SPI Slave aktivieren
88
  while (SDO == 0);      // Warten bis SDO = 1
89
}
90
91
// Grundfrequenz des Moduls einstellen
92
// Frequenz in 5kHz Schritten einstellbar. Frequenz in kHz angeben
93
void set_freq_rfm12(unsigned long ulFreq) {
94
  unsigned int temp;
95
96
  if (ulFreq < 800000)
97
    temp = (int) ((2*ulFreq - 860000) / 5);
98
  else
99
    temp = (int) ((ulFreq - 860000) / 5);
100
101
  // Wert für Register berechnen und prüfen ob im gültigen Bereich
102
  if (temp < 96)
103
    temp = 96;
104
  else if (temp > 3903)
105
    temp = 3903;
106
  
107
  // Wert in passendes Register schreiben
108
  temp += 0xA000;
109
  v_Write_rfm12(temp);
110
}
111
112
// Vor jeder Übertragung von zu sendenden Daten an das Modul muss auf SDO=1 
113
// gewartet werden um sicherzustellen, daß die vorherige Übertragung
114
// abgeschlossen ist.
115
// Die zu senden Daten werden mit dem Befehl 0xB800 kombiniert und über SPI
116
// übertragen, soll z.B. das Nutzdaten-Byte 0x35 gesendet werden, so wird an das
117
// Modul 0xB835 über SPI übertragen, sobald SDO=1 ist.
118
void v_Send_rfm12(unsigned char ucPaketLaenge, unsigned char data * data pucTX_Daten) {
119
  unsigned char i, temp;
120
121
  v_Write_rfm12(0x8239);  // Power Management Command: er=0, ebb=0, et=1, es=1, ex=1, eb=0, ew=0, dc=1
122
123
  // Preambel senden
124
  wait_rfm12();
125
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
126
  wait_rfm12();
127
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
128
  wait_rfm12();
129
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
130
  
131
  // Synchronisationsmuster senden
132
  wait_rfm12();
133
  v_Write_rfm12(0xB82D);  // HI Byte für Frame-Erkennung an Modul übertragen
134
  wait_rfm12();
135
  v_Write_rfm12(0xB8D4);  // LOW Byte für Frame-Erkennung an Modul übertragen
136
  
137
  // Daten senden
138
  for (i = 0; i < ucPaketLaenge; i++) {
139
    wait_rfm12();
140
    temp = *(pucTX_Daten + i);
141
    v_Write_rfm12(0xB800 + temp);  // Eigentliche Nutzdaten
142
  }
143
  
144
  // Zwei Dummybytes senden, damit der Sender nicht zu früh aufhört am Ende der Nutzdaten
145
  // Auf Empfängerseite müssen diese beiden Bytes dann rausgefiltert werden
146
  wait_rfm12();
147
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
148
  wait_rfm12();
149
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
150
151
  wait_rfm12();
152
  v_Write_rfm12(0x8209);  // Power Management Command: er=0, ebb=0, et=0, es=0, ex=1, eb=0, ew=0, dc=1
153
}
154
155
// n Datenbytes empfangen
156
void v_Receive_rfm12(unsigned char ucPaketlaenge, unsigned char data * data pucRX_Daten) {
157
  unsigned int uiTemp;
158
  unsigned char i;
159
  
160
  v_Write_rfm12(0x82C9);  // Power Management Command: er=1, ebb=1, et=0, es=0, ex=1, eb=0, ew=0, dc=1
161
  v_Write_rfm12(0xCA83);  // FIFO and Reset Mode Command: FIFO Level=8, al=0, ff=1, dr=1
162
163
164
  // 0xB000 an RFM12 senden und zweites Byte gleichzeitig empfangen
165
  for (i = 0; i < ucPaketlaenge; i++) {
166
    NSEL = 0;
167
    while(SDO == 0);
168
    uiTemp = ui_RW_rfm12(0xB000);
169
    *(pucRX_Daten + i) = uiTemp & 0xFF;
170
  }
171
172
  v_Write_rfm12(0x8209);  // Power Management Command: er=0, ebb=0, et=0, es=0, ex=1, eb=0, ew=0, dc=1
173
}

Vielleicht hilft es dir ja etwas weiter beim experimentieren. :)

Ciao,
     Rainer

von Michael U. (amiga)


Lesenswert?

Hallo,

die 3x 0xAA sind nötig, damit die Empfängerregelung und AFC sich 
einstellen können und die Bittakt-PLL einrastet. Das können auch mehr 
0xAA sein, 3 reichen aber.
Das Sync-Word gibt dann den FiFO frei und die nächsten Bits werden da 
reingeschoben.

Nach dem Empfang der gesendeten Anzahl Bytes muß der Fifo aus- und 
wieder eingeschaltet werden, damit auf das nächste Sync beim nächsten 
Datenpaket gewartet wird.
Macht man das nicht, wird alles was kommt, in den FiFo geschoben.
Rauschen, Fernthermometer, Funkamateure und was sich da noch so alles 
rumtreibt.

Nach dem Senden des Datenpaketes müssen keine weitern Bytes (auch keine 
0xAA) gesendet werden. Es muß nur gewartet werden, bis der Sender das 
letzte Byte fertig gesendet hat, bevor man dem RFM was Neues zu tun 
gibt.
Sonst wird das letzte Nyte eben unvollständig gesendet.

Vielleicht findest Du ja bei mir was:
http://www.avr.roehres-home.de

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Danke für die Antworten, ich werd das Beispiel von Rainer heut Abend 
noch ausprobieren.

MfG
Matthias

von Matthias S. (lecorde)


Angehängte Dateien:

Lesenswert?

Laut Datenblatt (RF12.pdf S.24) gibt mir der FR12 immer bescheid ob der 
SPI bereit ist um ein neues Bit aufzunehmen.

Wenn ich mir den Schreibevorgang des FIFOs am Logicanalyser angucke, 
sehe ich das nach dem Übertragen der ersten beiden Bytes (0x8238 und 
0xB8AA -> Erste Preamble) SDO permanent auf Low geht, ist das evt mein 
Problem?

von R. W. (quakeman)


Lesenswert?

Matthias S. schrieb:
> Laut Datenblatt (RF12.pdf S.24) gibt mir der FR12 immer bescheid ob der
> SPI bereit ist um ein neues Bit aufzunehmen.
Das ist korrekt. Dort ist ja ein schönes Beispiel dargestellt anhand 
dessen man die Arbeitsweise von SDO erkennen kann.

> Wenn ich mir den Schreibevorgang des FIFOs am Logicanalyser angucke,
> sehe ich das nach dem Übertragen der ersten beiden Bytes (0x8238 und
> 0xB8AA -> Erste Preamble) SDO permanent auf Low geht, ist das evt mein
> Problem?
Wieso Problem?

SDO=1 bedeutet, daß du weitere Daten reinschreiben kannst. Erst bei 
SDO=0 musst du warten bis es wieder 1 wird. Nachdem der RFM12 dein Byte 
vermutlich gerade am funken ist, musst du warten, bis er wieder bereit 
ist das nächste Byte zu empfangen. Da die Übertragungsrate des SPI aber 
normalerweise um einiges größer ist als die Übertragungsrate per Funk, 
sieht es in dem kleinen Abschnitt des LA natürlich aus, als wäre SDO 
immer 0.
In deinem Beispiel betreibst du den RFM12 ja mit 32kBps. Das wären bei 8 
Bits dann genau 8/32000 Sekunden pro Byte oder 250µs. Also kannst du 
davon ausgehen, daß SDO erst nach ~250µs wieder auf 1 geht nachdem es 
auf 0 gegangen ist.

Also würde ich sagen es ist doch alles im grünen Bereich bei dir. :)

Du musst natürlich vor jedem zu sendenen TX-Byte prüfen, ob der RFM12 
bereit ist neue Daten anzunehmen (SDO=1).

Du solltest, wenn du schon solch schöne Spielzeuge wie einen Agilent LA 
zur Verfügung hast, mal mehrere Bytes senden und das Ganze dann auch 
über den gesamten Zeitraum aufzeichnen. Dann sollte man das Verhalten 
etwas besser erkennen und verstehen können. :)

Ciao,
     Rainer

von Matthias S. (lecorde)


Angehängte Dateien:

Lesenswert?

Das könnte hinkommen.

Ich hab jetzt einen Funkscanner an das Oszilloskop angeschlossen. Wenn 
ich mehrere Bytes übertragen will seh ich an dem Funkscanner 
(Kopfhörerausgang) wie nur das letzte Byte von insges. 8Bytes übertragen 
wird. (Ich hab extra die Baudrate stark heruntergesetzt)

Ich stell mal die Bilder rein (Alles bei sehr langsamen 2kbps)

Bild 1: Signal 0xAA

Bild 2: Signal 0xFF

Bild 3: Signal 0xAA im zusammenspiel zum SPI

Ich werd mal in meinen Programm das SDO berücksichtigen (so wie Rainer 
es sagt) und die Baudrate wieder hochdrehen. Mal gucken was dann kommt.

MfG und Danke
Matthias

von R. W. (quakeman)


Lesenswert?

Wenn du SDO nicht berücksichtigst, also nicht wartest, bis die Daten 
gesendet wurden, dann überschreibst du mit den neuen Daten die noch zu 
sendenden Daten. Das Ergebnis ist auf jeden Fall nicht das was gewünscht 
ist und er sendet auch nicht mehr alle Bytes.

von Michael U. (amiga)


Lesenswert?

Hallo,

wenn man nicht nIRQ sondern das FIFO-Statusit abfragt, gibt es noch eine 
Falle: SDI muß L sein wenn nSEL auf L geht, damit der RFM das 
FFIT/RGIT-Bit auf SDO legt. SDI L bei der H/L-Flanke leitet ein 
Status-Read ein und nur dann ist SDO als Status gültig.

Also immer schön komplette Zyklen machen, SDI auf L, nSEL aktiv, SDO 
testen auf H, wenn ja -> Kommando + Byte raus/rein, nSEL auf H usw.

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Moin

Der Sender müsste laut Funkscanner richtig laufen und am RSSI Pin vom 
Empfänger kann ich nun auch das Signal messen. Aber trotzdem ist der 
FIFO des Ampfänger immer noch leer.

Komischerweise liefert mir das Statusregister des Senders folgende 
Aussagen:

- RSSI/ATS (ATS = )(RSSI = Die Signalstärke ist über dem eingestelltem 
Limit)

=> unabhängig davon wie Stark ich den Sender einstelle

- OFFS_6 (sign of offset)
- OFFS_2
- OFFS_0

=> Frequenzoffset (eigendlich normal)

Leider empfange ich immer noch nichts (Obwohl der Empfänger nun offen 
wie ein Scheunentor sein müsste und ich nun das SDO beidseitig 
berücksitige) Könnte das an dem Sender liegen (RSSI/ATS)?

Grüsse aus Emden
Matthias

von Michael U. (amiga)


Lesenswert?

Hallo,

auf dem Funkscanner kannst Du erkennen, daß der Sender rictig sendet 
oder daß er überhaupt was sendet?

Wenn Dein Timing für den Sneder nicht stimmt und Du z.B. ein Byte 
reinschreibst, bevor der RFM das vorige fertig gesendet hat, dann kommen 
weder 0xAA noch das Syncword beim Empfänger heil an und der Fifo starte 
nie.

Ich habe jetzt hier nicht alles geschaut, waren Deine Senderoutinen 
irgendwo dabei?

Zur Not kann ich hier auch einen Tiny mit einem RFM12 auf das Steckbrett 
stecken und mit Deinen Routinen mal was senden, was mein Sensorempfänger 
empfangen kann.

PS: Sendeleistung und Antenne sind erstmal sowas von egal, ich empfange 
den Sensor aus dem Keller hier im ersten Stock auch ganz ohne Antenne am 
Empfänger noch stabil.

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Angehängte Dateien:

Lesenswert?

Moin,

leider konnte ich gestern nicht mehr Antworten da mir was 
dazwischengekommen ist.

Ich hab jetzt eine Zip-Datei erstellt mit meinem Hauptprogramm 
(Funkmodul.c) und den Routinen für das Funkmodul (RFM.c + .h)

Ich hab da auch ein Oszillogram eingefügt (Print09) bei dem ich mir 
nicht sicher bin ob der Schreibvorgang ins FIFO richtig ist. So wie ich 
das sehe wird bei dem letzten Bit das SDO auf Low geschaltet. Trotzdem 
kann ich aber mit dem Funkscanner die gesendeten Daten bei einer 
niedrigen Baudrate erkennen (Print11).

Wäre nett wenn du dir das nochmal ansehen könntest.

MfG
Matthias

von Matthias S. (lecorde)


Lesenswert?

Zu dem Prgramm:

LED Grün soll leuchten wenn der Wert 0xCC übertragen und erfolgreich 
verglichen wurde.

von Michael U. (amiga)


Lesenswert?

Hallo,

ich weiß nicht, ob ich heute dazu komme, das Wetter hier sieht nicht 
nach Bastelzimmer aus. ;-))

Das SDO auf L könnte ja stimmen (FIFO ist ja jetzt zum Senden bereit.
In soclhen Details sind auch die diversen Datenblattunterlagen teilweise 
sehr unklar.

Der Fifo-Init beim Empfang stimmt so nicht wirklich.

RFM12_send_cmd(0x82C8);  // Empfänger ein
und dann
RFM12_send_cmd(0xCA81);  // set FIFO mode
RFM12_send_cmd(0xCA83);  // enable FIFO

Die Folge muß so sein, erst den Level setzen und dann einschalten.
Siehe auch Datenblatt und Codebeispiel von HopeRF (auch wenn das mehr 
Fehler als Funktionen enthält. ;)

Ich versuche mich mal durch Deine Einstellungen zu kramen, ob mir da 
noch was auffällt.


Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Das wär nett, ich versuch das von dir mal so einzuprogrammieren.

MfG
Matthias

von Matthias S. (lecorde)


Lesenswert?

Ich seh grad das ich in der Recieve Funktion das Warten auf SDO_Hi noch 
nicht richtig ist. Ich werd das überarbeiten

von Matthias S. (lecorde)


Angehängte Dateien:

Lesenswert?

So, jetzt wird permanent der Befehl 0xB000 geschickt (Solang SDO==0)

unsigned int RF12_RECEIVE(void)
{
  unsigned int FIFO_data;
  RF12_WRT_CMD(0x0000);
  LOW_SEL();
  while(~PINB&(1<<6))
  {
  FIFO_data=RF12_WRT_CMD(0xB000);  //B0xx: FIFO Daten auslesen
  }
}

In der Funktion RF12_WRT_CMD hab ich zudem das letzte HI_SEL() entfernt.

MfG
Matthias

PS: Lasst euch durch mich aber nicht das schöne Wetter vermiesen

von Matthias S. (lecorde)


Angehängte Dateien:

Lesenswert?

Weis jemand wie das Signal am Kondensator des RSSI aussehen muss?

Ich seh nur an der Flanke das was ankommt, sieht aber nur nach Rauschen 
aus.

Zum Oszillogramm:
Oberer Verlauf Empfänger (Pin RSSI)
Unterer Verlauf Sender (Aufgenommen mit Funkscanner)

MfG
Matthias

von Matthias S. (lecorde)


Angehängte Dateien:

Lesenswert?

So wie es ausseiht bekomm ich am Empfänger nun auch ein richtiges 
Signal. Blos komischerweise bekomm ich keine Daten.

Den FIFO les ich wie folgt aus:

1.) Empfänger starten
RF12_WRT_CMD(0x82C8);
short_delay();

2.) FIFO Mode einstellen
RF12_WRT_CMD(0xCA81);
short_delay();

3.) FIFO aktivieren
RF12_WRT_CMD(0xCA83);

4.) SDI auf false

5.) Chipselect auf false

6.) Warte auf SDO Hi und lese aus

7.) Chipselect auf Hi

Hab ich es soweit richtig verstanden wie man den FIFO ausliest oder muss 
man vorher noch das Stautusregister auslesen (was man ja eigendlich nur 
beim senden machen muss)?

Und wie ist der Ablfauf bei Punkt 6. mit dem SDO? Ist er die ersten acht 
Bits permanent auf true und gibt dann die Daten aus?

MfG
Matthias

Zum Oszillogramm:
Oberer Verlauf:  Empfänger (Pin RSSI)
Unterer Verlauf: Sender (Aufgenommen mit Funkscanner)

von R. W. (quakeman)


Lesenswert?

Schau dir doch einfach mal meine v_Receive_rfm12 Methode an. Die 
funktioniert bei mir sehr zuverlässig. Das ich MOSI (oder SDI) nicht auf 
0 setze liegt dadran, daß es standardmäßig auf 0 liegt bei meinem 
Controller.

von R. W. (quakeman)


Lesenswert?

Also Statusregister auslesen musst du weder beim empfangen noch senden. 
Das einzige was du brauchst ist das Prüfen auf SDO, was dem ersten Bit 
(FFIT/RGIT) des Statusregisters entspricht. Also man könnte sagen du 
prüfst auf das erste Status-Bit, aber nicht auf das gesamte 
Statusregister.

Du prüfst auf SDO als Pin und nicht per SPI. Sobald SDO=1 startest du 
die Abfrage per SPI indem du 0xB000 schreibst und von den empfangenen 
16Bit die letzten 8Bit sind dann deine Daten.

In meinem Code siehst du anhand "while(SDO == 0);", daß ich direkt den 
Pin SDO prüfe, was nichts mit SPI zu tun hat.

von Michael U. (amiga)


Angehängte Dateien:

Lesenswert?

Hallo,

da mein Eigenbau-Logic-Analyzer ja noch am RFM12 hängt hier mal der 
Empfangszyklus.

Ähnlich auf meiner Homepage
http://www.avr.roehres-home.de/logikanalyzer/s_index.html
Dei Software ist auch auf meiner Homepage im Archiv mit drin,
bei den Sensoren der USB-Empfänger.

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

@Rainer:
Mein Programm hat nun denselben Ablauf wie deins, bleibt aber leider in 
der while(SDO==0){} Schleife hängen.

Die Schleife ist für mich auch logisch, überschreibe den Wert solange 
bis SDO was ausgibt und gebe diesen Wert anschließend zurück.

von Michael U. (amiga)


Lesenswert?

Hallo,

Matthias S. schrieb:
> Mein Programm hat nun denselben Ablauf wie deins, bleibt aber leider in
> der while(SDO==0){} Schleife hängen.
>
> Die Schleife ist für mich auch logisch, überschreibe den Wert solange
> bis SDO was ausgibt und gebe diesen Wert anschließend zurück.

ich habe jetzt keine Gelegenheit, mir das zu SDO gehörige #define oder 
macro zu suchen.

Da SDO ja ein Bit eiens Ports ist, muß ja was in der Art

while((Portx & (1<<SDO)) == 0);

dahinterstecken.

PS: einer der Gründe, weshalb ich auch in C die "Normal-" Schreibweise 
bevorzuge, erspart mir an solchen Stellen das nachschauen, was da 
eigentlich passieren soll...

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Genau, ich hab da eine While Schleife eingefügt, die laut dem Debugger 
und dem Logikanalyser soweit funktioniert :(

Ist bei euch der Abstand der beiden Geräte und die Antennenlänge egal?

Ich hab den Verdacht dass das Signal bei Empfänger nicht richtig 
verarbeitet wird und deshalb der FIFO immer leer ist.

von Michael U. (amiga)


Lesenswert?

Hallo,

ja, ist in weiten Grenzen egal.
1
RFM12_send_cmd(0x0000);  // Status read
2
RFM12_send_cmd(0xC080);  // CLK-Frequenz / Batterie-Level
3
RFM12_send_cmd(0x80D7);  // FIFO ein, C = 11,5pF
4
RFM12_send_cmd(0xC2AB);  // Thresold, Filter
5
RFM12_send_cmd(0xCA81);  // FIFO-Level, 
6
RFM12_send_cmd(0xE000);  // WakeUp aus 
7
RFM12_send_cmd(0xC800);  // Low Duty Cycle aus, 
8
RFM12_send_cmd(0xC4F3);  // AFC
9
RFM12_send_cmd(0xA620);  // Frequenz
10
RFM12_send_cmd(0x948C);  // Bandbreite
11
RFM12_send_cmd(0xC610);  // Baudrate 19200
Du kannst ja die Parameter, die ich benutzt mal vergelichen oder 
benutzen,
für den RFM12 als Sender habe ich nichts zur Hand (RFM02 als Sender...).

Denek aber daran, ich habe 433MHz Module, Band usw. ist also anders.

die die etwas kommentiert ist, hier noch die Sendeeinstellungen des 
RFM02:
1
rfm02_send_cmd(0xCC00);   // Status read
2
rfm02_send_cmd(0xC0E0);   // Power Settings: Quarz ein, Synthesizer und PA ein bei Send-Command
3
rfm02_send_cmd(0xC2A0);   // low bat detector, TX Bit Sync, WakUp-Timer Calibrierung aus
4
rfm02_send_cmd(0x8883);   // Control: 1MHz Clock Out, 12,5pF Last Quarz, 120kHz Shift
5
rfm02_send_cmd(0xA620);   // Frequenz: 430MHz + (0,0025 * 0x620) -> 433,92MHz
6
rfm02_send_cmd(0xB200);   // Power 2 * -3dBm -> -6dBm
7
rfm02_send_cmd(0xD2C0);   // Set PLL: set 33%
8
rfm02_send_cmd(0xC810);   // Baudrate: 344827 / 19200 = 17 - 1 -> 0x10

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Moin moin,

mit deinen Registereinstellungen Empfängt er was, ich sende zwar CC mein 
Display zeigt aber E6 an.

Das Bitmuster ähnelt sich

11001100 CC
11100110 E6

-> Also um einen nach rechts verschoben.

Und wenn ich aus CC AA mache ändert sich der Wert beim Empfänger

Aber trotzdem könnt ihr euch nicht vorstellen wie sehr ich mich gerade 
freue. :-D :-D :-D

Mal gucken warum kein CC ankommt, aber immerhin

MfG und vielen Dank an Michael und Rainer

von R. W. (quakeman)


Lesenswert?

Matthias S. schrieb:
> @Rainer:
> Mein Programm hat nun denselben Ablauf wie deins, bleibt aber leider in
> der while(SDO==0){} Schleife hängen.
>
> Die Schleife ist für mich auch logisch, überschreibe den Wert solange
> bis SDO was ausgibt und gebe diesen Wert anschließend zurück.

Hmm ich glaube du hast das etwas falsch verstanden. Du sollst in der 
While Schleife nicht dauernd per SPI den Empfangsfifo abfragen, sondern 
warten und gar nichts machen, solange bis SDO auf 1 wechselt und genau 
dann den Empfangsfifo abfragen. :)
Wenn du genau hinschaust, dann siehst du, daß meine while Schleife ein 
Semikolon am Ende hat, weshalb er genau in der einen Zeile wartet und 
keinen weiteren Code ausführt. Es muss also lauten "while(SDO == 0);" 
und nicht "while(SDO == 0){...}" ;)


Michael U. schrieb:
> ich habe jetzt keine Gelegenheit, mir das zu SDO gehörige #define oder
> macro zu suchen.
>
> Da SDO ja ein Bit eiens Ports ist, muß ja was in der Art
>
> while((Portx & (1<<SDO)) == 0);
>
> dahinterstecken.
>
> PS: einer der Gründe, weshalb ich auch in C die "Normal-" Schreibweise
> bevorzuge, erspart mir an solchen Stellen das nachschauen, was da
> eigentlich passieren soll...

Naja, "normal" ist Definitionssache.
Denn SDO ist kein Makro sondern direkt der Portpin des Controllers. Bei 
den 8051ern sind alle Ports und viele SFR direkt bitadressierbar, 
weshalb ich eben nicht diesen "Umweg" über "(Portx & (1<<SDO)) == 0" 
gehen muß sondern direkt den Pin abfragen kann. Finde ich weit aus 
schneller und einfacher als wenn ich erst den Port einlesen und dann den 
Pin ausmaskieren müsste. ;)

Ciao,
     Rainer

von Matthias S. (lecorde)


Lesenswert?

Moin

Mein Quelltext sieht nach dem ganzen herumgebastle eh ein bischen 
bescheiden aus.

@Rainer
Jetzt hab ich das Semikolion auch gesehen -.- sry mein Fehler. Leider 
bin ich jetzt nicht mehr in meinen Labor aber ich werd das morgen früh 
gleich ausprobieren. Aber das beim ändern des zu übertragenen Wert sich 
der Angezeigte Wert am Empfängerdisplay ändert ist für mich wenigsten 
ein gutes Zeichen.

Heut Abend guck werd ich nochmal die Registereinstellungen von Michael 
mit meinen alten vergleichen, vielleicht bemerk ich dann den 
entscheidenen Unterschied.

Aber ich bin froh das ich was empfange und kann heut Nacht wenigstens 
besser Schlafen ;-).

MfG und schönes Wochenende
Matthias

von Michael U. (amiga)


Lesenswert?

Hallo,

Matthias S. schrieb:
> mit deinen Registereinstellungen Empfängt er was, ich sende zwar CC mein
> Display zeigt aber E6 an.
>
> Das Bitmuster ähnelt sich
>
> 11001100 CC
> 11100110 E6
>
> -> Also um einen nach rechts verschoben.

Die linke 1 dürfte noch zum Bit 7 des Kommandos gehören.
Da stimmt das Timing nicht, mit dem Du das empfangene Bit einliest oder 
Du schiebst falsch rein.
Ich vermute mal, Du bist da zu schnell, der Fifo kann nicht so schnell 
gelesen werden wie die Register des RFM.

Meine Leseroutine de Daten
1
for (j=0; j<8; j++)
2
  {     
3
    byte = (byte << 1);                                  // eins höher schieben
4
    if ((RFM12_PIN & (1<<RFM12_SDO)) == (1<<RFM12_SDO))  // Bit 1?
5
      {
6
        byte = (byte | 0x01);        // ja
7
      }
8
    asm("nop");
9
    RFM12_PORT |= (1<<RFM12_SCK);            // CLK auf H
10
    asm("nop");
11
    asm("nop");
12
    RFM12_PORT &= ~(1<<RFM12_SCK);            // CLK auf L
13
  }
14
*data_buf++ = byte;
15
RFM12_PORT |= (1<<RFM12_CS);          // CS auf H

Gruß aus Berlin
Michael

von R. W. (quakeman)


Lesenswert?

Michael U. schrieb:
> Ich vermute mal, Du bist da zu schnell, der Fifo kann nicht so schnell
> gelesen werden wie die Register des RFM.

Ich weiß ja nicht, auf welche Bitrate er mit seinem software SPI kommt. 
Aber ich betreibe den RFM12 per hardware SPI mit 2 Mbps ohne Probleme 
auch beim Auslesen des Empfangsfifo.
Laut Datenblatt kann der Fifo nur mit maximal f(res)/4 getaktet werden, 
was bei 10MHz Quarzfrequenz des RFM12 dann 2,5 Mbps entspricht. Wenn er 
software SPI benutzt muß er natürlich darauf achten, daß die Timings 
eingehalten werden. :)

Ciao,
     Rainer

von Michael U. (amiga)


Lesenswert?

Hallo,

Fox Mulder (quakeman): mache ich in einem anderen Projekt ähnlich, auch 
keine Probleme.

Beim Soft-SPI ist es eigentlich prinzipiell merklich langsamer, aber man 
schafft es schnell, daß 2 Port-Befehle zum setzen/löschen direkt 
hintereinander geraten. Dann ist der effektive Takt zwar durchaus nur 
ein paar 100kHz, der Pegelwechsel beider Signale in dem Moment 
eigentlich 5MHz bei 10MHz AVR-Takr. Da fragt man dann schnell die 
Leitung ab, bevor deren Pegel stabil ist.

In ASM habe ich da keine Probleme, in C darf ich da öfter ins .lss 
schauen, wenn ich nicht nutzloses Sicherheits-Warten betreiben will. ;-)
Sein Bitmuster sieht einfach so aus, als ob er entweder falsch 
reinschiebt oder liest, bevor SDO nach Taktwechsel auf dem neuen Pegel 
ist.

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Moin,

mit dem Timing ist alles i.O., bloss ich hab dummerweise das Verschieben 
der Daten am Anfang der Leseroutine gelegt, ist mir bei dem 
herumgebastle wohl versehentlich passiert.

Aber jetzt zeigt er mir den richtigen Wert am Display an.

Mich wundert nun bloss warum in dem "schönen" Beispiel von HopeRF das 
Statusregister ausgelesen wird, bevor die auf das FIFO beim Empfangen 
eingehen.

MfG
Matthias

von R. W. (quakeman)


Lesenswert?

Na das ist doch sehr schön. Nachdem der Grundstein jetzt gelegt ist 
kannst du ja fröhlich herumexperimentieren mit den RFM12. :)

Ich habe damals als ich mit denen angefangen hatte lieber erst mal 
hardware SPI genommen, da ich möglichst alle Fehlerquellen ausschließen 
wollte zu Beginn. Deshalb lief es bei mir zum Glück auch so ziemlich auf 
Anhieb. Aber da sieht man mal wieder, daß der Teufel im Detail steckt.

Wegen dem Statusregister habe ich nur gelesen, daß es wohl Sinn macht 
das nach dem Reset mindestens einmal auszulesen, da das RFM12 ansonsten 
wohl manchmal etwas herumspinnen könnte. Aber ein generelles auslesen 
hat meiner Meinung nach keinen weiteren Sinn. Was davon überhaupt stimmt 
ist aber fraglich, da davon nichts im Datenblatt drinsteht. ;)

Ciao,
     Rainer

von Matthias S. (lecorde)


Lesenswert?

Ich werd mich nun mit dem Übertragen von Nutzdaten beschäftigen (CRC, 
Zieladressen usw.).

Könnt ihr eure Signale quer durch mehrere Wände (ca. 4) empfangen?

MfG und vielen Dank nochmal für euren Support
Matthias

von Michael U. (amiga)


Lesenswert?

Hallo,

Fox Mulder schrieb:
> Wegen dem Statusregister habe ich nur gelesen, daß es wohl Sinn macht
> das nach dem Reset mindestens einmal auszulesen, da das RFM12 ansonsten
> wohl manchmal etwas herumspinnen könnte. Aber ein generelles auslesen
> hat meiner Meinung nach keinen weiteren Sinn. Was davon überhaupt stimmt
> ist aber fraglich, da davon nichts im Datenblatt drinsteht. ;)

Die Behauptung, das es gut ist als allererste Amtshandlung das 
Statusregister zu lesen, stammt u.a. von mir.
Ich hatte sonst manchmal unberechenbares Verhalten nach PowerOn/Reset.
Sender war scheinbar an, sendete aber nicht, Sender sendete, kam aber 
nichts an usw.

Ich hatte den Status dann beim Start als Debug ausgelesen und die Fehler 
traten promt nie wieder auf... Zur eigentlichen Ursache kann ich also 
nichts sagen.

Auch die Empfehlung, einen Elko ca, 10µ über die BEtriebsspannung der 
RFM-Module zu legen, stammt von meinen Sensoren. Ohne diesen wachten die 
irgendwann nicht mehr aus dem Sleep auf, die Stromaufnahme lag dann 
teilweise bei mehr als 25mA und das fanden meine Batterien nicht lustig.

Da die Sensoren jetzt seit einem Vierteljagr absolut stabil alle Minute 
ihre Daten schicken, scheint es zu helfen.

Matthias S. schrieb:
>Könnt ihr eure Signale quer durch mehrere Wände (ca. 4) empfangen?

Wird stark von den Wänden abhängen...
Mein Sensor im Keller ist ca. 6m entfernt, Altbau, 2 Decken.
Den empfange ich auch stabil komplett ohne Antenne am Empfänger.

Gruß aus Berlin
Michael

von Matthias S. (lecorde)


Lesenswert?

Michael U. schrieb:
> ...
> Auch die Empfehlung, einen Elko ca, 10µ über die BEtriebsspannung der
> RFM-Module zu legen, stammt von meinen Sensoren. Ohne diesen wachten die
> irgendwann nicht mehr aus dem Sleep auf, die Stromaufnahme lag dann
> teilweise bei mehr als 25mA und das fanden meine Batterien nicht lustig.
>
> Da die Sensoren jetzt seit einem Vierteljagr absolut stabil alle Minute
> ihre Daten schicken, scheint es zu helfen.
> ...


Den Kondensator hab ich bei mir auch berücksichtigt, da ich das auch 
hier im Forum gelesen hab.

Ich bin vorhin mit einem Mobilen Funkscanner der mir das 
Frequenzspektrum angezeigt hat durch das FH Gebäude gelaufen und konnte 
nur direkt vor dem Labor ein gedämpfte Signal empfangen. Aber in diesem 
Gebäude sind eh ziemlich dicke Wände und viele Stahlschränke die das 
Signal ordentlich dämpfen.

Ich bin mal gespannt wie das bei mir Zuhaus aussieht.

MfG
Matthias

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.