Jump to content

Empfohlene Beiträge

Geschrieben

Moin,

ich wollte mich mal an einer Schleife nebst Variablenliste versuchen und dachte, dass ich, bevor ich mich in das Lua-Abenteuer stürze, besser die Ereigniskette mal ganz herkömmlich ausprobiere. Und: Gute Entscheidung. Weil: Das klappt auch nicht. Und: Ich sehe den Logikfehler einfach nicht.

Beschreibung EV:

Ereignis 01 (Start): Schalter wird betätigt ....................................................................................... Var. setzen (Kran) = "01"

Ereignis 02: Var. (Kran) wird gesetzt ................... Bed.: Var. besitzt den Wert (Kran) = "01" .......... Transportgut auf/ab Kran > Holz_01

Ereignis 03: Kran hat Transportgut auf/ab .......... Bed.: Var. besitzt den Wert (Kran) = "01" .......... Var. setzen (Kran) = "02"

Ereignis 04: Var. (Kran) wird gesetzt ................... Bed.: Var. besitzt den Wert (Kran) = "02" .......... Transportgut auf/ab Kran > Fläche_02

Ereignis 05: Kran hat Transportgut auf/ab .......... Bed.: Var. besitzt den Wert (Kran) = "02" .......... Var. setzen (Kran) = "03"

... etc.

Ausführung: Schalter wird betätigt, Kran hebt Holz_01 an und setzt es auf dem im letzten Ereignis angegebenen Objekt ab.

Es wäre schön, wenn mir jemand vom Schlauch helfen würde.

Gruß, Berlioz

Geschrieben

Schau dir dein Ereignisprotokoll an. Da siehst du, ob und wann einzelne Schritte ausgeführt werden. Daraus kannst du vielleicht ableiten, warum der letzte Schritt viel zu früh ausgeführt wird.

Geschrieben

Moin Frank, moin Goetz,

Musteranlage muss ich mal schaun.  In der EV ist das das erste.

Ereignisprotokoll hab ich geschaut. Alles normal, bis zum ersten Kran-Zugriff. Dann rauscht das durch bis zum Schluss.

Gruß, Berlioz

Geschrieben

Hallo Berlioz,

da deine Ereignisse alle den gleichen Auslöser besitzen (Kran nimmt Transportgut auf/ab, Variable wird gesetzt), werden deine Ereignisse alle in einem Rutsch verarbeitet. Und da du in Ereignis A die Bedingungen für Ereignis B setzt, und dort die Bedingungen für Ereignis C usw, werden die Ereignisse nicht übersprungen, sondern der Reihe nach bis zum Ende abgearbeitet, und zwar sofort. Sehen tust du natürlich nur das Endergebnis.

Lösen kannst du dieses Problem, wenn du als erste Aktion in deinen Ereignissen eine Verzögerung von 0 Sekunden einbaust, dann werden die Aktionen nämlich erst im nächsten Frame abgearbeitet. Die saubere Lösung wäre jedoch das Zusammenfassen der vielen Ereignisse. Es passiert ja jedes Mal das gleiche, nur mit anderen Daten, je nach Zustand. So etwas kann man durch verschachtelte Bedingungen oder durch Tabellen lösen.

Viele Grüße,

Neo

Geschrieben

Hallo Neo,

das mit den Tabellen war ja meine erste Idee, wollte nur vorher prüfen, ob die Abfolge läuft. Und das war das Ergebnis.

Ich hatte vorher auch alle Ereignisse zusammengefasst, mal verschachtelt, mal nicht. Dies zerlegte mir stets den ganzen Zug. Aber da war vielleicht ein anderer Fehler meinerseits ausschlaggebend. Ich probiere weiter und das mit der 0-Verzögerunmg behalte ich im Hinterkopf.

Danke, Gruß, Berlioz

Geschrieben
vor 31 Minuten schrieb Neo:

Lösen kannst du dieses Problem, wenn du als erste Aktion in deinen Ereignissen eine Verzögerung von 0 Sekunden einbaust, dann werden die Aktionen nämlich erst im nächsten Frame abgearbeitet.

Eine sehr wichtige Information!

Geschrieben

Hallo,

vor 14 Minuten schrieb Andy:

Eine sehr wichtige Information!

