Forum: Mikrocontroller und Digitale Elektronik Funkprotokoll dekodieren


von Engi (Gast)


Lesenswert?

Hi, ich bin gerade dabei mir einen Empfänger für meine gute alte, WS2500 
Wetterstation von ELV zu programmieren. Das Funkprotokoll ist im Netz zu 
finden: http://www.dc3yc.homepage.t-online.de/protocol.htm .

Nun die große Frage, wie genau dekodieren. Da ein Bit durch 2 Zustände 
(log. 1 = 3*122us low + 7*122us high / log. 0 = 7*122us low + 3*122us 
high) codiert ist, geht es meiner Ansicht nach in Richtung Manchester. 
Die Codierung weist also ein 7 zu 3 Verhältnis auf. Um das dekodieren zu 
können, habe ich den Timer0 meines Atmega 8 (4mhz ext. Quarz) auf 
Prescale 8 und Startwert 195 zu stehen. Somit sollte er jetzt mit 8192Hz 
den Portb0 abfragen. Wenn HIGH dann wird eine Variable hochgezählt, 
paralel dazu läuft eine zweite Variable die mitzählt wenn 10 Timertakte 
abgearbeitet sind. Sind bis dahin nur 3 HIGH Zustände zusammen gekommen, 
entspricht dies der log. 0. Sind es hingegen 7* HIGH dann entspricht 
dies einer logischen 1. Nun fütter ich eine Variable mit diesen Daten. 
Dazu muss wiederum eine dritte Variable mitlaufen, welche zählt um das 
wie vielte BIT es sich handelt. Die Übergabe mache ich dann mit 
Variable.Bit = 1 oder 0.

Hier mal ein wenig CODE, wie ich es derzeit am laufen habe. Wie 
vermutet, läuft natürlich erstmal nix und das Display gibt nur wirres 
Zeug aus. Aber so richtig was, wie es in Bascom geht, habe ich noch nix 
so wirklich gefunden. Wenn, dann meistens weistestgehend unkommentiertes 
Zeug, wo ich als Neuling bei Bascom schnell den Durchblick verliere.
1
$regfile = "m8def.dat"
2
$crystal = 4000000
3
4
Config Timer0 = Timer , Prescale = 8
5
On Timer0 Timer_irq
6
Timer0 = 195
7
Enable Timer0
8
Enable Interrupts
9
10
  Dim Timercount As Byte       'Zählt ob 10 Timerzyklen durchlaufen wurden
11
  Dim Bitcount As Byte         'Zählt ob 3 mal oder 7 mal HIGH empfangen wurde
12
  Dim Datar As Byte            'Das eigentliche Datenbyte in dem die Daten abgelegt werden.
13
  Dim Bitzahler As Byte        'Gibt an um das wie vielte Bit des Bytes es sich handelt.
14
15
  Timercount = 1
16
  Bitcount = 0
17
  Datar = 0
18
  Bitzahler = 1
19
20
Config Pinb.0 = Input
21
Portb.0 = 1
22
23
Config Lcdpin = Pin , Db4 = Portc.2 , Db5 = Portc.3 , Db6 = Portc.4 , Db7 = Portc.5 , E = Portc.1 , Rs = Portc.0
24
Config Lcd = 16 * 2
25
26
27
Do
28
29
 Cls
30
31
 If Bitcount = 3 Then Datar.bitzahler = 0                   
32
'Wenn nur 3 high Impulse detektiert wurden, entspricht dies einer log. 0
33
34
 If Bitcount = 7 Then Datar.bitzahler = 1      
35
'Wenn hingegen 7 high Impulse detektiert wurden, entspricht dies einer log. 1
36
37
 If Bitzahler = 8 Then
38
  Cls
39
  Locate 1 , 1
40
  Lcd Bin(datar)
41
  Locate 1 , 2
42
  Lcd Datar
43
  Datar = 0
44
  Bitzahler = 1
45
 End If
46
47
48
Loop
49
50
51
Timer_irq:
52
53
    If Portb.0 = 1 Then Bitcount = Bitcount + 1             'Wenn Portb3 log. 1 ist, dann zähle die Variable bitcount um 1 hoch
