mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RFM12 868MHz


Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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. :)

// RFM12 initialisieren
// Grundfrequenz = 434,00MHz
// Eine 1 wird mit positivem Hub gesendet (bei mp=0, FSK=1) -> Tx-Freq = 434,00MHz + 45kHz =434,045MHz
// Eine 0 wird mit negativem Hub gesendet (bei mp=0, FSK=1) -> Tx-Freq = 434,00MHz - 45kHz =433,955MHz
void init_rfm12() {
  v_Write_rfm12(0x0000);  // Status auslesen da die Module ansonsten manchmal etwas spinnen
  v_Write_rfm12(0x80D7);  // el , ef , 11.5pf, 433 MHz band
  v_Write_rfm12(0x82C9);  // er , ebb , !et , !es , ex , !eb , !ew , dc
  
  // Frequenz einstellen
  set_freq_rfm12(434000);  // 434,00 MHz / 868,00 MHz

  v_Write_rfm12(0xC647);  // 4.8kbps
  v_Write_rfm12(0x94C4);  // Vdi , Fast , 67 kHz Bandbreite, 0db , -79dbm
  v_Write_rfm12(0xC2AC);  // al , !ml , Dig , Dqd4
  v_Write_rfm12(0xCA81);  // Fifo8 , Sync , !ff , dr
  v_Write_rfm12(0xC493);  // @pwr , +15/-16 f(res) , !st , !fi , oe , en
  v_Write_rfm12(0x9827);  // 45 kHz Frequenzhub, tx-power -21 dB, !mp
  v_Write_rfm12(0xE000);
  v_Write_rfm12(0xC800);
  v_Write_rfm12(0xC000);  // 1 MHz , 2.2V
}

// Einen 16Bit Wert senden
void v_Write_rfm12(unsigned int uiDaten) {
  // Slave aktivieren
  NSEL = 0;
  
  // Erstes Datenbyte senden
  SPDAT = uiDaten >> 8;
  
  // Warten bis Byte gesendet
  while ((SPSTAT & 0x80) == 0);
  // Flags zurücksetzen
  SPSTAT = 0xFF;

  // Zweites Daten Byte senden
  SPDAT = uiDaten & 0xFF;
  
  // Warten bis Byte gesendet
  while ((SPSTAT & 0x80) == 0);
  // Flags zurücksetzen
  SPSTAT = 0xFF;

  NSEL = 1;
}

// Einen 16Bit Wert senden und gleichzeitig 16 Bit empfangen
unsigned int ui_RW_rfm12(unsigned int uiDaten) {
  unsigned int temp;

  // Slave aktivieren
  NSEL = 0;
  
  // Erstes Datenbyte senden
  SPDAT = uiDaten >> 8;
  
  // Warten bis Byte gesendet
  while ((SPSTAT & 0x80) == 0);
  // empfangenes High-Byte laden
  temp = SPDAT;

  // Flags zurücksetzen
  SPSTAT = 0xFF;

  // Zweites Daten Byte senden
  SPDAT = uiDaten & 0xFF;

  // High-Byte an richtige Position bringen
  temp = temp * 256;
  
  // Warten bis Byte gesendet
  while ((SPSTAT & 0x80) == 0);
  // empfangenes Low-Byte laden
  temp += SPDAT;

  // Flags zurücksetzen
  SPSTAT = 0xFF;

  NSEL = 1;
  
  return temp;
}

// Warten bis RFM12 bereit
void wait_rfm12() {
  NSEL = 0;              // SPI Slave aktivieren
  while (SDO == 0);      // Warten bis SDO = 1
}

// Grundfrequenz des Moduls einstellen
// Frequenz in 5kHz Schritten einstellbar. Frequenz in kHz angeben
void set_freq_rfm12(unsigned long ulFreq) {
  unsigned int temp;

  if (ulFreq < 800000)
    temp = (int) ((2*ulFreq - 860000) / 5);
  else
    temp = (int) ((ulFreq - 860000) / 5);

  // Wert für Register berechnen und prüfen ob im gültigen Bereich
  if (temp < 96)
    temp = 96;
  else if (temp > 3903)
    temp = 3903;
  
  // Wert in passendes Register schreiben
  temp += 0xA000;
  v_Write_rfm12(temp);
}

