Bei der Planung der Blitzinfrastruktur (Wandschalter und Beleuchtung) meines neuen Hauses (das sich noch im Bau befindet) habe ich mich aufgrund meines Hintergrunds für die "automatisierte Route" entschieden und bin ein "altes" System / Netzwerk Administrator mit Programmierkenntnissen und viel Open-Source "Leidenschaft" und "Anwaltschaft") Ich versuche ernsthaft, es mit drei Arduinos und einem RPi2 zu implementieren.
Aufgrund der Anzahl / Position der Wandtasten und Lichter möchte ich drei MEGA-Schnittstellen verwenden, die sowohl die Wandtasten als auch die Lichter der umgebenden Räume miteinander verbinden. Darüber hinaus wird ein RPi2 (oder ähnliches) als "Controller" verwendet, um MEGAs bei Bedarf ordnungsgemäß zu programmieren und einige andere Geräte (Touchscreen, WLAN-Tablet / Smartphone, Fernbedienungen usw.) über die IP-Adresse anzuschließen. Netzwerk.
Das Schema, das ich zu implementieren versuche, ähnelt dem folgenden:
- 9 Lichter (L1 bis L9), die jeweils von einem eigenen Relais (R1 bis R9) gesteuert werden;
- 7 Wandtasten (WPB1 bis WPB7) zum Ein- und Ausschalten eines oder mehrerer Lichter;
- 3 MEGAs, die Wandtasten und Lichter verbinden;
- 1 RPi2 als "Supervisor" und "Internet / Ethernet-Gateway".
Mein Hauptproblem in der Architektur betrifft die Verbindung zwischen RPI2 und MEGAs. Da sich jedes Gerät mehrere zehn Meter voneinander entfernt befindet, endete ich mit nur zwei Optionen (bitte korrigieren Sie mich, wenn ich falsch liege):
- Ethernet
- RS485
( Übrigens: Ich schließe "drahtlose Verbindungen" ausdrücklich aus, da ich bereits alle elektrischen Leitungen auf "kompatible" Weise verlegt habe. Mit anderen Worten: Ich möchte drahtlose Technologien innerhalb des "steuernden Netzwerks" vermeiden. )
Ethernet werde ich aufgrund der etwas höheren Kosten und Komplexität als zweite Option wählen (zum Einschalten muss ein Switch benötigt werden; zusätzliche Verkabelungsprobleme usw.).
Ich habe den " RS485-Bus " ausgiebig untersucht und festgestellt, dass es aus physikalischer Sicht relativ einfach ist, ihn mit zwei Drähten in einer Multidrop-Konfiguration zu implementieren .
Aus "Anwendungssicht" sind die Dinge leider komplexer, da nur "Halbduplex" -Kommunikation unterstützt wird und, noch schlimmer, es keine Vorkehrungen gibt, um "Kollisionen" bei der Kommunikation zu vermeiden (deshalb wahrscheinlich das MODBUS-Protokoll) - Wird normalerweise auf dem RS485-Bus verwendet - bietet ein "Single-Master; Multiple-Slaves" -Szenario.
Vor den Fragen muss ich noch eine weitere Einschränkung hinzufügen: Ich möchte, dass die Infrastruktur "so fehlertolerant wie möglich" ist, insbesondere gegenüber Problemen mit dem BUS und / oder mit dem "Controller" (dem RPI2). Mit anderen Worten:
- Jedes MEGA sollte es erlauben, seine eigenen Lichter einzuschalten, wenn dies für einen eigenen Druckknopf erforderlich ist. Zum Beispiel:
- Wenn WPB1 L2 und L3 steuert, muss es auch dann funktionieren, wenn der BUS defekt oder der RPI2 ausgeschaltet ist.
- Wenn WPB3 L4 und L9 steuert, wird bei Problemen mit Bus / RPI2 nur L4 eingeschaltet, wenn WPB3 gedrückt wird.
Nach all dem sind hier meine Fragen:
Ist ein zweidrahtiger RS485-Multidrop-Bus eine geeignete Wahl für mein Szenario?
Wenn nicht, welche (möglicherweise billigen und einfachen) anderen Lösungen kann ich untersuchen?
Wenn ja, welche Logik muss ich auf MEGAs implementieren:
- a) Sie müssen in Bezug auf RPI2 als "Slave" fungieren, wenn sie Lichter einschalten, die über einen mit anderen MEGAs verbundenen Druckknopf gesteuert werden, oder wenn das RP2 beschließt, einige Lichter einzuschalten (z. B. aufgrund von Fern- / Internetzugang). ;;
- b) Sie müssen als "Master" fungieren, wenn einer ihrer Drucktasten gedrückt wird und ... dies muss RPI2 mitgeteilt werden, um Befehle an andere MEGAs zu senden und "gehostete" Lichter einzuschalten.
Wie für 3b) kann ich eine "Frequent-Polling" -Logik auf dem RPI2 implementieren, wenn MEGAs beim Drücken eines WPB als Master fungieren? Wenn ja, welcher Wert ist für eine solche Umfrage angemessen (1 Umfrage pro Sekunde? 5 Umfragen pro Sekunde? Zu viel? Zu niedrig?)
Ich verstehe, dass dies eine zu weit gefasste Frage ist, aber ich habe wirklich viele Nachforschungen angestellt und trotz vieler, vieler und vieler Online-Dokumentationen konnte ich keine Antwort auf diese Fragen finden.
Update 1
- In Bezug auf die Gesamtzahl habe ich 31 Lichter, die über 46 Wandtasten gesteuert werden können, die mehr oder weniger gleichmäßig auf 4 verschiedene Schalttafeln verteilt sind.
- Bei der Auswahl von MEGA (vs. UNO) habe ich mich aufgrund der größeren Anzahl von E / A-PINs für MEGA entschieden. Ich habe einfach das Board mit der maximalen Anzahl von PINs ausgewählt.
- Für das RPI2 habe ich mich für einen geeigneten "Computer" (im Vergleich zu einem zusätzlichen Mikrocontroller) entschieden, da ich eine Art "Entkopplung" zwischen dem "physischen Steuerungsnetzwerk" und der "Benutzerverwaltungsoberfläche" möchte. Mit anderen Worten, ich möchte, dass die Verwaltung von physischen Tasten / Relais von einem SPS-ähnlichen Gerät übernommen wird (Arduino: sehr schnelles Einschalten; Art von Echtzeitleistung; sehr zuverlässig; geringfügige / keine externen "Rechen" -Faktoren, die Verzögerungen verursachen / Probleme); Gleichzeitig wird die gesamte Benutzeroberfläche von einem realen Computer verwaltet, auf dem ich mithilfe von Technologien und Sprachen, die nicht gut zu Arduino passen, problemlos leistungsstarke HTTP-Webdienste und / oder wirklich komplexe "Logiken" schreiben kann (später - viel später - habe ich vor, mehrere 150 $ Full-HD 10.1 hinzuzufügen " Rund um das Haus gibt es Android-Tablets, die als drahtlose "Clients" für einen "leistungsstarken" Webserver (in Bezug auf die Rechenkapazität) fungieren. Außerdem habe ich vor, verschiedene Sensoren hinzuzufügen [Temperatur; Feuchtigkeit; Kontakte; Leistungsmesser; usw.], deren Daten aus Trend- / Archivierungsgründen gespeichert werden müssen). Daher habe ich über RPi2 unterrichtet, das leicht durch etwas Stärkeres ersetzt werden kann, falls es benötigt wird.
quelle
Antworten:
Ich habe einen langen Beitrag über RS485 geschrieben .
Erstens scheint Ihre Verwendung von Megas ein Overkill zu sein, es sei denn, Sie haben sie bereits zur Hand. Ein Uno oder eine der kleineren Formfaktor-Karten scheint vollkommen ausreichend zu sein, um einige Schalter zu überwachen und ein paar Lichter einzuschalten.
Sogar das RPI scheint unnötig. Ein anderer Uno kann problemlos Ihre RS485-Leitungen überwachen und über Ethernet (eine Ethernet-Abschirmung) eine Verbindung zum Rest Ihres Hauses herstellen oder was auch immer Sie tun.
Nun, Sie bauen das ein. Sie geben jedem Mega eine Adresse (z. B. im EEPROM gespeichert) und "adressieren" dann die gewünschte Adresse und warten dann auf eine Antwort. Zum Beispiel im Code von meiner obigen Seite:
Meister
Sie konfigurieren den RS485-Transceiver so, dass er entweder sendet oder empfängt. Normalerweise befindet es sich im Empfangsmodus und Sie wechseln in den Sendemodus, um ein "Datenpaket" zu senden. (Siehe "Senden aktivieren" oben).
Jetzt schaltet das adressierte Gerät seinen Transceiver in den "Send" -Modus und antwortet. Der Code in der Bibliothek, den ich geschrieben habe, hat eine Zeitüberschreitung. Wenn also dieser bestimmte Slave tot ist, läuft der Empfang ab. Vielleicht erinnern Sie sich am Master-Ende daran und versuchen, seltener damit zu kommunizieren. Oder es ist Ihnen egal, ob die Auszeit kurz ist.
Sklave
Hinweis : Der Beispielcode von meiner verlinkten Seite liest die Adresse nicht aus dem EEPROM, dies ist jedoch trivial zu implementieren.
Ich kann keinen bestimmten Grund erkennen, warum Sie die Sklaven nicht häufig befragen konnten. Was würde der Meister sonst noch tun? Sie können den Master auch als HTTP-Server einrichten, um von Ihrem Laptop oder einem anderen Teil des Hauses aus mit ihm zu kommunizieren.
Meine Verkabelung:
Um die Idee zu demonstrieren, habe ich zwei Unos aufgestellt, die über ca. 8 m Glockendraht verbunden sind (nicht einmal Twisted Pair und schon gar nicht abgeschirmt).
Ein Uno führte die Standard-ASCII-Tabellenskizze (bei 9600 Baud) aus, sein Tx-Pin ging in den LTC1480 und dann gingen die A / B-Pins zum Glockendraht.
Das andere Uno war als USB-Schnittstelle angeschlossen (Reset mit Masse verbunden) und gab nur das wieder, was auf dem Tx-Pin des USB-Anschlusses angekommen war.
Soweit ich sehen konnte, hat es perfekt funktioniert.
Meine obige Antwort ging davon aus, dass die Slaves eher versagen als der Master (ich kann mir nicht vorstellen, warum dies passieren würde, aber vielleicht aufgrund der Tatsache, dass es mehr Slaves als Master gibt und der Master Dinge wie Lichter nicht kontrolliert ).
Ich finde meine Arduinos äußerst zuverlässig, wenn ich einfache Dinge tue (wie das Aufschließen einer Tür, wenn eine RFID-Karte vorgelegt wird).
Es ist denkbar, dass Sie eine Rückfallposition in die Sklaven einbauen. Wenn sie jede Sekunde abgefragt werden und dann keine Umfrage eintrifft, könnten sie möglicherweise versuchen, als Master zu fungieren, möglicherweise in aufsteigender Reihenfolge der Gerätenummer, um Konflikte zu vermeiden. Ein Teil dieser Abfrage durch den "neuen Master" könnte darin bestehen, den "ursprünglichen Master" zu überprüfen, um festzustellen, ob er bereit ist, seine Aufgaben wieder aufzunehmen.
In die Bibliothek, die ich auf meiner verlinkten Seite beschrieben habe, ist eine Fehlerprüfung integriert. Die Idee ist, dass Sie durch Überprüfen einer CRC für das Paket sicherstellen, dass Sie nicht auf halbem Weg durch ein Paket kommen und die darin enthaltenen Daten falsch interpretieren.
Sie können auch zufällige Zufallszeiten einbauen, um einen Deadlock zu beheben, wenn zwei Slaves gleichzeitig versuchen, Master zu werden. Wenn ein Slave ausfällt, kann er eine zufällige (und zunehmende) Zeit warten, bevor er erneut versucht, einem anderen Slave die Möglichkeit zu geben, dies zu tun.
Gerben hat recht, aber ich würde mir Sorgen machen, dass eine Benachrichtigung über einen Wechsel unbemerkt blieb. Eine mögliche Problemumgehung besteht darin, dass die Slaves nicht mit Statusänderungen auf eine Abfrage antworten, sondern mit dem aktuellen Status antworten. So könnte es gehen:
Ich habe ein bisschen darüber nachgedacht, und ich denke, jetzt könnten Sie ein System erstellen, das im Grunde genommen masterfrei ist. Es könnte so funktionieren:
Jedes Gerät hat eine eigene Adresse, die es vom EEPROM (oder den DIP-Schaltern) erhält. z.B. 1, 2, 3, 4, 5 ...
Sie wählen einen Adressbereich aus, den Sie verwenden möchten (z. B. maximal 10).
Wenn das Gerät eingeschaltet wird, lauscht es zuerst auf andere Geräte, die auf dem Bus "sprechen". Hoffentlich hört es mindestens einen anderen (wenn nicht, siehe unten).
Wir entscheiden uns für ein festes "Nachrichtenpaket", beispielsweise von 50 Bytes, einschließlich Adresse, CRC usw. Bei 9600 Baud würde das Senden 52 ms dauern.
Jedes Gerät erhält einen "Zeitschlitz" und wartet, bis es an der Reihe ist, mit dem Bus zu sprechen.
Wenn sein Zeitschlitz eintrifft, wechselt er in den Ausgabemodus und sendet sein Paket, das seine eigene Adresse enthält. Daher können jetzt alle anderen Geräte ihren Status lesen (und gegebenenfalls darauf reagieren). Z.B. Gerät 1 meldet möglicherweise, dass Schalter 3 geschlossen ist, was bedeutet, dass Gerät 2 ein Licht einschalten muss.
Im Idealfall wissen Sie, dass Ihr Zeitfenster angekommen ist, da Ihre Geräteadresse um eins größer ist als das Paket, das Sie gerade abgehört haben. Z.B. Sie sind Gerät 3. Sie haben gerade gehört, dass Gerät 2 seinen Status ankündigt. Jetzt bist du dran. Natürlich wickeln Sie sich mit der maximalen Anzahl um, also kehren Sie nach Gerät 10 zu Gerät 1 zurück.
Wenn ein Gerät fehlt und nicht antwortet, geben Sie ihm (sagen wir) einen halben Zeitschlitz, um zu antworten, und nehmen dann an, dass es tot ist, und jedes Gerät im Bus geht jetzt davon aus, dass der nächste Zeitschlitz gestartet wurde. (z. B. Sie haben gehört, dass Gerät 2, Gerät 3 antworten sollte. Nach 25 ms Inaktivität kann Gerät 4 jetzt antworten.) Diese Regel gibt einem Gerät 25 ms Zeit, um zu antworten. Dies sollte ausreichend sein, selbst wenn es einen Interrupt oder ähnliches bedient.
Wenn mehrere Geräte nacheinander fehlen, zählen Sie für jedes fehlende Gerät eine Lücke von 25 ms, bis Sie an der Reihe sind.
Sobald Sie mindestens eine Antwort erhalten, wird das Timing neu synchronisiert, sodass jede Drift in den Uhren aufgehoben wird.
Die einzige Schwierigkeit besteht darin, dass beim ersten Einschalten (was gleichzeitig passieren kann, wenn die Stromversorgung des Gebäudes unterbrochen und dann wiederhergestellt wird) derzeit kein Gerät seinen Status sendet und daher nichts synchronisiert werden kann.
In diesem Fall:
Wenn das Gerät lange genug gehört hat, um alle Geräte zu hören (z. B. 250 ms) und nichts zu hören, geht es vorläufig davon aus, dass es das erste ist, und sendet eine Sendung. Möglicherweise tun dies jedoch zwei Geräte gleichzeitig und hören sich daher nie.
Wenn ein Gerät nichts von einem anderen Gerät gehört hat, wird die Zeit zwischen den Sendungen zufällig verschoben (möglicherweise wird der Zufallszahlengenerator aus seiner Gerätenummer entfernt, um zu vermeiden, dass alle Geräte die Sendungen "zufällig" um denselben Betrag versetzen).
Diese zufällige Staffelung um zusätzliche Zeit spielt keine Rolle, da sowieso niemand zuhört.
Früher oder später wird ein Gerät den Bus exklusiv nutzen und die anderen können dann auf die übliche Weise mit ihm synchronisieren.
Diese zufällige Lücke zwischen Kommunikationsversuchen ähnelt der von Ethernet, wenn mehrere Geräte ein Koaxialkabel gemeinsam nutzen.
Demo des masterfreien Systems
Dies war eine interessante Herausforderung, daher habe ich eine Demo zusammengestellt, in der dies ohne einen bestimmten Master durchgeführt wurde, wie oben beschrieben.
Zuerst müssen Sie die aktuelle Geräteadresse und die Anzahl der Geräte im EEPROM einrichten. Führen Sie diese Skizze aus und ändern Sie sie
myAddress
für jedes Arduino:Laden Sie dies nun auf jedes Gerät hoch:
Wenn Sie derzeit einen Schalter an A0 (Kurzschluss nach Masse) schließen, wird nacheinander eine LED (Pin 13) am nächsthöheren Gerät ausgeschaltet. Dies beweist, dass die Geräte miteinander sprechen. In der Praxis hätten Sie natürlich etwas Anspruchsvolleres in dem Paket, das gesendet wird.
Beim Testen stellte ich fest, dass die LED sofort ein- und ausgeschaltet zu sein schien.
Wenn alle Geräte getrennt sind, "sucht" das erste angeschlossene nach anderen Geräten. Wenn Sie Debugging-LEDs wie ich angeschlossen haben, können Sie sehen, dass die "Such" -LED in zufälligen Intervallen aufleuchtet, wenn sie ihr Paket mit zufällig variierenden Lücken sendet. Sobald Sie eine zweite angeschlossen haben, beruhigen sie sich und tauschen einfach Informationen aus. Ich habe mit drei gleichzeitig verbundenen getestet.
Mit HardwareSerial wäre es wahrscheinlich zuverlässiger - ich habe SoftwareSerial verwendet, um beim Debuggen zu helfen. Ein paar kleine Änderungen würden das erreichen.
Geänderter Schaltplan
Screenshots des Codes in Aktion
Diese Bilder zeigen, wie der Code funktioniert. Erstens, wenn nur ein Gerät angeschlossen ist:
An den dortigen Impulsen können Sie erkennen, dass das Gerät seine Daten in zufällig variierenden Intervallen sendet, um zu vermeiden, dass es weiterhin zu Konflikten mit einem anderen Gerät kommt, das im selben Moment eingeschaltet wurde.
Jetzt sehen wir Datenblöcke von zwei Geräten mit ungefähr gleich großen Lücken in der Mitte. Ich habe es für vier Geräte konfiguriert, aber nur zwei sind vorhanden, sodass wir zwei Datenblöcke und zwei Lücken sehen.
Jetzt, da drei Geräte online sind, sehen wir drei Datenblöcke und eine Lücke, da das fehlende Gerät umgangen wird.
Wenn Sie die Zahlen überprüfen, wurden diese mit der Baudrate genommen, die als Test auf 19200 Baud verdoppelt wurde.
Kabelführungstest
Für einen ordnungsgemäßen Hardwaretest habe ich die Geräte an meine interne UTP-Verkabelung angeschlossen. Ich habe ein Cat-5-Kabel, das von verschiedenen Räumen zu einer zentralen Steckdose führt. Wenn Sie von einem Ende des Hauses zum anderen gehen (eine angemessene Länge), funktioniert es immer noch einwandfrei. Zunächst befindet sich zwischen dem Arduino und der Wandsteckdose ein 5 m langes Kabel. Plus ein weiteres 5 m Kabel am anderen Ende. Dann gibt es ungefähr 2 x 15 m Läufe von den Räumen zum Schaltraum, und darin befindet sich ein kurzes Überbrückungskabel, um sie miteinander zu verbinden.
Dies war mit den Boards noch programmiert, um mit 19200 Baud zu laufen.
quelle
is a 10-polls per second, on a 9600 baud rate, a reasonable choice?
- In meinem aktuellen Test (siehe Screenshots) teste ich 4 Geräte wiederholt in 75 ms bei 19200 Baud, das sind 13 Statusberichte pro Sekunde. Grundsätzlich bedeutet dies, dass ein Gerät in 1/10 Sekunde auf eine Statusänderung (z. B. ein Schließen des Schalters) eines anderen Geräts reagieren sollte. In Ihrer ersten Frage wurden 4 Geräte erwähnt, sodass Sie ähnliche Ergebnisse erzielen sollten.Denken Sie daran, RS485 ist kein Protokoll, sondern eine Definition einer physischen Transportschicht. Mit dem Mega, wie Sie es ausgewählt haben, können Sie die serielle 1,2,3 verwenden und sie im Vollduplex-Modus über das RS485-Netzwerk ausführen. Sie können also empfangen, was Sie senden.
Ich habe es in einer Multi-Master-Konfiguration betrieben. Jedes Mega empfängt beim Senden auch das, was es gerade gesendet hat, und kann byteweise feststellen, ob es sich zurückziehen muss. Die Verzögerung vor der Rückkehr in die Leitung wird durch die Knotenadresse und den Zeitpunkt bestimmt, zu dem der Bus verfügbar wird.
Der Code verwendet die Schreibfunktion anstelle der Druckfunktion, mit der jedes Byte überprüft werden kann. (Mit der Zeit werde ich es wahrscheinlich per Software machen und CAN emulieren oder einfach einen Dosencontroller verwenden). Ja, 8 Bits funktionieren einwandfrei. Das neunte Bit ist ein Paritätsbit oder eine andere Verwendung, je nachdem, wer es definiert.
Mein Testsystem arbeitet mit Paketen und sendet in diesem Format:
| Länge | Ziel | Quelle | Sequenz | Befehl | Flags | Daten | Prüfen
und erwartet eine ACK als Antwort. Dies ist ein relativ einfacher erster Durchgang und hat keine illegalen Codes. Alle Bytes sind Hex, aber Sie können verwenden, was Sie wollen.
Dies gibt mir Carrier Sense, Mehrfachzugriff, aber mit destruktiver Schiedsgerichtsbarkeit. Wenn Sie möchten, dass CSMANDA nur eine CAN-physische Schicht verwendet oder die von Ihnen gesendeten Daten bitknallt, können Sie bitweise vermitteln. In der Software wird es nicht viel anders sein als im Sendeteil.
Ich plane, das RPi mit Linux als Hauptknoten zu verwenden. Mit 8-Bit-Daten funktioniert es einwandfrei. Ich habe vor ungefähr zwei Wochen mit dieser Konfiguration begonnen und bis jetzt läuft sie gut. Ich arbeite mit 9600 Baud und habe viel Freizeit.
Gil
quelle
Wenn Sie das Protokoll von Nick Gammon verwenden möchten, ist dies möglicherweise hilfreich: https://github.com/Sthing/Nick-Gammon-RS485
Es ist meine Implementierung des Protokolls in Python (zur Verwendung auf einem RaspberryPi). Ich habe bisher nur Python-to-Python getestet. Das Testen mit Nick Gammons Code steht als nächstes auf meiner To-Do-Liste.
/Ding
quelle
Ich denke, das CDBUS-Protokoll für RS485 ist genau das, was Sie wollen. Es führt einen Arbitrierungsmechanismus ein, der Konflikte wie den CAN-Bus automatisch vermeidet. Ich kann sogar Videostreams übertragen:
Vollständiges Video: https://youtu.be/qX5dh4wcfSk
Der Raspberry Pi kann gleichzeitig ein Vorschau-Video und einen Steuerbefehl ausgeben. Wir können den Erkennungsprozess auf dem PC überwachen. Wenn Probleme auftreten, ist es zweckmäßig, den Grund zu kennen und die Parameter anzupassen. Das Trennen des PCs hat keine Auswirkungen auf den Demo-Betrieb.
Darüber hinaus kann der Raspberry Pi jederzeit über den PC auf das Internet zugreifen und die Software einfach aktualisieren und fernsteuern.
Details zum CDBUS:
Update: Verbinden Sie den CDCTL-Bx-Controller mit einem Arduino:
quelle