54
    If Timercount = 10 Then                                 'Wenn 10 Runden um sind, dann wird sowohl bitcount als auch timercount auf 0 gesetzt
55
     Timercount = 0
56
     Bitcount = 0
57
     Bitzahler = Bitzahler + 1                              'Diese Variable gibt wieder wie viele Bits bereits empfangen wurden
58
    End If
59
    Timercount = Timercount + 1
60
61
Return

Momentan bin ich schon froh wenn die Präambel als auch das erste Byte 
richtig decodiert wird. Wenn ich erstmal weiss wie sowas richtig 
decodiert wird, dann sollte der Rest kein Thema mehr sein. ich bin für 
Vorschläge und Ideen offen und danke Euch schon mal im Vorraus ;).

von Conny G. (conny_g)


Lesenswert?

Hallo Engi,

ich hab das in C implementiert, würde Dir das helfen?
Könnte ich Dir schicken.
Müsste sich eigentlich gut 1:1 in Bascom übersetzen lassen.

Vg,
Konrad

von Engi (Gast)


Lesenswert?

Versuch kann nicht schaden. Denke mal auch, das sich die Befehle soweit 
ähneln sollten, das ich vielleicht gar draus schlau werde.

von Conny G. (conny_g)


Angehängte Dateien:

Lesenswert?

Ist insgesamt noch etwas "hacky", könnte man noch ordentlich aufräumen. 
Gehört zu meinen Erstlingswerken beim AVR programmieren... Noch jede 
Menge Debug-Ausgabe per UART drin. Funktioniert aber recht gut.

Habe dafür aus meinem alten kaputten ELV-Receiver den eigentlichen 
Funkempfänger ausgebaut und dann wieder die Schmitt-Trigger-Schaltung 
drumrumgemacht, die das Signal etwas pimpt bevor es zum uC geht.

Verwendet den INT0 Interrupt, der zählt Takte bis die Flanke wechselt.
So kann der Prozessor auch andere Dinge machen und muss nur ab und zu 
mal "receivedPacket" überprüfen.

Implementiert ist es als zweistufige State Machine, eine "low level" für 
die Bits: Bit geht los, Takte zählen und entscheiden ob das jetzt ein 
Bit war oder "Fehler". Das zählen mit gewissen Toleranzen.

Ich habe festgestellt, dass mit zunehmender Entfernung sich das Timing 
der Bits "verschmiert", d.h. wenn man Taktzyklen der empfangenen Bits 
z.B. als Debug ausgibt, dann wird die Verteilung der Bits breiter.

Die zweite Stufe State Machine kümmert sich darum, ob ich die Präambel 
empfangen habe und speichert die Bits dann als Nibbles. Und weiss 
wieviele Nibbles ich für ein bestimmtes Gerät empfangen sollte. Und 
prüft dann am Ende die Prüfsumme und setzt wenn alles passt dann 
"receivedPacket = 1".

Im Hauptprogramm würdest dann so etwa feststellen, ob Daten da sind:
1
ATOMIC_BLOCK( ATOMIC_FORCEON )
2
{
3
  tmpReceivedPacket = receivedPacket;
4
}
5
6
if ( tmpReceivedPacket )
7
{
8
  for ( int i = 0; i < nibble_ptr; i++ )
9
  {
10
    sprintf( str, "%02x ", nibble[i] );
11
    usartSendString( str );
12
  }
13
  usartSendChar( '\r' );
14
  usartSendChar( '\n' );
15
16
  reset();
17
}

von Mr. X (Gast)


Lesenswert?

Engi schrieb:
> (log. 1 = 3*122us low + 7*122us high / log. 0 = 7*122us low + 3*122us
> high)

Man kann es auch so sehen:
 - Eine fallende Flanke markiert den Anfang einer Bitübertragung
 - Wenn das Signal nach 610µs noch Low ist, handelt es sich um
   eine log.1, sonst um eine log. 0

von Conny G. (conny_g)


Lesenswert?

