Moin moin, kennt jemand vielleicht eine Lib für Atmel für Datenübertragung über ein 433MHz Sender/Empfänger-Paar? Nachdem man keine gemeinsame Clock hat, muss man ja wohl über Pulsbreite gehen? Die Länge der Pulse wird allerdings ordentlich verschliffen durch die Sender/Empfänger. Sender-µC sind bei mit mehrere Attiny85 und Empfänger ein AtMege64M1. Die Übertragung ist nicht zeitkritisch, aber die Sender laufen auf Batterie, sollten also nicht ständig senden müssen. Übertragen möchte ich 3 Bytes, wovon Byte 1 die Sender-ID & Checksum, Byte 2 die Art der Daten und Byte 3 die Nutzdaten sind. Die Empfänger-Module scheinen eine art Auto-tune zu haben. Wenn keiner etwas sendet wird das Hintergrundrauschen verstärkt. Demnach erscheint mir Interrupt-basierte Abfertigung nicht geeignet, weil der ständig auslösen würde. Hat jemand Erfahrung damit
Fabian F. schrieb: > Die Empfänger-Module scheinen eine art Auto-tune zu haben. Wenn keiner > etwas sendet wird das Hintergrundrauschen verstärkt. Ja, die einfachste Ausführung sind "Regenerativempfänger", die nach Art eines Röhrenaudions arbeiten. Allerdings mit automatischer Transistorregelung: Die Verstärkung wird stets so weit aufgedreht, bis der Empfänger etwas empfängt. Also empfängt diese Art Empfänger immer etwas: Entweder ein starkes Nutzsignal. Oder schwaches weißes Rauschen als Datenmüll. > Demnach erscheint mir Interrupt-basierte Abfertigung nicht geeignet, > weil der ständig auslösen würde. > > Hat jemand Erfahrung damit Doch, interruptbasierte Auswertung ist das einzig sinnvolle. Du brauchst aber ein sinnvolles Sendeprotokoll und Du mußt beim Emfpang entsprechend filtern. Hast Du Dir schon mal ein Protokoll angesehen, wie "drahtlose Temperatursensoren" oder "Funksteckdosen" mit solchen billigen 433-MHz Sedern und Empfängern umgehen? Im Prinzip wird einfach mit Ein-Aus-Tastung gesendet und das wird am Empfänger in High-Low umgesetzt. Das typische Sendeprotokoll sieht zum Beispiel so aus: - Sende "Trainingbits" - Sende ein "superlanges Start-Bit" - Sende die Daten-Bits Die "Trainingsbits" dienen dabei anfänglich nur dazu, dass der Empfänger seine Verstärkung so auf das Sendesignal einregelt, dass er dessen Sendung einwandfrei erkennen kann. Das "superlange Startsignal" ist dann das Signal für den Empfänger, ab Erkennung des Signals mit der Decodierung von Nutz-Bits zu beginnen. Die dann folgenden Datenbits werden einfach gezählt: Wenn z.B. 32 Datenbits gesendet werden, wird beim Empfang nach 32 Bits die Plausibilität ausgewertet, also z.B. ob die CRC-Prüfsumme stimmt. Die einzelnen Bits können entweder mit zwei Längen codiert werden, z.B.: 0-Bit: 600 µs HIGH und 1200 µs LOW 1-Bit: 1200 µs HIGH und 600 µs LOW Startbit: 8000 µs HIGH und 600 µs LOW Oder als Bits mit unterschiedlicher Länge und gleicher Pause, z.B.: 0-Bit: 600 µs HIGH und 400 µs LOW 1-Bit: 1200 µs HIGH und 400 µs LOW Startbit: 8000 µs HIGH und 400 µs LOW Die Empfangslogik kann dann als Finite State Machine realisiert werden, die drei Zustände hat: - warte aufs Starbit - warte aufs nächste Bit - Datensatz vollständig Die Programmlogik in der Change-ISR muß dann nur sinnvoll je nach empfangenen High/Low Impulsdauern zwischen den drei Zuständen umschalten bzw. Bits zählen, bis ein vollständiger Datensatz empfangen wurde, den das Hauptprogramm dann auswerten kann. Und der Datenmüll zwischen den Aussendungen wird einfach dadurch ausgefiltert, dass wenn im Status "warte aufs nächste Bit" eine falsche Bitlänge außerhalb einer vorgegebenen Toleranz empfangen wird, der Status stets auf "warte aufs Startbit" gesetzt wird. Wobei die Toleranzen durchaus recht großzügig bemessen sein dürfen.
Evtl. kommt auch eine Arduino-Lib in Frage. Zumindest kann man sich da auch einige Idee holen: * http://www.airspayce.com/mikem/arduino/VirtualWire/ * http://www.airspayce.com/mikem/arduino/RadioHead/ * https://code.google.com/p/rc-switch/
Ok, danke. Ich weiß nicht ob hier irgendwas auf 433MHz sendet. Ich hab mal was auf Sender-Seite Programmiert. Wenn ich nichts sende sieht es aus wie auf Bild 23. Die Daten sind auf bild 30. Hab ich das so richtig Verstanden? Wie würde man das dann auswerten? ISR-auf steigende Flanke->Timer starten->Stop auf nächster steigender Flank->Zeit in ein array schreiben und am ende evaluieren?
Fabian F. schrieb: > Ich hab mal was auf Sender-Seite Programmiert. > Wenn ich nichts sende sieht es aus wie auf Bild 23. > Die Daten sind auf bild 30. > Hab ich das so richtig Verstanden? Das sieht soweit schon mal gut aus: - 5 Trainingspulse (nur zum Einpegeln der Empfängerverstärkung) - überlanger Startimpuls - Anzahl n Bits als zu übertragende "Payload" Innerhalb der Payload scheint es bei Dir drei verschiedene Bitlängen zu geben: HIGH-Bits in einfacher und doppelter Länge sowie LOW-Bits in einfacher, doppelter und vierfacher(?) Länge? Kannst Du mal das Sende-Codeschema genau beschreiben? Oder soll das eine Mehrfachaussendung werden? Im Falle einer Dreifachaussendung einer identischen Payload wäre das Sendeschema: - Trainingsbits - Überlanges Startbit - Payload zum ersten - Überlanges Startbit - Payload zum zweiten - Überlanges Startbit - Payload zum dritten Also Trainingsbits nur vor der ersten Sendung, danach bei den Folgeaussendungen jeweils zwar das Überlange Startbit und dann die Payload. > Wie würde man das dann auswerten? ISR-auf steigende Flanke->Timer > starten->Stop auf nächster steigender Flank->Zeit in ein array schreiben > und am ende evaluieren? Ich mache das nur unter Arduino mit Change-Interrupt auf beide Flanken. In der Interruptbehandlung wird der Pin-Status 1 oder 0 ausgelesen und die Zeitdifferenz gebildet aus aktuellem und letztem Timerstand, sowie der aktuelle Timerstand gespeichert. Und je nachdem weiß man dann - wenn der Pegel jetzt HIGH ist, haben wir die Zeit für einen LOW-Impuls - wenn der Pegel jetzt LOW ist, haben wir die Zeit für einen HIGH-Impuls Bei LOW-Impuls: Wenn Dauer +/- Toleranz == Startimpulsdauer, dann setze "counting" auf true und "bitcount" auf 0. Ansonsten: Wenn Impulslänge einem 1-Bit entspricht: Bit merken, bitcount++ Wenn Impulslänge einem 0-Bit entspricht: Bit merken, bitcount++ Wenn danach bitcount== Anzahl Bits in der Payload ==> Ergebnis z.B. in einen FIFO-Puffer schieben Beim Auftreten "falscher" Bitlängen ==> counting=false, bitcount=0 Mit welcher Taktfrequenz soll denn Dein Controller laufen? Hast Du schon irgendwelche Timer für irgendwas verbraten oder sind noch alle Timer frei verfügbar?
Jürgen S. schrieb: > Innerhalb der Payload scheint es bei Dir drei verschiedene Bitlängen zu > geben: HIGH-Bits in einfacher und doppelter Länge sowie LOW-Bits in > einfacher, doppelter und vierfacher(?) Länge? Die unterschiedlichen Längen waren keine Absicht. Zwischen den Bytes hat er die richtigen Werte in einem großen Array im EEPROM gesucht, was offenbar länger gedauert hat, als eine Bitbreite. Jetzt such ich mir die Werte vorher zusammen. Jetzt hab ich nur noch 2 Längen > > Kannst Du mal das Sende-Codeschema genau beschreiben? Ich hab festgestellt, dass ich den Reciever erst mit einem langen Startbit (5 ms) aufwecken muss. Also sende ich jetzt: Startbit - 5ms high Signal Marker - 10x200µs High-Low Payload - Byte 1-3 Stuffing Byte > Ich mache das nur unter Arduino mit Change-Interrupt auf beide Flanken. Mein Sender Empfänger- Paar verschleift mir die Bit-längen ziemlich. Auf sender-Seite mache ich 200µs high, dann 200µs low (Für 0) oder 400µs high und 200µs low (für 1). Auf der Empfängerseite kommt an: 0: 115µs high 285µs low 1: 205µs high 400µs low Die zeitliche Position der steigenden Flanken stimmt also, die der fallenden ist grotesk verzerrt. Ich trigger daher nur auf die steigende Flanke. Damit verpasse ich das letzte Bit, also hab ich noch ein Byte angehängt. Davon kann ich dann die ersten höheren 7 Bit als Checksumme nutzen. > In der Interruptbehandlung wird der Pin-Status 1 oder 0 ausgelesen und > die Zeitdifferenz gebildet aus aktuellem und letztem Timerstand, sowie > der aktuelle Timerstand gespeichert. Und je nachdem weiß man dann > - wenn der Pegel jetzt HIGH ist, haben wir die Zeit für einen LOW-Impuls > - wenn der Pegel jetzt LOW ist, haben wir die Zeit für einen HIGH-Impuls > > Bei LOW-Impuls: Wenn Dauer +/- Toleranz == Startimpulsdauer, dann setze > "counting" auf true und "bitcount" auf 0. > Ansonsten: > Wenn Impulslänge einem 1-Bit entspricht: Bit merken, bitcount++ > Wenn Impulslänge einem 0-Bit entspricht: Bit merken, bitcount++ > Wenn danach bitcount== Anzahl Bits in der Payload ==> Ergebnis z.B. in > einen FIFO-Puffer schieben > Beim Auftreten "falscher" Bitlängen ==> counting=false, bitcount=0 Danke für den Part. Hab ich genau so übernommen, nur, dass ich nicht zwischen High und Low differenziere. > Mit welcher Taktfrequenz soll denn Dein Controller laufen? Der Sender mit 1 MHz, der Empfänger mit 8MHz > Hast Du schon irgendwelche Timer für irgendwas verbraten oder sind noch > alle Timer frei verfügbar? Alle timer noch Frei. Für die Messung der Länge der Pulse hab ich den 16-Bit Timer mit 1 MHz hergenommen. Für die Checksumme hatte ich mir einfach gedacht Byte1+byte2+byte3=CHK Läuft ein uint8 einfach über(und fängt bei 0 an) wenn das größer als 255 wird, oder ist der dann limitiert auf 255?
Mit der Prüfsumme zusammen hättest Du die Möglichkeit eine höhere Toleranz beim Abstand der Flanken zuzulassen, z.B. +/-10% akzeptierst Du als die gewünschte Länge. Wenn am Ende der CRC stimmt, dann hast Du valide Daten empfangen. Dann muss Du kein Byte anhängen wg. fehlender fallender Flanke. Ich habe mir mal einen Empfänger für uralte ELV-Funksensoren einer Wetterstation selbst gebaut und dort festgestellt, dass die Flankenabstände durch schwächeres Signal sehr stark verzerrt werden - ab einem bestimmten Level hast du nur noch mit hoher Toleranz eine Chance. Das Protokoll gibt's hier: http://www.dc3yc.privat.t-online.de/protocol.htm Aber das kombiniert mit einer Prüfsumme und ggf. einer State Machine (z.B. Präambel 11111111 > Nibble > Bit 1 > Nibble > Bit 1 > Nibble ... > CRC ) gibt Dir die Sicherheit, dass Du echte Daten erkannt hast und Du kannst an die Grenzen gehen. Die State Machine resettet einfach immer, wenn das Empfangene nicht dem erwarteten entspricht. Und durch die Präambel weisst sofort, ob da überhaupt der Anfang von Daten im Gange ist. D.h. bei "wirrem" Emfang geht die Statemachine nach wenigen Bits sofort wieder auf Anfang und Du verpasst nichts. Es könnte auch nach jedem Nibble/Byte eine Parität mitkommen, dann weisst an der Stelle schon, ob das sein kann. Ich hänge Dir die Library für den ELV-Empfang und Versand in C einfach mal an.
:
Bearbeitet durch User
Hat mich grad selber interessiert. Wie man sieht hab ich sehr hohe Toleranz eingestellt: #define BIT_TOLERANCE 12 #define BIT0_TICKS 54 // 53 #define BIT1_TICKS 24 // 23 #define BIT_TICKS 80 // 76 Also bei Bit 1 sogar 50% der Soll-Flankenzeit, bei Bit 0 25%.
Fabian F. schrieb: > Mein Sender Empfänger- Paar verschleift mir die Bit-längen ziemlich. Auf > sender-Seite mache ich 200µs high, dann 200µs low (Für 0) oder 400µs > high und 200µs low (für 1). > Auf der Empfängerseite kommt an: > 0: 115µs high 285µs low > 1: 205µs high 400µs low Wie nah beieinander befinden sich Sender und Empfänger dabei? Falls sich Sender und Empfänger sehr nah beieinander befinden, kann es sein, dass der Empfänger aufgrund der hohen Feldstärke total übersteuert wird, und Regenerativempfänger verzerren in dem Fall extrem stark. Abhilfe wäre dann, den Abstand zwischen Sender und Empfänger zu vergrößern, dann sollte die Verzerrung kleiner werden. > Für die Checksumme hatte ich mir einfach gedacht Byte1+byte2+byte3=CHK > Läuft ein uint8 einfach über(und fängt bei 0 an) wenn das größer als 255 > wird, oder ist der dann limitiert auf 255? Kann man machen, das Byte läuft einfach über. Du bekommst als Prüfsumme dann bei einem uint8 quasi "Summe modulo 256". Bei 433MHz-Temperatursensoren habe ich schon gesehen, dass für das Prüfsummenbyte einfach alle Datenbytes mit "bitweisem XOR" verknüpft werden. Ich habe aber keine Ahnung, ob das ggf. gegenüber einer Prüfsumme irgendwelche Vorteile bei der Fehlererkennung hat.
Jürgen S. schrieb: > Fabian F. schrieb: >> Mein Sender Empfänger- Paar verschleift mir die Bit-längen ziemlich. Auf >> sender-Seite mache ich 200µs high, dann 200µs low (Für 0) oder 400µs >> high und 200µs low (für 1). >> Auf der Empfängerseite kommt an: >> 0: 115µs high 285µs low >> 1: 205µs high 400µs low > > Wie nah beieinander befinden sich Sender und Empfänger dabei? > > Falls sich Sender und Empfänger sehr nah beieinander befinden, kann es > sein, dass der Empfänger aufgrund der hohen Feldstärke total übersteuert > wird, und Regenerativempfänger verzerren in dem Fall extrem stark. > Abhilfe wäre dann, den Abstand zwischen Sender und Empfänger zu > vergrößern, dann sollte die Verzerrung kleiner werden. Sehr nah. Sind noch auf einem Panel. Ich hab das Funkmodul mal mit einem Kabel verbunden und weiter weg bewegt. jetzt sieht es besser aus (s. Bild) > Kann man machen, das Byte läuft einfach über. > Du bekommst als Prüfsumme dann bei einem uint8 quasi "Summe modulo 256". Sollte für meine Zwecke reichen. Ob ein Wert plausibel ist erkenne ich auch so. Dass sich die Temperatur im Wohnzimmer auf einen Schlag um 30° ändert ist unwarscheinlich. @ Conny G Dankeschön. Für dieses Projekt ist das vermutlich etwas overkill. Könnte ich aber wohl brauchen wenn ich den Türöffner automatisere. Der soll nur öffnen wenn wirklich ich vor der Tür stehe :-)
Fabian F. schrieb: > Sehr nah. Sind noch auf einem Panel. Ich hab das Funkmodul mal mit einem > Kabel verbunden und weiter weg bewegt. jetzt sieht es besser aus (s. > Bild) Ich habe nochmal in alte Arduino-Codes von mir reingeschaut, in denen es um die Decodierung von gekauften Tchibo und anderen Funktemperatursensoren geht, und dabei ist mir beim Datenprotokoll im Zusammenspiel mit den handelsüblichen Sensoren folgendes aufgefallen: Die relevanten Informationen werden nicht in den On-Phasen des Funksignals gesendet, sondern nur in den Off-Phasen (LOW). Es gibt also eine inverse Sendelogik. D.h. das auszuwertende überlange Startbit nach den Trainingsbits wird nicht mit Sender-Ein gesendet, sondern mit umgekehrter Sendelogik als Sender-Aus, entsprechend Empfänger-LOW. Die relevanten Bits der Payload genau so: Ausgewertet wird immer die Sendepause als Bitlänge für ein 0-Bit oder 1-Bit, und zwischendrin wird kurz gesendet, aber die Sendedauer ist irrelevant für die Datenauswertung. Das dient vermutlich zur Optimierung der Laufzeit beim Batteriebetrieb: Wenn man möglichst wenig Sendezeit hat, hält die Batterie um so länger durch. Falls Du also auch für Batteriebetrieb planst, ist vermutlich die "umgekehrte Sendelogik" mit Codierung von Startbit, 0-Bit und 1-Bit in den Sendepausen (LOW-Zeiten) günstiger als die Auswertung der Sendezeiten (HIGH-Zeiten). Für eine optimale Reichweite benötigen diese billigen Sender/Empfänger übrigens eine Antenne. Im einfachsten Fall für gute Reichweite eine Lambda/4-Antenne in Form von 17,5 cm Draht, angelötet am "Ant" Lötauge des Senders bzw. Empfängers.
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.