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.
'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 ;).
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
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:
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
@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.
@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
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 ;).
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.
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
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.
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.
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.
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.
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.
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
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.
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.
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
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.
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.
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.