Forum: Mikrocontroller und Digitale Elektronik AVRs und RFM-Funkmodule --- Wie da rangehen?


von Julian K. (illuminatus)


Lesenswert?

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

von Stefan W. (wswbln)


Lesenswert?

...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"

von Julian K. (illuminatus)


Lesenswert?

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.

von Kai G. (runtimeterror)


Lesenswert?

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

von Julian K. (illuminatus)


Lesenswert?

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

von Benedikt K. (benedikt)


Lesenswert?

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.

von Julian K. (illuminatus)


Lesenswert?

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

von Benedikt K. (benedikt)


Lesenswert?

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.

von Julian K. (illuminatus)


Lesenswert?

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

von Avr N. (avrnix) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.