UPT Programmiertool : CAN-Simulator

 

Inhalt

  1. CAN Message Generator / Bus-Simulator
    1. Einleitung
    2. Extraktion von CAN-Signal-Definitionen aus UPT-Variablen
      1. Behandlung von 'zu sendenden' UPT-Variablen ('TX' aus Sicht des simulierten Gerätes)
    3. Die Option 'Werte in Simulation einspeisen'
    4. Die Option 'Auf echtem CAN-Bus senden'
    5. Definitionstabelle für CAN-Signale
      1. Stimulus (Numerischer Ausdruck mit einer 'Generatorfunktion')
      2. Sendezyklus (Interval für periodisch gesendete Signale)
      3. Parameter zum Abbilden ('mappen') von Signalen in CAN-Messages
    6. Das "Update-Intervall" des Simulators
    7. Automatisierung / Programmierbare Testabläufe
      1. Tabelle mit programmierbaren "Conditional Actions" (Ereignisse und Reaktionen)
        1. 'select'..'case'..'endselect'-Blöcke in den 'Conditional Actions'
      2. Spezielle Interpreterfunktionen des CAN-Simulators
        1. CAN-Empfang per can_rx(<ID> <Datenfeld>) abfragen
      3. Spezielle Interpreterkommandos des CAN-Simulators
        1. Zugriff auf CAN-Signale, interne Variablen, programmierbare Timer
        2. Details zum kommandogesteuerten Senden von Signalen
        3. Signal-Sende-Timing und per Kommando "erzwungenes" Senden
        4. Das Senden gemultiplexter CAN-Messages
        5. Direktes Senden / "Einspeisen" von CAN-Messages per can_tx(<ID> <Datenfeld>)
      4. Haltepunkte und Einzelschritt-Betrieb in den Conditional Actions
      5. Programmierbare Buttons (auf Registerkarte "Automatisierung")
      6. Textkonsole (Editorfenster mit Anzeige von per 'csim.print' erzeugten Meldungen)
      7. Optionen zur Synchronisation zwischen Applikation (Display-Simulator) und CAN-Simulator

  2. Tipps zur Verwendung des CAN Message Generators (für Fortgeschrittene)

CAN Message Generator / Bus-Simulator

Einleitung

Steht Ihnen ein 'realer' CAN-Bus, z.B. Fahrzeug mit Motorsteuergerät und passendem CAN-Bus-Adapter zur Verfügung, dann benötigen Sie den in diesem Dokument beschriebenen CAN-Generator/Simulator nicht. Ein Test der Applikation am 'echten Gerät' ist immer besser als diese Simulation, denn die Simulation kann keine Fehler wie z.B. falsch eingestellte CAN-Bus-Parameter (Baudrate, Sampling Point, Abschlusswiderstände), Kabelfehler, usw. aufdecken.
Ist der Weg zum 'echten CAN-Netzwerk' aber zu weit, bietet sich der Ersatz von (aus Sicht des Terminals empfangenen) CAN-Signalen durch den in diesem Dokument beschriebenen CAN-Generator/Simulator an. Der Simulator kann aus dem Hauptmenü des Programmiertools über 'Werkzeuge' .. 'CAN Message Generator / Bus Simulator' geöffnet werden.

Der CAN-Simulator kann Signale ohne physikalisches CAN-Interface in die Simulation innerhalb des Programmiertools einspeisen, oder mit Hilfe eines geeigneten CAN-Interfaces die Signale (verpackt in CAN- oder CAN-FD-Messages) auf einem oder zwei 'echten' CAN-Bussen zu senden.


Screenshot des 'CAN-Simulators' (Teil des UPT-Programmiertools) mit Definitionen von zu sendenden CAN-Signalen.
Farbige Markierungen entsprechen dem CAN-Message-Layout (rechts unten).

Die Bedeutung der Spalten in der oben gezeigten Tabelle wird in den folgenden Kapiteln noch genauer vorgestellt. In der Spalte Expression / Stimulus kann ein numerischer Ausdruck definiert werden, mit dem das in der Zeile definierte CAN-Signal mit 'ständig neuen' Werten versorgt werden kann. Der i.A. aus einem Stimulus berechnete 'aktuelle' Wert wird in der Spalte 'Current Value' angezeigt. Darüberhinaus können mit dem CAN-Simulator auch komplexere Testabläufe automatisiert werden.

Extraktion von CAN-Signal-Definitionen aus UPT-Variablen

Fast alle Informationen über ein bestimmtes Signal (z.B. "Drehzahl") sind bereits in der Applikation enthalten (z.B. nach Import aus einer entsprechenden Datenbank). Sie können daher mit wenigen Mausklicks aus den UPT-Display-Variablen, aber auch (falls vorhanden) aus der importierten CAN-Datenbank übernommen werden:
  1. Fenster des CAN-Simulators öffnen: Im Hauptmenü unter Werkzeuge .. CAN Message Generator / Bus-Simulator
  2. Dort: Signal hinzufügen .. ALLE Signale aus UPT-Display-Variablen übernehmen
  3. Haken vor Werte in Simulation einspeisen setzen, evtl. auch Auf echtem CAN-Bus senden (Vorsicht !).
  4. In die Zeile mit dem zu ändernden Wert klicken um ein Signal zu selektieren
  5. Mit dem vertikalen Schieber den selektierten Wert ändern
Der oben beschriebene Ablauf ist nur die einfachste (schnellste) Möglichkeit, um ein einzelnes Signal zu verändern. Sollen mehrere Werte 'ständig' geändert werden, bietet sich die Eingabe eines numerischen Ausdrucks (Stimulus, 'Erregerfunktion') in der Tabellenspalte Expression (Stimulus) an.

Behandlung von 'zu sendenden' UPT-Variablen ('TX' aus Sicht des simulierten Gerätes)