jein, der Vorschlag ist eher als Notlösung zu sehen. Besser wäre es, wenn so wenige Ereignisse wie möglich definiert werden. Sobald ihr mehrere Ereignisse habt, die den gleichen Auslöser besitzen, solltet ihr stutzig werden und prüfen, ob diese Trennung in mehrere Ereignisse wirklich Sinn macht. Sinnvoll ist sie ab V5 eigentlich nur noch, wenn es sich um völlig verschiedene Themenkomplexe handelt.

Viele Grüße,

Neo

Geschrieben

Moin,

okay, versuche mich jetzt an Lua. Ist bestimmt auch für die weiterführende EV-Gestaltung sinnvoll.

Bei Taster wird betätigt läuft dies:

$("Schienenkran").variables["Kran1"] = $("Holz05")
$("Schienenkran").crane:moveTo ($("Schienenkran").variables["Kran1"])

Bei Taster wird betätigt läuft dies nicht:

Ladefolge = {$("Holz05"),$("Holz11")}
$("Schienenkran").variables["Kran1"] = self.Ladefolge [1]
$("Schienenkran").crane:moveTo ($("Schienenkran").variables["Kran1"])

Gruß, Berlioz

Geschrieben

Hallo,

vor 29 Minuten schrieb Berlioz:

$("Schienenkran").variables["Kran1"] = self.Ladefolge [1]

das self dort ist falsch, mit self greifst du auf das aktuelle Ereignis als Objekt zu. Du willst aber auf eine Tabelle zugreifen, die du global definiert hast. Lass das self einfach weg.

Viele Grüße,

Neo

Geschrieben

Hallo Neo,

nur-- Ladefolge [1] --hatte auch nicht funktioniert, daher hatte ich-- $("Schienenkran").variables["Kran1"] = $("Schalter wird betätigt").Ladefolge [1] --zum Finden geschrieben.

das-- self -- setzte das Programm selber beim Abspeichern.

Gruß, Berlioz

Geschrieben

Hallo Neo,

sorry, hatte das self im falschen Ereignis herausgenommen, da hatte ich noch die Liste falsch. Es funktioniert natürlich, wie Du sagtest.

Vielen Dank, Gruß, Berlioz

Geschrieben

Moin,

mein Rechner hat jetzt einen neuen Belüfter. Der Pausentag tat offensichtlich auch mir ganz gut: Transportablauf läuft jetzt auf der Testanlage wie geplant ab.

A3C2FF7F-A0C4-44E4-96F5-CA7D03DD712A

Würde mich über Anmerkungen der Expädde freuen,

Gruß, Berlioz

Geschrieben (bearbeitet)

Ja, hast Du doch schön gemacht! (und so ein feines Tasterchen, hihi)

Allerdings: Wenn Du jetzt die Anlage mittendrin speichern würdest und wieder lädst, erlebst Du eine Überraschung.
Deine Holzladungspositionen und der Status des Kran wurden gespeichert. Nicht aber die Variable Var_Ladefolge, weil sie eine reine Lua-Variable ist und die werden nicht gespeichert! Mach eine Modulvariable draus. Kannst sie in Lua dann so ansprechen:  $("Ereignis").variable["Var_Ladefolge"]. Dann klappt's auch mit dem Nachladen.

Noch besser: Wenn Du 'Kran1' und 'Kran2' schon dem 'Schienenkran' zuordnest, mach das am besten auch mit 'Var_Ladefolge'. Dann ist das zusammen, was zusammen gehört..

Gruß
  Andy

Bearbeitet von Andy
Geschrieben (bearbeitet)
vor 8 Stunden schrieb Berlioz:

Würde mich über Anmerkungen der Expädde freuen,

Das ist gut, denn aus deinem Versuch kannst du sehr viel lernen.

Ich möchte mit deiner Variablen "Kran2" beginnen. Darin speicherst du einen Text, den du als Bedingung auswertest. Das ist nicht klug, weil der Vergleich von Texten besonders aufwändig ist. Eigentlich willst du nur zwei Zustände unterscheiden. An und Aus. Dafür gibt es einen besonderen Variablentyp namens Boolean. (Der Name geht auf George Boole, den Vater der booleschen Algebra zurück.) In einem Boolean speichert man entweder true oder false (für wahr oder falsch)

