Forum: Mikrocontroller und Digitale Elektronik RFM12 Statusabfrage


von Sebastian F. (snake080)


Angehängte Dateien:

Lesenswert?

Hi,
ich möchte 2 RFM12 miteinander kommunizieren lassen. Klappt natürlich
bisher nicht. Also Fehlersuche. Die guten Datenblätter/
Beispielprogramme habe ich schon erfolglos durchforstet.
Ich weiss durch ein Funkempfänger dass mein Sender sendet. Sowohl
Trägerfrequenz als auch Daten.
Beim Empfänger kommt nichts an. Also habe ich mir erst mal das Auslesen 
der
Statusbytes vorgenommen... da bekomme ich auch nix.

Ich verwende den Hardware SPI von einem Mega8. für das Status abfragen
einen Software SPI (oder kann man 2x auslesen für die 16Bit?)
Kann mir jemand bitte einen Tipp geben? Danke!

von R. W. (quakeman)


Lesenswert?

Um 16Bit per SPI zu übertragen einfach 2x hintereinander abfragen. Das 
funktioniert problemlos. Du musst nur dadrauf achten, zwischen den 
beiden Übertragungen die nSEL Leitung auf 0 zu belassen.

Ciao,
     Rainer

von Sebastian F. (snake080)


Lesenswert?

Das mit der Statusabfrage habe ich inzwischen hin bekommen. Nun meckert 
der Status vom Empänger ich hätte ein zu starkes Sendesignal (RSSI) Und 
der FIFO ist leer...

von Sebastian F. (snake080)


Angehängte Dateien:

Lesenswert?

So, auch das klappt nun. Nur wird mit immer angezeigt, dass der FIFO 
leer ist. Es kommen also keine Daten an...

von H. G. (ledi)


Lesenswert?

Kann hier bitte jemand posten, wie das Statusregister genau abgefragt 
wird?

Danke!

von Sebastian F. (snake080)


Lesenswert?

Moins,
grundsätzlich indem du 2 x 0x00 sendest und einliest. Per Hardware SPI 
wäre das 0x00 senden -> einlesen. Nochmal 0x00 senden -> einlesen.

Das ist auch nach wie vor das einzige, was ich hinbekommen habe. Mit 
einem Frequenzanalyser sehe ich zwar, dass die Trägerfrequenz da ist und 
auch was sendet aber mein Empfänger empfängt nichts... wie programmierst 
du?

von H. G. (ledi)


Lesenswert?

Mir geht es da derzeit ähnlich. TX scheint zu funktionieren, aber RX 
funzt noch nicht.

Nochmal zum Auslesen des Statusregisters:

1. 0x00 senden --> Commando zum Auslesen des Statusbyte
2. 0x00 senden --> Ausgabe 1. Statusbyte am SDO
3. 0x00 senden --> Ausgabe 2. Statusbyte am SDO

Ist das so korrekt?

von Ziegenpeter (Gast)


Lesenswert?

Ich kenn mich zwar nicht so aus mit Hardware-SPI (mache das "per Hand"), 
aber ich denke du müsstest in der rfm_com_send das SPDR wieder auslesen.

so ungefähr:
1
rfm_com_send:
2
  out  SPDR, YH
3
send_wait_1:
4
  sbis  SPSR, SPIF
5
  rjmp  send_wait_1
6
  in  YH, SPDR ; <======
7
  out  SPDR, YL
8
send_wait_2:
9
  sbis  SPSR, SPIF
10
  rjmp  send_wait_2
11
  in YL, SPDR ; <======
12
ret

von Sebastian F. (snake080)


Angehängte Dateien:

Lesenswert?

Oh, das ist noch die alte .inc (vom Mai). Damit hatte gar nichts 
funktioniert. Ich hatte inzwischen die Default Einstellungen geändert. 
Damit habe ich wenigstens ein DQD beim Receiver bekommen. Wenn auch noch 
keine Daten.
Ich hänge mal meine neue an.

Es ist natürlich wie Ziegenpeter schreibt:

1. 0x00 senden
2. SPDR einlesen (Bit15-Bit8 vom Status)
3. 0x00 senden
4. SPDR einlesen (Bit7-Bit0 vom Status)

von Ziegenpeter (Gast)


Lesenswert?

Ah ok, hab nochmal in die neue Version geguckt.
Du scheinst beim Senden garnicht zu warten bzw. zu überprüfen wie der 
FIFO-Status ist.
Hab meinen Code jetzt nicht zur Hand, aber ich meine da musst du SDO 
abfragen ob 0 (oder umgekehrt), ohne ein komplettes Byte zu lesen.
Normale Register kannst du schreiben ohne zu warten, aber bei Senden (in 
den FIFO schreiben) musst du checken ob er bereit ist ein neues Byte 
aufzunehmen.


Und noch einen Fehler entdeckt:
1
  ldi  YH, 0x2d      ; Sync Hi-Byte
2
  ldi  YL, 0xd4      ; Sync Low-Byte
3
  rcall  rfm_data_send
Das Sync-Word schickst du auch falsch (in YH kommt der Befehl, nicht das 
Daten-Byte).
So muss das:
1
  ldi  YL, 0x2d      ; Sync Hi-Byte
2
  rcall  rfm_data_send
3
  ldi  YL, 0xd4      ; Sync Low-Byte
4
  rcall  rfm_data_send

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich hab gestern den RX Teil des RFM12 im Interrupt hinbekommen. Wie der 
Ziegenpeter schon schrieb, muss man da auf "high" des SDO warten, bevor 
man über "0xB200" die Daten einliest. Die Daten stehen dann im LSB vom 
rückgelesenen Wert von SDI.



Hab dir mal meine vorab RFM12 Routine angehangen. Die ist für einen 
ATtiny2313 geschrieben. Also ohne Hardware SPI. Aber das Prinzip wird 
dadurch hoffentlich klarer.

Gruß Steffen

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Ach ja, hier mal das Auslesen des RX_FIFO

