# Array in Nov Ram



## COOLT (12 August 2009)

hey leute ich hätte da mal wieder ein problem und zwar:
Ich weis, dass man Merker als %Q blablabla setzen kann und das mit dem Novram dann verknüpfen aber geht das ganze auch mit einem Array? weil ich will ein Array ins Nov RAM schreiben damit das z.B. bei einem Reboot erhalten bleibt


----------



## iguazu (12 August 2009)

Hallo Coolt,

ich würde das Problem folgendermaßen lösen:

1) Struktur erstellen:
erstelle eine Struktur, z.B.:

TYPE ST_NOVRAM :
STRUCT
        bVariable: BOOL;
        abVariable: ARRAY[1..10] OF BOOL;
        sString: STRING(80);
        rReal: REAL;
END_STRUCT
END_TYPE

2) Variable deklarieren:
stStruktur             AT %Q*            :ST_NOVRAM;

3) System-Manager:
Projekt übersetzen, im System-Manager neu einlesen

4) NOV-Ram:
eine neue Variable beim NOV-Ram-Ausgang anfügen, die Struktur auswählen und zum Schluß noch verknüpfen (siehe Schreenshot)


Damit sind alle Variablen die ins NOV-Ram sollen an einer Stelle im Programm.Nur mal so als kleines Beispiel.

Grüßle
iguazu


----------



## COOLT (12 August 2009)

Kann ich nich einfach das Array mit

```
arrBenutzerliste    :    ARRAY[1..Max_Benutzer] OF st_User;        (*    Benutzerliste mit ID, Level und Name der Anwender    *)
```
mit 

```
arrBenutzerliste  AT %Q*  :    ARRAY[1..Max_Benutzer] OF st_User;        (*    Benutzerliste mit ID, Level und Name der Anwender    *)
```
so deklarieren? funktioniert das nicht auch?


----------



## iguazu (12 August 2009)

Hallo,

klar, funktioniert auch (siehe Screenshot).
ich hoffe ich konnte dir weiterhelfen.

Grüßle
iguazu


----------



## bonatus (13 August 2009)

Hallo,

ich wurde das nicht so machen. Es gibt einen entscheidenten nachteil bei dieser Methode. Bei einem Stop oder Reset der Steuerung werden alle Ausgänge auf Null gesetzt so auch die vom NovRam und so sind alle Daten weg!

Der bessere Weg ist das schreiben der NovRam Daten über den Baustein FB_NovRamReadWriteEx oder FB_NovRamReadWrite.

Ich hab mir einen Baustein gebastelt der die NovRam Struktur kontrolliert und bei einer Änderung der Daten die NovRam Struktur in den NovRam schreibt.

Zum Start des Programms wird die Struktur einmalig eingelesen.

gruß bonatus


----------



## repök (13 August 2009)

bonatus schrieb:


> Hallo,
> 
> ich wurde das nicht so machen. Es gibt einen entscheidenten nachteil bei dieser Methode. Bei einem Stop oder Reset der Steuerung werden alle Ausgänge auf Null gesetzt so auch die vom NovRam und so sind alle Daten weg!
> 
> ....



Also das ist jetzt mal quark. die daten bleiben erhalten.


----------



## bonatus (13 August 2009)

Hallo repök,

wenn du die Daten des NovRams aus Ausgang deklarierst z.B.: NovRamOut AT %Q* ist es aber so. Alle Ausgänge werden auf 0 bzw. FALSE gesetzt und die Daten sind weg!

Hast du es schonmal ausprobiert?


----------



## repök (13 August 2009)

Ja genauso, und es hat immer funktioniert.


----------



## bonatus (13 August 2009)

Mir ist es zu unsicher.

Muss jeder selber wissen. Ich wollte es nur mal anmerken.


----------



## repök (13 August 2009)

das nov-ram kaufst du doch extra für solche zwecke zu. und ich hatte damit noch nie probleme.


----------



## COOLT (13 August 2009)

Danke euch für die hilfe leute aber jetz hab ich ein kleines Problem und zwar:

```
(* Generated automatically by TwinCAT - (read only) *)
VAR_CONFIG
    .COMin_COMport AT %IB0 : PcComInData;
    .COMout_COMport AT %QB528 : PcComOutData;
    .COMin_KL6001 AT %IB66 : KL6inData;
    .COMout_KL6001 AT %QB594 : KL6outData;
END_VAR
```
Das sind die Var_Configs und wenn ich das Programm mit strg+F8 debuggen lasse sagt der mir:

```
Warnung 1990: Kein 'VAR_CONFIG' für 'P_Benutzerlisten_Initialisierung.arrBenutzerliste'
```
Da bin ich mir dann nich so sicher ob das so ganz funktioniert.
Weis einer wie ich die arrBenutzerliste da rein bekomme?

Und wenn ich

```
VAR
    arrBenutzerliste    AT%QB524:    ARRAY[1..Max_Benutzer] OF st_User;        (*    Benutzerliste mit ID, Level und Name der Anwender    *)
END_VAR
```
benutze dann sagt er mir

```
Fehler 3801: P_Benutzerlisten_Initialisierung (3): Die Variable 'arrBenutzerliste' ist zu groß (48600 Byte)
```
Weis einer wie ich das deklarieren sollte am besten?


----------



## Cerberus (14 August 2009)

Wie es im Code schon so schön heißt sind diese Var_Configs "Generated automatically by TwinCAT". Die entsprechende Warnung ist auch normal. Sie kommt immer, wenn du irgendwelche Ein- oder Ausgänge in deinem Programm hast, die du im Systemmanager noch nicht verknüpft hast. Verknüpfe einfach deine Variablen im Systemmanager und übersetze das Programm erneut. Dann müsste die Warnung weg sein.


----------



## COOLT (14 August 2009)

o.k. Danke dir 
Jetz hat er wieder das Problem:

```
Fehler3801:P_Benutzerlisten_Initialisierung (3) : Die Variable 'arrBenutzerliste' ist zu groß (48600 Byte)
```
is aufgetaucht nachdem ich das Projekt neu eingelesen habe.
so dann weiter im Text, nächstes Problem. Ich möchte das das Array ins Novram gespeichert wird und von dort dann bei einem System neustart wieder ausgelesen wird wie geht das? Weil ich hab das ja jetz nur als Ausgang deklariert und nich auch noch als Eingang soll ich dafür einfach mal noch nen Array festlegen was dann in das Ausgangsarray per FB oder Programm reinschreibt?


----------



## repök (14 August 2009)

iguazu schrieb:


> Hallo Coolt,
> 
> ich würde das Problem folgendermaßen lösen:
> 
> ...


 
so wirds gemacht......


----------



## COOLT (14 August 2009)

Das sagt mir jetz aber noch nich wie ich die teile von da wieder auslesen kann. um die vorhandenen dann im programm zu überschreiben.


----------



## repök (14 August 2009)

Im Reiter Allgemeines DPRAM gibt es ein Häkchen zu setzen : Auto Init linked PLC Outputs. das muss gesetzt sein. dann is fertig.


----------



## COOLT (14 August 2009)

Das struct dingen bringt mich auch nich weiter ich das Struct was bei mir hinter array steht ist ja :

```
TYPE st_User :
STRUCT
    sUserID:STRING;
    sUserlvl:STRING;
    sUserName:STRING;
END_STRUCT
END_TYPE
```
Und wenn ich versuche das mit dem dpram zu verknüpfen sagt der mir es wäre zu groß.
Ich denke mal das der novram für so eine große Datenmenge nicht ausgelegt ist.


----------



## repök (14 August 2009)

Wieviele user willst du anlegen? vieleicht mal mit weniger probieren? 
Die Strings verkürzen würde ich auch noch. Kein schwein braucht 255 zeichen für seinen namen.  also blabla:String[10]. der wäre jetzt 10 zeichen lang.


----------



## COOLT (14 August 2009)