Da das UPT (User Programmable Terminal, z.B. "MKT-View") CAN-Signale optional auch senden kann (statt diese als reine 'Anzeige' nur zu empfangen), besteht bei der oben beschriebenen Extraktion von CAN-Signal-Definitionen ein potenzielles Problem:
Würde der CAN-Simulator solche Signale ebenfalls auf dem CAN-Bus senden, könnten sich von der CAN-Hardware nicht auflösbare Kollisionen (*) ergeben. Ausser für "Stress-Tests" (bei dem im Labor CAN-Identifier-Kollisionen bewusst provoziert werden) sollte das gleichzeitige Senden des gleichen CAN-Message-Identifiers von mehreren CAN-Knoten vermieden werden.
Seit 2023-01-05 vermeidet der im "CAN Terminal Programming Tool" integrierte CAN-Simulator das oben beschriebene Problem wie folgt:

(*) Wenn zwei CAN-Knoten gleichzeitig versuchen, eine Message mit dem gleichen Identifier zu senden, dann versagt die Kollisionserkennung während der 'Arbitrierungsphase', wenn beide Identifier exakt gleichzeitung (und damit 'ungestört') gesendet werden.
Beide sendenden Knoten senden dann (nach der aus ihrer Sicht 'erfolgreichen' Arbitrierung) ihre Datenfelder. Während der Sendung des CAN-Datenfelds findet aber keine Kollisionserkennung statt. Beide Knoten senden aber i.A. Datenfelder mit unterschiedlichem Inhalt, was Bus-Fehler verursacht (error frames), und fehlendes 'Acknowledge', da keiner der angeschlossenen Knoten einen Frame mit korrekter Prüfsumme empfangen kann.
Der Fehler kann sich wegen CAN-"Retransmit" (automatische erneute Sendeversuche) mehrfach wiederholen.


Die Option 'Werte in Simulation einspeisen'

Mit der Option Werte in Simulation einspeisen dienen die z.B. per Schieber geänderten Werte in der programmiertool-interne "Simulation" als Ersatz für vom CAN-Bus empfangene.
Diese Option reicht in vielen Fällen bereits aus, um eine Applikation am PC / im PC zu testen. Sie hat - im Gegensatz zur Option 'Auf echtem CAN-Bus senden' keine Auswirkungen auf die Funktion externer Geräte, und erfordert kein CAN-Bus-Interface am PC.


Die Option 'Auf echtem CAN-Bus senden'

Die Option Auf echtem CAN-Bus senden sollte nur verwendet werden, wenn der PC (Programmiertool) direkt mit dem MKT-View per CAN-Interface verbunden ist, aber darüberhinaus keine anderen Teilnehmer am CAN-Netzwerk hängen. Das Programmiertool sendet nämlich in diesem Fall die Telegramme, die das Terminal (MKT-View) im Normalfall nur empfangen würde - was, im laufenden Betrieb "am Fahrzeug" zu schwerwiegenden Kollisionen führen dürfte, wenn zwei Knoten (der PC und ein Steuergerät im Fahrzeug) CAN-Telegramme mit dem gleichen CAN-Message-Identifier senden. In einigen Fällen kann dies bis zum Zustand 'Bus-Off' führen, d.h. einer der Teilnehmer stellt seine CAN-Sendungen ein.
Die Option 'Auf echtem CAN-Bus senden' wirkt sich wie hier beschrieben auch auf das Verhalten des Simulator-Befehls can_tx() (zum direkten "Senden" kompletter CAN-Messages) aus.

Siehe auch: Aufzeichnen und Abspielen von CAN-Telegrammen per 'CAN-Snooper',
        Abspielen von aufgezeichneten CAN-Telegrammen im Simulator,
        Das CAN-Bus-Interface im/am PC.


Definitionstabelle für CAN-Signale

Im allgemeinen werden die Signaldefinitionen für den CAN-Simulator wie in der Einleitung beschrieben aus den Variablen-Definitionen der Applikation extrahiert.
Alternativ können Signaldefinitionen auch manuell in die Definitionstabelle eingegeben werden.


Definitionstabelle für den CAN-Signal-Simulator

Die Spalten in der Tabelle entsprechen z.g.T. den im Handbuch des Programmiertools vorgestellten Eigenschaften von Variablen, die mit CAN-Signalen verknüpft sind.
Details zur Bedeutung "CAN-(Message-)ID", "Position des niederwertigsten Bits", "Intel/Motorola" (Byte Order), usw. finden Sie im oben verlinkten Dokument.
Name
Im Normalfall aus der Variablen-Definitions-Tabelle übernommener Name.
Bei Signalen, die nicht aus einer CAN-Datenbank importiert wurden, sollte hier ein eindeutiger, 'sprechender' Name eingegeben werden.
Tipp zu den Signalnamen:
Per Kontext-Menü (Anklicken des Namens mit der rechten Maustaste) kann eine globale Suche nach dem Namen gestartet werden (d.h. nicht nur in der CAN-Simulation, sondern auch auf allen Anzeigeseiten, und in Event-Definitionen der Applikation, in denen eine gleichnamige Display-Variable verwendet wird).

Expression (Stimulus)
Optionale 'Generatorfunktion'. Wenn vorhanden, wird dieser numerische Ausdruck vom Display-Interpreter ständig neu berechnet (Intervall aus dem Eingabefeld auf der rechten Seite), und das Ergebnis als neuer Signalwert in die Spalte "Current Value" übernommen.
Per Doppelklick in leere Zellen in dieser Spalte kann ein numerischer Ausdruck erzeugt werden, mit dem eine niederfrequente Sinusfunktion für das entsprechende Signal berechnet werden kann. Jedes Signal erhält dabei eine leicht unterschiedliche Frequenz. Die Amplitude wird passend zu den Einstellungen in den Spalten MinValue und MaxValue skaliert. Um dies für alle in der Tabelle enthaltenen Signale zu wiederholen, wählen Sie unter 'Weitere Optionen...' den Menüpunkt 'Stimuli für ALLE Signale erzeugen'. So können mit wenig Aufwand für alle in der geladenen Applikation verwendeten CAN-Signale ständig wechselnde "Dummy-Werte" erzeugt werden, z.B.:
isin(tsim_ms) / 4   erzeugt eine Sinusfunktion
                mit der Amplitude 32767/4 = ca. 8191
                und Periodendauer 1024 Millisekunden, d.h. Frequenz etwa 1 Hz,
                deren erster positiver Nulldurchgang
                beim Start der CAN-Simulation beginnt.