von Steffen H. (avrsteffen)


Lesenswert?

Steffen H. schrieb:
> man über "0xB200" die Daten einliest

Berichtigung: ..man über "0xB000" die Daten einliest.

von Sebastian F. (snake080)


Lesenswert?

Das sind ja mal super Tipps.
Natürlich habe ich meine Testplatinen bei der Arbeit liegen. Also komme 
ich erst Montag dazu das zu testen :(

Nach dem Oszillogramm habe ich aber schon einen Fehler gesehen (Mal 
abgesehen von dem Syncwort - Ist ja irgendwie logisch...
Den /CS habe ich immer runtergezogen, die Übertragung gemacht und dann 
wieder auf HIGH gesetzt. Ich hatte den Eindruck das funktioniert auch?

von Steffen H. (avrsteffen)


Lesenswert?

Sobald du den Empfänger eingeschaltet (0x8280) und den FIFO 
initialisiert (0xCA81)+(0xCA83) hast musst du /CS auf LOW setzen und nun 
auf SDO = high warten.
Ist SDO = high kannst du mit 0xB000 ein Datenbyte aus dem FIFO lesen. 
Die sync-Bytes werden ja normalerweise (nur wenn du es selber so 
wünscht) nicht in den FIFO geschrieben. Du hast also die reinen 
Nutzdaten im FIFO stehen.

Wenn du es mit deiner "rfm_com_send" machst, dann wird ja erst CS auf 
LOW gezogen, dein Datenbyte eingelesen und dann CS wieder auf High 
gesetzt. Soweit alles okay. Wenn deine gesendeten Daten aus mehr als ein 
Byte bestehen musst du ja jetzt weitere Bytes aus dem FIFO lesen, bevor 
du de FIFO wieder resetest. Dazu musst du also nach dem "rfm_com_send" 
den CS wieder auf LOW ziehen und auf SDO = High warten bis du das 
nächste Byte aus dem FIFO lesen kannst.

Zur INFO: FIFO RESET =
FIFO wartet nun wieder auf eintreffende Sync-Bytes bevor er gefüllt 
wird. Alle anderen empfangenen Bytes werden vom FIFO ignorriert.


Ich hoffe ich hab jetzt keinen Fehler gemacht.

Steffen

von H. G. (ledi)


Lesenswert?

Super!!!
Das ist eine tolle Erklärung. Vielen Dank, das hat mir sehr geholfen.

Ich habe noch eine Frage zum nIRQ (PIN 2 am RFM12).

Diesen Pin möchte ich gerne nutzen, um am Mikrocontroller einen ext. 
Interrupt auszulösen.
D.h: wenn Nutzdaten am Empfänger eintreffen, soll der nIRQ einen 
Interrupt auslösen und in der Interrupt-Routine wird das FIFO mit den 
empfangenen Daten ausgelesen.

Weis jemand, welche Einstellungen ich am RFM12 vornehmen muss?

Danke!

von Helfer (Gast)


Lesenswert?

ehtersex hat RF12 support und kann mit dem Modul sowohl im 
polling-Betrieb wie auch Interrupt-gesteuert umgehen. Hab ich allerdings 
nie getestet, vlt. findest du im Source ja Anhaltspunkte, wie das Modul 
konfiguriert werden kann.

https://github.com/ethersex -> ethersex  hardware  radio / rfm12

HTH! :)

von Steffen H. (avrsteffen)


Lesenswert?

Hallo

Ich hab auch gedacht, ich könnt den nIRQ Pin als Interrupt benutzen. 
Allerdings bleibt der bei meinem RFM12 ständig auf LOW! Hab es sogar mit 
Pullup Widerstand (10k gegen VCC) versucht. Aber nichts zu machen. 
Dauer-low.

Ich benutze nun den SDO Pin für den Interrupt!
1. Ich brauche nur 4 Leitungen zum RFM12
2. Der SDO wird HIGH wenn der FIFO gefüllt ist -> Interruppt auf 
steigende Flanke

Das klappt herrvorragend so. Das geht gleichermaßen im RX und im TX 
Modus.
Wenn man den SDO zum Auslösen des Interrupts nimmt, muss man halt nur 
den Interrupt ausschalten nach dem Eintritt in die ISR. Sonst wird ja 
stets und ständig ein neuer Interrupt durch das Auslesen des FIFO's 
erzeugt. Denn da liest man ja denn die Daten über SDO ein.
Dann nur noch darauf achten den Interrupt vor verlassen der ISR wieder 
eizuschalten.

Ach ja, der /CS sollte auf LOW sein während man auf den Interrupt 
wartet.

Schönen 1.Advent
Steffen

von H. G. (ledi)


Lesenswert?

Ich habe eine Frage zum unten stehenden Codeausschnitt:

rf12_trans(0x8238);      // TX on
rf12_ready();

Das verstehe ich: TX einschalten und auf FIFO warten
Danach kommen 5x Datenübertragungen (AA,AA,AA,2D,D4)! Was hat das für 
einen Sinn?
Wenn ich aber diesen Teil entferne, werden aber keine Daten mehr 
übertragen.

Kann mir bitte jemand erklären warum?


In der For-Schleife werden die Daten des Arrays nacheinander gesendet 
bis number erreicht wird.
1
void rf12_ready(void)
2
{  cbi(RF_PORT, CS);
3
  while (!(RF_PIN&(1<<SDO))); // wait until FIFO ready
4
}
5
6
void rf12_txdata(unsigned char data, unsigned char number)
7
{  unsigned char i;
8
  rf12_trans(0x8238);      // TX on
9
  rf12_ready();
10
11
  rf12_trans(0xB8AA);
12
  rf12_ready();
13
  rf12_trans(0xB8AA);
14
  rf12_ready();
15
  rf12_trans(0xB8AA);
16
  rf12_ready();
17
  rf12_trans(0xB82D);
18
  rf12_ready();
19
  rf12_trans(0xB8D4);
20
21
  for (i=0; i<number; i++)
22
  {  rf12_ready();
23
    rf12_trans(0xB800|(data++));
24
  }
25
  rf12_ready();
26
  rf12_trans(0x8208);      // TX off
27
}

von Holger W. (holgerw)


Lesenswert?

Mit den 3 AA werden Empfänger und Sender synchronisiert (immer 01 
Bitwechsel), 2D D4 sagt dem Empänger, jetzt gehts los.

Holger

von H. G. (ledi)


Lesenswert?

Ahaaaaaa!

Steht das auch irgendwo im Datenblatt?

von Holger W. (holgerw)


Lesenswert?

weiss ich jetzt nicht mehr, evtl. auch in dem von SiLabs von denen wohl 
der Chip da ist. Vieles hab ich aus dem Thread von Benedikt 
herausgelesen.
Holger

von Sebastian F. (snake080)


Lesenswert?

Je nachdem welches Datenblatt du hast. Ich empfehle das RF12 
(http://www.hoperf.com/upload/rf/RF12.pdf). Das sind die besten 
Informationenen drin. Das vom RFM12 
(http://www.hoperf.com/upload/rf/RFM12.pdf) ist auch ok.

In den Datenblättern steht unter:
7.FIFO & Reset Mode Command
Das Bit2 (al) der FIFO bei erkannten Sync Bytes gefüllt wird. 
(Empfänger)

Konnte das basteln nicht abwarten und habe mir vorhin meine Tranceiver 
geholt und bearbeite gerade die .incs :-)

von Steffen H. (avrsteffen)


Lesenswert?

Steffen H. schrieb:
> Ich benutze nun den SDO Pin für den Interrupt!
> 1. Ich brauche nur 4 Leitungen zum RFM12
> 2. Der SDO wird HIGH wenn der FIFO gefüllt ist -> Interruppt auf
> steigende Flanke

Wow.. Ganz so einfach war es dann doch nicht. Dieses gilt nur für RFM12 
RX.

Im RFM12 TX Mode ist es ein bisschen anders.

1. Problem:
Nach dem Umschalten des RFM12 in den TX-Modus ist der SDO erst mal auf 
HIGH. Also wird der Interrupt (steigende Flanke) erstmal nicht 
ausgelöst. :-(
2.Problem:
Wenn das letzte Datenbyte an den FIFO übergeben wurde heißt das ja 
nicht, dass es auch schon gesendet wurde. Man kann den RFM12 TX Modus 
also noch nicht werlassen!

Ich hab dafür bis jetzt noch keine anständige Lösung gefunden. Die 
ganzen Codes von Benedikt laufen im polling Betrieb ab.

Ich will aber RX und TX im Interrupt erledigen lassen. Dafür hab ich mir 
ein RF_FLAG Register angelegt wo unter anderem das Flag "rf_ready" und 
"rf_mode" drin ist.

Ich mache es jetzt so:
>>Umschalten von RX -> TX -> und wenn fertig wieder alles aus
1. RFM12_rf_off (0x8208) -> /CS = HIGH
2. 1ms warten
3. Sendebuffer mit Daten zum Senden füllen
4. Pointer auf Sendebuffer initialisieren
5. Sender RFM12_tx_on einschalten (0x8238) -> /CS = HIGH
   Im Flagregister wird das "rf_mode" Flag auf "1" gesetzt
6. nSEL auf Low ziehen (/CS = LOW)
7. mittels rcall Befehl die Interuppt-Routine aufrufen um den FIFO
   erstmalig zu füllen
8. Ab jetzt kann man warten bis das "rf_ready" Flag "1" ist
9. Wenn "rf_ready" Flag "1" ist, dann nach 1ms den Sendemodus 
ausschalten
   -> RFM12_rf_off


Die zwei Punkte 8. und 9. sind noch nicht ganz sauber. Ich hab aber noch 
keine Lösung dafür gefunden wie ich erkenne, dass das letzte Datenbyte 
den RFM12 verlassen hat. Denn vorher darf man ja den RFM Sender nicht 
ausschalten.

Kann mir da jemand helfen? Oder irgendwie auf die Sprünge helfen?

Steffen

von Holger W. (holgerw)


Lesenswert?

Also ich empfange im Interrupt, sende aber ohne.
In der Ini einmal den Status lesen mit 0000 löscht den nIRQ.
Dann schalte ich empfangen ein und die Daten werden per IRQ empfangen.
Zum senden schalte ich den IRQ im PIC aus, sende die Daten, lese den 
Status, schalte dann wieder auf Empfang um und gebe den IRQ im PIC 
wieder frei
Das funktioniert sehr gut bei mir.

Holger

von Sebastian F. (snake080)


Angehängte Dateien:

Lesenswert?

Ich habe mal meine .inc ein wenig geändert. Leider war es nicht meine 
letzte, wo wenigstens das DQD angezeigt wurde. Jetzt habe ich wieder den 
Fehler des zu starken Signals... hat da vll jemand eine Idee?

von Holger W. (holgerw)


Lesenswert?

Zu starkes Signal ? wie denn das ?
Sicher dass das Hardware SPI so funktioniert ? Software SPI ist doch so 
einfach, da weiss man doch ganz genau ob es funktioniert, vielleicht 
stimmen die Einstellungen nicht in der Hardware.
Ich kann nur PIC Assembler und C, mit deinen Sourcen kann ich nicht viel 
anfangen.
Ich habe die Inits von Benedikt übernommen und damit von Anfang an keine 
Probleme gehabt.

Holger

von Sebastian F. (snake080)


Lesenswert?

Das werde ich auch nochmal machen (Die Inits von Benedikt). Und mal den 
Hardware SPI auschalten und nen Software einbauen...

von H. G. (ledi)


Lesenswert?

Kannst du bereits Daten senden und empfangen?
Falls ja, bitte poste deine Sende- und Empfangsroutine!

von Ziegenpeter (Gast)


Lesenswert?

Sebastian F. schrieb:
> rfm12.inc

Das zweite rfm_ready in der rfm_data_send solltest du weglassen.
Wenn er einmal ready ist, dann ist er für die ganzen 16 Bit ready, nicht 
nur für das HI-Byte.

von Holger W. (holgerw)


Lesenswert?

Falls ich gemeint bin, ja, hab aber "nur" C18 Sourcen.
Holger

von Ziegenpeter (Gast)


Lesenswert?

Zum Senden im Interrupt-Modus wollte ich noch schreiben, dass ich es so 
mache (benutze aber die eigentliche IRQ-Leitung nicht die SDO):

Wenn ich mit den eigentlichen Daten fertig bin, schiebe ich noch ein 
"Padding-Byte" in den FIFO.
Wenn der RFM12 bereit ist, noch ein Byte aufzunehmen, schalte ich ab,
weil im FIFO Platz für zwei Byte ist. D.h. wenn ich ein Padding-Byte 
drin hab und noch eins reinschieben dürfte (mach ich aber nicht), sind 
alle Nutzdaten gesendet und ich kann abschalten.

von Steffen H. (avrsteffen)


Lesenswert?

Ziegenpeter schrieb:
> benutze aber die eigentliche IRQ-Leitung nicht die SDO

Das klappt aber nur beim Senden, oder?

von Steffen H. (avrsteffen)


Lesenswert?

Sebastian F. schrieb:
> Ich habe mal meine .inc ein wenig geändert. Leider war es nicht meine
> letzte, wo wenigstens das DQD angezeigt wurde. Jetzt habe ich wieder den
> Fehler des zu starken Signals... hat da vll jemand eine Idee?

Was funktioniert denn jetzt noch nicht richtig?

Hast du einen funktionierenden Sender? Dann kannst du ja erst mal deinen 
RFM12 Receiver zum funktionieren bringen.

Gruß Steffen

von Ziegenpeter (Gast)


Angehängte Dateien:

Lesenswert?

Steffen H. schrieb:
> Das klappt aber nur beim Senden, oder?

Funktioniert beides ohne Probleme.
Ich hab das ganze schon etwas länger am laufen, deshalb kann ich mich 
nicht erinnern ob bzw. welche Probleme ich beim Interrupt hatte. Ich 
glaube keine.
An der Schaltung hab ich auch nichts besonderes (IRQ direkt verbunden, 
10 KOhm gegen VCC am FSK/DATA/nFFS).

Im Interrupt-Handler lese ich den Status und falls das RGIT/FFIT Bit 
gesetzt ist, schreib bzw. lese ich ein Byte in/aus dem FIFO.

Hab mal meinen Interrupt-Handler als Datei angehängt.

von Sebastian F. (snake080)


Lesenswert?

Das Problem bei meiner Initialisierung ist, dass der Empfänger beim 
Status lesen dauernd Das RSSI-Bit setzt. Da ich von Funktechnik nicht 
wirklich Ahnung habe habe ich natürlich beim Empfänger schon 
verschiedenste Varianten im "Receiver Control Command" ausprobiert. Aber 
nie was Sinnvolles hinbekommen. Mit den Datenblatt-Settings & denen von 
Benedikt war es das selbe. Irgendwann hatte ich eine Sender/Empfänger 
Initialisierung, die soweit ok war, dass das RSSI nicht mehr kam. Die 
ist aber irgenwie verschwunden :-( Ich muss zugeben, dass ich dann das 
Projekt auch zur Seite gelegt habe, gerade weil auch keiner in ASM 
wirklich helfen konnte.
Jetzt baue ich gerade ein Software SPI zusammen. Eigentlich fertig, will 
aber noch nicht richtig...
Mir würde schon die rfm Bibliothek von Ziegenpeter helfen, da ich 
gesehen habe, dass er es unter ASM programmiert hat...

von Ziegenpeter (Gast)


Angehängte Dateien:

Lesenswert?

Sebastian F. schrieb:
> Mir würde schon die rfm Bibliothek von Ziegenpeter helfen

Kein Problem, ich glaub die Vorlage dafür hab ich auch aus irgend einem 
Beitrag hier im Forum.

Das Senden und Empfangen der Daten selbst geht nicht über die 
rf12_txData/rf12_rxData, sondern über den Interrupt-Handler, den ich 
oben schon gepostet hab.

Hier noch die Funktionen, mit denen ich das Senden und Empfangen 
anstoße:
1
;//==========
2
initRf12Receiving:
3
4
  clr rRfDataPos
5
  rcall rf12_rxInit
6
  ldi rRfStat, RF_STAT_RXWAIT
7
  rcall rf12_readStatus
8
  sbi EIMSK, INT0 ;// activate INT0
9
  ret
1
;//==========
2
startRf12Transfer:
3
4
  rcall rf12_readStatus
5
6
  ldi r17, 0x82 ;// TX on
7
  ldi r16, 0x38
8
  rcall rf12_trans
9
10
  ldi r17, 0xb8 ;// transmit 0xAA (for syncronization)
11
  ldi r16, 0xaa
12
  rcall rf12_trans ;// don't wait - interrupt when first byte transmitted
13
  
14
  ldi rRfStat, RF_STAT_SENDING
15
  ldi rTmp, RF_TX_PHASE_AA2 ;// next step: 2nd 0xaa byte
16
  sts mRfTxPhase, rTmp
17
  sbi EIMSK, INT0 ;// INT0 activate
18
  ldi rTmp, RF_TIMEOUT
19
  mov rRfTimeout, rTmp ;// timeout handling in timer2 interrupt handler
20
  clr rRfDataPos
21
22
  ;// interrupt handler (externalInt0) will do the rest
23
  ret
1
;//==========
2
.dseg
3
mRfTxPhase:  .byte 1
4
.equ RF_TX_PHASE_AA1 = 0
5
.equ RF_TX_PHASE_AA2 = 1
6
.equ RF_TX_PHASE_AA3 = 2
7
.equ RF_TX_PHASE_SYNC1 = 3
8
.equ RF_TX_PHASE_SYNC2 = 4
9
.equ RF_TX_PHASE_LEN = 5
10
.equ RF_TX_PHASE_DATA = 6
11
.equ RF_TX_PHASE_FLUSH1 = 7
12
.equ RF_TX_PHASE_END = 8

von H. G. (ledi)


Lesenswert?

Hat jemand den Interrupt Handler von Ziegenpeter in C?

von Christoph H. (christoph_b)


Lesenswert?

wäre auch an einem Interrupt Handler in C interessiert

von Steffen H. (avrsteffen)


Lesenswert?

Hallo

Ich hab es immer noch nicht hinbekommen mit dem nIRQ als Interuppt. Der 
ist ständig auf LOW!

Wie ist denn der Zustand des nSEL (/CS) Eingangs nach der 
Initialisierung? Ich setze ihn ja dann auf LOW (aktiv) um mit Interuppt 
zu arbeiten.


Steffen

von Ziegenpeter (Gast)


Lesenswert?

Steffen H. schrieb:
> Ich setze ihn ja dann auf LOW (aktiv) um mit Interuppt
> zu arbeiten.

Wie du oben in der initRf12Receiving siehst, ist das letzte vor dem 
Aktivieren des Interrupt ein readStatus.
Demnach ist der nSel/CS während der Interrupt-Phase auf HIGH gesetzt.

Wenn's nicht das ist - hast du auch den rigtigen nIRQ angeschlossen? Der 
ist direkt neben dem SDO.
Könnte mir vorstellen, dass man den INT und IRQ verwechseln könnte.

von Holger H. (onifred)


Angehängte Dateien:

Lesenswert?

Christoph B. schrieb:
> wäre auch an einem Interrupt Handler in C interessiert

Hallo,
Habe letztes Jahr mit den Modulen experimentiert.
Habe 2x Pollin RFM Boards mit Mega8 benutzt.
Nachdem es funktionierte, habe ich mich gleich wieder etwas anderem 
gewidmet. Also noch nicht längere Zeit getestet.
Sind auch Infos aus diesem Forum eingeflossen.
Kommentare sind auch wohl etwas spärlich.
Werde nächstes Jahr eine Heizungssteuerung damit bauen.

Gruß onifred

von Steffen H. (avrsteffen)


Lesenswert?

Ziegenpeter schrieb:
> Demnach ist der nSel/CS während der Interrupt-Phase auf HIGH gesetzt

Aha, das mach ich ja nicht so. Werd ich aber mal noch ausprobieren. 
Vielleicht liegt es wirklich an dem /CS.

>Wenn's nicht das ist - hast du auch den rigtigen nIRQ angeschlossen? Der
>ist direkt neben dem SDO.

Ja, ich hab es mit dem richtigen nIRQ versucht. Beim RFM02 ist das alles 
ein wenig anders. Deswegen dachte ich mir, ich probier das beim RFM12 
auch mal so.

Denn beim RFM12 kann man beim Senden den SDO Pin überwachen oder für den 
Interuppt mißbrauchen. Der wird nach dem Füllen des Sende FIFOs solange 
auf "LOW" gehalten, bis der FIFO wieder leer ist. Dann geht der SDO 
wieder auf "HIGH". Dadurch hab ich mir halt den zusätzlichen nIRQ 
gespart. Und ich muss auch nicht den Status auslesen.

Aber trotzalledem werd ich das mit dem nIRQ mal noch ausprobieren.

Danke Ziegenpeter
(auch ein verrückter Name :-))

von Holger W. (holgerw)


Angehängte Dateien:

Lesenswert?

Hallo,
im Anhang mal meine RFM12.c, zugeschnitten auf einen PIC 18F für C18 
Compiler.
Senden erfolgt direkt, Empfangen im Interrupt.
Vielleicht kann jemand zumindest Anregungen entnehmen.
Es basiert größtenteils auf dem Code von Benedikt.
Damit laufen bei mir 3 Geräte:
Temperaturfühler aussen, Temperaturfühler /-regler innen, RFM12-USB 
Stick am PC mit Datenaustausch / Auswertung
seit einigen Wochen problemlos.

Holger

von H. G. (ledi)


Lesenswert?

Holger W. schrieb:
> Hallo,
> im Anhang mal meine RFM12.c, zugeschnitten auf einen PIC 18F für C18
> Compiler.
> Senden erfolgt direkt, Empfangen im Interrupt.
> Vielleicht kann jemand zumindest Anregungen entnehmen.

Dein Code gefällt mir sehr gut, da ordentlich dokumentiert!!!
Ich werde ihn auf AVR mit SPI-Schnittstelle umschreiben und wenn alles 
funktioniert hier posten.

von Sebastian F. (snake080)


Lesenswert?

Juhuu, bei mir funkt es jetzt auch. Ich hatte zwar nicht so wirklich 
Erfolg mit dem Software SPI (liegt aber daran, dass ich hier kein 
Digitales Oszi habe). Aber mit Hardware konnte ich endlich ein Byte 
übertragen. Jetzt kommt natürlich die Anpassung, dass alles vernünftig 
läuft.
Das Problem war das nSel, welches ich immer nach den Befehlen wieder auf 
High gesetzt habe.
Danke an alle unterstützenden! Wenn die Bibliothek fertig ist werde ich 
sie natürlich posten.

von H. G. (ledi)


Lesenswert?

Gratuliere!
Bitte poste deinen Code!

von Steffen H. (avrsteffen)


Lesenswert?

Hallo

Jetzt versteh ich gar nix mehr. Verhält sich denn jeder RFM12 anders???

Sebastian F. schrieb:
> Das Problem war das nSel, welches ich immer nach den Befehlen wieder auf
> High gesetzt habe.

Ziegenpeter schrieb im Beitrag #2437188
> Demnach ist der nSel/CS während der Interrupt-Phase auf HIGH gesetzt.


Demnach funktioniert es bei Ziegenpeter mit nSEL=1 und bei Sebastian mit 
nSEL=0.
In anderen Beiträgen hab ich auch schon mal gelesen:
> Alles funktionierte schon mal einwandfrei, aber seit neulich will nichts
> mehr so funktionieren..

Schon etwas komisch, oder?



Gruß Steffen.

von H. G. (ledi)


Lesenswert?

Hallo,

so wie ich das sehe, herrscht hier das allgemeine Problem, dass man (ich 
auch nicht) eigentlich nicht so genau weiss, welche Schritte im 
einzelnen durchzuführen sind, um ein Byte vom Sender an den Empfänger zu 
senden.

Das Ding dann richtig zu programmieren, ob in C, Assembler oder... ist 
denke ich nicht das Problem.

Und ein geposteter Code, mit vielen Funktionen, Macros etc. kann auch 
schnell noch mehr Verwirrung stiften.

Daher bitte ich jemanden, einen Beitrag zu schreiben, wo die einzelnen 
Schritte die durchzuführen sind erklärt werden.

z.B:
Senden eines Bytes:

1.) nSEL auf Low
2.) Sender mit 0x8238 einschalten
3.) Bit xy im Register xy löschen
4.) Synchronisieren (3 mal AA senden)
5.) Startbedingung senden (2D und D4)

