Umändern der Persistente Daten

j_poool

Level-1
Beiträge
107
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo!

Habe in einem Forum dieses Bsp. gefunden
IF( NOT FP_Write.BUSY ) THEN (* Nur bearbeiten, wenn kein Schreibauftrag läuft*)
uDifference := MEMCMP(pBuf1 := ADR(stPersistent),pBuf2 := ADR(stPersistent_Save), n := SIZEOF(stPersistent));
IF uDifference <> 0 THEN
MEMCPY(destAddr := ADR(stPersistent_Save), srcAddr := ADR(stPersistent), n := SIZEOF(stPersistent));
bDataChanged := TRUE;
END_IF
END_IF


(* Daten sichern *)
FP_Write(
NETID:= ,
PORT:= 801,
START:= bDataChanged,
TMOUT:= t#10s,
MODE:= 0,
BUSY=> ,
ERR=> ,
ERRID=> );

IF( bDataChanged ) THEN
bDataChanged := FALSE;
END_IF;
, der mir Persistente Date speichert, das Programm läuft einwandfrei und ich verwende es schon auf einige Projekte.

Nur, jetzt habe ich meine SPS mit einem Panel erweitert, meine Variablen die ich im Panel brauche kann ich mit dem Kommentar (*HMI*) beschreiben und dann mit die Programmiersoftware einfacher importieren. Wenn aber die Variablen in einer Struktur abgelegt sind kann die Programmiersoftware (iXDeveloper von Beijer) nicht das Kommentar (*HMI*) erkennen und so werden die Variablen nicht importiert.

Meine frage ist: wie kann ich das oben zugefügte Beispiel so umändern dass die zu speichernde Variablen in die VAR_GLOBAL_PERSISTENT ausgelesen werden?
 
Hallo,

sind das nicht zwei verschiedene Dinge ?

Das gezeigte Programm speichert einfach nur alle Persistent-Variablen. !ALLE VARIABLEN, egal wo!

Das die Software den Kommentar bei globalen Variablen nicht lesen kann ist scheinbar ein Softwarproblem des Herstellers des Panels.

Sollten jedoch wirklich nur Probleme bei Globalen variablen bestehen, kannst du ja die gesamte Struktur irgendwo "nicht global" speichern und von dort aus nutzen.

Vieleicht hilfts ja...

MfG CAS
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Cas
Im Programm wird eine Funktion durchgeführt die, die Struktur enthaltene Variablen auf umänderungen durchcheckt.

Als Anfänger kann ich das Programm nicht so umänder dass die globale Variablen auf änderungen durchcheckt.

Danke für deine Hilfe
 
Hallo!

Habe in einem Forum dieses Bsp. gefunden , der mir Persistente Date speichert, das Programm läuft einwandfrei und ich verwende es schon auf einige Projekte.

Nur, jetzt habe ich meine SPS mit einem Panel erweitert, meine Variablen die ich im Panel brauche kann ich mit dem Kommentar (*HMI*) beschreiben und dann mit die Programmiersoftware einfacher importieren. Wenn aber die Variablen in einer Struktur abgelegt sind kann die Programmiersoftware (iXDeveloper von Beijer) nicht das Kommentar (*HMI*) erkennen und so werden die Variablen nicht importiert.


Meine frage ist: wie kann ich das oben zugefügte Beispiel so umändern dass die zu speichernde Variablen in die VAR_GLOBAL_PERSISTENT ausgelesen werden?


Hallo JP,

leider kenne ich den ixDeveloper noch nicht. Aber alles was ich schon gesehen habe deutet darauf hin, dass starke Ähnlichkeiten zur Vorgängerversion bestehen...


So wie ich das verstehe, hast du 2 Probleme.

1. Wie kann eine Variable aus einer Struktur mit dem Display verknüpft werden?
-> Wenn hinter der Struktur bereits die Markierung (* HMI *) steht und dennoch nicht importiert wird, dann geht das importieren von Strukturen höchst wahrscheinlich nicht.
:confused:

2. Wie können Variablen Persistent angelegt werden, so dass bei Änderung automatisch die Funktion WritePersistentData angestoßen wird?
-> Am besten ist es wenn alle Persistenten Variablen an einem Ort zusammenhängend deklariert sind. Du kannst sie direkt unter deiner Variablen „stPersistent“ fortführen.
Code:
[FONT=Courier New][COLOR=#000000][SIZE=2]VAR_GLOBAL PERSISTENT[/SIZE][/COLOR][/FONT][FONT=Courier New]
[/FONT][FONT=Courier New][COLOR=#000000][SIZE=2](* Diese Variablen bleiben erhalten beim Übertragen der SW und bei Stromausfall.*)[/SIZE][/COLOR][/FONT][FONT=Courier New]
  [/FONT][FONT=Courier New][SIZE=2]stPersistent  [COLOR=#000000]: ST_PersistenteDaten; [/COLOR][COLOR=#00ae00](* HMI *)[/COLOR][/SIZE]
 [/FONT][FONT=Courier New][SIZE=2][COLOR=#000000] b_Weiche_01   AT %MX0.0   : BOOL;    (* HMI *)[/COLOR][/SIZE]
 [/FONT][FONT=Courier New][SIZE=2][COLOR=#000000] b_Weiche_02   AT %MX0.1   : BOOL;    (* HMI *)[/COLOR][/SIZE]
 [/FONT][FONT=Courier New][SIZE=2][COLOR=#000000] di_Teile_S1   AT %MD64    : DINT;    (* HMI *)    [/COLOR][/SIZE]
 [/FONT][FONT=Courier New][SIZE=2][COLOR=#000000] di_Teile_S2   AT %MD68    : DINT;    (* HMI *)    [/COLOR][/SIZE]
[/FONT][FONT=Courier New][COLOR=#000000][SIZE=2]END_VAR[/SIZE][/COLOR][/FONT]
Jetzt benötigst du noch eine Möglichkeit, um Änderungen zu erkennen. Entweder du vergleichst Variable für Variable mit Ihrem Zustand (temporäre Spiegelvariable) aus dem letzten Zyklus und setzt bei Ungleichheit das Bit „bDataChanged“, oder du bastelst dir eine Funktion, die das mit dem ganzen belegten Merkerbreich macht. ;)
Sieh dir mal die Funktion MEMCMP und MEMCPY genauer an...

Bei den Geräten mit Atom-Prozessoren gibt es eine eingebaute 1s USV - z.B. beim CX50xx. Dort reicht die Deklaration als Persistent aus* – die ganze Vergleicherei könnte entfallen... :ROFLMAO:

Gruß
Chräshe
___________________
*
[FONT=Arial, sans-serif][FONT=Arial, sans-serif]Ein kleiner Einzeiler mit dem Aufruf der Funktion FB_S_UPS ist leider dennoch notwendig...[/FONT][/FONT]

Code:
[FONT=Courier New]PROGRAM MAIN[/FONT]
[FONT=Courier New] VAR[/FONT]
[FONT=Courier New]   fbUPS      : FB_S_UPS;    (* UPS-FB instance *)[/FONT]
[FONT=Courier New]   eUpsMode   : E_S_UPS_Mode  := eSUPS_WrPersistData_Shutdown; [/FONT]
[FONT=Courier New] ...[/FONT]
[FONT=Courier New] END_VAR[/FONT]
  
[FONT=Courier New] fbUPS(eUpsMode := eUpsMode);(* immer als erste Anweisung stehen lassen *)[/FONT]
 
Zuletzt bearbeitet:
Hallo Chräshe!!!

Sieh dir mal die Funktion MEMCMP und MEMCPY genauer an...
Die zwei Bausteine verwende ich schon in meinem Programm, nur muss ich das so ändern, dass die Global angelegte Variablen auf umänderungen durchgecheckt werden. Meine Variablen mit der Adresse %I* oder %Q* darf ich auch nicht in eine Struktur einfügen ->Fehler und iXDeveloper erkennt nicht die Variablen in eine Struktur.

IF( NOT FP_Write.BUSY ) THEN (* Nur bearbeiten, wenn kein Schreibauftrag läuft*)
uDifference := MEMCMP(pBuf1 := ADR(stPersistent),pBuf2 := ADR(stPersistent_Save), n := SIZEOF(stPersistent));
IF uDifference <> 0 THEN
MEMCPY(destAddr := ADR(stPersistent_Save), srcAddr := ADR(stPersistent), n := SIZEOF(stPersistent));
bDataChanged := TRUE;
END_IF
END_IF

Anstatt stPersistent sollte mit MEMCMP die Globale Persistente Daten vergleichen, aber da kann ich nicht einfach auf VAR_GLOBAL PERSISTENT umändern.

Wie kann ich die Globale Variablen auf änderungen überprüfen?

Vielen Dank für deine Hilfe :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie kann ich die Globale Variablen auf änderungen überprüfen?

Hallo JP,

bitte schreib mal, welche CPU du hast.
Wenn es eine CPU mit Atom-Prozessor und 1s-USV ist, kannst du dir die ganze Vergleicherei sparen...:rolleyes:

Ansonsten sieh dir mal die Funktion MEMCMP und MEMCPY genauer an...

(auf die blauen Wörter kann man drauf klicken…:rolleyes:)

Als Starthilfe:
Code:
uDifference := MEMCMP(pBuf1 := ADR(%MB0),pBuf2 := ADR(%MB1000), n := 800);
Hier werden ab %MB0 800 Byte mit dem Speicherbereich ab %MB1000 verglichen.
Normal vermeidet man Hardware-Adressen, aber was anderes fällt mir auf die Schnelle auch nicht ein…

Gruß
Chräshe
 
Hallo Chräshe

bitte schreib mal, welche CPU du hast.
Wenn es eine CPU mit Atom-Prozessor und 1s-USV ist, kannst du dir die ganze Vergleicherei sparen...:rolleyes:
ich verwende eine CX9000, mit CX5000 da sind keine Probleme, aber für eine einfache Steuerung muss man auch was kostengünstig anbieten....

Hier werden ab %MB0 800 Byte mit dem Speicherbereich ab %MB1000 verglichen.
Ich habe ja die Persistente Variablen Global angelegt Bild1.jpg
Online sehe ich die Adresse der einzelne Variablen Bild2.jpg
:confused: Muss ich alle Variablen auswerten :confused: das ist ja eine sinnlose und unendliche arbeit, wenn ich z.B. ab %IB0 bis %IB1000 mit MEMCMP die Variablen auf änderungen überprüfe werden ja auch NICHT Persistente Eingänge einbezogen........
Code:
IF( NOT FP_Write.BUSY ) THEN        (* Nur bearbeiten, wenn kein Schreibauftrag läuft*)
    uDifference := MEMCMP(pBuf1 := ADR(%IB0),pBuf2 := ADR(%IB1000), n := (800));
    IF uDifference <> 0 THEN
        MEMCPY(destAddr := ADR(%IB0), srcAddr := ADR(%IB1000), n := SIZEOF(800));
        bDataChanged := TRUE;
    END_IF
END_IF

:ROFLMAO: Bin noch zu jung kann nicht alleine gehen, bitte hilfe mir beim aufstehen :ROFLMAO:
 

Anhänge

  • Bild1.jpg
    Bild1.jpg
    82,9 KB · Aufrufe: 12
  • Bild2.jpg
    Bild2.jpg
    83 KB · Aufrufe: 11
Zuletzt bearbeitet:
:ROFLMAO: Bin noch zu jung kann nicht alleine gehen, bitte hilfe mir beim aufstehen :ROFLMAO:

Hallo JP,

ich hätte eher vermutet du bist bequem... ;)

Dein Ansatz sieht ganz gut aus. Aber beachte, dass du den Merker- und nicht den Eingangsbereich verwendest → AT %MX0.0 … und die Adressen selbst festlegst...!
Wenn du alle persistenten Variablen hintereinander schreibst, und alle anderen lässt wie bisher, dann bist du doch schon fertig!

Gruß
Chräshe
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Chräshe!!!

Jetzt habe ich viel rumprobiert und versucht, jedoch die Geschichte ist lang und kompliziert.......

Da ich nicht Daten die dauernd ändern können, löse ich das Problem indem ich einfach die Daten 1-2x am Tag speichere.
Trotzdem vielen Dank!!!:D
 
Hallo JP,

gib zu du willst mich veräppeln!
:rolleyes:
Jetzt habe ich viel rumprobiert und versucht, jedoch die Geschichte ist lang und kompliziert...

Code:
[FONT=courier new]
[SIZE=2]IF( NOT FP_Write.BUSY ) THEN        (* Nur bearbeiten, wenn kein Schreibauftrag läuft*)[/SIZE]     
    uDifference := MEMCMP(pBuf1 := ADR(%[COLOR=#ff0000][B]I[/B][/COLOR]B0),pBuf2 := ADR(%[COLOR=#ff0000][B]I[/B][/COLOR]B1000), n := (800)); 
    [SIZE=2]IF uDifference <> 0 THEN[/SIZE]         
        MEMCPY(destAddr := ADR(%[COLOR=#ff0000][B]I[/B][/COLOR]B0), srcAddr := ADR(%[COLOR=#ff0000][B]I[/B][/COLOR]B1000), n := SIZEOF(800));         
        [SIZE=2]bDataChanged := TRUE;[/SIZE]     
[SIZE=2]    END_IF[/SIZE] 
[SIZE=2]END_IF[/SIZE][/FONT]

Wenn du die 4 I gegen ein M eintauschst, könnte es schon funktionieren. Viellicht wäre es noch ratsam, keine Lücken im Speicherbereich zu lassen. Fülle diese Lücken einfach mit Reserve-Platzhaltern. Sonst kann der Compiler diesen eventuell für andere Variablen in Beschlag nehmen und dein Speicher wird durch den unkontrolliert häufigen Zugriff erst recht in Mitleidenschaft gezogen!

Was du noch beachten musst, ist die Speicherorganisation. Bei CoDeSys ist die Zählweise anders als bei Siemens!
Zum Beispiel würde die Adresse %MD48 die Bytes Nr. 192, 193, 194 und 195 im Merkerbereich adressieren (48 * 4 = 192)...

Angenommen das ist dir alles zu aufwändig – wie wäre es mit einer Taste im Display „Änderung speichern“?
Mit der setzt du kurz den Start von der Funktion „WritePersistentData“ und gut ist...

Gruß
Chräshe
 
Zurück
Oben