Jeder Vergleich liefert als Ergebnis ein true oder false, weil zwei Terme entweder gleich sind oder nicht.
Deshalb erwartet eine Bedingung (sprich: das if) immer ein true oder false.

Wenn du "Kran2" auf true bzw. false setzt, dann kannst du einfach schreiben if Kran2 then und benötigst keinen Vergleich.

-- für Kran_go
if $("Schienenkran").variables["Kran2"] then
  $("Schienenkran").crane:moveTo ($("Schienenkran").variables["Kran1"])
  $("Schienenkran").variables["Kran2"] = false
end

-- für Kran_Ende
if not $("Schienenkran").variables["Kran2"] then
  Var_Ladefolge = Var_Ladefolge + 1
  $("Schienenkran").variables["Kran1"] = Ladefolge [(Var_Ladefolge)]
  $("Schienenkran").variables["Kran2"] = true
end

Beachte bitte, dass unter Kran_Ende geprüft wird, ob "Kran2" nicht wahr ist!
if not Kran2 then

Diese Änderung gibt es als Entwurf unter Content-ID: E4CB71C1-6591-45B6-9346-88A84E4E8746

Bearbeitet von Goetz
Anlagen-ID hinzugefügt
Geschrieben (bearbeitet)

Die zusätzliche Variable Kran2 für "go" und "wait" ist aber eigentlich Umstandskrämerei und du kannst das alles einfacher haben.

Wenn dein Kran einen Schritt erledigt hat, dann soll er den nächsten nachladen.
Und wenn er den nachgeladen hat, dann soll er ihn ausführen.
Also kannst du doch ebenso gut auf die Änderung der Variablen Kran1 reagieren
und auf Kran2 ganz verzichten:

 

-- Schalter01 wird betätigt

Ladefolge = {
  $("Holz05"),$("Kklm505_11"),
  $("Holz06"),$("Kklm505_05"),
  $("Holz12"),$("Kklm505_06"),
  $("Holz05"),$("Kklm505_12"),
  $("Holz06"),$("Kklm505_11"),
  $("Holz12"),$("Kklm505_05"),
  $("Holz05"),$("Kklm505_06"),
  $("Holz06"),$("Kklm505_12"),
  $("Holz12"),$("Kklm505_11"),
  $("Holz05"),$("Kklm505_05"),
  $("Holz06"),$("Kklm505_06"),
  $("Holz12"),$("Kklm505_12")
  }

Var_Ladefolge = 1
$("Schienenkran").variables["Kran1"] = Ladefolge[Var_Ladefolge]


-- Variable Kran1 wird gesetzt

$("Schienenkran").crane:moveTo ($("Schienenkran").variables["Kran1"])


-- Kran Schienenkran hat ein Transportgut aufgenommen/abgesetzt

Var_Ladefolge = Var_Ladefolge + 1
$("Schienenkran").variables["Kran1"] = Ladefolge[Var_Ladefolge]


-- mehr braucht es nicht!

Eine letzte Unschönheit ist, dass die Variable "Var_Ladefolge" zum Schluss einen zu hohen Wert bekommt und damit in der Tabelle "Ladefolge" ins Leere greift. Glücklicherweise verträgt die Kransteuerung das und tut nichts, wenn moveTo() eine leere Adresse zugewiesen bekommt.

Aber du könntest den Wert prüfen und etwas anderes tun, wenn das Ende der Tabelle erreicht ist.

-- Kran Schienenkran hat ein Transportgut aufgenommen/abgesetzt

Var_Ladefolge = Var_Ladefolge + 1
if Var_Ladefolge <= #Ladefolge then     -- das # vor dem Tabellennamen steht für "Anzahl der Elemente in dieser Tabelle"
  $("Schienenkran").variables["Kran1"] = Ladefolge[Var_Ladefolge]
else
  $("Schienenkran").crane:reset()
end

Leider sieht ein crane:reset() in diesem Fall nicht schön aus. Die Reihenfolge der Bewegungen ist falsch.

Als Entwurf hochgeladen unter Content-ID: D6E75AB2-4FE7-4B7A-A36D-31665635BC24

 

Weiterhin viel Spaß bei deinen Experimenten :)

 

