Weichendecoder mit Servo

little.yoda
Site Admin
Beiträge: 385
Registriert: 14.09.2018, 19:05
Hat sich bedankt: 8 Mal
Danksagung erhalten: 20 Mal

Re: Weichendecoder mit Servo

Beitrag von little.yoda » 24.06.2019, 20:48

Lorenzo hat geschrieben:
22.06.2019, 09:51
little.yoda hat geschrieben:
21.06.2019, 18:42
Im Prinzip schwebt mir vor, dass man Variablen im Config-File definieren kann, die auf GPIO zurückgreifen.
Aber diesen Ansatz habe ich noch nicht zu ende durchdacht.
Kann man dann auf diese Variablen auch von allen Programmteilen aus zugreifen? Diese ganze Trennung mit Klassen hat in Bezug auf Übersichtlichkeit ja was für sich, stellt mich aber immer noch vor einige Herausforderungen.
Die Idee ist, dass du in der Config-Datei einen Variablen Bereich hast. Dort kannst du sagen, dass sich z.B. die Variable ID aus den Werten von GPIO X, Y und Z berechnet.

Im restlichen Bereich der Config-Datei kannst du dann einfach sagen id="${ID}".
Lorenzo hat geschrieben:
22.06.2019, 09:51
Da komme ich erst ganz langsam dahinter, wie das geht. Dank deiner geduldigen Unterstützung :D
Du warst immer sehr "pflegeleicht". Ein paar Tipps und du läufst los und programmierst. Das gefällt mir sehr.
Lorenzo hat geschrieben:
22.06.2019, 09:51
Dazu dann gleich noch eine Frage: wie stelle ich das an, aus ConnectorTurnout2Value heraus einen Status-String an CmdTransceiverMQTT zu schicken, so dass dieser dann die dortige publish Funktion nutzt um den Status über MQTT zu senden?
Wenn du mir sagst, was du vor hast, kann ich dir hoffentlich ein Vorschlag machen.

Lorenzo
Beiträge: 34
Registriert: 20.04.2019, 19:24
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Weichendecoder mit Servo

Beitrag von Lorenzo » 24.06.2019, 22:12

little.yoda hat geschrieben:
24.06.2019, 20:48
Du warst immer sehr "pflegeleicht". Ein paar Tipps und du läufst los und programmierst. Das gefällt mir sehr.
Danke. So ein Lob tut gut :P
little.yoda hat geschrieben:
24.06.2019, 20:48
Die Idee ist, dass du in der Config-Datei einen Variablen Bereich hast. Dort kannst du sagen, dass sich z.B. die Variable ID aus den Werten von GPIO X, Y und Z berechnet.

Im restlichen Bereich der Config-Datei kannst du dann einfach sagen id="${ID}".
Ich vermute, das betrifft im Wesentlich statische Werte, wie z.B. das einmalige Einlesen eines DIP-Schalters beim Start für Weichenadresse etc.

Ich plane aber auch, dynamische Werte einzulesen. Hintergrund ist, dass ich eine Weichenherzpolarisierung habe. Falls nun mal ein Zug aus der falschen Richtung kommt, bekomme ich ein Signal über einen MCP23017, dass die Weiche aufgeschnitten wird. Daraufhin schalte ich dann automatisch (hoffentlich rechtzeitig :lol:) die Weiche um und das bistabile Relais zur Weichenherzpolarisierung bekommt einen entsprechenden Impuls.

Ein weiterer Input wäre das Signal zur Lagekennung der Weiche, so dass ich nach Einschalten weiß, in welcher Lage sich die Weiche befindet und zusätzlich auch im Betrieb prüfen könnte, ob der Stellbefehl richtig ausgeführt wurde.