K mit der String verkürzung isses klein genug geworden. und 200 is erstmal nen Start wert ich arbeit schließlich in einer nicht gerade kleinen Firma
glaube zwar kaum das mehr als 100 leute zugang zur gleichen maschine brauchen aber egal es soll für viele ausgelegt sein.

Danke euch leute damit wäre mal wieder ein Problem weniger in meinem Projekt xD
Mfg
COOLT


----------



## COOLT (14 August 2009)

So ich hab das ganze mal getestet und als ich dann aus meinem Programm die vorgegebenen Benutzernahmen rausgenommen habe und das ganze dann im online modus resettet habe und neu gestartet habe hat er jetz die karte nimmer erkannt.


----------



## bonatus (14 August 2009)

Hallo,

versuch mal deine NovRam Daten manuell zu schreiben und nicht direkt als Ausgang zu definieren.

Bei einem Neustart musst du aber die Daten aus dem NovRam einmalig deiner Struktur übergeben.

gruß bonatus


----------



## COOLT (18 August 2009)

und wie mach ich das?


----------



## bonatus (18 August 2009)

Hallo,

ich schick dir mal ein bild als anregung mit.

Die Variable INFO_REMANENT wird auf true gesetzt sobal deine eingelesene Struktur die Werte des NovRams enthält.

Ich hab selber hab die NovRam Struktur in 2 Unterstrukturen unterteilt. Eine Zyklische die aller 5 Sekunden geschrieben wird und die andere Azyklisch die nur bei Änderung eines Zustands der Struktur geschrieben wird.

Hoffe es hilft dir ein wenig weiter.


----------



## COOLT (18 August 2009)

Danke dir für die Anregung, aber laut Beckhoff sollte das eigentlich nichmehr Notwendig sein seit Version 2.9 um auf das Novram draufzuschreiben.


----------



## bonatus (18 August 2009)

Es ist jedem selber überlassen wie man es macht. Ist die Freiheit die man hat.


----------



## COOLT (18 August 2009)

HM Also ich denke mal ich beschreibe dir mal genau mein Problem vielleicht kannste ja dann dein Jpg meinen Bedürfnissen anpassen damit ich wei was ich schreiben soll. Also:
Das Array was ich in den Nov Ram schreiben will ist ein Array mit einer Struktur die die UserID den UserNamen und das Userlevel enthält. Dieses Array kann über eine Visualisierung verändert werden. Dieses Array soll dann in den NovRam geschrieben werden und bei einem Systemneustart vom NovRam neu eingelesen werden.
Hoffe ich habs jetzt genau genug erklärt.
Und erwarte hoffnugsvoll einen Lösungsvorschlag.
Mfg
COOLT


----------



## bonatus (18 August 2009)

Hallo,

ich habs mal versucht so in etwa zu machen.

NR_Struktur ist deine NovRam Struktur, über die Variable Daten_Speichern schreibst du die Werte. Wie du das jetzt auslegts ist dein Ding - Button, Abfrage, Zyklus,...

gruß bonatus


----------



## COOLT (18 August 2009)

Danke dir ich werd das ganze mal ausprobieren und dir dann bescheidgeben obs funktioniert.


----------



## COOLT (18 August 2009)

Ich verstehe das mit dem Udint dingern noch nich so ganz. Was muss ich nun da angeben damit er das Array 

```
arrBenutzerliste       :    ARRAY[1..Max_Benutzer] OF st_User;
```
anspricht? also von dort liest und dort auch wieder reinschreibt?
Und vor allem was is das für ne Addresse? woher bekomme ich die? Wo kann ich die ablesen?


----------



## bonatus (18 August 2009)

Hallo,

du schreibst das gesamte Array arrBenutzerliste direkt in den NovRam. 

Also NR_Struktur=arrBenutzerliste vgl. mit Bild.

Da brauchst du dir keine Gedanken machen über irgendwelche UDINTs und so.

Edit: Du musst nur darauf achten das dein Array nicht größer ist als dein NovRam Speicher.

gruß bonatus


----------