(Erläuterung: Die Interpreter-Funktion tsim_ms liefert die seit dem Start der CAN-Signal-Simulation ("Run") vergangene Zeit in Millisekunden als Integer-Wert. Die ältere -aber in jeder Firmware vorhandene- Funktion ti_ms liefert dagegen die seit dem Start der Display-Applikation (bzw. "simulierten Einschalten" des Targets) verstrichene Zeit. Die Funktion isin erwartet einen Argumentenbereich von 0..1023 (entspricht 0..360°) für eine volle Sinusschwingung, und liefert einen Wertebereich von -32767 bis +32767. Ein- und Ausgänge sind Integer-Werte.)

Current Value
Aktueller Wert für die Simulation. Quelle: Vertikaler Schieber oder der o.g. numerische Ausdruck (Stimulus).

TX cycle (ms)
Sendezyklus für dieses Signal in Millisekunden.
Ohne Sendezyklus (0 ms) wird ein Signal bei jeder Änderung (per Schieber oder Stimulus) sofort gesendet, d.h. "ereignisgesteuert".
Unter 'Weitere Optionen...' / 'Sende-Intervall für ALLE Signale setzen' können Sie mit zwei Mausklicks die zyklische Sendung aller in der Tabelle definierter Signale erzwingen. Das Intervall wird dabei aus dem Eingabefeld in der rechten Fensterhälfte in alle Definitionszeilen übernommen, für die noch kein Sende-Intervall definiert ist.

Message ID
Hexadezimaler CAN-Message-Identifier. Dreiziffrig für "Standard-IDs" (11 Bit), achtziffrig für "Extended IDs" (29 bit).

Bus
Für Systeme mit mehreren CAN-Schnittstellen, die auch mit unterschiedlichen Baudraten betrieben werden können.
Diese Funktion wurde bislang nur mit mehrkanaligen Interfaces von Kvaser getestet, z.B. 'Kvaser Hybrid 2xCAN/LIN'.
Für "Bus 1" definierte Signale/Messages werden dann auf Kvaser's "Ch.1" (Label am DSUB-Stecker) gesendet, usw.

LSB pos
Position des niederwertigen Bits im CAN-Datenfeld (0..63 bei "normalem" CAN).

Num bits
Anzahl Datenbits, mit denen dieses Signal AUF DEM CAN-BUS übertragen wird.

Byte order
Hier nur 'M'="Motorola" oder 'I'="Intel", der altbekannte nervtötende Krampf namens 'Endianness'..

Data Type
U=unsigned integer, S=signed integer, F=single precision float, D=double precision float.
Typ des per CAN übertragenen 'rohen' Wertes (nicht skaliert).

Factor
Multiplikator für die Konvertierung des per CAN übertragenen 'rohen' Wertes in einen physikalischen Wert.

Offset
Wird bei der Konvertierung des per CAN übertragenen 'rohen' Wertes in einen physikalischen Wert addiert:
  Physikalischer Wert (z.B. Öldruck in Bar) = CAN-Rohwert * Faktor + Offset

MinValue, MaxValue
Zulässiger Bereich für den physikalischen Wert. Wird im CAN-Simulator auch für den vom "vertikalen Schieber" verwendet: Ganz oben = Maximum, ganz unten = Minimum.

Multiplexer
Definition eines Signal-Multiplexers für mehrfach genutze Bitfelder im CAN-Message-Datenfeld.
Details und Format wie hier beschrieben.
Im CAN-Simulator werden gemultiplexte Signale automatisch (der Reihe nach) mit den in der Definitionstabelle enthaltenen Multiplexer-Werten gesendet.
Der Sendezyklus eines gemultiplexten Signals bestimmt, wie oft der entsprechende Multiplexer, und damit möglicherweise auch andere Signale (in der gleichen Message) gesendet werden.
Ist das Multiplexer-Signal selbst (mit einem eigenen Signal- bzw. Variablenamen) in einer eigenen Tabellen-Zeile definiert, dann darf für die Zeile des Multiplexers kein Stimulus definiert sein. Grund:
Würde der Multiplexer z.B. mit einer Sinusfunktion als Stimulus belegt, dann würden alle (gemultiplexten) Signale in der gleichen CAN-Message mit undefinierten Werten gesendet. Seit 02/2021 weist der CAN-Simulator durch ein rotes Kreuz in der Tabellenzelle mit dem Stimulus (Expression) darauf hin, dass an dieser Stelle mit hoher Wahrscheinlichkeit ein Fehler vorliegt.


Fälschlicherweise definierter Stimulus ("Expression") für ein Multiplexer-Signal.

Der Fehler-Indikator ("rotes Kreuz") verschwindet wenn der fehlerhafte Stimulus entfernt wird.
Siehe auch: Besonderheiten beim Senden gemultiplexter CAN-Messages.


Um die Definitionstabelle schnell mit Daten zum Testen einer 'Display-Applikation' zu füllen, laden Sie die Applikation (*.upt oder *.cvt) zunächst im Programmiertool. Dann schalten Sie aus dem Hauptfenster des Tools in den Simulator um ("Werkzeuge".."CAN Messag Generator / Bus Simulator"), und klicken auf den Button mit dem Titel "Signal(e) hinzufügen" / "Add Signal(s)", und wählen im unten gezeigten Popup-Menü die Funktion "ALLE Signale aus UPT-Display-Variablen übernehmen" / "Copy ALL signals from UPT display variables" :