.....usw.

von Sebastian F. (snake080)


Lesenswert?

Stimmt schon, das ist alles ein wenig verwirrend. Bei mir ist es auf 
jeden Fall so, dass der nSEL vom Empfänger auf Low sein muss. Dann 
bekomme ich das SDO->High wenn er was empfangen hat.
Wenn ich alles vernünftig am laufen habe versuche ich mal eine 
Reihenfolge zu schreiben. Jetzt ist es ja mehr was zusammengewürfeltes, 
um überhaupt was hinzubekommen. :-)

von Steffen H. (avrsteffen)


Lesenswert?

Sebastian F. schrieb:
> Stimmt schon, das ist alles ein wenig verwirrend. Bei mir ist es auf
> jeden Fall so, dass der nSEL vom Empfänger auf Low sein muss. Dann
> bekomme ich das SDO->High wenn er was empfangen hat.
> Wenn ich alles vernünftig am laufen habe versuche ich mal eine
> Reihenfolge zu schreiben. Jetzt ist es ja mehr was zusammengewürfeltes,
> um überhaupt was hinzubekommen. :-)

Wie wäre es mit einem Wiki Eintrag. Ich würde dann auch mithelfen. 
Allerdings streube ich mich moch vor dem Neuanlegen.

von Sebastian F. (snake080)