## COOLT (18 August 2009)

hm muss ich nich iwie noch die NovRam mit iwas verknüpfen? damits auch richtig übernommen wird?

//€dit: weil iwie schreibt der da anscheinend noch nix rüber.

//€dit€dit: Habs nämlich gerade mal ausprobiert: erst normal durchlaufen lassen, damit er das array draufschreibt dann ausgeloggt die vorherige benutzerinitialisierung rausgenommen und dann neu geladen, so dass er eigentlich das Array aus dem Nov Ram hätte holen müssen. Aber iwie hat ers nich.


----------



## bonatus (18 August 2009)

Nein, das muss halt nicht mehr gemacht werden. Über die DeviceId (nDevId - siehe System Manager NovRam - Allgemein -->Id) wird festgelegt welcher Speicherbereich beschrieben wird. Den Haken "Auto Init linked PLC Outputs" musst oder kannst du rausnehmen.


----------



## COOLT (18 August 2009)

Also ich hab jetz alles so gemacht wie du es vorgeschlagen hast. Die ID ist laut System Manager die 4 ergo hab ich da jetz anstatt der 5 wie bei dir ne 4 eingetragen und den rest so übernommen

```
IF fbEinlesen.O_bReadDone THEN
    NovRamReadGO:=TRUE;
ELSE
    NovRamReadGO:=FALSE;
END_IF

IF NOT fbEinlesen.O_bNovRamWriteGO THEN
    NovRamWriteGO:=TRUE;
ELSE
    NovRamWriteGO:=FALSE;
END_IF

(*********************************************)
(*    NovRam beschriftung    *)
IF NovRamReadGO THEN
    fbNovRamReadWriteEx.nDevId:=4;
    fbNovRamReadWriteEx.bRead:=TRUE;
    fbNovRamReadWriteEx.bWrite:=FALSE;
    fbNovRamReadWriteEx.cbSrcLen:=SIZEOF(arrBenutzerliste);
    fbNovRamReadWriteEx.cbDestLen:=0;
    fbNovRamReadWriteEx.pSrcAddr:=ADR(arrBenutzerliste);
    fbNovRamReadWriteEx.pDestAddr:=0;
    fbNovRamReadWriteEx.nReadOffs:=0;
    fbNovRamReadWriteEx.nWriteOffs:=0;
END_IF
(*********************************************)
(*    NovRam Auslesung    *)
IF NovRamWriteGO THEN
    fbNovRamReadWriteEx.nDevId:=4;
    fbNovRamReadWriteEx.bRead:=FALSE;
    fbNovRamReadWriteEx.bWrite:=TRUE;
    fbNovRamReadWriteEx.cbSrcLen:=0;
    fbNovRamReadWriteEx.cbDestLen:=SIZEOF(arrBenutzerliste);;
    fbNovRamReadWriteEx.pSrcAddr:=0;
    fbNovRamReadWriteEx.pDestAddr:=ADR(arrBenutzerliste);
    fbNovRamReadWriteEx.nReadOffs:=0;
    fbNovRamReadWriteEx.nWriteOffs:=0;
END_IF
(*********************************************)
```
Das NovRamReadGo wir gesetzt sobald ich mich einmal abgemeldet habe.
Ich habe als ersten durchgang noch 

```
IF NOT bInitialisiert THEN        (*    Beginn der Festlegung    *)
arrBenutzerliste[1].sUserID:='1643109';
arrBenutzerliste[1].sUserlvl:='Admin';
arrBenutzerliste[1].sUserName:='Christian';
arrBenutzerliste[2].sUserID:='1646211';
arrBenutzerliste[2].sUserlvl:='Techniker';
arrBenutzerliste[2].sUserName:='Rafael';
arrBenutzerliste[3].sUserID:='1650637';
arrBenutzerliste[3].sUserlvl:='Admin';
arrBenutzerliste[3].sUserName:='Tobias';
FOR i:=1 TO Max_Benutzer DO    (*    Belegung der restlichen Plätze im Array mit leeren IDs    *)
IF arrBenutzerliste[i].sUserID='' THEN
    arrBenutzerliste[i].sUserlvl:='Kein level vorhanden';
    arrBenutzerliste[i].sUserID:='0000000';
    arrBenutzerliste[i].sUserName:='Noch nicht besetzt';
END_IF
END_FOR;
bInitialisiert:=TRUE;

END_IF
```
dringelassen und dann ausgeloggt das mit (**) ausgeklammert und nochmal eingeloggt resettet und dann konnt ich mich nimmer anmelden. weil das Array nit beschriftet wurde. Obwohl O_bNovRamWriteGO am anfang meine Schrittkette true gesetzt wird schreibt das NovRam trotzdem nich in mein Array.