@Mr X:
ich habe das ein bisschen anders gemacht: ich starte mit jeder fallenden 
Flanke einen Counter und zähle die Takte für Low.
Bei steigender Flanke wird der Count gespeichert.
Bei nächster fallender Flanke wird geschaut:
- Gesamttakte gleich Bitlänge +/- bestimmter Toleranz?
- Ja -> wir akzeptieren das als Bit.
   (Nein -> Fehler, Reset, alle bisher gespeicherten Bits löschen. Von 
neuem.)
- Bit prüfen: Wenn Takte_Low in einem Bereich von +/- "Toleranz" für Bit 
0, dito für Bit 1.
   Takte ausserhalb der Bandbreite: Reset, von vorne.

von Conny G. (conny_g)


Lesenswert?

@Engi:
ich hätte übrigens auch eine Senderoutine dazu, sah ich gerade.
Hatte ich wohl noch nicht in die Lib eingebaut.
Vielleicht möchtest ja auch mal eine Sensor selber bauen.
Gib Bescheid, wenn Interesse.

Vg,
Konrad

von Stefan S. (engi)


Angehängte Dateien:

Lesenswert?

So, hab mich mal angemeldet ;).

@Konrad, japp bin an allem interessiert was mir weiter helfen könnte. 
Von daher natürlich auch an Deiner Routine. Wenn ich die Sensoren 
empfangen kann, dann sollte es nicht schwer sein, einen Sender selbst zu 
bauen. Hab schon vor, später mal noch einen Blitzdetektor zu bauen, der 
die Anzahl der detektierten Blitze als Temperatur oder Feuchtigkeitswert 
ausgibt und natürlich sendet.

Leider ist es mir nicht gelungen aus dem C Code schlau zu werden. Ich 
danke Dir trotzdem. Ein Versuch war es zumindest wert.

_________________________________________________________________

So, zum aktuellen Projekt. Derzeit sieht es so aus, das ich einen 
Interrupt an INT1 zu laufen habe. Detektiert dieser eine fallende 
Flanke, wird der Timer1 gestartet und um das der Interrupt nicht gleich 
wieder auslöst, wird dieser erstmal solange abgeschaltet wie keine 8 
Bits empfangen wurden. Ist die Zeit für 8 Bits um, wird der Timer wieder 
deaktiviert und der Interrupt zeitgleich wieder aktiviert.

Mir gehts nach wie vor darum, erstmal wenigstens die Präambel zu 
detektieren. Aktueller Code ist angehangen.

Edit:
Ich hab meinen Code noch eben kommentiert. Die große Datei im kb Bereich 
ist die kommentierte und die empfehle ich Euch ;).

von Stefan S. (engi)


Angehängte Dateien:

Lesenswert?

So, Endstand für diese Nacht befindet sich oben im Anhang. Stand: LCD 
gibt nur 00000000 aus. Ist als wenn nix empfangen wird. Und das obwohl 
der Empfänger wahnsinnig rauscht. Gerade wenn er "nur" an einem 
stabilisierten Netzteil hängt, statt direkt an einer Batterie, sind vor 
lauter Rauschen kaum Nutzdaten zu empfangen. Allerdings höhre ich 
mittels Ohrhöhrer mit, hört man immer wieder ein zehntel Sekunden langes 
"beeep". Denke mal, das sind die Sensorpakete die ich dekodieren will. 
Empfänger ist ein HFS301 von ELV.

Juti, mal gucken was der morgige Tag bringt. Gute Nacht Euch allen.

von Conny G. (conny_g)


Lesenswert?

Wenn ich es richtig gesehen habe, dann sampelst Du 1x nach 
60.000/4.000.000 Zeit und entscheidest dann welches Bit es ist?
Das klappt so nicht weil in der Zwischenzeit das Pin sich schon 20 x 
geändert haben kann - das Rauschen des Funkraums.
Lass lieber den Int0 immer laufen und Messe da die Zeit zwischen den 
Flankenwechseln und entscheide mit Toleranz, was Du akzeptierst. Also 
Timer auf Bitfrequenz * 30, also 20-25 kHz, damit kannst feiner auflösen 
und die Toleranz besser justieren.
Und bei jeder steigenden Flanke (da bin ich mir grad nicht sicher) setzt 
Du den Timer Counter auf Null, speicherst bei der nächsten steigenden 
Flanke die Zeit und bei der nächsten fallenden entscheidest Du:
- war das jetzt ein Bit, dh ist die Gesamtzeit von steigend zu steigend 
gleich der erwarteten Bitlänge +/- 10%?
- wann fand der Wechsel statt, nach 3/10 oder nach 7/10? Wieder +/-10%.
- wenn eins von den beiden nicht passt, hast kein gültiges Bit empfangen 
und fängst wieder von vorne an, dh alle Bits verwerfen, Bitcounter = 0, 
State = warte auf Präambel.
- ansonsten Bit speichern, BitCount++, State Machine-Checker aufrufen 
"But empfangen", Counter auf Null und auf die nächste steigende Flanke 
warten

