# Brauche Hilfe bei AWL-Programm



## shiznit (20 April 2011)

Hallo zusammen,

habe einige Probleme bei der Umsetzung meiner Überlegung.Ich möchte,dass die Zustände von Tastern in einem Merkerwort abgelegt werden und mit den vorherigen Zuständen verglichen werden --> falls ungleich --> dann sollen beide Wörter ODER verknüpft werden,damit ich den aktuellen Zustand habe.

Folgendes Programm habe ich geschrieben:
Die Kommentare sind so verfasst,wie ich es gern hätte,nicht wie es das Programm umsetzt.
Entschuldige mich im Vorraus, ich weiss nicht wie ich mein Programmcode hier rein lade,habe es deshalb kopiert.

Bitte um genaue Erläuterung der Fehlermeldungen

PROGRAM PLC_PRG
VAR
    Taster0: BOOL;
    Taster1: BOOL;
    Taster2: BOOL;
    MWT: WORD;                  (*Merkerwort Taster*)
    MWS: WORD;                  (*Merkerwort Speicher*)
    comm: MBM_COMMUNICATE;                 (*Fertiger Kommunikationsbaustein von Modbus TCP/IP*)
    WriteCoils:ARRAY[0..MB_MAXDATABOOLVALUE] OF BOOL;      (*Data-Array*)
END_VAR

LD        Taster0                 (*Lade Taster0 und ...*)
    ST        MWT.0                       (*...speicher den Zustand an die Stelle .0 des Merkerwortes Taster*)
    LD        Taster1                  (*------ ||-------*)
    ST        MWT.1                      (*------ ||-------*)
    LD        Taster2                  (*------ ||-------*)
    ST        MWT.2                       (*------ ||-------*)

    LD        MWT                      (*Lade das Merkerwort Taster und ...*)
    EQ        MWS                       (*...vergleiche es mit Merkerwort Speicher*)
    JMPC    ENDE                    (*Wenn MWT = MWS, dann springe zu "ENDE"*)

    LD        MWT                        (*Lade das Merkerwort Taster*)
    LD        MWS                        (*Lade das Merkerwort Speicher*)
    OR                                           (*Verknüpfe beide Wörter ODER und ...*)
    ST        MWS                       (*...und speicher das Ergebnis wieder im MWS*)

    LD        MWS.0                              (*Lade den Zustand der Stelle ".0" und ...*)
    ST        WriteCoils[0]              (*...speicher ihn in den "Data-Array"*)
    LD        MWS.1                               (*------ ||-------*)
    ST        WriteCoils[1]              (*------ ||-------*)
    LD        MWS.2                               (*------ ||-------*)
    ST        WriteCoils[2]              (*------ ||-------*)
    S        comm.xStrobe              (*Setze den Eingang xStrobe des Bausteins "comm"*)
                                 (*xStrobe = Eine pos. Flanke startet den Baustein*)
ENDE:
    ANDN    comm.xBusy              (*Wenn der Ausgang comm.xBusy = FALSE       dann...*)
    R        comm.xStrobe               (*...setze den Eingang xStrobe des Bausteins "comm" zurück*)
                                  (*xBusy = TRUE : Baustein ist noch beschäftigt*)

Fehlermeldungen:






Warnung 1500LC_PRG(12) : Diese Expression enthält keine Zuweisung.Es wird ein Code generiert.
Fehler 4022LC_PRG(16) :Operand erwartet
Fehler 4032LC_PRG(18 ) :1 Operanden sind zu wenige für 'OR'.Es werden min. 2 erwartet.
Fehler 4200LC_PRG(27) :'LD' erwartet

Ich hoffe ihr steigt da durch...brauche dringend hilfe
LG


----------



## shiznit (20 April 2011)

Nehme auch gerne Vorschläge in ST entgegen


----------



## rheumakay (20 April 2011)

hallo
du must das OR zwischen die LD Anweisungen schreiben

