Forum: HF, Funk und Felder Minimalistische Funkübertragung mit 433Mhz Modulen (XY-MK-5V und FS1000A)


von Seb W. (mrwagner)


Lesenswert?

Hi,

ich beschäftige mich seit einiger Zeit Mikrocontroller und hab auch 
schon einige Sachen mit Sensoren und Co. gemacht. Für viele Sachen die 
ich noch machen möchte benötige ich aber eine Kommunikation zwischen den 
einzelnen Mikrocontrollern. Da ich Funksteckdosen mit den Micocontroller 
geschaltet habe, habe ich noch XY-MK-5V und FS1000A da. Die Module sind 
recht billig und ich könnte diese auch sehr gut dazu benutzen um mehrere 
Sender zu basteln. Diese schicken dann Sachen wie Temperatur und Co. an 
einen Empfänger und der schickt es an den PC weiter und dort wird es 
dann in die Datenbank geschrieben.

Problem ist die Umsetzung, auch weil ich in der Elektronik- und 
Micocontrollerecke nicht so bewandert bin. Es gibt mehrere Beispiele im 
Netz die vermutlich funktionieren, aber dann Libarys benutzen die nur 
für Arduino und Co. gedacht sind. Ich würde das ganze selber aufbauen, 
damit auch auch verstehe was ich da mache.