// Vor jeder Übertragung von zu sendenden Daten an das Modul muss auf SDO=1 
// gewartet werden um sicherzustellen, daß die vorherige Übertragung
// abgeschlossen ist.
// Die zu senden Daten werden mit dem Befehl 0xB800 kombiniert und über SPI
// übertragen, soll z.B. das Nutzdaten-Byte 0x35 gesendet werden, so wird an das
// Modul 0xB835 über SPI übertragen, sobald SDO=1 ist.
void v_Send_rfm12(unsigned char ucPaketLaenge, unsigned char data * data pucTX_Daten) {
  unsigned char i, temp;

  v_Write_rfm12(0x8239);  // Power Management Command: er=0, ebb=0, et=1, es=1, ex=1, eb=0, ew=0, dc=1

  // Preambel senden
  wait_rfm12();
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
  wait_rfm12();
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
  wait_rfm12();
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
  
  // Synchronisationsmuster senden
  wait_rfm12();
  v_Write_rfm12(0xB82D);  // HI Byte für Frame-Erkennung an Modul übertragen
  wait_rfm12();
  v_Write_rfm12(0xB8D4);  // LOW Byte für Frame-Erkennung an Modul übertragen
  
  // Daten senden
  for (i = 0; i < ucPaketLaenge; i++) {
    wait_rfm12();
    temp = *(pucTX_Daten + i);
    v_Write_rfm12(0xB800 + temp);  // Eigentliche Nutzdaten
  }
  
  // Zwei Dummybytes senden, damit der Sender nicht zu früh aufhört am Ende der Nutzdaten
  // Auf Empfängerseite müssen diese beiden Bytes dann rausgefiltert werden
  wait_rfm12();
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA
  wait_rfm12();
  v_Write_rfm12(0xB8AA);  // TX Data = 10101010 = 0xAA

  wait_rfm12();
  v_Write_rfm12(0x8209);  // Power Management Command: er=0, ebb=0, et=0, es=0, ex=1, eb=0, ew=0, dc=1
}

// n Datenbytes empfangen
void v_Receive_rfm12(unsigned char ucPaketlaenge, unsigned char data * data pucRX_Daten) {
  unsigned int uiTemp;
  unsigned char i;
  
  v_Write_rfm12(0x82C9);  // Power Management Command: er=1, ebb=1, et=0, es=0, ex=1, eb=0, ew=0, dc=1
  v_Write_rfm12(0xCA83);  // FIFO and Reset Mode Command: FIFO Level=8, al=0, ff=1, dr=1


  // 0xB000 an RFM12 senden und zweites Byte gleichzeitig empfangen
  for (i = 0; i < ucPaketlaenge; i++) {
    NSEL = 0;
    while(SDO == 0);
    uiTemp = ui_RW_rfm12(0xB000);
    *(pucRX_Daten + i) = uiTemp & 0xFF;
  }

  v_Write_rfm12(0x8209);  // Power Management Command: er=0, ebb=0, et=0, es=0, ex=1, eb=0, ew=0, dc=1
}

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

Ciao,
     Rainer

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

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

MfG
Matthias

Autor: Matthias S. (lecorde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu dem Prgramm:

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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wär nett, ich versuch das von dir mal so einzuprogrammieren.

MfG
Matthias

Autor: Matthias S. (lecorde)
Datum:

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

Autor: Matthias S. (lecorde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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)

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael U. (amiga)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ja, ist in weiten Grenzen egal.
RFM12_send_cmd(0x0000);  // Status read
RFM12_send_cmd(0xC080);  // CLK-Frequenz / Batterie-Level
RFM12_send_cmd(0x80D7);  // FIFO ein, C = 11,5pF
RFM12_send_cmd(0xC2AB);  // Thresold, Filter
RFM12_send_cmd(0xCA81);  // FIFO-Level, 
RFM12_send_cmd(0xE000);  // WakeUp aus 
RFM12_send_cmd(0xC800);  // Low Duty Cycle aus, 
RFM12_send_cmd(0xC4F3);  // AFC
RFM12_send_cmd(0xA620);  // Frequenz
RFM12_send_cmd(0x948C);  // Bandbreite
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:
rfm02_send_cmd(0xCC00);   // Status read
rfm02_send_cmd(0xC0E0);   // Power Settings: Quarz ein, Synthesizer und PA ein bei Send-Command
rfm02_send_cmd(0xC2A0);   // low bat detector, TX Bit Sync, WakUp-Timer Calibrierung aus
rfm02_send_cmd(0x8883);   // Control: 1MHz Clock Out, 12,5pF Last Quarz, 120kHz Shift
rfm02_send_cmd(0xA620);   // Frequenz: 430MHz + (0,0025 * 0x620) -> 433,92MHz
rfm02_send_cmd(0xB200);   // Power 2 * -3dBm -> -6dBm
rfm02_send_cmd(0xD2C0);   // Set PLL: set 33%
rfm02_send_cmd(0xC810);   // Baudrate: 344827 / 19200 = 17 - 1 -> 0x10 

Gruß aus Berlin
Michael

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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
for (j=0; j<8; j++)
  {     
    byte = (byte << 1);                                  // eins höher schieben
    if ((RFM12_PIN & (1<<RFM12_SDO)) == (1<<RFM12_SDO))  // Bit 1?
      {
        byte = (byte | 0x01);        // ja
      }
    asm("nop");
    RFM12_PORT |= (1<<RFM12_SCK);            // CLK auf H
    asm("nop");
    asm("nop");
    RFM12_PORT &= ~(1<<RFM12_SCK);            // CLK auf L
  }
*data_buf++ = byte;
RFM12_PORT |= (1<<RFM12_CS);          // CS auf H

Gruß aus Berlin
Michael

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.