Alt:
LD        MWT                        (*Lade das Merkerwort Taster*)
    LD        MWS                        (*Lade das Merkerwort Speicher*)
    OR                                           (*Verknüpfe beide Wörter ODER und ...*)
    ST        MWS                       (*...und speicher das Ergebnis wieder im MWS*)

Neu:
LD        MWT                        (*Lade das Merkerwort Taster*)
OR                                           (*Verknüpfe beide Wörter ODER und ...*)
    LD        MWS                        (*Lade das Merkerwort Speicher*)
    ST        MWS                       (*...und speicher das Ergebnis wieder im MWS*)


----------



## shiznit (20 April 2011)

Habe ich gemacht.
Neue Fehlermeldungen:

Zeile/Netzwerk 15: Operand erwartet   * WARUM?*
                     16: 1 Operanden sind zu wenige für 'OR'.Es werden min. 2      erwartet.     *WARUM?*
                     27: 'LD' erwartet      *WOFÜR?*


----------



## shiznit (20 April 2011)

Bitte,Bitte........hier sind doch so viele Cracks und meine Überlegung kann doch nicht so schwer sein sie umzusetzten. (außer für mich).Bin nämlich ein blutiger Anfänger


----------



## shiznit (20 April 2011)

Habe aus einem Datenblatt,dass man Wörter nicht mit dem Befehl 'EQ' vergleichen kann bzw gar keine Vergleiche durchführen kann.Nur INT,DINT und REAL.
Stimmt das? und wie würde man das denn sonst machen?


----------



## StructuredTrash (20 April 2011)

Alt:
LD MWT (*Lade das Merkerwort Taster*)
LD MWS (*Lade das Merkerwort Speicher*)
OR (*Verknüpfe beide Wörter ODER und ...*)
ST MWS (*...und speicher das Ergebnis wieder im MWS*)

Neu:
LD MWT (*Lade das Merkerwort Taster*)
OR (*Verknüpfe beide Wörter ODER und ...*)
LD MWS (*Lade das Merkerwort Speicher*)
ST MWS (*...und speicher das Ergebnis wieder im MWS*) 

Ganz neu:
LD MWT (*Lade das Merkerwort Taster*)
OR MWS (*Lade das Merkerwort Speicher*)
ST MWS (*...und speicher das Ergebnis wieder im MWS*)


----------



## StructuredTrash (20 April 2011)

shiznit schrieb:


> Habe aus einem Datenblatt,dass man Wörter nicht mit dem Befehl 'EQ' vergleichen kann bzw gar keine Vergleiche durchführen kann.Nur INT,DINT und REAL.
> Stimmt das? und wie würde man das denn sonst machen?


Mag sein, dass das bei Möller so ist. Dann nimm doch INT statt WORD für "MWT/MWS". Könnte natürlich sein, dass dabei wieder kein bitweiser Zugriff mit "MWT.x" möglich ist. Dann gibt es immer noch die Typumwandlung "WORD_TO_INT".


----------



## rheumakay (20 April 2011)

hallo shiznit,
wie weit bist du...
wenn du noch fehler hast, hänge doch einmal einen screenshot des Programms mit an..so kann man auch von hier aus dir helfen


----------



## PN/DP (20 April 2011)

Alt: ... - Neu: ... - Ganz neu: ... - Richtig neu:

```
LD MWT (*Lade das Merkerwort Taster*)
ST MWS (*...und speicher es im MWS*)
```
Das "sperrige" OR ist logisch falsch - das Loslassen der Taster würde dann nicht an den Slave übertragen und die Aktoren würden eingeschaltet bleiben. Jede Taste könnte nur einmal gedrückt werden, danach bleibt das zugehörige Bit in MWS und WriteCoils auf TRUE und es gäbe bei den Aktoren keine Änderung mehr.

@shiznit
Wenn Du für die Fortsetzung Deines Problems schon ein neues Thema aufmachst, dann erwähne bitte wenigstens das vorherige Thema, wo Du beschrieben hast, was Du eigentlich realisieren willst. In dem vorherigen Thema ist Dir übrigens dreimal erklärt und gezeigt worden, daß Du den aktuellen Zustand des Merkwortes UNVERÄNDERT in das Merkwort_alt übernehmen sollst. Nichts mit OR oder so ...