Angehängte Dateien:

Lesenswert?

So, jetzt habe ich was, wo man drauf aufbauen kann.
Allerdings gibt es ein kleines Problem: Wenn ich 5 Byte sende, kommt das 
erste richtig an. Alle folgenden sind um 1 Bit verschoben!? Kennt dieses 
Phänomen jemand?

von Holger W. (holgerw)


Lesenswert?

nie gehabt. Stimmt dein SPI ?
Holger

von Sebastian F. (snake080)


Angehängte Dateien:

Lesenswert?

Wenn er nicht stimmen würde, wäre doch das erste Byte auch falsch, oder?
Achso, die .inc Datei hatte ich gerade vergessen.

von Holger W. (holgerw)


Lesenswert?

irgendwie ist mir das zu unübersichtlich und schlecht dokumentiert.
Wieso machst du verschiedene inits für senden und empfangen ?
Mir fällt das auf
  sbi  SPI,  nSEL    ; Chip select auf 1
  nop
  nop
  cbi  SPI,  nSEL    ; Chip select auf 0

der erste schaltet CS aus, der zweite ein, einschalten sollte doch am 
Anfang und ausschalten am Ende der Routine sein ?
Hab es jetzt aber nur eben mal überflogen.
Prinzipiell geht es ja, du empfängst ja was.