Schritte zum schnellen Ausfüllen der 'Signal-Definitions-Table' mit Daten aus der geladenen Display-Applikation

Über den Button "Weitere Optionen.." ("More ...") ...
    "Stimuli für ALLE Signale erzeugen" ("Generate stimuli for ALL signals")
können Sie anschließend für jedes Signal einen eigenen Stimulus erzeugen (Sinuskurve mit zum Wertebereich passender Amplitude, und von der Signalnummer abhängiger Frequenz, damit alle Signale unterschiedliche Werte haben).

Der Inhalt der Definitionstabelle kann auch als CSV-Datei exportiert werden. Wählen Sie dazu unter 'Weitere Optionen' den Menüpunkt 'Definitionen in Datei speichern'. Im gleichen Menü finden Sie auch die Funktion zum Importieren der Definitionstabelle. Wenn die CSV-Datei mit den Signaldefinitionen existiert, wird sie beim nächsten Programmstart nach dem Öffnen des CAN-Simulators automatisch geladen.


Das 'Update-Intervall' des CAN-Simulators

Das in rechten Teil des Simulatorfensters einstellbare 'Update-Intervall' steuert die Aktualisierungsrate der Simulation. Dazu gehören die zyklische Auswertung der Tabelle mit den Signal-Definitionen (inkl. Stimuli), aber auch das SPS-ähnliche Abarbeiten der "Conditional Actions" (Details dazu im folgenden Kapitel). Abhängig von der verwendeten Hardware (PC), Grafik und Betriebssystem könnte die grafische Benutzeroberfläche etwas länger als den eingestellten Wert benötigen. Dies wurde bislang nur bei Intervallen unter 100 Millisekunden beobachtet.


Automatisierung / Programmierbare Testabläufe

In den meisten Fällen reicht die in den vorhergehenden Kapiteln beschriebene zyklische Sendung von CAN-Signalen als 'Ersatz' für ein echtes Netzwerk.
Für komplexe Testfälle bietet der CAN-Simulator aber auch eine 'programmierbare' Steuerung, mit der ähnlich wie mit den 'Event-Definitionen' im Display-Programm bestimmte Ereignisse definiert werden können, und abhängig davon daraufhin durchgeführte Reaktionen.

Tabelle mit programmierbaren "Conditional Actions" (Ereignisse und Reaktionen)

Die "Conditional Actions" werden als Tabelle auf der Registerkarte 'Automatisierung' des CAN-Simulators angezeigt.
Die Funktion ähnelt den vom Display bekannten Event-Definitionen. Ähnlich wie bei einer SPS werden alle Zeilen (mit 'Ereignissen' und 'Reaktionen') genau einmal pro Update-Zyklus abgearbeitet.
Liefert eine in der Spalte "IF..." programmierte Bedingung (numerischer Ausdruck) einen Wert ungleich Null (d.h. logisch "TRUE"), dann wird die in der Spalte "THEN..." definierte Reaktion (Kommadozeile) ausgeführt. Ausdrücke und Kommandos werden vom gleichen Interpreter ausgewertet, der auch für die Simulation des programmierbaren Terminal verwendet wird. Speziell für den CAN-Simulator wurde der Befehlssatz des Interpreters allerdings so erweitert, dass sich CAN-Simulation und Simulation der Display-Applikation "nicht in die Quere" kommen. So verfügt der CAN-Simulator über eine eigene Zeitbasis (tsim), eigene Timer (csim.t0 .. t9), eigene Variablen (csim.var.<VarName>), einen eigenen Befehl zum Prüfen des Empfangs einer bestimmten CAN-Nachricht (csim.can_rx()), usw.

Screenshot "Conditional Actions"
'Conditional Actions' im CAN-Simulator (mit Test aus programs/CANSim_for_SignalMultiplexerTest.csv).
In der Statuszeile (unten) wird der momentane Wert aus dem Ausdruck 'unter dem Mauspfeil' angezeigt.


Alle Bedingungen, deren Auswertung im letzten Update-Zyklus einen Wert ungleich Null lieferten (d.h. "TRUE") werden in der Tabelle mit einem grünen Hintergrund hervorgehoben. Tritt bei der Berechnung oder beim Aufruf eines Kommandos ein Fehler auf, dann wird die entsprechende Tabellenzelle rot markiert, und die Statuszeile (unterhalb der Tabelle) zeigt eine detailierte Fehlermeldung. Eine gelb gefärbte Zelle in der ersten Spalte (mit den Zeilennummern) bedeutet, dass ein in dieser Zeile gesetzter Haltepunkt die Ausführung der "Conditional Actions" pausiert hat. In diesem Fall kann der Ablauf Schritt für Schritt (ab der "gelben Zeile") fortgesetzt werden.

Um die Reihenfolge der 'Ereignisse und Reaktionen' in der Definitionstabelle zu ändern, ziehen Sie die Zelle mit dem Titel 'Nr' bei gedrückter linker Maustaste nach oben oder unten. Während des Verschiebens zeigt die Tabelle die neue Position der Zeile, an der die verschobene Zeile beim Loslassen der Maustaste eingefügt würde, mit einer breiten horizontalen Line an.

Um den aktuellen Wert einer Variablen, oder dem Teil eines numerischen Ausdrucks in der Tabelle zu inspizieren, bewegen Sie den Mauspfeil an die entsprechende Position innerhalb der Tabelle, ohne die Tabelle anzuklicken. Wenn der Interpreter das 'Wort' unter dem Mauspfeil auswerten kann, dann wird das Ergebnis im Anzeige/Editierfeld direkt unterhalb der Tabelle angezeigt.