Bisher habe ich zwei Atmega8 wo ein Sender und ein Empfänger dranhängt. 
Beide mit 5V versorgt und bei Beiden steckt ein ca. 17cm langer Draht 
als Antenne im dazu vorgesehenen "Loch". Die beiden sind direkt 
nebeneinander. Ich habe mir das so vorgestellt, dass ich erstmal ein 
Signal (z.B. High, Low, Low) erzeuge was dann vom Empfänger aufgenommen 
wird. Das hab ich schon bei der Funksteckdose so gemacht. "Einfach" das 
Signal genau angeschaut und dann versucht mit Pin auf 1 oder 0 den 
Sender anzusprechen um das gleiche Signal zu erzeugen. Das Signal habe 
ich mir wie hier beschrieben 
(http://gimlie.net/433-mhz-signale-auslesen-und-auswerten) angesehen.


Das Problem ist jetzt das Empfangen. Es sollten erstmal mehrere Bits 
über die Leitung geschickt und vom Empfänger empfangen werden. Ein Bit 
(0 oder 1) liegt dabei in der Manchester-Codierung vor. Das Signal kann 
ich dann auch über den schnell zusammengebastelten Empfänger mit 
Audacity anschauen und es wird auch korrekt erzeugt.

Das Empfangen habe ich mir vom Prinzip so vorgestellt, dass eine 
Schleife läuft die testet ob der Pin, an dem der Empfänger hängt, 0 oder 
1 ist. Falls er 1 oder 0 ist, läuft solange eine Schleife bis der Pin 
wieder auf 0 oder 1 schaltet. Durch einen Timer kann ich dann ermitteln 
wie lange das Signal am Pin angelegen hat. Aus der Dauer kann ich dann 
dann ermitteln ob es Rauschen war (kurze Spitzen) oder es sich um das 
Signal vom Sender handelt (längeres High-Signal). Momentan bin ich 
soweit, dass ich eine LED mit der Fernbedienung der Funksteckdose bzw. 
meinen Sender anschalten kann. Der Empfänger erkennt einfach, dass ein 
längeres High Signal ankommt. Das Ziel ist aber, dass er mehrere Bits 
erkennt. Dann hätte ich es geschafft. Würde das vom Prinzip so gehen?

Kann ich mir nicht vorstellen, da die Tutorials zu dem Thema teilweise 
so viel Quellcode enthalten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Seb Wagner schrieb:
> dass eine Schleife läuft die testet ob der Pin, an dem der Empfänger
> hängt, 0 oder 1 ist. Falls er 1 oder 0 ist, läuft solange eine Schleife
> bis der Pin wieder auf 0 oder 1 schaltet.

Normalerweise würde man sowas über Interrupts machen.  Ideal wäre
timer input capture, dann bekommst du direkt die zeitlichen Abstände
der Flanken heraus.  Ggf. muss man eine Totzeit einprogrammieren, um
bei völlig unsinnigem „Herumzappeln“ des Pins einen Interruptsturm zu
vermeiden.

von Seb Wagner (Gast)


Lesenswert?

Danke für den Hinweis mit den Interrupt. Ich bin dann durch die 
Interrupts noch mal auf einige kleine Beispiele mit UART gestoßen, wo 
ich dann auch endlich die Funktionsweise von Uart verstanden habe.


Ich hatte die letzten Tage dann mal versucht die Sache auch über UART zu 
realisieren, weil dort das Problem der Auswertung der Funksignale quasi 
schon gelöst ist und ich theoretisch nur auslesen muss. Ich hab dazu 
Bascom AVR genutzt, da es zum rumprobieren einfacher als C finde.

Einzelne gesendete Zeichen zu empfangen war möglich, die sind meist 
angekommen und ich konnte halt wenn ein bestimmtes Zeichen ankam eine 
LED leuchten lassen. Hat zwar nicht immer geklappt. Strings konnte ich 
ebenfalls senden und das Signal sah auch gut aus, aber da hab ich es 
nicht hin bekommen den kompletten String auszulesen.


Mit dem Befehl INPUT hat er auf Jedenfall erkannt, dass immer CARRIAGE 
RETURN angekommen ist. Zumindest der Teil vom String ist immer 
zuverlässig angekommen. Ich werde mich noch mal an meine ursprüngliche 
Idee ran setzen und die Signale selber über high/Low erzeugen und 
auswerten.

von Wolfgang (Gast)


Lesenswert?

Seb Wagner schrieb:
> Es gibt mehrere Beispiele im
> Netz die vermutlich funktionieren, aber dann Libarys benutzen die nur
> für Arduino und Co. gedacht sind. Ich würde das ganze selber aufbauen,
> damit auch auch verstehe was ich da mache.

Arduinos sind bis auf wenige Ausnahmen ganz normale ATmega Prozessoren. 
Auf den Boards sind nur die Pins anders bezeichnet, als im ATmega 
Datenblatt. Die Arduino Bibliotheken kannst du dir einfach ansehen oder 
auch in Atmel-Studio benutzen und z.B. im Simulator angucken, was 
passiert.

von Seb W. (mrwagner)


Angehängte Dateien:

Lesenswert?

Ich bin jetzt an einen Punkt den ich nicht ganz verstehe. Wie empfohlen 
nutze ich für die Auswertung der Signale die Input Capture Funktion vom 
Timer1 was prinzipiell super klappt.

Zu Testzwecken habe ich alles erstmal in Bascom AVR programmiert und der 
Empfänger empfängt auch zu Testzwecken eine Folge von 10 High-Signalen.
Das Signal sollte auch gut aussehen (Siehe Bild im Anhang). Der 
Empfänger arbeitet mit 1Mhz. Timer1 ist so konfiguriert, dass ein 
Interrupt ausgelöst wird wenn eine aufsteigende Flanke kommt. Bei 10 
High-Bits würde also theoretisch 9 mal ein Interrupt ausgelöst werden. 
Das klappt auch super und ich kann auch eine LED blinken lassen wenn die 
10 High-Signale empfangen werden. Bei Timer1 hab ich Prescale = 8 
gewählt und Noise Cancel eingestellt damit nicht auf alle High Signale, 
die durch Rauschen entstehen reagiert wird.

Jetzt wollte ich eine Folge von High und Low Signalen empfangen. Meine 
Idee war, die Signale anhand der Zeit bis zur nächsten aufsteigenden 
Flanke zu erkennen.
Je nachdem ob es sich um eine 1 oder 0 handelt ist die Zeit bis zur 
nächsten Flanke nach einem High oder Low Signal um eine halbe 
Signallänge länger.

Das sollte theoretisch auch funktionieren, dazu ist es aber nötig die 
Zeit genau zu messen und da gibt es momentan ein Problem.



Die Unterbrechungsroutine zum Testen sieht bei mir momentan so aus:
1
Config Timer1 = Timer , Prescale = 8 , Capture_edge = Rising , Noise Cancel = 1  
2
3
...
4
...
5
6
Icp_isr:
7
   Zeitstempel = Icr1 #ICR auslesen um Zeitpunkt des Interrupts zu ermitteln
8
   Timer1 = 0 #Timer auf 0 setzen um Zeit bis zur nächsten Flanke zu ermitteln
9
10
   If Zeitstempel > 200 And Zeitstempel < 1500 Then 
11
      I = I + 1 #Bei Jedem High-Signal um 1 erhöhen
12
      If I > 8 Then #Wenn mehr als 8 High-Signale angekommen sind LED blinken
13
         Portd.7 = 1
14
         Waitms 15
15
         Portd.7 = 0
16
         Waitms 15
17
      End If
18
   Else
19
      I = 0 #Falls kein High Signal erkannt wird I auf 0 setzen
20
   End If
21
Return

Das klappt wie geschrieben super, aber mein Problem ist der Zeitstempel 
der von 200 bis 1500 reicht. Sobald ich da Versuche den Bereich enger zu 
machen blinkt die LED teilweise nicht mehr. Ein Toleranzbereich muss 
sein, aber der Bereich ist doch deutlich zu groß? Irgendwas muss da 
schon bei der Zeiterfassung schief laufen?

: Bearbeitet durch User
von Henrik Haftmann (Gast)


Lesenswert?

Hm, falsches Pferd!

Auf Fragen zu Bascom wird Dir hier niemand antworten können, weil's 
keiner benutzt und damit niemand lesen kann. WinAVR wäre das richtige 
Pferd gewesen um von Arduino wegzukommen.

So wie's aussieht sehe ich nirgendwo den Start/Stopp der Stoppuhr. 
Richtige Programmierer machen auch das nicht, sondern lassen einen 8- 
oder 16-bit-Zähler einfach immer durchlaufen und messen ZeitDIFFERENZEN:
1
 static int tlast;
2
 int t = ICR;
3
 int dt = t-tlast;
4
 tlast = t;
5
 if (800<=dt && dt<1000) ...
Das interessante an der Subtraktion in Zeile 3 ist, dass diese auch bei 
Zählerüberläufen das richtige Ergebnis liefert. C-Programmierer 
verlassen sich darauf. In Basic kann das schief gehen. Weil niemand weiß 
wie Basic sich verhält. Das hat man vergessen zu definieren.

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.