Ich habe ja MQTT eingebunden. Damit kann ich auch über MQTT die Weiche stellen und Zustandsinfos zurückmelden. Das funktioniert so weit so gut. Ich kann aus CmdTransceiverMQTT heraus auch einen Stellbefehl an ConnectorTurnout2Value schicken. Das klappt alles.
Für den Fall, dass der Stellbefehl aber über DCC kommt, würde ich diesen neuen Weichenstatus ebenfalls über MQTT melden. Fernes Ziel hierbei ist, den Gleisplan als Webseite im LAN zur Verfügung zu stellen, um von dort quasi über eine grafische Oberfläche die Weichen parallel zu DCC zu steuern. Das bedingt natürlich, dass die Weicheninfo immer synchronisiert sein muss. Ich hoffe, das war einigermaßen verständlich.

Beste Grüße
Lorenzo

little.yoda
Site Admin
Beiträge: 385
Registriert: 14.09.2018, 19:05
Hat sich bedankt: 8 Mal
Danksagung erhalten: 20 Mal

Re: Weichendecoder mit Servo

Beitrag von little.yoda » 27.06.2019, 21:19

So 100%ig habe ich es wohl immer noch nicht verstanden.

Kannst du es evtl. mal in ein pseudo-code packen?
So in Richtung Ereignis => Aktion

Etwas spekuliert:
Ich würde eine neue Action-Klasse für die Steuerung erzeugen.

Die Klasse empfängt dabei Weichenbefehle (siehe ConnectorTurnout2Value) und hat die Möglichkeit Weichenbefehle zu senden (ActionSendTurnoutCommand). Je nach den Zuständen des Belegmodules kann dann die notwendige Aktion vorgenommen werden

Lorenzo
Beiträge: 34
Registriert: 20.04.2019, 19:24
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Weichendecoder mit Servo

Beitrag von Lorenzo » 28.06.2019, 08:45

Wenn einem klar ist, was man machen will, ist es nicht immer so einfach, seine Gedanken so klar mitzuteilen, damit es auch andere verstehen. Deine Gedanken gehen aber schon in die richtige Richtung mit der Action-Klasse.