Holger

von H. G. (ledi)


Lesenswert?

Sebastian F. schrieb:
> So, jetzt habe ich was, wo man drauf aufbauen kann.
> Allerdings gibt es ein kleines Problem: Wenn ich 5 Byte sende, kommt das
> erste richtig an. Alle folgenden sind um 1 Bit verschoben!? Kennt dieses
> Phänomen jemand?

Versuch mal ein Byte (z.B. 0xA1) einzeln zu senden und das ein paar mal 
hintereinander!

Was passiert dann?

von Steffen H. (avrsteffen)


Lesenswert?

Ziegenpeter schrieb:
> Wenn ich mit den eigentlichen Daten fertig bin, schiebe ich noch ein
> "Padding-Byte" in den FIFO.
> Wenn der RFM12 bereit ist, noch ein Byte aufzunehmen, schalte ich ab,
> weil im FIFO Platz für zwei Byte ist. D.h. wenn ich ein Padding-Byte
> drin hab und noch eins reinschieben dürfte (mach ich aber nicht), sind
> alle Nutzdaten gesendet und ich kann abschalten.

Super. So hab ich es jetzt auch gemacht. Und siehe da: Es geht 
problemlos. Ganz ohne warten oder irrgendwelche delays.

Danke Ziegenpeter

Gruß Steffen