State-Machine-Checker "Bit empfangen":
- Warte auf Präambel & bitzahl = PräambelBitZahl?
   Ja:  empfangene Bits = 0000001?
      Ja: Hurra!!! State = Warte auf Nibble.
   Nein: Bitctr auf 0

von Stefan S. (engi)


Lesenswert?

Japp richtig, ich hatte gestern Abend, eher Nacht, den Timer auf die 
Bitfrequenz gesetzt und nur geschaut was für ein Pegel am Pin gerade an 
liegt und dies dann direkt in die Bits der Datenvariable geschoben.

Das was Du schreibst, klingt richtig gut. Logisch nachvollziehbar. Also 
einfach mit dem Timer das Bit abtasten und schauen wann innerhalb der 
Bitzeit der Pegelwechsel statt fand und wie lang die Bitzeit war. ich 
denke, das sollte ich hinbekommen in Bascom.

von Conny G. (conny_g)


Lesenswert?

Hast Du ein Oszi?
Es ist sehr hilfreich und lehrreich auf einem Kanal den Sender 
anzuschauen (an den Pins des Sendemoduls anklemmen) und auf dem anderen 
Kanal das Signal am Avr.
Dann verstehst viel besser, was da passiert und wie sic das Rauschen von 
Deinem Signal unterscheidet.
Sonst muss man rein mit Annahmen, Vorstellungskraft und Symptomen 
arbeiten, das ist hier recht anstrengend.
V.a. Weißt dann auch ob es mit steigender oder fallender Flanke losgeht.

von Stefan S. (engi)


Lesenswert?

So ind die Richtung dachte ich bereits. Leider hab ich kein Oszi, aber 
im Netz gibt die Freeware "Scope" welche ein Oszi mittels Soundkarte und 
LINE-IN realisiert. Hab ich mir mal gezogen und hoffe das ich dort klare 
Ergebnisse sehe die mir weiter helfen.

von Conny G. (conny_g)


Lesenswert?

Das ist schon mal besser wie nichts sehen.
Kann nur den Kauf eines Oszilloskops empfehlen, muss auch nichts grosses 
sein. Ich habe auch nur ein digitales am USB-Port, so eins:
http://www.ebay.de/itm/DSO-2090-100Msa-s-USB-PC-Virtual-Speicher-Oszilloskop-/160550881003?pt=Mess_Pr%C3%BCftechnik&hash=item25619406eb
nur von Conrad, nicht aus China. Hab vermutlich 100 Euro mehr gezahlt 
als das hier kostet.

So ein Scope ist zwar nicht so supertoll, da haben die Leute hier schon 
recht:
Beitrag "Beurteilung "Voltcraft DSO-2090 dgt Oszi""
aber das meiste lässt sich ok damit machen.

Z.B. ist genau in dieser Situation super, wenn man 2 Kanäle parallel 
ankucken kann. Dann kannst Du den Kanal, der am Sender hängt als Trigger 
nehmen Dir eine paar Mikro-/Millisekunden-Sequenz aufzuzeichnen und 
siehst dann schön, was der Sender verschcikt und was beim Empfänger bei 
rauskommt.
Denn der Sender hat ein ganz cleanes Signal und wenn er nichts sendet 
ist auch Ruhe auf der Leitung.

Wenn Du nämlich nur den Empfänger beobachtest, dann hilft Dir der 
Trigger nichts, weil Du ständig das allgemeine Rauschen hast, das in 
Bits umgesetzt wird und so ständig massiv was los ist auf dem Portpin 
des AVR.