shiznit schrieb:


> Habe aus einem Datenblatt,dass man Wörter nicht mit dem Befehl 'EQ' vergleichen kann bzw gar keine Vergleiche durchführen kann.Nur INT,DINT und REAL.
> Stimmt das?


WORDs kann man nicht auf GRÖSSER oder KLEINER vergleichen, aber auf GLEICH und UNGLEICH darf man vergleichen.
Gibt es in Deinem (Moeller-)Programmiersystem keine Onlinehilfe zu AWL? Üblicherweise ruft man die Hilfe zu einem Befehl mit F1 oder Shift-F1 auf. 
Man muß keine zu kurz gehaltenen Datenblätter lesen.




shiznit schrieb:


> Entschuldige mich im Vorraus, ich weiss nicht wie ich mein Programmcode hier rein lade,habe es deshalb kopiert.


Um Programmcode gut lesbar in einen Beitrag einzufügen gibt es die [CODE]-Tags, die erzeugt man im Beitragseditor mit dem *#*-Button "Code einfügen". Also:
*[CODE]*
Programmcode ...
*[/CODE]*



shiznit schrieb:


> Fehler 4200LC_PRG(27) :'LD' erwartet


Neu:

```
ENDE:
[B]LDN[/B] comm.xBusy (*Wenn der Ausgang comm.xBusy = FALSE dann...*)
R comm.xStrobe (*...setze den Eingang xStrobe des Bausteins "comm" zurück*)
(*xBusy = TRUE : Baustein ist noch beschäftigt*)
```

Harald


----------



## StructuredTrash (20 April 2011)

PN/DP schrieb:


> Das "sperrige" OR ist logisch falsch - das Loslassen der Taster würde dann nicht an den Slave übertragen und die Aktoren würden eingeschaltet bleiben. Jede Taste könnte nur einmal gedrückt werden, danach bleibt das zugehörige Bit in MWS und WriteCoils auf TRUE und es gäbe bei den Aktoren keine Änderung mehr.
> 
> @shiznit
> Wenn Du für die Fortsetzung Deines Problems schon ein neues Thema aufmachst, dann erwähne bitte wenigstens das vorherige Thema, wo Du beschrieben hast, was Du eigentlich realisieren willst. In dem vorherigen Thema ist Dir übrigens dreimal erklärt und gezeigt worden, daß Du den aktuellen Zustand des Merkwortes UNVERÄNDERT in das Merkwort_alt übernehmen sollst. Nichts mit OR oder so ...



Vielleicht war es ja gerade das Problem, dass wir den Wunsch nach dem OR im ersten Thread ignorriert haben. Ich habe dort gerade noch einmal nachgelesen. Es war nur die Rede von gedrückten Tastern und "Ausgänge setzen". Das Loslassen kommt dann vielleicht im nächsten Thread.


----------



## shiznit (21 April 2011)