von H. G. (ledi)


Lesenswert?

Hallo Steffen!

poste bitte mal deinen Code!

von H. G. (ledi)


Lesenswert?

Hallo Leute!

Bitte um Eure Hilfe!
Ich verwende das RFM12B (868 MHz) und möchte ein Byte von Tx auf Rx 
übertragen.
Auf der Rx-Seite soll das empfangene Byte am PORTC mit LEDs angezeigt 
werden.

Ich sende von Tx alle 1000ms das Byte 0x05 und es passiert nichts.

Ich poste hier mal meine Tx Routine, vielleicht sieht jemand einen 
Fehler!

Danke!
1
// main.c
2
3
#define F_CPU 8000000UL
4
#include <util/delay.h>
5
6
void send(void);
7
8
int main(void)
9
{
10
  rf12_init();          // RFM12 initialisieren
11
12
13
  while(1)
14
  {
15
    send();            // Alle 1 Sek. Daten senden
16
    _delay_ms(1000);
17
  }
18
}
19
20
21
void send(void)
22
{  
23
  rf12_txdata(0x05);        // Sende Datenbyte 0x05
24
}
25
26
27
28
29
// rf12.c
30
31
#define F_CPU 8000000UL
32
#include <util/delay.h>
33
34
#define RF_PORT  PORTA
35
#define RF_DDR  DDRA
36
#define RF_PIN  PINB
37
38
#define SDI    6
39
#define SCK    5
40
#define CS    4
41
#define SDO    1
42
43
unsigned short rf12_trans(unsigned short wert)
44
{  
45
  unsigned short werti = 0;
46
  unsigned char i;
47
48
  cbi(RF_PORT, CS);
49
  for (i=0; i<16; i++)
50
  {  if (wert&32768)
51
      sbi(RF_PORT, SDI);
52
    else
53
      cbi(RF_PORT, SDI);
54
    werti<<=1;
55
56
    if (RF_PIN&(1<<SDO))
57
      werti|=1;
58
    sbi(RF_PORT, SCK);
59
    wert<<=1;
60
    _delay_us(0.3);
61
    cbi(RF_PORT, SCK);
62
  }
63
  sbi(RF_PORT, CS);
64
  return werti;
65
}
66
67
void rf12_init(void)
68
{
69
  RF_DDR  =(1<<SDI)|(1<<SCK)|(1<<CS);
70
  RF_PORT  =(1<<CS);
71
72
  _delay_ms(200);        // wait until POR done
73
74
  rf12_trans(0x80E7);      // Enable FIFO, 868MHZ, 12pF
75
  rf12_trans(0x82D9);      // er, ebb, es, ex, dc
76
  rf12_trans(0xA67C);      // Set Frequency 868,3MHz
77
  rf12_trans(0xC647);      // 2400 Baud
78
  rf12_trans(0x94A0);      // VDI out, fast response, Bandbreite 134kHz
79
  rf12_trans(0xC2AC);      // CR auto mode, slow mode, digital filter
80
  rf12_trans(0xCA81);      // FIFO generates IT @ 8 bit received data bits, no sensitive reset
81
  rf12_trans(0xC483);      // AFC a1, oe, en
82
  rf12_trans(0x9852);      // Tx configuration, FSK modulation parameters, output power -5dB
83
  rf12_trans(0xE000);      // disable wakeup timer
84
  rf12_trans(0xC800);      // disable low duty cycle mode
85
  rf12_trans(0xC000);      // battery detector and MCU clock divider
86
}
87
88
89
90
void rf12_ready(void)
91
{  cbi(RF_PORT, CS);
92
  while (!(RF_PIN&(1<<SDO))); // wait until FIFO ready
93
}
94
95
void rf12_txdata(unsigned char data)
96
{  
97
  rf12_trans(0x8238);      // TX on
98
  rf12_ready();
99
100
  rf12_trans(0xB8AA);      // Synchronisation 3x AA senden 
101
  rf12_ready();        // damit sich der Empfänger 
102
  rf12_trans(0xB8AA);      // auf den Bitstrom synchronisieren kann
103
  rf12_ready();
104
  rf12_trans(0xB8AA);
105
  rf12_ready();
106
  rf12_trans(0xB82D);      // Datenschlüssel 2D und 4D senden, damit der Empfänger erkennt,
107
  rf12_ready();        // wo die Nutzdaten beginnen
108
  rf12_trans(0xB8D4);
109
  rf12_ready();
110
111
  rf12_trans(0xB800 | data);  // Sende Daten
112
  rf12_ready();
113
114
  rf12_trans(0xB8AA);      // Sende 2x Dummybyte AA, damit der Sender
115
  rf12_ready();        // nicht zu früh abgeschaltet wird
116
  rf12_trans(0xB8AA);
117
  rf12_ready();
118
  
119
  rf12_trans(0x8208);      // TX off
120
}