Deshalb muss man sich auch daran gewöhnen, dass die Emfangsroutine quasi 
ständig am rotieren ist und andauernd meint es geht jetzt die Präambel 
los um beim 1. oder 2. Bit festzustellen, dass das nix ist. Man hat 
ständig steigende Flanken von dem Rauschen.
Deshalb ist die Methode auf die Flanken zu hören und die "Abstände" zu 
zählen auch die einzige die funktioniert, also mal nach 50% Bit 
reinsampeln hat deshalb keine Erfolgsaussichten, weil man nicht sieht, 
was in der Zwischenzeit passier tist.

von engi (Gast)


Lesenswert?

Naja die Sache mit Soundkarte soll wohl nicht so Top sein. Wegen 
internen Kodensatoren die aus Rechteck mehr Sinus machen. Hab aber hier 
so ein Buch über Bascom programmieren mit Cd. Und da ist auch ein 
Programm für atmega8 bei welchem über adc die Spannung misst und über 
rs232 an Computer schickt. Der stellt das ganze mittels plotter Programm 
als Kurve dar. Gibt nur wieder ein Problem, der atmega8 sollte seine 
16mhz bekommen wegen maximale Samplerate. Ich hab derzeit aber nur 4 und 
20mhz hier. 20mhz kann aber der atmega8 bereits nicht mehr. Um das doch 
noch was halbwegs brauchbares raus kommt, werde ich erstmal 8mhz intern 
nehmen und bei nächster Bestellung auch mal nen Satz 16er Quarze 
bestellen.

Stimmt, wenn man sieht was man dekodieren will, dann fällt das 
wesentlich leichter. Wegen Sensor, hab einige hier als Reserve, teils 
ohne Temperaturfühler und bei denen werde ich mir erstmal ein sauberes 
Signal anschauen und danach das Protokoll programmieren. Wenn das dann 
fertig ist, gehts an Empfänger. Dann kommt der an den atmega zum 
Wetterdatenempfang ran.

von engi (Gast)


Lesenswert?

Hab mal schnell geschaut, elv hat für nicht viele Euros ein usb 
Oszilloskop im Programm. zwar nur ein Kanal, aber besser als garkein 
oszi. Ist aber Bausatz. Aber wer Controller programmiert, sollte auch 
löten können. Hier mal der Link: 
www.elv.de/usb-mini-scope-modul-usb-msm-komplettbausatz.html

von Stefan S. (engi)


Lesenswert?

Juti, mit Oszi wird erstmal nix. Hab das Wochenende über versucht 
mittels Atmega8, ADC und RS232 mir eines zu bauen. Der Plan war, das ein 
selbst geschriebenes Programm aufm PC die Daten entgegen nimmt und in 
ein Diagramm in Echtzeit einträgt. Hab den Timer0 (AVR), der die Daten 
sendet mit 8192Hz laufen lassen und in dieser Frequenz wurden die Daten 
auch an den PC gesendet. Dem Atmega hat es nicht gestört die Daten so 
schnell zu senden. Nur der PC kam nicht hinterher. Folge: Dem PC sind 
RS232 Telegramme mit 8192Hz (19200/34800 Baud) einfach zu schnell und 
dieser hängt sich auf. Damit wird also nix. Leider sieht es dank 
Arbeitslosigkeit auch mies mit dem Geld und damit mit dem Bausatz Oszi 
von ELv aus. Naja irgendwie werde ich es hoffentlich hinbekommen. Udn 
wenn nicht, dann wird das Projekt wieder in Angriff genommen wenns 
wieder finanziell stimmt.

von Conny G. (conny_g)


Lesenswert?

Denke für diese Frequenz müsste das mit der Soundkarte aber schon ok 
funktionieren. Schon mal probiert?
Selbst wenn es keine ganz klaren Rechtecke mehr sind, siehst wenigstens 
was passiert und das ist hier wirklich hilfreich.

von Conny G. (conny_g)


Lesenswert?

Hehe, oder mach sowas ... kleines Brainstorming:

größeren Atmel nehmen, Atmega328 oder gleich den mit 128k.
Und im AVR die Bittiefe reduzieren von 8bit auf 4bit - für digitale 
Signale reicht das vielleicht noch.
Und dann komprimieren und 2 Nibbles (4bit) in ein Byte.
Und vielleicht einfach im AVR Puffern und Blockweise schicken.