Zunächst möchte ich mich mal bedanken, dass ihr euch so viele Geganken macht.(Abgegebene Danke gibt es wenn's klappt )

Ich probier die Aufgabenstellung mal komplett zu beschreiben:
Ich habe 3 Taster an der Mastersteuerung und 3 LED's an der Slavesteuerung(jeweils Möller XC-CPU201 V),die über Modbus TCP/IP kommunizieren.Wenn ich einen Taster betätige(egal welchen/nur tasten,nicht halten),soll die dazugehörige LED geschaltet werden,d.h. der Eingang Strobe(comm.xStrobe) muss gesetzt werden.Wenn sich der Zustand irgend eines Tasters ändert,muss der Eingang Strobe rückgesetzt werden und wieder gesetzt werden,da eine pos. Flanke den Baustein startet und dann erst den aktuellen Zustand an den Slave übergibt.Kurz gesagt: drücke Taster1,LED1 an...drücke Taster2,LED1 aus-->LED2 an.

Bisheriges Programm:

```
LD        Taster0            (*Lade Taster0 und ...*)
    ST        MWT.0                (*...speicher den Zustand an die Stelle .0 des Merkerwortes Taster*)
    LD        Taster1            (*------ ||-------*)
    ST        MWT.1                (*------ ||-------*)
    LD        Taster2            (*------ ||-------*)
    ST        MWT.2                (*------ ||-------*)

    LD        MWT                (*Lade das Merkerwort Taster und ...*)
    EQ        MWS                (*...vergleiche es mit Merkerwort Speicher*)
    JMPC    ENDE                (*Wenn MWT = MWS, dann springe zu "ENDE"*)

    LD        MWT                (*Lade das Merkerwort Taster*)
    OR        MWS
    ST        MWS                (*...und speicher das Ergebnis wieder im MWS*)

    LD        MWS.0                (*Lade den Zustand der Stelle ".0" und ...*)
    ST        WriteCoils[0]        (*...speicher ihn in den "Data-Array"*)
    LD        MWS.1                (*------ ||-------*)
    ST        WriteCoils[1]        (*------ ||-------*)
    LD        MWS.2                (*------ ||-------*)
    ST        WriteCoils[2]        (*------ ||-------*)
    S        Strobe        (*Setze den Eingang xStrobe des Bausteins "comm"*)
    (*xStrobe = Eine pos. Flanke startet den Baustein*)
ENDE:
    LDN        comm.xBusy (*Wenn der Ausgang comm.xBusy = FALSE dann...*)
    R        comm.xStrobe (*...setze den Eingang xStrobe des Bausteins "comm" zurück*)
    (*xBusy = TRUE : Baustein ist noch beschäftigt*)
```
Bisherige Funktion des Programms:
Strobe wird erst TRUE,wenn ich denn Taster2 betätigt habe.Und Strobe wird nicht zurückgesetzt.


----------



## shiznit (21 April 2011)

Hier nochmal meine Überlegung in ST:

```
MWT.0 := Taster0;
MWT.1 := Taster1;
MWT.2 := Taster2;

 CASE step OF
0:
    IF MWT=MWS  THEN
        step:=1;
        ELSE step:=2;
    END_IF;

1:
    Strobe:=FALSE;
2:
    MWS:=MWT OR MWS;
    WriteCoils[0]:=MWS.0;
    WriteCoils[1]:=MWS.1;
    WriteCoils[2]:=MWS.2;
    Strobe:=TRUE;

END_CASE;
```

Bisherige Funktion:
Bleibt immer in "step1".Merkt sich die Zustände nicht.
Muss dazu sagen, dass ich mit ST noch weniger Erfahrungen habe.Obwohl die Aufgabe in ST gelöst werden soll,möchte ich sie erst mal in AWL verstehen/lösen.


----------



## shiznit (21 April 2011)

Hallo zusammen,

hier noch einmal eine neue Überlegung mit Ausschaltverzögerung.Sie funktioniert zwar,aber macht sie auch Sinn?

```
LD        Taster0            (*Lade Taster0 und ...*)
    ST        MWT.0                (*...speicher den Zustand an die Stelle .0 des Merkerwortes Taster*)
    LD        Taster1            (*------ ||-------*)
    ST        MWT.1                (*------ ||-------*)
    LD        Taster2            (*------ ||-------*)
    ST        MWT.2                (*------ ||-------*)

    LD        MWT                (*Lade das Merkerwort Taster*)
    ST        MWS                (*...und speicher das Ergebnis wieder im MWS*)

    LD        MWS.0                (*Lade den Zustand der Stelle ".0" und ...*)
    ST        WriteCoils[0]        (*...speicher ihn in den "Data-Array"*)
    LD        MWS.1                (*------ ||-------*)
    ST        WriteCoils[1]        (*------ ||-------*)
    LD        MWS.2                (*------ ||-------*)
    ST        WriteCoils[2]        (*------ ||-------*)
    (*setze den Strobe mit Ausschaltverzögerung*)
    LD        Taster0 
    OR        Taster1
    OR        Taster2
    ST        tof1.IN
    CAL        TOF1(PT:= T#2s)
    LD        TOF1.Q
    ST        Strobe
```


----------



## StructuredTrash (21 April 2011)

Du musst zunächst mal mit Deinem Kommunikationsbaustein klarkommen. Ich kenne den zwar nicht, denke aber, dass es prinzipiell so aussehen muss:

```
LD comm.xBusy
jmpc Label1        (* Kein neuer Strobe, solange der FB noch am Senden ist *)

(* Muss etwas gesendet werden? Wenn ja, *)
LD True                     (* das fehlte in Deinem ersten Programm, deshalb
                                    wurde Strobe nur bei Taster2 gesetzt *)
S comm.xStrobe

Label1:
CAL comm           (*Erst den Comm-FB aufrufen *)

LDN comm.xBusy    (* dann abfragen, ob er fertig ist *)
R comm.xStrobe
```
Für die Funktion der LED's laut Deinem Post #12 ist mehr als nur eine OR-Verknüpfung von MWT und MWS notrwendig. Dafür sind aber noch zwei Fragen zu klären. Was soll passieren, wenn
1. zwei Taster gleichzeitig gedrückt werden?
2. ein Taster gedrückt wird, während ein anderer noch gedrückt ist?
Und vielleicht noch: Sollen irgendwann auch alle LED's wieder ausgeschaltet werden?
Und noch eine Frage: Was soll passieren, wenn der Taster, dessen LED bereits leuchtet, erneut gedrückt wird?


----------



## shiznit (26 April 2011)

Hallo zusammen,

hoffe ihr hattet schöne Ostern.
@StructuredTrash:Habe deinen Vorschlag nun so umgesetzt

```
LD        Taster0            (*Lade Taster0 und ...*)
    ST        MWT.0                (*...speicher den Zustand an die Stelle .0 des Merkerwortes Taster*)
    LD        Taster1            (*------ ||-------*)
    ST        MWT.1                (*------ ||-------*)
    LD        Taster2            (*------ ||-------*)
    ST        MWT.2                (*------ ||-------*)

    LD        MWT                (*Lade das Merkerwort Taster und ...*)
    EQ        MWS                (*...vergleiche es mit Merkerwort Speicher*)
    OR        comm.xBusy        (* Kein neuer Strobe, solange der "comm" noch am Senden ist *)
    JMPC    Ende

    (* Muss etwas gesendet werden? Wenn ja, *)
    LD        MWT                (*Lade das Merkerwort Taster*)
    ST        MWS                (*...und speicher das Ergebnis wieder im MWS*)

    LD        MWS.0                (*Lade den Zustand der Stelle ".0" und ...*)
    ST        WriteCoils[0]        (*...speicher ihn in den "Data-Array"*)
    LD        MWS.1                (*------ ||-------*)
    ST        WriteCoils[1]        (*------ ||-------*)
    LD        MWS.2                (*------ ||-------*)
    ST        WriteCoils[2]        (*------ ||-------*)
    LD        TRUE
    S        Strobe

Ende:
    (*Aufruf des "comm-FB" *)
    LD        192
    MB_MakeIP     168,119,201
    ST        Comm.dwIPAddress
    CAL        Comm(xStrobe := Strobe, wPort := 502, bUnitIdentifier := 1, bFunctionCode := 15, wOffset := 0, wCount := 30, wOffsetAdd := 0, wCountAdd := 3, xarDataOut := WriteCoils, xCloseImmediate := TRUE, tTimeout := T#3000ms)

    LD        Comm.xarDataIn
    ST        ReadCoils

    LDN        comm.xBusy    (*abfragen, ob "comm"  fertig ist *)
    R        Strobe
```



> Was soll passieren, wenn
> 1. zwei Taster gleichzeitig gedrückt werden?
> 2. ein Taster gedrückt wird, während ein anderer noch gedrückt ist?
> Und vielleicht noch: Sollen irgendwann auch alle LED's wieder ausgeschaltet werden?
> Und noch eine Frage: Was soll passieren, wenn der Taster, dessen LED bereits leuchtet, erneut gedrückt wird?


zu 1. : beide LED's an
zu 2. : siehe 1.
zu 3. : ja,wenn der dazugehörige Taster erneut gedrückt wird
zu 4. : siehe 3.


----------



## StructuredTrash (26 April 2011)

shiznit schrieb:


> @StructuredTrash:Habe deinen Vorschlag nun so umgesetzt


Und, funktioniert comm.xBusy denn jetzt richtig?



shiznit schrieb:


> zu 1. : beide LED's an
> zu 2. : siehe 1.
> zu 3. : ja,wenn der dazugehörige Taster erneut gedrückt wird
> zu 4. : siehe 3.


Dafür brauchst Du zwei weitere Variablen. Ich nenne sie mal
MWP (Taster-Impulse) und
MWA (Taster-Status im vorangegangenen Programmzyklus).


```
LD       MWT
XOR    MWA
AND    MWT
ST       MWP

EQ        0
OR comm.xBusy
JMPC    Ende

LD       MWP
XOR    MWS
ST       MWS

(* Hier dann das Umsetzen in WriteCoils und Setzen von comm.xStrobe *)

Ende:

LD       MWT
ST       MWA

(* und dann den comm-Aufruf usw. *)
```


----------



## shiznit (27 April 2011)

> Und, funktioniert comm.xBusy denn jetzt richtig?


jo,funktioniert.

```
LD       MWT
XOR    MWA
AND    MWT
ST       MWP
```
warum das "AND  MWT" ?
habe diese Zeile mal weggelassen und habe die selbe Funktion.

P.S.: Wie geht das mit dem zitieren,dass man in der ersten Zeile den Beitrag anzeigen lassen kann?


----------



## Verpolt (27 April 2011)

shiznit schrieb:


> P.S.: Wie geht das mit dem zitieren,dass man in der ersten Zeile den Beitrag anzeigen lassen kann?



so..........?


----------



## StructuredTrash (27 April 2011)

shiznit schrieb:


> warum das "AND  MWT" ?
> habe diese Zeile mal weggelassen und habe die selbe Funktion.



Hm, bei mir hat das nicht dieselbe Funktion. Das "AND MWT" dient dazu, nur die steigenden Flanken der Tastersignale in "MWP" zu speichern. Wenn Du es weglässt, wird nach Loslassen des Tasters auch das entsprechende Bit in "MWS" wieder gelöscht.
Könnte allerdings sein, dass Du den Taster loslässt, bevor "comm.xBusy" wieder False wird. Dann würde es nicht auffallen.


----------



## shiznit (28 April 2011)

StructuredTrash schrieb:


> Könnte allerdings sein, dass Du den Taster loslässt, bevor "comm.xBusy" wieder False wird. Dann würde es nicht auffallen.


Stimmt .

Wie müsste das denn aussehen,wenn ich mal annehme:
Drücke Taster1,LED1 an
Taster1 loslassen,LED1 aus.

Eigentlich ne einfache Überlegung,bekomm das aber mit dem setzten von "Strobe" nicht hin.

P.S.: Ist für mich schwierig,sich in die Abläufe so schnell reinzudenken


----------



## StructuredTrash (28 April 2011)

shiznit schrieb:


> Wie müsste das denn aussehen,wenn ich mal annehme:
> Drücke Taster1,LED1 an
> Taster1 loslassen,LED1 aus.
> 
> Eigentlich ne einfache Überlegung,bekomm das aber mit dem setzten von "Strobe" nicht hin.


Die Grundstruktur für Dein Programm hast Du ja nun, daran brauchst Du nichts mehr ändern.
Vielleicht fällt der Groschen eher, wenn die Aufgabe etwas anders formuliert wird. Gesendet werden muss bei MWT<>MWS, und dabei soll MWS=MWT werden.


----------