'select'..'case'..'endselect'-Blöcke in den 'Conditional Actions' (CA)
Neben einfachen "IF.."/"THEN.." - Bedingungen kann die Definitiontabelle unter 'Automatisierung' auch zur Implementierung von Auswahllisten (Verzweigung nach einer Vielzahl von Werten) verwendet werden. Hier ein Beispiel, mit der ein Drehzahlverlauf beim Anlassen eines Motors simuliert wurde:

 Nr IF.. (Condition) THEN.. (Action) 
1initialisingcsim.var.SendState := 0 : csim.ts0(10)
1csim.t0csim.tr0 : csim.var.SendState := 1 // start state machine
2select(csim.var.SendState)// Verzweigung nach dem Inhalt von 'SendState' ...
3case 1 :csim.sig.EngineRPM := 0 : csim.var.SendState++ // Stillstand
4case 2 :csim.sig.EngineRPM := 500 : csim.var.SendState++ // Anlasser dreht
6case 3 to 100 :csim.sig.EngineRPM := csim.sig.EngineRPM + 12.3 // Motor startet
7csim.var.SendState++ // increment to next state
8default :csim.var.SendState := 0 // state machine stops, engine keeps running :o)
9endselect// end select(SendState)

Ähnlich wie ein Anweisungsblock mit select..endselect in der Script-Sprache 'rutscht' auch im CAN-Simulator das Programm nicht von einer case-Zeile in die nächste case- oder default-Zeile durch. Im Gegensatz zur Programmiersprache "C" ist daher kein 'break' nach jedem 'case' erforderlich, um dieses 'Durchrutschen' (fall-through) zu verhindern.
Hinweis: Im Gegensatz zur Pascal und zu MKT's Script-Sprache wird hier bei 'select'..'case'..'endselect' kein 'else' zur Abdeckung 'aller anderen Werte' verwendet, sondern das aus 'C' geläufige 'default:'-Label. Dieses Prinzip wurde gewählt, um nicht mit der normalen else-Abfrage (als "Gegenteil von der Bedingung in der vorhergehenden Zeile") zu kollidieren.
Hinweis: Als diese Beschreibung erstellt wurde, unterstützte 'select' im CAN-Simulator nur numerische Auswahlwerte (Ganzzahl oder Fließkomma). Zeichenketten konnten im Gegensatz zur Script-Sprache nicht als Auswahlwerte verwendet werden.
Im Gegensatz zu "C" (und zur compilierten Script-Sprache) sind case-Werte nicht auf Konstanten beschränkt, denn der Interpreter muss Werte (egal ob Konstante oder Variable) immer zur Laufzeit auswerten.

Spezielle Interpreterfunktionen des CAN-Simulators

In den meisten Fällen bestehen die im vorhergehenden Kapitel beschriebenen 'Bedingungen' (Ereignisse) aus einfachen Vergleichen, wie z.B. tsim > 10.
Im CAN-Simulator können auch normale Interpreter-Funktionen verwendet werden, z.B. für die Statusabfrage des CAN-Controllers.
Darüberhinaus stehen im für den CAN-Simulator erweiterten Interpreter noch die foldenden Funktionen zur Verfügung, die speziell für den Einsatz in den 'Conditinal Actions' (Tabellenspalte 'IF..') vorgesehen sind:

Zur Erinnerung: Eine Funktion liefert einen Wert an den Aufrufer zurück, und kann daher auch als Teil eines numerischen Ausdrucks verwendet werden. Ein Kommando (bzw. Prozedur) tut dies nicht, und kann daher kein Teil eines numerischen Ausdrucks bzw. einer Bedingung sein.

CAN-Empfang per can_rx(<ID> <Datenfeld>) abfragen
Die Interpreterfunktion can_rx dient zum Testen, ob seit dem letzten Aufruf eine CAN-Message mit einem bestimmten Identifier oder/und einem bestimmten Inhalt im Datenfeld empfangen wurde.
Die Syntax ist an den CAN-Tester für Windows angelehnt, und entspricht dem Format des Kommandos can_tx() (mit dem CAN-Telegramme in die Simulation eingespeist, aber auch auf einem 'echten' CAN-Bus gesendet werden können). Die Länge des CAN-Datenfelds ergibt sich automatisch aus dem z.B. hexadezimal definierten Datenfeld (mit "xx" als Platzhalter für Datenbytes, die für die Filterung jeden beliebigen Wert annehmen dürfen).
Für den Einsatz als 'Bedingung' (condition) liefert can_rx() [beim Aufruf mit einer Argumentenliste in Klammern] den Wert 1 = TRUE, wenn eine entsprechende CAN-Message im CAN-FIFO gefunden wurde; anderfalls 0 = FALSE.

Beispiele :

can_rx( 0x123 00 11 22 33 44 55 66 77 )
   prüft, ob seit dem letzten Durchlauf durch die gleiche Zeile in den 
   'conditional actions' eine CAN-Message mit dem hexadezimalen Identifier 0x123,
   und dem hexadezimalen 8-Byte-Datenfeld 00 11 22 33 44 55 66 77 
   empfangen wurde.