Oder gleich alles zusammen nachher:
Für 1 Sekunde bei 20Khz Sampling brauchst dann 10k pro Kanal, 20k für 
Beide, das könnte mit einem 32 oder 64k AVR gehen.
Wenn Du 2 Kanäle machst, Sender und Empfänger, kannst auch durch den 
Sender triggern lassen (weil der cleanes Signal hat) und beide Kanäle 
speichern für die Signaldauer (<100 Millisekunden?) und nachher 
gesammelt an den PC senden.

Am PC kannst es dann sogar einfach in Excel / Openoffice auswerten und 
vergleichen.

Konrad

von Stefan S. (engi)


Lesenswert?

So in die Richtung gingen meine aktuellen Ideen derzeit auch. Die Länge 
eines ganzen Datenpaketes ist mir ja bekannt. Handelt sich um max 42 
Bits in Folge. Da der Sender ein sauberes Signal liefert, einfach warten 
bis mal ein high Signal anliegt und dann erstmal in den Eeprom 
schreiben. Wenn dann die Zeit für ein Signal abgelaufen ist, wird das 
mitschreiben beendet und die Daten liegen nun im Speicher bereit zur 
Abholung. Und da kann sich der PC dann auch alle Zeit der Welt lassen um 
die Daten abzurufen und darzustellen. Dann hätte ich endlich das Signal 
und wüsste wie ich vorgehen muss.

von Stefan S. (engi)


Lesenswert?

Hab jetzt eine Seite gefunden wo gar schon Signale mal mit einem Logic 
Analyzer aufgenommen wurden und die Signale genau erklärt sind. Neue 
Erkenntnis: Die Präambel besteht aus 10*0. Sieht man dann auch so im 
Diagramm. Soll allerdings offenbar von Sensor zu Sensor verschieden 
sein. Der eine sendet 10 Nullen ehe es richtig los geht, der andere nur 
7.

Hier nun die Seite die wirklich gut ist und viel verrät:
http://www.f6fbb.org/domo/receiver/

Und hier ist ein Screenshot vom Signal:
http://www.f6fbb.org/domo/sensors/ws_signals.php

Das hilft mir jetzt richtig weiter, weil ich nun alles genau 
nachvollziehen kann. Ein eigenes Oszilloskop wäre dennoch nicht übel, 
gibt ja noch andere Sensoren von anderen Herstellern, die von den 
Nachbarn betrieben werden und wenn ich die mit einbinden könnte, hätte 
ich mehr Daten für meine Wetterstation :D.

von Stefan S. (engi)


Lesenswert?

Hab noch was. Eben im Netz gefunden. Richtig guter Logic Analyzer, 
aufgebaut mit einem PIC. Er kann bis zu acht Kanäle und runter bis 200 
Nanosekunden Samplerate. Es ist alles dabei. Inklusive Software für den 
PC aber natürlich auch copilierte *.hex Datei zum direkten Aufspielen 
auf den PIC, als auch das Programm selbst als *.asm Datei. Alles was man 
noch braucht, ist ein 10 Mhz Quarz, ein PIC 18F2620 (bei Reichelt etwas 
über 6 Euro), ein MAX232, ein RS232 Anschluss und noch einige 
Kondensatoren und Wiederstände. Alles in allem vielleicht um die 15 Euro 
Gesamtkosten.

Hier der LINK: http://www.tedrossin.net46.net/Electronics/Pic/Pic.html
Und runter scrollen zu: Cheap Logic Analyzer.

Denke mal, das sollte mir das geld wert sein. Da ich mich vor den AVR's 
auch eine zeit lang mit den PIC's beschäftigt habe, liegt noch ein 
PICKIT2 hier bei mir rum. Hoffe das unterstützt den 18F2620. Denn wenn, 
dann könnte das Unternehmen maximal daran scheitern.

von Conny G. (conny_g)


Lesenswert?

Cool, das ist perfekt, genau sowas brauchst Du!
Und find ich auch spannend für mich :-)

von Conny G. (conny_g)


Lesenswert?

Und, schon weiter gekommen?

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.