Aktuell läuft:
  • DCC Daten empfangen -> Weichenservo wird entsprechend gestellt
  • HTML Daten empfangen -> Weichenservo wird entsprechend des Vorgabewinkels in Grad gestellt (wird von mir aber nicht verwendet)
  • MQTT Daten empfangen -> Weichenservo wird entsprechend gestellt (da verwende ich in meiner MQTT Routine den Befehl: controller->notifyTurnout(Addr, dir, 5);
Was mir jetzt noch fehlt:
  • das 'saubere' Reagieren auf Zustände, die am MCP23017 anliegen. Ich habe das mal versucht, in der CmdTransceiverMQTT::loop() mit Pin* pin01 = new Pin("E0A0"); und GPIOobj.digitalRead(pin01);
    Das geht zwar grundsätzlich, aber es gibt nach einer Weile immer einen Reset. Ist so also noch keine Lösung. Vielleicht darf man ja aber auch nicht in einer Schleife immer wieder new Pin aufrufen?!?

    Hier könnte ich mir vorstellen, dass die Zustände am MCP global zur Verfügung stehen, so dass ich sie jederzeit von überall her abfragen kann, oder aber dass bestimmte Zustände bestimmte Action Routinen aufrufen, z.B. bei Vorliegen eines bestimmten gesetzten Bits, controller->notifyTurnout(Addr, dir, 5) aufgerufen wird. Das habe ich versucht, in void Controller::notifyGPIOChange(int pin, int newvalue) unterzubringen. Das mag bei mir aber der Compiler nicht. Dazu kenne ich mich mit den Klassen noch nicht gut genug aus.
  • die nächste Herausforderung ist für mich, die Zustände der Weiche auch über MQTT publish zu veröffentlichen, damit dort die Weichenzustände (z.B. für ein Gleisstellbild) synchron verfügbar sind.
    Das könnte ich mir z.B. so vorstellen, dass ich so wie ich das Weichenstellen mit controller->notifyTurnout(Addr, dir, 5); auslöse, auch den Status mit controller->notifyMQTT(Addr, Status); anstoße, so dass in CmdTransceiverMQTT der Status dann über publish veröffentlicht wird.
    Wenn ich einen Befehl über MQTT bekomme, kann ich innerhalb von CmdTransceiverMQTT einen Status wieder senden (mache ich hier mit CmdTransceiverMQTT::_instance->sendStatus(status);), aber aus anderen Modulen heraus kriege ich das nicht hin :(

    Macht es hier Sinn, bzw. ist es möglich, MQTT->publish in einer ActionMQTT zu verwalten (analog ActionServo), die ich dann von überall her aufrufen kann? MQTT senden und empfangen wären dann in zwei unterschiedlichen Modulen, was ja auch einen gewissen Charme hat.
Ich hoffe, ich war jetzt etwas verständlicher, ansonsten bitte weiterlöchern und fragen.

Beste Grüße und großen Dank für deine Mühen
Lorenzo

little.yoda
Site Admin
Beiträge: 385
Registriert: 14.09.2018, 19:05
Hat sich bedankt: 8 Mal
Danksagung erhalten: 20 Mal

Re: Weichendecoder mit Servo

Beitrag von little.yoda » 01.07.2019, 22:11

Anwort hat bisschen länger gedauert, aber bei dir muss ich mir etwas mehr Zeit für die Antwort nehmen.

Was ich bislang verstanden habe:

- Weichenbewegung über MQTT auslösen und per MQTT zurückmelden
- Je nach GPIO Änderung, sollen Weichenbefehle ausgelöst werden

Richtig?

Dann würde ich es in zwei Klassen aufteilen:
- Eine MQTT-Klasse, die das empfängen und senden der MQTT Befehle übernimmt.
- Eine Klasse, die nur auf die GPIO hört und dabei Weichenbefehle auslöst.
Lorenzo hat geschrieben:
28.06.2019, 08:45
Was mir jetzt noch fehlt:
  • das 'saubere' Reagieren auf Zustände, die am MCP23017 anliegen. Ich habe das mal versucht, in der CmdTransceiverMQTT::loop() mit Pin* pin01 = new Pin("E0A0"); und GPIOobj.digitalRead(pin01);
    Das geht zwar grundsätzlich, aber es gibt nach einer Weile immer einen Reset. Ist so also noch keine Lösung. Vielleicht darf man ja aber auch nicht in einer Schleife immer wieder new Pin aufrufen?!?
Durch new erzeugt du immer ein neues Objekt und irgendwann hast du keinen Speicher mehr.
Lösung: Variable in der Klasse deklarieren, einmal im Konstruktor erzeugen und dann immer nur GPIOobj.digitalRead(pin01); nutzen

Lorenzo hat geschrieben:
28.06.2019, 08:45
Hier könnte ich mir vorstellen, dass die Zustände am MCP global zur Verfügung stehen, so dass ich sie jederzeit von überall her abfragen kann, oder aber dass bestimmte Zustände bestimmte Action Routinen aufrufen, z.B. bei Vorliegen eines bestimmten gesetzten Bits, controller->notifyTurnout(Addr, dir, 5) aufgerufen wird. Das habe ich versucht, in void Controller::notifyGPIOChange(int pin, int newvalue) unterzubringen. Das mag bei mir aber der Compiler nicht. Dazu kenne ich mich mit den Klassen noch nicht gut genug aus.[/list]
Der saubere Weg wäre, dass deine Klasse von INotify erbt und du anschließend die Funktion virtual void GPIOChange(int pin, int newValue);implementierst, um über Änderungen an den GPIO imformiert zu werden.
In Config.cpp muss du dann deine Klasse noch als Notify-Klasse registieren: controller->registerNotify(a);
Lorenzo hat geschrieben:
28.06.2019, 08:45
  • die nächste Herausforderung ist für mich, die Zustände der Weiche auch über MQTT publish zu veröffentlichen, damit dort die Weichenzustände (z.B. für ein Gleisstellbild) synchron verfügbar sind.
Analog zu oben: Dazu sollte deine MQTT Klasse von INotify erben und anschließend die Klasse TurnoutCmd(int id, int direction, int source) implementieren, um über Weichenänderungen informiert zu werden.
In Config.cpp muss du dann wieder deine Klasse noch als Notify-Klasse registieren: controller->registerNotify(a);



Lorenzo hat geschrieben:
28.06.2019, 08:45
Macht es hier Sinn, bzw. ist es möglich, MQTT->publish in einer ActionMQTT zu verwalten (analog ActionServo), die ich dann von überall her aufrufen kann? MQTT senden und empfangen wären dann in zwei unterschiedlichen Modulen, was ja auch einen gewissen Charme hat.[/list]
siehe oben. Lieber bei der Klassen teilen.

Im Prinzip ist das Konzept einfach:
- Wenn du auf irgendeine Änderung lauschen willst, implementiere die Klasse inotify und nutzt in Config.cpp controller->registerNotify(a);
- Wenn du eine Änderung auslösen willst, notifyturnout

Wobei ich bei dem letzten Punkt gerade mir unsicher bin. Wie willst du die Lösung betreiben.
An einer Z21 Zentrale?

Die Rückmeldung an eine z21 ist noch nicht ganz fertig. Auch für das Thema Traktion muss ich diese Funktion noch einbauen.

Lorenzo
Beiträge: 34
Registriert: 20.04.2019, 19:24
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Weichendecoder mit Servo

Beitrag von Lorenzo » 02.07.2019, 08:30

little.yoda hat geschrieben:
01.07.2019, 22:11
Was ich bislang verstanden habe:

- Weichenbewegung über MQTT auslösen und per MQTT zurückmelden
- Je nach GPIO Änderung, sollen Weichenbefehle ausgelöst werden

Richtig?
Ja, das ist richtig. Zusätzlich können aber parallel auch Befehle über DCC kommen, die ebenfalls ausgeführt werden und über MQTT zurückgemeldet werden. Da spricht aber, so wie ich das sehe, nichts dagegen.
little.yoda hat geschrieben:
01.07.2019, 22:11
Dann würde ich es in zwei Klassen aufteilen:
- Eine MQTT-Klasse, die das empfängen und senden der MQTT Befehle übernimmt.
- Eine Klasse, die nur auf die GPIO hört und dabei Weichenbefehle auslöst.
Das mit den Klassen muss ich mir noch aneignen und dann genauer ansehen. Hier gibt es noch einiges zum Lernen für mich. Da muss der Knoten erst einmal platzen ;) Ich werde da jetzt erst einmal ein bisschen rumprobieren. Falls ich gar nicht weiterkomme, würde ich mich dann gern wieder bei dir melden.
little.yoda hat geschrieben:
01.07.2019, 22:11
Im Prinzip ist das Konzept einfach:
- Wenn du auf irgendeine Änderung lauschen willst, implementiere die Klasse inotify und nutzt in Config.cpp controller->registerNotify(a);
- Wenn du eine Änderung auslösen willst, notifyturnout

Wobei ich bei dem letzten Punkt gerade mir unsicher bin. Wie willst du die Lösung betreiben.
An einer Z21 Zentrale?
Ich versuche jetzt erst einmal, ob ich es schaffe die Klassen korrekt zu implementieren. Den Lösungsansatz über MQTT habe ich gewählt, damit ich über ein Web Interface die Weichen steuern (und monitoren) möchte. Ansonsten fahre ich seit Jahren mit einer LGB und einer Massoth Zentrale. Eine Z21 Zentrale besitze ich nicht. Ich schätze mal, solange meine anderen Zentralen funktionieren, werde ich darauf auch nicht umsteigen.

Antworten