Bearbeitet von Goetz
Content-ID hinzugefügt
Geschrieben (bearbeitet)

Man kann auch ganz darauf verzichten, das nächste Ziel in einer Objektvariablen abzulegen.

Im folgenden Beispiel nutze ich die Objektvariable "Ziel" für die Zahl, welche die nächste Tabellenposition bestimmt. (Ursprünglich "Var_Ladefolge" genannt)
Außerdem prüfe ich bei einem Klick auf den Startknopf, ob die Sequenz schon läuft. Dafür benutze ich die Objektvariable "Ziel" mit folgendem Trick:

Eine Variable gilt in Lua als true, wenn sie einen Inhalt hat. Ist sie leer (= nil), dann wird sie als false gewertet.

Mit if not Ziel then kann ich also sagen:

Nur ausführen, wenn kein Wert in Ziel steht!

Taster01 wird betätigt

if not $("Schienenkran").variables["Ziel"] then
  $("Schienenkran").variables["Ziel"] = 2
  $("Schienenkran").crane:moveTo (Ladefolge[1])
end

 

Die Ladefolge gehört nicht in das Skript für "Taster01 wird betätigt", weil die nicht bei jedem Tastendruck neu angelegt werden muss.
Die gehört in ein eigenes Skript.
Solch ein Skript im Basismodul wird beim Start der Anlage einmal ausgeführt.
Es ist für all die Dinge gedacht, die man zu Beginn einmal initialisieren (= auf Anfang setzen) möchte.

<> Skript

Ladefolge = {
  $("Holz05"),$("Kklm505_11"),
  $("Holz06"),$("Kklm505_05"),
  $("Holz12"),$("Kklm505_06"),
  $("Holz05"),$("Kklm505_12"),
  $("Holz06"),$("Kklm505_11"),
  $("Holz12"),$("Kklm505_05"),
  $("Holz05"),$("Kklm505_06"),
  $("Holz06"),$("Kklm505_12"),
  $("Holz12"),$("Kklm505_11"),
  $("Holz05"),$("Kklm505_05"),
  $("Holz06"),$("Kklm505_06"),
  $("Holz12"),$("Kklm505_12")
}
  

Diese Variante 2 hat nur 2 Ereignisse, denn die Änderung der Variable ist kein Trigger mehr.
Wozu auch? Ich will ja den nächsten Schrott ausführen, wenn der vorherige erledigt ist.
Damit genügt doch der Trigger "hat Transportgut aufgenommen/abgesetzt"

Kran hat ein Transportgut aufgenommen/abgesetzt

local Ziel = $("Schienenkran").variables["Ziel"]

if Ziel <= #Ladefolge then
  $("Schienenkran").crane:moveTo(Ladefolge[Ziel])
  $("Schienenkran").variables["Ziel"] = Ziel + 1
else
  $("Schienenkran").crane:reset()
  $("Schienenkran").variables["Ziel"] = nil
end

Bitte beachten, dass die Objektvariable "Ziel" am Ende der Sequenz wieder auf nil gesetzt wird, damit der Knopf den Zyklus erneut starten kann.

Die lokale Variable "Ziel" hat nur den Zweck, das Skript lesbarer zu machen.

Variante 2 gibt es als Entwurf unter der Content-ID: 8B8C5D4A-576A-42F0-BA99-94613C049C61

Bearbeitet von Goetz
Korrekturen im Skript
Geschrieben

Hallo Andy, hallo Goetz,

vielen Dank für Eure tollen Ratschläge. Es gibt noch viel zu erkunden im MBS-Lua-Land.

Ich wollte das unbedingt mit der Liste oder Tabella ausprobieren. Das ist so genial und übersichtlich!

Entspricht also var = false in V5 var = [leer] in V4?

Geplant ist für jeden Zug (max. 3-4) eine Ladeliste zu erstellen oder durch Zugeinfahrt in der Liste die entsprechenden Zeilen zu ersetzen, dies dürfte aber im Aufwand ähnlich sein.

Gruß, Berlioz

Geschrieben
vor 53 Minuten schrieb Berlioz:

Entspricht also var = false in V5 var = [leer] in V4?

