das Rückmeldemodul

Das Rückmeldemodul (RmM) ist ein wichtiger Baustein im märklin-Digitalsystem.
Nur mit Hilfe das RmM können wir erfahren, was auf unserer Anlage geschieht,

Allerdings liefert uns das RmM diese Informationen oder Daten nicht freiwillig oder gar regelmäßig, sondern wir müssen dafür sorgen, das uns die benötigten Informationen zur rechten Zeit zur Verfügung stehen.
Die erforderliche Instruktion können wir

Die Instruktion beauftragt das Interface, das / die betreffenden RmM auszulesen und uns die Antwort zu liefern.
Diese Anwort erhalten wir dann in codierter Form.
Codiert bedeutet, daß wir nicht den Status aller 16 Eingänge separat erfahren, sondern wir erhalten 2 Bytes (= 16 Bit) zurück.
Diese müssen erst noch durch eine kleine Programm-Routine in einen 16-Bit-String gewandelt werden.

Anschließend können wir dann mit If / End If -Blöcken die einzelnen Bits auswerten.

Die ansonsten übliche Programmstruktur mit Select Case / End Case sollten wir nicht verwenden, da bei Select Case das Programm von oben nach unten durch die Struktur läuft und die erste zutreffende Bedingung abarbeitet. Danach verläßt das Programm den Case-Block.
Das bedeutet, wenn z.B. die Kontakte 3, 6 und 12 auf "1" stehen, wird nur Kontakt 3 ausgewertet. Kontakt 6 wird frühestens beim nächsten und Kontakt 12 beim übernächsten Timer-Ereignis berücksichtigt.
Sollte sich jedoch in der Zwischenzeit Kontakt 4 z.B. melden, müssen 6 und 12 noch eine Runde warten. Wenn es dadurch auch nicht zu Unfällen kommen muß, so können doch erhebliche, nicht beeinflussbare, zeitliche Verzögerungen auftreten.

Programm-Routine zum Abfragen eines RmM

Timer Beschreibung
Private Sub TimerRmM_Timer()

Static A, B, C As String
Static I As Integer

A = ""
B = ""
C = ""

' --- alle Zeichen des InputBuffers liefern
RS232.InputLen = 0

' ---- InputBuffer lesen und damit LÖSCHEN
' --- (damit er 'sauber' ist)
A = RS232.Input

' ---- evtuellen 'Schrott' in 'A' löschen
A = ""
 

' ---- Befehl für das 1. RmM
RS232.Output = Chr(193)
 

' ---- warten, bis 2 Bytes empfangen wurden
Do While Len(A) < 2
   A = A & RS232.Input
   DoEvents
Loop

' ------------------------------- empfangene Daten auswerten

' --- bitweise in String eintragen
B = Asc(Left(A, 1))            
' --- linkes Byte bearbeiten
For I = 7 To 0 Step -1        
' --- vom höchsten Bit an...
   C = C & Sgn(Val(B) And 2 ^ I)
Next
 
B = Asc(Right(A, 1))          
' --- rechtes Byte bearbeiten
For I = 7 To 0 Step -1          '
 --- vom höchsten Bit an...
   C = C & Sgn(Val(B) And 2 ^ I)
Next


' ---------------------------------------------- Bits einzeln auswerten
' ---- Bit 1
If Mid(C, 1, 1) = "1" Then
   Code
   ...
End If

' ---- Bit 2
If Mid(C, 2, 1) = "1" Then
   Code
   ...
End If

' ---- Bit 3
If Mid(C, 3, 1) = "1" Then
   Code
   ...
End If

End Sub

Für alle, die sich mit dem CommControl noch nicht so gut auskennen, hier die Beschreibung der einzelnen Programmzeilen.
 

 


jede Zahl > 0 liefert die entspr. Anzahl von Zeichen aus dem InputBuffer. Bei "0" werden ALLE Zeichen geliefert.


.Input liest und löscht den InputBuffer. Wir müssen ihn löschen, um irgendwelche Reste von vorhergegangenen Operationen zu entfernen.

Falls irgendein Rest im Buffer stand, steht er jetzt in A . Und da können wir ihn auch nicht gebrauchen. Auf diese Art können wir ihn löschen.

Befehl um das 1. RmM zu lesen
Eintrag in die Logdatei vornehmen


wir warten, bis das Interface uns mindestens 2 Bytes geschickt hat.

 


hier wird das linke der beiden Bytes in Bits 'zerlegt'.
Beispiel:
ein empfangenes A hat den lt. ASCII-Tabelle den
dezimalen Wert 65.
Das entspricht einem hexadezimalen Wert von 41.
Folglich sieht das linke Byte binär so aus:
0100 0001.

 

an dieser Stelle hat C eine Länge von 16 Stellen
z.B. 0100 0001 0001 0001
In diesem Beispiel haben sich die Rückmeldekontakte
2, 8, 12 und 16 gemeldet.


















Der Einsatz eines (oder mehrerer) RmM erfordert eine sorgfältige Planung und Programm-Struktur.
Wenn mehrere Züge gleichzeitig fahren und Kontakte auslösen können, müssen wir immer mit zeitlichen Verzögerungen der angeforderten Programmtätigkeiten rechnen.
Beispiel:
Mehrere Züge sind unterwegs und Zug A löst Kontakt 3 aus.
Das Programm erkennt den Kontakt und beginnt eine Weichenstraße von 5 Weichen / Signalen zu schalten. Rechnet man für jeden Schaltimpuls 300 mSec, dann ist für mehr als 1,5 Sekunden die Verbindung zwischen PC und Interface blockiert.
Wenn in dieser Zeit Zug B und Zug C weitere Kontakte auslösen, werden diese (noch) nicht bearbeitet. Erst nach Fertigstellung der Weichenstraße für Zug A kann sich das Programm um weitere Kontakte kümmern. Verlangt jetzt Zug B ähnlich umfangreiche Schaltarbeiten, können wir uns gut vorstellen, wann endlich Zug C 'bedient' wird.

Natürlich könnte man während des Schaltens einer Weichenstraße die RmM auf weitere aktive Kontakte abfragen.
Aber damit geraten wir nur noch tiefer in die Predouille.
Wollen wir in einem solchen Fall die halbfertige Weichenstraße einfach 'hängen' lassen ? Und was ist, wenn ein dritter und vierter Kontakt in dieser Zeit eintrifft ? Wie soll sich das Programm daran erinnern, das es noch eine (oder sogar zwei) unvollendete Weichenstraßen gibt ?
Oder noch schlimmer: Kontakt 3 oder 4 verlangen die Schaltung einer Weiche aus Weichenschaltung 1, allerdings in die andere Richtung !
Man kann leicht erahnen, in welchen für einen Irrgarten das führt.

Ich plädiere deshalb ganz entschieden für das bekannte Konzept ENA (Eins Nach dem Anderen).
Das mag dem einen oder anderen altmodisch erscheinen, ist aber wesentlich sicherer.
In unserem Beispiel müssen Zug B und Zug C eben solange an einem Signal warten, bis ihr Auftrag ausgeführt worden ist.

Sehr gute Dienste kann uns der schon erwähnte Trace leisten. Bei 'unerklärlichen' Schaltvorgängen auf der Anlage kann man damit sehr schnell feststellen, wer oder was diese Vorgänge ausgelöst hat.