von H. G. (ledi)


Lesenswert?

Hab den Fehler bereits gefunden! :-)

Die Tx-Routine ist korrekt. Der Fehler lag in meiner Rx-Routine!

von Steffen H. (avrsteffen)


Lesenswert?

H. G. schrieb:
> Hallo Steffen!
>
> poste bitte mal deinen Code!

Hallo H. G.

Das wird dir leider nicht sehr viel weiter helfen. Denn ich code in ASM. 
Auch dem Sebastian hilft es nicht viel weiter, da ich ein eigenes 
Protokoll zur Datenübertragung verwende.
Das Protokoll hab ich mir selber ausgedacht und beinhaltet eine 
SLAVE-Adresse wegen der Multimasterfunktionalität und einen CRC wegen 
der Datensicherheit. Dazu kommt noch ein Start- und Endebyte.
Außer Start- und Endebyte wird alles im ASCII Code übertragen, da ich 
auch Propleme mit Bytes größer 0x7F hatte.
Das 1.Byte hatte ich noch korrekt empfangen und dann ging es los wie bei 
Sebastian.

Um dem ganzen aus dem Weg zu gehen sende ich jetzt nur noch 
ASCII-Zeichen (0x20..0x7F) oder Steuerzeichen (0x01..0x1F).

Außerdem bin ich durch das EndeByte (EOT = EndOfTransmission = 0x04) 
nicht an eine bestimmte Datenlänge gebunden wie in den meisten 
Beispielen hier.

Wenn es auch für euch interessannt ist, dann werd ich den Code posten 
sobald er multifunktional ist.

zum Protokoll:

01. Byte : 0x01 = SOT = Start of Transmission
02. Byte : SLAVE Adresse BCD1 (ASCII)
03. Byte : SLAVE Adresse BCD0 (ASCII)
04. Byte : 0x0A = LF = LineFeed
05. Byte : Data als Steuerzeichen oder ASCII \
06. Byte : Data als Steuerzeichen oder ASCII  > DataPaket (variabele 
Länge)
07. Byte : 0x0A = LF = LineFeed              /  -> Paketende
..   ..       ..
..   ..       ..
xx. Byte : Data als Steuerzeichen oder ASCII\
xx. Byte : Data als Steuerzeichen oder ASCII \
xx. Byte : Data als Steuerzeichen oder ASCII  > DataPaket (variabele 
Länge)
xx. Byte : Data als Steuerzeichen oder ASCII /
xx. Byte : 0x0A = LF = LineFeed             /   -> Paketende

xx+1. Byte : CRC BCD1 (ASCII) CRC= eor über alle Datenbytes + SLAVE 
Adresse
xx+2. Byte : CRC BCD0 (ASCII)      + LF wie sie gesendet werden (ASCII)
xx+3. Byte : 0x04 = EOT = End of Transmission

Dies funktioniert bereits ohne Probleme. Habe gestern auch meinen RFID 
Reader im Funksystem erfolgreich eingebunden.


Gruß Steffen

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Und hier mal das Protokoll auf HTerm.

von Sebastian F. (snake080)


Lesenswert?

Hi Steffen,
ich bin zwar immer noch dabei Einstellungen zu testen, woran das liegen 
könnte aber die Idee einfach auf ein Bit zu verzichten und den ASCII 
Code zu nehmen ist schon genial.

von Duplex (Gast)


Lesenswert?

@H.G. Ledi,

Das kann nicht funktionieren, da die RFM nur im halpduplex arbeiten !

Entweder senden oder empfangen.

Du benötigst also zeitgleich einen Sender und einen Empfänger, also 2 
Module !

von H. G. (ledi)


Lesenswert?

> @Duplex:
>
> Das kann nicht funktionieren, da die RFM nur im halpduplex arbeiten !
>
> Entweder senden oder empfangen.
>
> Du benötigst also zeitgleich einen Sender und einen Empfänger, also 2
> Module !

Ja, das ist schon klar.
Ich habe auch 2 Module. Senden und Empfangen funktioniert auch bereits.

von Steffen H. (avrsteffen)


Lesenswert?

Hallo

Na, schon lange kein Eintrag mehr hier zu finden. Scheinbar hat 
Sebastian sein RFM12 bendigen können oder er ist schon verzweifelt.

Ich jedenfalls habe nun endlich auch ein RFID-Funk-Modul zum laufen 
gebracht. Bilder und Code gibt es demnächst.

Wie ist der Stand der Dinge bei dir Sebastian?


Gruß Steffen

von Sebastian F. (snake080)


Lesenswert?

Hi, ich bin teilweise am Verzweifeln...
Ich wollte zuerst das mit das mit den 7Bit-ASCII probieren. Dabei hatte 
ich dann bei 16Byte irgendwo wieder ein Byte, welches komplett 
übertragen wurde, warum auch immer...
Da ich keine hohen Geschwindikeiten brauche baue ich gerade eine 
Ein-Byte Übertragung zusammen, wo dann der Empfänger das übertragene 
zurücksenden soll und der Sender dann ein OK oder die Daten noch einmal 
senden soll. Lustigerweise sollte es funktionieren, allerdings springt 
der Sender nach dem lesen nicht zurück, sondern irgendwohin ins Nirvana 
- und der µC wird resettet. Das ist auch in der Simulation so. Bin aber 
zwischen den ganzen Weihnachtsfeiern dran :-)

von Holger W. (holgerw)


Lesenswert?

Das mit den 7 Bit ist Blödsinn, auch wenn es erstmal so scheint dass es 
funktioniert. Das Problem muss an anderer Stelle stecken.
Mit den Beispielen von Benedikt hatte ich recht schnell Erfolge und 
meine Routinen (siehe oben) beruhen größtenteils immer noch darauf.
Ich übertrage ca. 20 Bytes mit 4800 Baud und alle 8 Bit breit, z.b. 
negative Temperaturen letzte Nacht.

Holger

von Steffen H. (avrsteffen)


Lesenswert?

Hallo

Steffen H. schrieb:
>Ich jedenfalls habe nun endlich auch ein RFID-Funk-Modul zum laufen
>gebracht. Bilder und Code gibt es demnächst.

Hier nun auch die Sourcen und ein paar Bilder vom RFID-Funk-Modul.
Beitrag "RFID-RFM12-Funkmodul"


Holger W. schrieb:
>Das mit den 7 Bit ist Blödsinn, auch wenn es erstmal so scheint dass es
>funktioniert. Das Problem muss an anderer Stelle stecken.

Ich hab es mit vollen 8bit ehrlich gesagt garnicht nochmal probiert. 
Aber vieles über ASCII zu senden sehe ich trotz allledem als Vorteil. Es 
werden zwar dadurch größere Pakete übertragen, aber dafür kann man 
Steuerzeichen für Start- und End of Transmission oder anderweilig 
versenden. Außerdem hat man die "0" als Strigende zur Verfühgung.

Sebastian F. schrieb:
>Ich wollte zuerst das mit das mit den 7Bit-ASCII probieren. Dabei hatte
>ich dann bei 16Byte irgendwo wieder ein Byte, welches komplett
>übertragen wurde, warum auch immer...

Das kommt mir jetzt aber wirklich komisch vor. Willst du eine feste 
Byteanzahl übertragen?


Gruß Steffen

von Holger W. (holgerw)


Lesenswert?

Steuer- oder Endezeichen oder sowas brauche ich nicht.
Im ersten Byte kommt die Anzahl, danach Steuerbytes und die Nutzdaten, 
danach 2 Prüfbytes. Die Anzahl wird auf Maximum geprüft und danach die 
Anzahl der Daten gelesen, gegen die Prüfsumme verifiziert.
ASCII senden hat den Vorteil, dass man sich nicht um genügend 
Flankenwechsel sorgen muß, das kommt aber bei mir nicht vor.

Holger

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.