Hallo Berlioz,
das kann man so gar nicht mehr unbedingt vergleichen. In V4 waren die Variablen praktisch typenlos, in V5 wird da sehr genau drauf geachtet.
[leer] taucht ja in V5 auch noch gelegentlich auf, bezieht sich dann aber mehr auf ein nicht vorhandenes Objekt (eigentlich $("") - obwohl ich nicht sicher bin, ob dies dann dem immer entspricht). In V4 konnte es auch (z.B. bei einem Text) soviel wie 'nicht vorhanden' bedeuten. Götz hat hier aus dem relativ komplexen Typ String einfach einen sehr schnellen Boolean gemacht. Was 'true' und 'false' in dem Fall bedeuten, sollte man aber kommentieren.

Geschrieben
vor 10 Stunden schrieb Berlioz:

Entspricht also var = false in V5 var = [leer] in V4?

Nein, das tut es nicht. (Wenngleich beides manchmal für ähnliche Zwecke verwendet wird)

true und false sind die Grundlage von allem. was in deinem PC passiert. Das ist

  • "ja" und "nein"
  • "erfüllt" und "nicht erfüllt"
  • "wahr" und "falsch"

Es ist ein einzelnes bit, welches entweder auf 1 (= true) oder 0 (= false) steht. 

true und false sind die Basis für jede Verzweigung. Es gibt eine Bedingung, die entweder "erfüllt" oder "nicht erfüllt" ist. Ist die Bedingung true, dann wird der eine Programmteil ausgeführt. Ist sie false, dann geht es mit dem anderen Programmteil (nach dem else) weiter.

 

vor 9 Stunden schrieb Andy:

Was 'true' und 'false' in dem Fall bedeuten, sollte man aber kommentieren.

Ich plädiere für aussagekräftige Variablennamen anstelle zusätzlicher Kommentare.

Beispielsweise Position_ist_erreicht anstelle von Kran2, denn diese Variable wird in Berlioz Beispiel immer dann auf true gesetzt, wenn der Kran ein Ladegut aufgenommen/abgesetzt hat.

 

vor 10 Stunden schrieb Berlioz:

Ich wollte das unbedingt mit der Liste oder Tabella ausprobieren.

Und du hast schon im ersten Anlauf einiges erreicht und gelernt. Aber bevor du jetzt mit drei oder vier Zügen weitermachst, kümmere dich vorab darum, das neu erlernte Wissen richtig zu durchschauen. "Jetzt nutzen und später mal lernen" funktioniert nicht.

Bau die Beispiele nach, ohne sie abzuschreiben. Damit meine ich nicht, dass du sie auswendig lernen sollst. Das wäre Blödsinn. Du musst dich mit den Beispielen und Erklärungen beschäftigen, bis du sie in allen Details verstehst. Wenn du sie durchschaust, dann kannst du sie selbst herleiten. Wenn du sie nicht selbständig bauen kannst, dann gibt es noch offene Fragen. Denen musst du dann nachgehen. Und wir helfen dir gerne dabei.

Geschrieben

Moin,

das mit Lua geht voran ... langsam ... aber ich bin zuversichtlich. Hab überlegt, die Ideen der Probe-Anlage "Holzverladung" in die große Anlage "Unter-Dampf" zu übernehmen. Bin dann wieder auf ein altes Problem gestoßen: ich kann die Größe der Bodenplatten nicht verändern, ohne dass sich deren Skalierung von 1 auf 1,839 (N auf H0) ändert. Dies macht einen Großteil der Textulierungen unbrauchbar. Ich versteh einfach nicht, wo da mein Fehler liegt.

Gruß, Berlioz

Geschrieben

Hallo Berlioz,
hilf nochmal mit dem Problem:
Deine Holzverladung ist als Anlage auf N eingestellt und der Boden bringt bereits Skalierung 1,839 mit. Hat aber eigentlich keine Textur.
Wo geht das Problem genau los?

Erstelle ein Benutzerkonto oder melde dich an, um zu kommentieren

Du musst ein Benutzerkonto besitzen, um einen Kommentar verfassen zu können

Benutzerkonto erstellen

Neues Benutzerkonto für unsere Community erstellen.

Neues Benutzerkonto erstellen

Anmelden

Du hast bereits ein Benutzerkonto? Melde dich hier an.

Jetzt anmelden
×
×
  • Neu erstellen...