----------



## bonatus (19 August 2009)

Hallo,

wenn du etwas in den NovRam geschrieben hast schau mal in die Variable 

cbWrite		: UDINT; 

des FBs FB_NovRamReadWriteEx da wird die Anzahl der geschriebenen Bytes hineingeschrieben.

Das gleiche dann auc mal beim lesen mit  

cbWrite		: UDINT; 

Die beiden Variablen müssten die gleiche Werte haben, aber ungleich Null.


----------



## COOLT (21 August 2009)

Jo die gleichen werte sind da und auch ungleich null aber iwie übernimmt er die Daten nit aus dem NovRam wenn ich das mal resettet hab.


----------



## bonatus (21 August 2009)

Versuch mal die Daten manuell aus dem NovRam zu lesen und deaktiviere mal deinen FB zum schreiben der Daten.

Verändern sich beim Schreiben der Daten eigentlich auch die Daten im System Manager (DPRAM(Online)) ?


----------



## COOLT (21 August 2009)

Da ändert sich garnix.


----------



## COOLT (21 August 2009)

Iwie tut sich da garnix im NovRam. Wenn ich mein Programm am laufen habe dann ändert das Wohl das es schreit und liest wenn ich Karte draufhab und runter nehme aber mehr auch nich.


----------



## bonatus (21 August 2009)

Hallo,

wenn du es über den FB FB_NovRamReadWriteEx machst musst du nichts weiter verknüpfen. Das ist ja eingtlich das gute daran. Hast du evtl noch alte "Ausgänge" mit dem NovRam Verknüpft?

Edit: Einlesen musst du doch nur einmalig beim Hochfahren oder nach einem Reset, wenn dein Programm läuft und mit den Daten arbeitet musst nicht mehr einlesen. Dann schreibst du nur noch den NovRam.


----------



## COOLT (21 August 2009)

Nö alles Clean


----------



## COOLT (21 August 2009)

Danke für die Überlegungs ansetze und Vorschläge aber ich mach das jetz einfach mit nem Global_var_persistent da schreib ich mein Array rein und gut is. Da bleiben die auch nach nem Reset erhalten.
Mfg
COOLT

// Thema hiermit abgeschlossen


----------



## grosser_marco (22 September 2009)

Im übrigen pflichte ich bonatus bei:
Wir haben einen Versuch gemacht mit NOVRAM-Variable, die als AT%Q* deklariert und dann im Systemmanager verknüpft wurden.
Diese Variablen überleben einen System-Stop, einen System-Restart und einen Reset-All. Aber einen PLC-Stop bei laufendem System überleben sie nicht!!!!!
Und wer wie ich aus der S7-Welt kommt, der klickt schnell mal auf PLC-Stop und danach wieder auf PLC-Start, weil er von S7 gewöhnt ist, daß die Variablen erhalten bleiben...
Demnach ist das Schreiben mit FBReadWriteNOVRAMEx definitiv die bessere Wahl. Übrigens werden als Persistent oder Retain deklarierte Variablen nur bei korrektem Herunterfahren des Systems auf der Platte abgelegt. Nach einem Absturz (BSOD oder Spannungsausfall) arbeitet das System unter Umständen mir den Daten weiter, die beim LETZTEN ordentlichen Herunterfahren gespeichert wurden...


----------

