RFM12B-Ersatz

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • RFM12B-Ersatz

      Hallo zusammen
      Ich bin dabei meinen Universalsender hier mit dem RFM69CW zu verheiraten. Die Leiterplatte ist dafür vorgesehen. Mittlerweile habe ich das Modul zum Senden gebracht und der Empfang scheint hier auch zu funktionieren. Letzte Woche bei mir zuhause bekam ich vorwiegend Datenschrott mit eingebetteten korrekten Datentelegrammen. Geändert habe ich eigentlich nichts.
      Nun habe ich festgestellt dass sich das Ganze ab und zu aufhängt und ich muss dann die Speisung neu anlegen. Frage: ist beim RFM69 der Reseteingang notwendig und sollte er mit einem uP-Ausgang verbunden werden? Dies würde eine Überarbeitung der Leiterplatte bedingen.
      Weiter habe ich einen komischen Effekt: Wenn ich den uP programmiere und ein RFM69 ist auf der Leiterplatte so funktioniert die Kombination vorerst nicht. Ich muss dann den uP ein zweites Mal programmieren und dann funktioniert es. Hat hier jemand eine Idee wo das Problem liegen könnte?
      Tipps sind willkommen :)
    • Sein Reset sollte schon angeschlossen sein, mindestens jedoch ein Pullup an seinem Chip Select (Pin B.2)
      Sonst ist er beim Flashen aktiv und bekommt ein Haufen Daten mit dehnen er so gar nichts anfangen kann. Hier und da versucht irgendwas zu antworten. Das dann den Flashvorgang sabotiert. Erstaunlich das es beim zweiten mal funktioniert. Vermutlich ist er dann so konfus das er erstmal gar nichts mehr sagt.

      Im normalem Betrieb ist ein Reset eher eine Notlösung. Da muß ein Problem vorliegen das damit nur kaschiert würde. Stromversorgung,Wackelkontakt, Störungen? Das sollte die Software abfangen können?
    • In der Zwischenzeit habe ich den RFM12B als Empfänger auf der Testleiterplatte zum Laufen gebracht; funktioniert ohne grosse Fehlauswertungen (CRC immer ok).
      Mit dem RFM69 auf der Testleiterplatte funktioniert der Empfang auch jedoch mit geschätzten 10% Fehlauswertungen (CRC nicht ok). Diese Fehlauswertungen müssen aber die Preambel und die 2 Sync-Worte passiert haben. Eventuell weil der RFM69 empfindlicher ist als der RFM69? Warum er nach einiger Zeit hängt liegt wahrscheinlich an einem Timeout?-Register und davon hat es reichlich. Wird wohl noch einen Moment dauern bis ich das gefunden habe.
      Ich schalte die CS-Leitung des RFM entweder ohne Pullup-Widerstand direkt (bei 3.3V) oder mittels eines Widerstandsteilers (bei 5V) an einen uP-Ausgang an. Beim Programmieren des uP wird der Reseteingang auf 12V gelegt. Ich nehme an dass in diesem Falle die Ports ihren programmierten Status beibehalten (kein high Z). Ansonsten hätte es bis heute nicht funktioniert.
      Warum ich beim Programmieren bei angeschlossenem RFM69 meist 2x programmieren muss ist mir nicht klar, kann jedoch auch an meiner Ungeduld liegen ;)
    • jepe wrote:

      Beim Programmieren des uP wird der Reseteingang auf 12V gelegt.
      nur bei HV-Programmierung, macht man ja nur, wenn der Controller verfust ist.

      jepe wrote:

      Ich nehme an dass in diesem Falle die Ports ihren programmierten Status beibehalten
      Wenn der Controller in Reset gezogen wird, haben alle Ports ihren Status verloren. Sie sind dann alle auf Eingang ohne Pullup.
    • Wird beim Programmieren der Reseteingang auf 0 gezogen? Dann wären alle Ports high-Z und der Chipselect des RFM würde in der Luft hängen resp beim Spannungsteiler an 0 und somit eingeschaltet. Ausserdem würde dann der RFM-Ausgang mit dem Programmer-Ausgang kollidieren, wer gewinnt? Und das Ganze ohne Probleme während der letzten Jahre?
      In dem Falle scheint das dem RFM (bis heute) nicht zu schaden ausser, vielleicht, beim RFM69.
    • Nun, wenn alles mit 3.3V betrieben wird so bleibt der CS des RFM noch eine Weile high wenn der uP-Ausgang hochohmig wird; eine Variante warum es bisher problemlos funktioniert hat.
      Bei Speisung 3.3V und 5V wird es interessanter da ich die Pegelumsetzung mit einem Widerstandsteiler mache. Wird der High-Ausgang des uP hochohmig so wird der CS des RFM auf 0 gelegt und somit eingeschaltet. Da nun jedoch zwischen RFM und dem uP-Eingang ebenfalls ein Widerstand (1.5k) als Teil des Spannungsteilers liegt arbeitet der Programmer auf diese Last von 1.5k und das wird er wohl können.
      Nun, nochmals Glück gehabt, aber bei zukünftigen LP-Revisionen werde ich immer einen externen Widerstand nach Plus einfügen (ausser beim Spannungsteiler, da funktioniert es wie oben beschrieben)
    • Bei Speisung 3.3V und 5V wird es interessanter da ich die Pegelumsetzung mit einem Widerstandsteiler mache. Wird der High-Ausgang des uP hochohmig so wird der CS des RFM auf 0 gelegt und somit eingeschaltet. Da nun jedoch zwischen RFM und dem uP-Eingang ebenfalls ein Widerstand (1.5k) als Teil des Spannungsteilers liegt arbeitet der Programmer auf diese Last von 1.5k und das wird er wohl können.
      Ich habe das nun mal nachgeprüft und es ist so wie ich vermutet habe.
    • Hallo
      Ich brauche wieder einmal eure Tipps/Hilfe. Ich arbeite immer noch am RFM69CW als Empfänger. Zum Testen werte ich meine 4 Temperatursender aus die im Minutenabstand senden. Dies funktioniert auch für 2min bis Stunden. Dann jedoch geschieht folgendes:
      - als erstes Zeichen nach der Sync-Sequenz folgt das Längenbyte. Dieses wird als 0 detektiert.
      - daraufhin wird die Sequenz verworfen und das Fifo mir Fifioverrun geresettet.
      - beim Empfang der nächsten Sequenz wird die Länge der folgenden Sequenz mit hex20 angegeben.
      - die Sequenz wird ausgelesen (ist natürlich falsch da die richtige Sequenz hex0B lang ist) aber dann habe ich bemerkt dass nicht das Fifo ausgelesen wird sondern die Register (z.B. ab hex0F 32 Bytes)
      - danach wird nichts mehr decodiert

      Die Flagregister 1 und 2 zeigen jedoch nichts auffälliges an. Ich habe schon alle mir bekannten Möglichkeiten ausprobiert.
      - nur Flag in Interruptroutine, Daten aus Fifo im Mainprogramm ausgelesen
      - komplettes Fifo in Interruptroutine ausgelesen
      - in Interruptroutine zuerst 1. Byte ausgelesen, getestet und dann, wenn ok: restliche Bytes ausgelesen, wenn nicht ok: Fifo gelöscht
      - in Interruptroutine zuerst 1. Byte ausgelesen, getestet und dann, wenn ok: restliche Bytes ausgelesen, wenn nicht ok: ebenfalls restl. Bytes ausgelesen
      - in Interruptroutine zuerst auf Modus Standby gesetzt, 1. Byte ausgelesen, getestet und dann, wenn ok: restliche Bytes ausgelesen, wenn nicht ok: ebenfalls restl. Bytes ausgelesen, zum Schluss wieder auf Modus Rx
      - und immer vor dem Ende der Interruptroutine nochmals Fifo gelöscht mit FifoOverrun

      Nachdem diese Versuche keinen Erfolg brachten habe ich es mit einem Reset versucht. Wenn die Datenlänge < 3 oder > 60 ist werden alle Register mit den Initialwerten neu gesetzt.
      Resultat: Ich speichere in Register 1 (Mode) Rx-Mode. danach lese ich das Register 1 zurück und es steht da Tx-Mode oder Sleep oder...nur nicht Rx-Mode.
      Auch wenn ich den Befehl nach 1 Sekunde widerhole wird er nicht gespeichert.

      Für mich stellt sich die Frage: was macht der RFM69 wenn die Empfangsdatenlänge 0 ist?
      Ich habe auch schon beobachtet dass dies auch bei Datenlänge 1 und 2 geschehen ist. Daraufhin habe ich auch bei diesen Datenlängen das Fifo ausgelesen anstatt nur zu resetten. Hat aber alles nichts geholfen. Leider sind die Tests etwas mühsam da der Effekt erst nach einer gewissen Zeit eintritt.

      Hat jemand, der sich mit dem RFM69 beschäftigt hat, ähnliche Probleme gehabt und wie gelöst?

      Ich habe mein Testprogramm angehängt (bitte nicht kritisieren, es sieht furchtbar aus)
      Files
    • jepe wrote:

      Rfm_funkirq:
      Disable Interrupts
      Reg_wert27 = Read_reg(regh27_irqflags1) 'wie sehen die Flagregister aus
      Reg_wert28 = Read_reg(regh28_irqflags2) 'Auswertung im main-Loop
      Im Interrupt Intrerrupts zu sperren ist wie Eulen nach Athen tragen.
      Sie sind da doch schon gesperrt, weil man im Interrupt ist?

      Die Auswertung der Register sollte doch die darauffolgenden Aktionen auslösen?

      Ich habe gerade kein Datenblatt zum RFM69, aber ich würde es erstmal so wie christi85 hier machen:
      github.com/cristi85/RFM69
    • Ich schalte im Interrupt immer alle anderen möglichen Interrup's ab.
      Die Register werden nur ausgelesen und später im Hauptprogramm analysiert. Dies um den Interrupt möglichst kurz zu halten.
      Da der Empfänger immer laufen soll habe ich nicht weiter auf RFM69-interne Umschaltzeiten geachtet. Wo sinnvoll? habe ich einen kurzen wait-Status eingefügt.

      Den Link werde ich mir ansehen, ist leider in C und meine C-Kenntnisse sind etwa gleich wie meine Französisch-Kenntnisse a_45_132ca9f5

      Anbei einige Auswertebilder
      Files
      • Auswertung OK1.png

        (238.65 kB, downloaded 12 times, last: )
      • Absturz14a.png

        (14.6 kB, downloaded 10 times, last: )
      • Absturz15a.png

        (72.06 kB, downloaded 11 times, last: )
    • Hallo jepe,
      die Interrupts noch einmal global in der ISR zu sperren ist vielleicht nur ein Schönheitsfehler.
      Aber sie zu erlauben, bevor die ISR fertig ist, das ist sehr gefährlich.
      Nach deinem Enable Interrupts werden noch sämtliche Register des Controllers zurückgeschrieben. Wenn du dann die Ints global freigibst und es wartet einer auf Ausführung (also wieder der Int0) dann wird wieder die ISR aufgerufen.
      Wie Michael schon sagte, es ist überflüssig und zudem noch gefährlich. Nimm beide Befehle raus aus der ISR.

      Du kannst auch mal probieren, in der Read_reg Funktion den Spiin erst mal einer normalen Variable zuzuweisen und erst danach den Funktionswert auf diese Variable zu setzen. Es ist nicht sicher, dass Spiin das so verarbeitet wie du es dir vorstellst.

      The post was edited 2 times, last by Franz ().

    • Hallo Franz
      ich habe jetzt mal die 2 Interrupt-Befehle rausgenommen. Nun warte ich was passiert :sleeping:
      Ich habe jedoch ein andere Verständnisproblem: ich verstehe deinen Einwand was nach Enable Interrupt geschehen könnte. Ich dachte bisher es wird nur der aufrufende Interrupt gesperrt, die anderen bleiben aktiv. Diese könnten dann den laufenden Interrupt wieder unterbrechen u.s.w. Deshalb habe ich immer alle Interrupts gesperrt. Ich habe bis jetzt auch nie etwas negatives bemerkt.

      Nun, nach 12 Min. hängt das Ganze wieder und zwar wieder mit Länge = 0; danach geht er in den TX-Modus und aus.

      Ich habe in der Zwischenzeit auch das C-Programm von christi85 angeschaut. So wie ich es verstanden habe wird bei Länge = 0 abgebrochen und der Empfänger neu gestartet; eigentlich fast so wie ich es ebenfalls gemacht habe nur etwas ausführlicher. Er lädt nochmals Register REGPACKETCONFIG2 [RFM69_writeReg(REG_PACKETCONFIG2, (RFM69_readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks.]
      Das hat sich jedoch nicht geändert. Ich werde dies mal nachbauen.
    • Zum Verständnis.

      Wenn am Controller ein Interrupt auftritt, dann sperrt der Controller automatisch alle Interrupts und springt dann in die ISR-Routine.
      Das Sperren der Interrupts geschieht durch setzen des I-Flags im SREG-Register. Das entspricht dem Basic-Befehl 'Disable Interrupts'.

      Wenn die ISR abgearbeitet ist und die letzte Anweisung Return (IRET) ausgeführt wird, springt der Controller zurück ins Hauptprogramm und löscht automatisch wieder das I-Flag im Statusregister SREG, was dem 'Enable Interrupts' entspricht.

      Du musst also gar nix in der ISR machen, keine Interrupts aktivieren/ deaktivieren. Und das sollst du auch nicht! Dann gibts da auch keine Probleme.

      Wie @Franz schon erwähnt hat, gibt's Probleme, wenn du in der ISR Interrupts erlaubst. Die können dann deine ISR unterbrechen und dann geht's meistens schief.
      Das wäre dann das Thema Nested Interrupts. Dazu habe ich mal ein Lexikon-Beitrag geschrieben. Falls dich das interessieren sollte.
    • Danke für die Erklärung. Von früher war ich der Meinung dass man die Interrupts explizit sperren muss. Wieder was gelernt. :)
      Das führt mich zur nächsten Frage:
      Wird der Print-Befehl per Interrupt oder per Polling abgearbeitet? Ich habe dazu nichts gefunden.
      Was geschieht mit einem Print-Befehl in einer Interrupt-Routine; bei Polling ist es klar, wird wohl sofort ausgeführt. Bei Interrupt-Betrieb nach Beendigung des laufenden Interrupts?

      P.S. auch nachdem ich den Empfangs-Restart gemäss C-Programm gestaltet habe hängt sich der RFM69 nach einiger Zeit auf. Er geht auf den Tx-Mode.