Hallo Freunde der Mikrocontrollertechnik! :D Ich habe vor, Messdaten in einem mobilen Gerät mit einem AVR einzuholen und dann via RFM-Modul zu einer feststehenden Empfangsstation zu schicken. Nachdem mein erster Versuch mit einem RFM01 und einem RFM02 schon gescheitert ist, bevor ich richtig angefangen hatte, und ich nach einem Stöbern hier im Forum gemerkt habe, wie komplex das Thema ist, wollte ich vor einem erneuten Versuch erstmal kompetenten Rat einholen, wie ich das am besten aufbaue. Zunächst mal: Wären 2 RFM12 nicht besser? Ich habe gelesen, dass häufig Daten fehlerhaft ankommen und wenn, brauche ich doch eine Möglichkeit, sie erneut anzufordern (sprich bidirektionale Kommunikation). Außerdem scheint mir das RFM12 zum Senden wesentlich handlicher, da es im Gegensatz zum RFM02 eine Sende-FIFO hat und ich die Daten deshalb nicht (so habe ich das verstanden) im Takt der Baudrate dorthin schicken muss. Jetzt zu der Beschaffenheit der µC: Das Problem ist, das beide MCUs (im Daten sendenden Gerät und in der Empfangsstation) auch noch zeitkritische Aufgaben übernehmen sollen. Von daher kann ich schlecht die schon vorhandene Lösung auf der Tutorial-Seite für RFM12-Module übernehmen, bei der sich die Software um das komplette serielle Interface kümmert. Viel lieber würde ich das die Hardware machen lassen. Leider sind die Module aber nicht komplett SPI-kompatibel (zumindest das RFM02 nicht, weil die zu übertragenden Daten im Baudraten-Takt gesendet werden müssen, welchen der IRQ-Pin vorgibt), obwohl ich mir da überlegt habe, ob ich nicht was tricksen könnte. Wäre ein USI die bessere Wahl? Da könnte ich auf einen externen Takt umschalten, wenn es an die Daten geht. Ich überlege, was ich für einen µC kaufen soll. Oder würdet ihr mir dazu raten, einen kleinen µC die ganze Sache mit dem Funkmodul machen zu lassen, der die hier schon vorgestellte Software-Schnittstelle verwendet und dem der eigentliche µC die Daten zuschickt (sagen wir mal via SPI)? Vielen Dank für Eure Hilfe! Julian
...ich würde die Suchfunktion dieses Forums benutzen und mich erst mal in diesen Thread (danke Benedikt et al.!) einlesen: Beitrag "Beispielprogramm für RFM12 433MHz Funk-Module"
Eben das habe ich getan, Benedikts Programm habe ich und ich habe es mir auch bereits angeschaut. Wie ich schon sagte, ist hier die serielle Schnittstelle rein über die Software selbst gebaut und daher für meine Anwendung nicht tauglich, da es den µC zu sehr in Anspruch nimmt. Ich habe mich bereits ausführlich damit auseinander gesetzt und nahm an, dies würde aus meiner Beschreibung des Problems hervorgehen. Ich würde nur ungern gleich einen extra Controller nur für den Funkchip abkommandieren, irgendwie muss diese Schnittstelle doch unter Kontrolle zu kriegen sein. Deswegen wollte ich mir den Rat von Leuten einholen, die schon viel Erfahrung mit den Modulen haben.
Was wird denn Zeitintensives gemacht? Vielleicht lässt sich da ja was optimieren? Kenne jetzt Benedikts Code nicht, wie viel % CPU zieht der denn etwa? Die RFM-Module haben wir noch nicht getestet... oxidieren hier erstmal nur rum. Gruß Kai
Hallo Kai, na, Benedikts Code macht die serielle Schnittstelle komplett über Software. D.h. während etwas gesendet wird, ist der Controller mehr oder weniger blockiert, weil, um die nötigen Zeitverzögerungen zu erzeugen, also die Länge eines Bits z.B., einfach nur eine Schleife durchzählt. Mein Controller wird voraussichtlich, den AD-Wandler benutzen und einige Sachen via PWM steuern. Eventuell könnte man ja, wenn man alles andere geschickt über Interrupts und Timer laufen lässt, bei diesen Schleifen einfach dazwischen springen und alles nötige machen lassen. Wenn der Takt schnell und die Baudrate niedrig und die Interrupt-Routinen kurz genug sind, sollte die kleine Abweichung in der Länge eines Bits, die sich dadurch ergibt, nicht weiter auffallen. Aber da kommt mir gerade eine Idee: Könnte ich den Sende- (und Empfangs-) vorgang nicht auch asynchron ablaufen lassen? Ich müsste doch nur, anstatt für die Timeout-Routine eine Schleife durchlassen zu lassen, die die MCU so lange blockiert, eine Konstruktion mit einem Timer bauen: Die Routine zum Senden (Empfangen) wird aufgerufen und läuft ganz normal durch. Immer, wenn die Timeout-Routine aufgerufen wird, kopiert sie sich die Rücksprung-Adresse vom Stack und speichert sie zwischen (also wohin sie in der Routine zum Senden (Empfangen) zurückspringen würde). Dann initialisiert sie einen Timer, der nach Ablauf der zu wartenden Zeitspanne einen Interrupt auslöst. Sie holt sich die Rücksprungadresse der Routine zum Senden (Empfangen) vom Stack und springt zurück (ins Hauptprogramm, von wo aus die Sende- (Empfangs-) routine aufgerufen wurde. Die Interruptroutine des Timers holt sich dann die zuvor zwischengespeicherte Rücksprungadresse der Timeout-Routine und springt an diese Stelle. Der Code der Sende- (Empfangs-) Routine wird dann bis zum nächstens Aufruf der Timeout-Routine ausgeführt. Diesmal springt die Timeout-Routine dann nicht dorthin zurück, von wo die Sende- (Empfangs-) routine aufgerufen wurde, sondern dorthin, wo der Befehlcounter vor dem Auslösen des Timer-Interrupts war. Da sich diese Rücksprungadresse an der selben Stelle im Stack befindet, muss dafür noch nicht einmal der Code geändert werden, lediglich das Global Interrupt Flag muss wieder aktiviert werden, da ja kein reti-Befehl erfolgt. Das würde zur Folge haben, dass die Sende- (Empfangs-) routine direkt nach dem ersten Aufrufen der Timeout-Routine zurückgibt und der Rest des Sendevorgangs vollkommen asynchron und eben interruptsgesteuert abläuft. Wichtig ist nur, dass im restlichen Code dann keine allzu langen Interruptroutinen oder Abschnitte mit deaktiviertem Global Interrupts Flag vorkommen, weil sonst die Bit-Länge zu stark variiert, wenn die Routine des Timer-Interrupts nicht sofort ausgeführt wird. Falls der Timer-Interrupt aufgrund der restlichen Software immer nur verzögert ausgeführt werden kann, könnte man auch die PWM-Funktion der Timer für die Schnittstelle missbrauchen. Mit einem etwas höheren Prescaler müsste man es hinbekommen, dass der Timer beim raufzählen genau dann von 0 bei einem Compare Match ankommt, dass die Zeit einer Bit-Länge verstrichen ist. Im TCCRx-Register kann man einstellen, ob bei einem Compare Match der zugehörige PWM-Pin high oder low gesetzt werden soll. Löst der Compare Match Interrupts des Timers aus, so wurde das aktuelle Bit auf den Port gegeben. Schaut man jetzt nach, ob das nächste Bit 0 oder 1 ist und stellt den Timer ein, beim nächsten Compare Match den PWM-Pin entsprechend zu verändern, so ist quasi in der Einstellung des Timers das nächste Bit zwischengespeichert und sein Status (0 oder 1) wird, wenn es an der Zeit ist, unabhängig von dem, was die Software gerade macht, auf den PWM-Pin übertragen. Im Endeffekt bleibt der MCU also eine Bit-Länge Zeit, die Interruptroutine des Timers auszuführen. Nur wie ich dann noch ein Clocksignal erzeugen soll, weiß ich gerade nicht. Insgesamt sind das ja alles recht schöne Ideen, aber ich weiß eben nicht, wie realistisch es ist, das umzusetzen, und ob es nicht auch einfacher ginge. Deshalb möchte ich mir hier ja gerade Rat holen. Ein frohes neues Jahr! Julian
Julian Krick wrote: > Hallo Kai, > na, Benedikts Code macht die serielle Schnittstelle komplett über > Software. D.h. während etwas gesendet wird, ist der Controller mehr oder > weniger blockiert, weil, um die nötigen Zeitverzögerungen zu erzeugen, > also die Länge eines Bits z.B., einfach nur eine Schleife durchzählt. Von welcher seriellen Schnittstelle redest du ? Ich verwende den Hardware UART, und mittlerweile auch SPI für das RFM12, also nix in Software. Nur beim RFM02 schiebe ich die Bits per Software raus, da dieser kein FIFO hat.
Hallo Benedikt, bei den Programmen, die ich mir angeschaut habe, hattest du eine Funktion rf12_trans, die die SPI-Schnittstelle nachgeahmt hat. Für das RF02 gabs dann nochmal ne extra Funktion, die den Takt vom IRQ-Pin als Clock verwendet hat. Das ist zumindest die Software, die auf der AVR-Seite unter Projekte zum Download bereit steht. Gibt es da auch noch eine andere Version? Ich hab nichts gefunden, was die Hardware SPI nutzt. Da ich gerade versuche, das RFM02 zum Laufen zu bringen, habe ich eben dieses Problem mit dem IRQ-Takt. Ich hab mir mal die Beschreibung des USI angeschaut. Müsste ich damit nicht beides hinbekommen? Also ganz auf eine Software-Lösung verzichten können? Schließlich kann ich doch sowohl eine Clock erzeugen, als auch auf ein externes Clock-Signal umstellen. Also müsste ich sowohl Befehle als auch Daten mit dieser Schnittstelle senden können. Noch was: Ich habe gehört, dass die Daten öfters fehlerhaft übertragen werden, wegen Funk halt, da kommen ja öfters irgendwelche Störungen rein. Wenn ich aber die Funkbrücke nur in eine Richtung aufbaue, dann habe ich keine Möglichkeit, die Daten erneut anzufordern, wenn sie als fehlerhaft erkannt worden sind. Sollte ich deswegen nicht lieber gleich 2 RFM12 nehmen, anstatt ein RFM01 und ein RFM02? Dann könnte ich mir auch das ganze Gerangel mit dem IRQ-Takt sparen, weil der RFM02 keine FIFO hat und alles über die Hardware-SPI machen, oder? Das Problem ist einfach, dass die MCU noch alles Mögliche nebenbei machen soll, und logischerweise dann auch manchmal gleichzeitig mit einer Übertragung. Ich weiß nicht, ob es möglich ist, das alles über Interrupts zu machen, während der Controller ansonsten durch die Timeouts in der Software-SPI blockiert ist. Ich wäre wirklich dankbar für ein paar richtungsweisende Antworten! Im Moment schwimme ich in einem Meer von konfusen Informationen und weiß nicht, wie ich ansetzen soll. Vielen Dank schonmal! Gruß Julian
Julian Krick wrote: > bei den Programmen, die ich mir angeschaut habe, hattest du eine > Funktion rf12_trans, die die SPI-Schnittstelle nachgeahmt hat. Für das > RF02 gabs dann nochmal ne extra Funktion, die den Takt vom IRQ-Pin als > Clock verwendet hat. OK, das ist das RFM02, das ist eine Außnahme. Bei allen anderen Modulen läuft alles über SPI. Ich würde vom RFM02 abraten und stattdessen das RFM12 verwenden, eben wegen der dummen Ansteuerung. > Ich hab mir mal die Beschreibung des USI angeschaut. Müsste ich damit > nicht beides hinbekommen? Also ganz auf eine Software-Lösung verzichten > können? > Schließlich kann ich doch sowohl eine Clock erzeugen, als auch auf ein > externes Clock-Signal umstellen. Also müsste ich sowohl Befehle als auch > Daten mit dieser Schnittstelle senden können. An sich ja, das Problem ist aber, dass zur Initialisierung der Takt an CLK angelegt werden muss, um die Daten zu übertragen. Für das Senden der Daten, liefert das Modul aber den Takt an CLK/SDO. Man müsste also umschalten. > Noch was: Ich habe gehört, dass die Daten öfters fehlerhaft übertragen > werden, wegen Funk halt, da kommen ja öfters irgendwelche Störungen > rein. Wenn ich aber die Funkbrücke nur in eine Richtung aufbaue, dann > habe ich keine Möglichkeit, die Daten erneut anzufordern, wenn sie als > fehlerhaft erkannt worden sind. Sollte ich deswegen nicht lieber gleich > 2 RFM12 nehmen, anstatt ein RFM01 und ein RFM02? Dann könnte ich mir > auch das ganze Gerangel mit dem IRQ-Takt sparen, weil der RFM02 keine > FIFO hat und alles über die Hardware-SPI machen, oder? Ja, würde ich auch machen. Wobei die RFM12 ziemlich gut sind. Solange der Empfänger innerhalb der Reichweite ist, kommen die Daten eigentlich auch immer an.
Benedikt K. wrote: > Julian Krick wrote: > >> Ich hab mir mal die Beschreibung des USI angeschaut. Müsste ich damit >> nicht beides hinbekommen? Also ganz auf eine Software-Lösung verzichten >> können? >> Schließlich kann ich doch sowohl eine Clock erzeugen, als auch auf ein >> externes Clock-Signal umstellen. Also müsste ich sowohl Befehle als auch >> Daten mit dieser Schnittstelle senden können. > > An sich ja, das Problem ist aber, dass zur Initialisierung der Takt an > CLK angelegt werden muss, um die Daten zu übertragen. Für das Senden der > Daten, liefert das Modul aber den Takt an CLK/SDO. Man müsste also > umschalten. Moment, so wie ich das verstanden habe, erzeuge ich doch für die Befehle die Clock selber und für die Daten hole ich sie mir vom IRQ-Pin. Ich müsste also, um beides an den CLK-Pin von meiner MCU zu bekommen eine Logik vorschalten, die zwischen den beiden Signalen umschaltet (damit der IRQ-Takt nicht an den CLK-Pin des RFM02-Moduls kommt) und natürlich jedes mal die USI neu konfigurieren, wenn ich zwischen Daten und Befehlen wechsle. Ach, mit Initialisierung meinst du die Befehle, die ich nach dem Einschalten der Versorgungsspannung an SDO schicken muss, ne? Ja, jetzt vestehe ich.^^ Ich denke, dann werde ich nochmal 14 € für 2 RFM12's investieren, bevor ich mich noch stundenlang mit dem 02 herumplage. Außerdem kann ich dann bei bedarf noch einiges an Funktionalität hinzufügen. Danke für die Beratung! Gruß Julian
Guck mal auf http://www.comwebnet.de dort gibt es ein Testboard zum RFM12 ,RF12 Modul. Und auch Übertragunglösungen etc. sogar Projekte Wetterstation etc.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.