can_rx( 0x123 FF xx xx )
   prüft, ob seit dem letzten Durchlauf (.. s.O. ..) eine CAN-Message
   mit einem Drei-Byte-Datenfeld empfangen wurde, bei der im ersten
   Datenbyte der Wert 0xFF (hexadezimal) enthalten war.
   Der Wert im zweiten und dritten Datenbyte spielt in diesem Beispiel
   keine Rolle ('xx' dient wie im CAN-Tester für Windows als Platzhalter
   für ein in der Message vorhandenes Datenbyte mit beliebigem
   Inhalt (Wert).

Spezielle Interpreterkommandos des CAN-Simulators

Zusätzlich zu den Standard-Kommandos des Interpreters wurden die folgenden Befehle speziell für die Verwendung in der Spalte mit dem Titel 'THEN..' in der Tabelle mit den 'Conditional Actions' implementiert:

Zugriff auf CAN-Signale, interne Variablen, und programmierbare Timer
In der Tabelle mit den "Conditional Actions" werden üblicherweise nur wenige CAN Signale (per Signalname) gesetzt, die der CAN-Simulator dann einmal pro Update-Zyklus in CAN-Telegramme oder vergleichbare 'Container' umgesetzt und gegebenenfalls gesendet werden - ähnlich wie bei Signalen, für die ein eigener Stimulus definiert wurde. Beispiele dafür wurden im vorhergehenden Kapitel präsentiert.
Der Interpreter bietet darüberhinaus selbstdefinierte
interne Variablen, die im Gegensatz zu CAN-Signalen und Applikations-Variablen ("Netzwerk-Variablen") nur innerhalb des CAN-Simulators bekannt sind.
Auch die programmierbaren Timer können als 'Signalgeneratoren' für CAN-Signale verwendet werden. Dazu kann z.B. der Timer-Wert per Stimulus, aber auch per 'Conditional Action' an das Signal gekoppelt werden. Die dazu benötigten Funktionen und Kommandos wurden bereits vorgestellt.
Im nächsten Unterkapitel folgen Details die für einfache Test-Anwendungen nicht erforderlich sind.

Details zum kommandogesteuerten Senden von Signalen
In diesem Unterkapitel werden Details und Erweiterungen zum Setzen von Signalen (Zuweisungen an csim.<SigName>) vorgestellt. Eine Zuweisung kann in der langen Form erfolgen, z.B.:
csim.sig.EngineRPM.value := 2300
oder in der kurzen Form (ohne ".sig" und ".value", falls sich dadurch keine Kollision mit anderen Namen ergibt):
csim.sig.EngineRPM := 2300
Diese Zuweisungen erfolgen als Kommando in den 'Conditional Actions', Spalte "THEN.." (Aktion). Jede Zuweisung kann so an eine beliebige Bedingung geknüpft sein.
Selbst wenn für das Ziel (im Beispiel "EngineRPM" = Motordrehzahl) ein Stimulus definiert wäre, hätte die Zuweisung per Kommando immer Vorrang vor dem vom Stimulus gelieferten Wert. Erst wenn die Bedingung für die Zuweisung an das Signal nicht mehr erfüllt ist, übernimmt wieder der Stimulus die Kontrolle (sofern vorhanden).
Der Stimulus für ein bestimmtes Signal kann auch 'programmgesteuert' dauerhaft ein- und ausgeschaltet werden (also nicht nur für einen Update-Zyklus). Beispiel:
csim.sig.EngineRPM.enable_stimulus := 0 // disable signal stimulus
csim.sig.EngineRPM.enable_stimulus := 1 // enable signal stimulus
Stimuli die per "enable_stimulus = 0" passiv sind werden in der Signal-Definitionstabelle mit einem blauen Kreuz (unter dem numerischen Ausdruck) markiert.
Stimuli die nur temporär im aktuellen Zyklus keine Verwendung fanden (da das Signal per Zuweisung an den aktuellen Wert gesetzt wurde) werden in der Tabelle mit einem grünen Kreuz markiert.

Zur Erinnerung: Die Auswertung der Stimuli und 'Conditional Actions' erfolgt ähnlich wie bei einer SPS (Speicherprogrammierbaren Steuerung). Das Senden aller Funktionsausgänge (hier z.B. CAN-Signale) erfolgt nur einmal pro Zyklus (genau: am Ende vom Zyklus, nachdem alle Zeilen in der Signal-Definitions-Tabelle und in den 'Conditional Actions' abgearbeitet wurden). Egal wie oft Sie den Wert eines CAN-Signals in einem Zyklus neu setzen - das Signal wird bis auf seltene Ausnahmen (*) maximal einmal pro Zyklus gesendet.

Der in der Signal-Definitionstabelle definierbare Sendezyklus ("TX cycle" in Millisekunden) stellt in diesem Fall nur das Minimum dar: Ein Signal mit "TX cycle"=50 ms wird bei einem Update-Intervall von 200 Millisekunden maximal 5 mal pro Sekunde gesendet, nicht 20 mal.

Das folgende Kapitel beschreibt den Zusammenhang zwischen dem Update-Intervall des Simulators, dem individuellen Sende-Zyklus eines Signals, dem Setzen eines Signalwertes per Zuweisung an csim.sig. (Kommando), und dem Zeitpunkt, an dem die i.A. aus mehreren Signalen zusammengesetzte CAN-Message (oder ähnlicher Container) tatsächlich gesendet wird.
Signal-Sende-Timing / per Kommando "erzwungenes" Senden
Am Ende eines Zyklus (mit einstellbarem Update-Intervall) werden alle zu sendenden Signalwerte in ihre 'Container' (CAN Messages, PDUs, PDOs, etc) gemappt, in die im Display-Simulator laufende Applikation eingespeist, oder/und per CAN-Bus in ein "echtes" Netzwerk gesendet.
Wie bereits in den vorhergehenden Kapiteln erläutert, werden Signale, für die kein zyklisches Senden in der Definitionstabelle konfiguriert wurde ("TX Cycle" = 0), ereignisgesteuert gesendet (d.h. immer dann, wenn der per Stimulus oder Zuweisung gesetzte Wert vom alten Wert aus dem vorherigen Update-Zyklus abweicht).
Es kann daher bis zu einem Update-Intervall dauern bis der neue Wert 'im Netzwerk' erscheint.

Für spezielle Anwendungen kann das Senden eines Signals unabhängig vom Sendezyklus oder Änderung des Signalwertes erzwungen werden. Beispiel:
Auf diese Weise wird das Signal (am Ende des Update-Zyklus) auch dann gesendet, wenn kein zyklisches Senden konfiguriert wurde (TX Cycle = 0), und der Wert gegenüber dem vorherigen Zyklus nicht geändert wurde. Das "Sende-Anforderungs-Flag" (tx_flag) wird automatisch gelöscht, sobald das zu sendende Signal in seinen Container (CAN-Message, ..) gemappt wurde.

Das Senden gemultiplexter CAN-Messages
Abhängig von den Sende-Intervall können gemultiplexte Signale beim Senden per CAN-Simulator ein auf den ersten Blick "unerwartetes" Verhalten zeigen:

CAN-Senden per can_tx(<ID> <Datenfeld>)
Das Interpreterkommando can_tx kann zum Senden einfacher CAN-Messages verwendet werden, die nicht vom CAN-Simulator wie in den vorhergehenden Kapiteln beschrieben aus einzelnen Signalen zusammengestellt werden sollen.
Stattdessem wird der zu sendende CAN-Message-Identifier, und i.A. auch das zu sendende Datenfeld direkt in der geklammerten Parameterliste übergeben.
Die Länge des Datenfelds wird nicht extra angegeben (die Anzahl zu sendender Bytes ergibt sich schlicht und einfach aus deren Zählung).

Beispiele :

can_tx( 0x123 00 11 22 33 44 55 66 77 )
    "Sendet"(*) eine CAN-Message mit dem hexadezimalen 11-Bit-Message-Identifier 0x123,
    und dem hexadezimalen 8-Byte-Datenfeld 00 11 22 33 44 55 66 77,
    oder (ohne die Option 'Auf echtem CAN-Bus senden')
    speist eine entsprechende CAN-Message in die im Programmiertool laufende
    Simulation ein (als Ersatz für eine von einem Steuergerät gesendete
    Message).

can_tx( 0xABCDEF.x 01 02 03 04 05 06 )
    "Sendet"(*) eine CAN-Message mit 29-Bit-Message-ID 0x00ABCDEF (.x = "Extended"),
    und dem angegebenem Datenfeld.

Der "can_tx()"-Befehl des CAN-Simulators verwendet den gleichen Parser wie der in manchen programmierbaren Geräten ("ohne CANopen") implementierte Befehl ctx(). Da beide Befehle den gleichen Parser verwenden, kann auch can_tx() den Inhalt von Variablen (im Datenfeld) verwenden, mit Konvertierung in die hier spezifizierten Datentypen (z.B. ".il" = "Intel-Long", ".mw" = "Motorola-Word", ... ).


(*) "Senden" auf einem 'echten' CAN-Bus erfolgt nur, wenn die Option 'Auf echtem CAN-Bus senden' gesetzt ist. Ohne diese Option werden die per can_tx() -und aus Sicht des simulierten Steuergerätes- "gesendeten" CAN-Messages lediglich in die im Programmiertool laufende Simulation des Anzeigegerätes (MKT-View) eingespeist.

Haltepunkte und Einzelschritt-Betrieb in den Conditional Actions

Für die 'Hardcore'-Fehlersuche können in den Conditional Actions (CA) auch Haltepunkte (breakpoints) gesetzt werden. Erreicht das Programm dann die entsprechende Zeile mit einer erfüllten Bedingung (condition = TRUE), dann 'feuert' der Haltepunkt, und das periodische Abarbeiten der CA-Tabelle (wie auch das periodische Auswerten der Stimuli für CAN-Signale) wird unterbrochen (pausiert). Diese Pause beginnt genau zwischen der Auswertung der Bedingung (condition) und dem Abarbeiten der entsprechenden Reaktion (action).

Um einen Haltepunkt zu setzen, klicken Sie in der Tabelle auf der Registerkarte Automatisierung in der gewünschten Zeile auf die erste Spalte (mit dem Titel 'Nr'), und wählen im daraufhin angezeigten Kontext-Menü den Eintrag 'Breakpoint in Zeile X umschalten'. Dies funktioniert sowohl bei laufendem wie auch bei gestopptem CAN-Simulator.
Wenn der Haltepunkt später auslöst, bleibt die Simulation an der Stelle stehen, und die noch abzuarbeitende Zeile wird durch einen gelben Hintergrund markiert. Gleichzeitig erscheint ein entsprechender Hinweis in der Statuszeile, z.B.:
Conditional actions hit breakpoint in line 34, press F11 for single-step.
Drücken Sie in diesem Zustand die Funktionstaste F11 (mit dem Tastaturfokus in der CA-Tabelle), um die Anweisungen in der Tabelle schrittweise abzuarbeiten, oder klicken Sie auf 'Run' um das Programm weiterlaufen zu lassen (bis zum nächsten Stop per Haltepunkt). In diesem Fall started 'Run' die Simulation nicht neu, und setzt auch nicht das initialising-Flag mit dem üblicherweise selbstdefinierte Variablen auf die Startwerte gesetzt werden.

Siehe auch: Optionen zur Synchronisation zwischen Applikation (Display-Simulator) und CAN-Simulator.

Programmierbare Buttons (auf Registerkarte "Automatisierung" / "Automation")

Die drei Buttons im oberen Teil der Registerkarte "Automatisierung" sind frei programmierbar. Sie können z.B. zum Aufruf beliebiger Kommandos durch den Bediener verwendet werden, ähnlich wie die Kommandozeilen in der Spalte mit dem Titel 'THEN...' in den 'Conditional Actions'.
Ist eine Kommandozeile für einen Button hinterlegt, dann wird diese beim Anklicken des Buttons mit der linken Maustaste aufgerufen. Andernfalls, oder beim Anklicken eines 'programmierbaren' Buttons mit der rechten Maustaste, oder (für Touchscreen-Benutzer) beim Anklicken mit gedrückter Shift-Taste wird das unten gezeigte Popup-Menü geöffnet, mit dem der Button gegebenenfalls "umprogrammiert" werden kann:


Screenshot des CAN-Simulators mit Kontext-Menü für "Programmierbare Buttons"

Die 'Beschriftung' eines Buttons ('Caption') kann nicht nur manuell, sondern auch programmgesteuert geändert werden. Dazu dient eine Zuweisung an csim.btn[0..2].caption.
Der 'OnClick'-Handler eines Buttons (Kommandozeile, die beim Anklichen des Buttons an den Interpreter übergeben wird) kann ähnlich wie die Zellen in der Tabellenspalte mit dem Titel "THEN.." (Aktionen) frei programmiert werden. Mehrere Kommandos können per Doppelpunkt getrennt in eine Zeile eingetragen werden, z.B.:

Button-Text (Caption)OnClick (Kommandozeile)
Stop Simulationcsim.btn[0].caption := "Stopped" : csim.stop

Alternativ kann die Beschriftung selbst als 'variable Anzeige' verwendet werden. Als 'Caption' wird dafür ein String-Ausdruck wie im folgenden Beispiel (Anzeige eines Zählers für bestimmte CAN-Messages) verwendet:
 Caption:   "Count7=";csim.Count7
Die für einen programmierbaren Button als 'Caption:' definierte Zeichenkette wird vom Interpreter periodisch ausgewertet (alle 500 ms), und das Resultat ('Evaluated:') als Beschriftung übernommen. Wie beim Befehl csim.print werden mehrere Parameter per Komma getrennt. Bei der 'Ausgabe' (hier: Beschriftung eines Buttons) wird statt Komma ein einzelnes Leerzeichen emittiert. Ein Semikolon (als Trennzeichen) erzeugt dagegen kein Leerzeichen. Im oben gezeigten Beispiel ist 'Count7' eine anwenderdefinierte Variable, die nur innerhalb des CAN-Simulators gültig ist.

Die "Programmierung" der Buttons ('Caption' und Kommandozeile für den 'OnClick'-Handler) wird zusammen mit anderen Tabellen in der Konfigurationsdatei (*.csv) abgespeichert. Diese kann so zu Testzwecken zusammen mit der Applikation (*.cvt) an den Endkunden oder weitere Entwickler weitergegeben werden, falls dort kein 'echtes' CAN-Netzwerk vorhanden ist.

Textkonsole (Editorfenster mit Anzeige von per 'csim.print' erzeugten Meldungen)

Die während eines Testlaufs mit dem Kommando csim.print oder csim.write generierten Ausgaben werden in einer mehrzeiligen 'Konsole' (Editor) auf der Registerkarte Automatisierung, oder als Vollbild unter 'Konsole' angezeigt:


Screenshot mit der 'Text-Konsole' des CAN-Simulators
mit absichtlich übertriebenem Einsatz von Farben.

Texte können aus der 'Konsole' per Copy & Paste zu Dokumentationszwecken als 'Rich Text' in eigene Dateien übernommen werden.
Das Konsolenfenster war ursprünglich auf 100 Zeilen mit 128 Zeichen pro Zeile begrenzt. Werden per print oder write mehr Zeilen in das Fenster gedruckt, dann wird der vorhandene Text automatisch gescrollt, wobei die obere (älteste) Zeile verschwindet.
Die momentane Position des Textcursors kann als Null-basierte Textkoordinate per csim.tscreen.cx (cursor x = Spalte) und csim.tscreen.cy (cursor y = Zeile) gelesen und gesetzt werden. Die Konstanten csim.tscreen.width und csim.tscreen.height liefern die Größe des Textpuffers für Anzeige in der Konsole, gemessen in 'Zeichen pro Zeile' (128 ?) und 'Anzahl Zeilen' (100 ?).

Vorder- und Hintergrundfarben sind wegen der Anzeige als 'Rich Text' sehr begrenzt. Bei der Zuweisung an csim.tscreen.fc (foreground colour) und csim.tscreen.bc (background colour), oder bei der Übergabe von Farbwerten als Funktionsparameter an csim.print sollten daher nur die folgenden symbolischen Farb-Konstanten verwendet werden:
clBlackclWhite   clRed    clGreen    clBlue  
clCyan clMagentaclYellowclDkGrayclLtGray
Per Default erfolgt die Anzeige in der Konsole 'schwarz auf weiß'. Per csim.tscreen.cls kann der Inhalt der kompletten Textkonsole gelöscht werden (wobei der Hintergrund mit der vorher an csim.tscreen.bc zugewiesenen Farbe gefüllt wird). Mit dem Kommando csim.tscreen.fill(x1,y1,x2,y2," ") kann ein rechteckiger Bereich des Fensters mit dem angegebenen Zeichen (in diesem Beispiel mit Lerzeichen) gefüllt werden.

Beide Kommandos für die Ausgabe von Texten (csim.print und csim.write) unterstützen die unten aufgeführten Steuerzeichen und einige (wenige) HTML-ähnliche Tags. Der einzige Unterschied zwischen 'print' und 'write' ist das autmomatische Anhängen von 'carriage return' ("\r") und 'new line' ("\n") an den auszugebenden String bei print (mit automatischem Löschen aller alten Zeichen im Rest der Zeile). Beides unterbleibt bei write.
Steuerzeichen und -Sequenzen in Zeichenketten bei der Ausgabe in die Textkonsole:

Optionen zur Synchronisation zwischen Applikation (Display-Simulator) und CAN-Simulator

Unter 'Weitere Optionen' (Button im Fenster des CAN-Simulators) stehen die folgenden Optionen zur Synchronisation von Display-Applikation und CAN-Simulation zur Verfügung:

Tipps zur Verwendung des CAN Message Generators (für Fortgeschrittene)