Siemens S7 V5.5 en arrays

High met Henk

Special Member

ik ben nog steeds bezig met het kast alarm systeem (https://www.circuitsonline.net/forum/view/155568/2), maar loop tegen een probleem aan...

arrays willen bij mij nog niet zo heel erg (heb problemen met het begrip pointers in algemeen, ik weet het LASTIG)

ik heb deze tutorial gebruikt: https://www.xj3.nl/dokuwiki/doku.php?id=indirect_adressing

maar mijn tijd is tekort / verstand te beperkt (invullen naar eigen inzicht), dus inmiddels is mijn trail version expired. (ff op een VM opnieuw installeren)

ik ben ook niet zo handig met AWL, liever Ladder of FB (ST wordt niet ondersteund)

mijn CPU is een S7 314, voor wat er toe doet.

Hetgeen ik probeer te schrijven zit in de bijlage: ik krijg het gewoon niet voor elkaar om de indexen van het array op een normale manier te gebruiken in Step 7 V5.5....

Voor het programma te begrijpen:
ik tel elders hoeveel kasten er open zijn:
Dit is de variabele no of cabinets closed
Verder heb ik een variabele INT_TIME dit is de tijd van de dag in 1 integer in minuten.

ik heb 4 strings met maximaal 32 kasten.
ik houd bij hoeveel kasten er op een tijdstip dicht zijn.
Dit is dus vastgelegd in de variabele INT_CAB_TIME
Dit is een 2D array met in de eerste index het string nummer en in de 2e index zit het kast aantal: Het opgeslagen getal is de tijd dat die kasten dicht waren.

als het systeem unarmed is, zal ik die dingen nog wel moeten leeghalen, maar dat is voor nu even een detail.

Als het systeem armed is, tel ik hoeveel kasten er dicht mogen zijn.
Maximaal dus 32. Ik houd dus niet bij welke kast er dicht is, maar een AANTAL kasten. een kast moet 30 minuten dicht zijn om mede beveiligd te zijn. Dit beschermt tegen stuiterende contacten.
Als een kast 30 minuten dicht is, telt hij dus mee. Anders niet!
Ik begin bij 0 kasten en dat aantal loopt dus op tot ik binnen 30 minuten zit. De tijd loopt door, dus als een er 10 kasten dicht zitten en 5 minuten later gaat de volgende kast dicht, dan gaat telt hij pas 35 minuten later 11 kasten.
Dat aantal sla ik op in: BYTE_OPEN_CABS_ALLOWED

daarna komt de test dat ik ergens ingegeven heb hoeveel kasten er in die string horen te zitten. Dat test ik dus tegen de variabele
BYTE_MAX_CABS_IN_STRING welke dus ook weer een index heeft in de variabele STRING_NO
Als er meer kasten beveiligd zijn dan er in de string zitten, gaan er dingen niet goed en is er dus reden om alarm te slaan (er is met het systeem geklooit of een fout)

Tenslotte de laatste test:
ik test of BYTE_OPEN_CABS_ALLOWED niet kleiner is dan hetgeen ik nu open heb.

Zullen wel wat schoonheidsfoutjes in zitten, maar de structuur zal wel werken.
Vraag is echter: kan iemand een stukje aangeven hoe ik die arrays kan indexeren??

[Bericht gewijzigd door High met Henk op zondag 31 oktober 2021 20:41:38 (55%)

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Ik heb je pdf niet geopend maar wat als er achter elke input een timer met ondelay met daar 2 move instructies waarvan 1 geinverteerd is. De move instuctie schrijven het zelfde adres ,maar dan een 1 als timer hoog is.

Aan het einde een optel instructie van 32 adressen waar dan je totaal resultaat uitkomt. Dan heb je geen gedoe met arrays.

Het is maar een idee die mij zo te binnen schiet.

High met Henk

Special Member

Ehhmm ik heb geen DI.

Gebruik AI en tel op met ca 0.5 mA.

Dan kan het nog steeds wel, maar met 128 timers en opslaan is het niet echt functioneel.

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Dan heb ik het niet helemaal goed gelezen. Maar je kan altijd een FC maken war je de timer met een systeempuls laat werken en dan telt. Echter die hoeveelheid timers maakt de PLC niks uit. Je hebt er ruim 500 tot je beschikking.

Ik heb nog eens gelezen wat als je een vergelijk maakt dus wat je nu meet en een seconde later en een timer triggert kan je dan je waarde actualiseren. 27567 / 16 = 1723 digit per 0,5ma
Door een actuele waarde met een deelfuntie DIV kan je dus ook waarde genereren van aantal kasten.

High met Henk

Special Member

Dat deel heb ik al.

Daar zit probleem niet in.

Maar om 21.30 ga ik waarschuwen dat we om 22.00 op alarm gaan.

Als ik om 21.30 10 kasten dicht heb..
En om 21.35 11 kasten.
En om 21.45 12 kasten.

Dan beveilig ik dus om 22.00 10 kasten
Om 22.05 zijn 11 kasten beveiligd
Om 22.15 zijn er 12 kasten beveiligd.

Ik houd dus in het array op de 2e index het aantal kasten bij. Die waarden moeten dus alleen maar oplopen.

Ik zoek gewoon uit hoe ik die indexen kan gebruiken.
Dat wil mij niet lukken in S7 V5.5

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Wordt er niet simpeler op. Arrays zijn niet helemaal mijn ding,succes

Kan je niet beter een array van UDT's aanmaken?

http://www.acro.be/Downloads/BasisPLC/Hoofdstuk%208_Databouwstenen.pdf

[Bericht gewijzigd door coldrestart op maandag 1 november 2021 11:24:30 (15%)

High met Henk

Special Member

Optellen van die 30 minuten in een UDT is lastiger.
Maar kan later evt nog.

Maar zit ik nog steeds met een array en indexen.
En dat wil ik ook wel, maar krijg het in S7 v5.5 niet aan de praat

[Bericht gewijzigd door High met Henk op maandag 1 november 2021 12:24:30 (21%)

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Arrays en indexeren/shiften zou ik zelf in SCL doen, dan is het een eitje.
AWL en pointers ben ik zelf niet zo'n fan van, het wordt al snel onduidelijk wat er precies gedaan wordt.

High met Henk

Special Member

Op 1 november 2021 12:27:18 schreef Jorn:
Arrays en indexeren/shiften zou ik zelf in SCL doen, dan is het een eitje.
AWL en pointers ben ik zelf niet zo'n fan van, het wordt al snel onduidelijk wat er precies gedaan wordt.

Dat is allemaal heel leuk ALS SCL (ST door mij foutief genoemd) zou kunnen in STEP 7 V5.5

En dat kan dus niet.

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Op 1 november 2021 16:38:44 schreef High met Henk:
[...]

Dat is allemaal heel leuk ALS SCL (ST door mij foutief genoemd) zou kunnen in STEP 7 V5.5

En dat kan dus niet.

Jawel, dat kan wel, maar moet je apart installeren als optie, en volgens mij ook apart een licentie voor hebben, maar zou ook gewoon als trial moeten werken.

Voor 5.6: https://support.industry.siemens.com/cs/document/109748118/where-do-yo…

[Bericht gewijzigd door Jorn op maandag 1 november 2021 17:36:53 (18%)

High met Henk

Special Member

Heb je daar dan ook een voorbeeld van hoe het werkt?

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???
GJ_

Moderator

Op 1 november 2021 12:27:18 schreef Jorn: AWL en pointers ben ik zelf niet zo'n fan van, het wordt al snel onduidelijk wat er precies gedaan wordt.

Ik vind het juist een eitje in AWL, net wat je gewent bent natuurlijk.

In scl mogelijkheden zat
zomaar even wat ingerost, ik doe nog zelden wat in 5.6 alles is al een paar jaar TiaPortal

code:


FUNCTION_BLOCK  FB77
TITLE   = 'Arraytest'
VERSION : '1.0'
AUTHOR  : Peter
FAMILY  : Arrays
VAR_INPUT


 
   
END_VAR
VAR

mxarr: INT;
anloginputvalue : INT;   //input value analog 4-20mA =  0-1000  every door offset 50 points 
IntArray : ARRAY [0..32] OF INT;
TimeArray: ARRAY [0..32] OF TIME;
//doubelarray
D_array: ARRAY[0..32] OF ARRAY[0..2] OF INT;
UdtArray: ARRAY[0..32] OF udt77;
END_VAR


VAR_TEMP



  i: INT;
  anlogincount: INT;


END_VAR    

BEGIN


FOR i := 0 TO mxarr DO
    intarray[i]:= i+30;
    timearray[i]:= dINT_TO_time(INT_TO_DINT( i*1000));
END_FOR;

//double array

D_array[2,1] := 1;
//udt array
//if analog inputvalue = xx.x mA then
udtarray[0].deurstatus := true;

//end if;

//scan all, add hysterese ?
 FOR anlogincount := 0 TO 1000 BY 50 do
   IF anlogincount = anloginputvalue THEN
     udtarray[0].deurstatus := true;
   ELSE
     udtarray[0].deurstatus := false;
   END_IF;
END_FOR;

END_FUNCTION_BLOCK

code:


TYPE UDT77
// header  
STRUCT
  DeurStatus : BOOL;  //open dicht
  DeurTijd : TIME; 
  tekst : STRING[30]:='' ;
 END_STRUCT;
 END_TYPE
High met Henk

Special Member

heb even ergens een mooie TIA portal geregeld en loop nu even te hannesen met date en time

ik wil op de Hmi in aparte velden de datum en tijd hebben.

echter ik krijg het niet voor elkaar om de datum goed te krijgen.

ik weet dat het date and time formaat 8 bytes is en ik

byte 0 moet hebben voor het jaar
Byte 1 voor de maand
byte 2 voor de dag

maar ik kan op 1 of ndere manier niet filteren.
AND operaties werken niet.
tijd aftrekken kan wel..

ik ben al aan het klooien geweest met fomules etc..

maar zo moeilijk moet het toch niet zijn??

HMI moet voor leken een tijd en datum kunnen instellen, dus aparte velden voor elke waarde

op de achtergrond wil ik ze weer samenvoegen tot een nieuwe DT
Voor de tijd heb ik e.e.a. al voor elkaar, maar de datum is echt erg lastig!

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???
High met Henk

Special Member

klein schopje...

niemand die weet hoe ik normaal dagen, maanden en jaren uit een datum kan trekken?

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???
GJ_

Moderator

Gewoon in een merkerdubbelwoord stoppen is het eenvoudigste natuurlijk. BV MD100En dan MB100 voor het jaar, MB101 voor de maand, enz
Of in de DB stoppen, bv BD100.DBD0. En dan het jaar uit MB100.DBB0 enz enz

Als je het moeilijk wil doen kun je ook schuiven en een AND er op loslaten of zo.
Genoeg mogelijkheden.

High met Henk

Special Member

In SCL is het dus niet zo makkelijk om over ladderof fbd maar te zwijgen.

Ik kan een date and time alleen in een int stoppen
Een and lukt ook niet op dit var type..

De int maakt er time in Ms sinds 1-1-1990 van

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???
GJ_

Moderator

Stop toch met SCL en ga fijn AWL programmeren, dan was je al klaar geweest >:-)

Zet het desnoods in een aparte bouwsteen en doe alleen die in AWL. Die mogelijkheid heb je, gebruik hem dan ook.

Als ik het goed begrijp wil je een date_and_time variabele uit elkaar trekken en opdelen in de afzonderlijke waarden?
Kan in SCL simpel door er met een AT instructie een masker van het gewenste type er overheen te leggen, in dit geval een struct met de losse waarden.

De losse velden zijn in mijn voorbeeld te benaderen als DateTimeStruct.Jaar bijvoorbeeld.

Onderstaande code maakt een unix time stamp
het stukje wat je nodig bent staat onder
"// read system time"
Wat voor HMI is het, de meeste kunnen datum en tijd gewoon weer geven in een singele i/o field.

code:


FUNCTION "UnixTimeStamp" : String
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_TEMP 
      Leapyears : Int;
      Days_from_1970 : DInt;
      days_from_BeginOfYear : Array[1..12] of Int;
      l_unixtime : DInt;
      sfc1_ret_val : Int;
      CDT_systemtime : Date_And_Time;
      systemtime AT CDT_systemtime : Struct
         Year_CDT : Byte;
         Month_CDT : Byte;
         Day_CDT : Byte;
         Hour_CDT : Byte;
         Minute_CDT : Byte;
         Second_CDT : Byte;
         MSec : Word;
      END_STRUCT;
      Year : Int;
      Month : Int;
      Day : Int;
      Hour : Int;
      Minute : Int;
      Second : Int;
      Msecs : Int;
   END_VAR


BEGIN
	// Convert system time to unix time
	// (seconds until 1970-01-01 00:00)
	
	
	
	
	
	#Leapyears := 0;
	#Days_from_1970 := 0;
	
	// days of current month without leap day
	
	#days_from_BeginOfYear[1] := 0;
	#days_from_BeginOfYear[2] := 31;
	#days_from_BeginOfYear[3] := 59;
	#days_from_BeginOfYear[4] := 90;
	#days_from_BeginOfYear[5] := 120;
	#days_from_BeginOfYear[6] := 151;
	#days_from_BeginOfYear[7] := 181;
	#days_from_BeginOfYear[8] := 212;
	#days_from_BeginOfYear[9] := 243;
	#days_from_BeginOfYear[10] := 273;
	#days_from_BeginOfYear[11] := 304;
	#days_from_BeginOfYear[12] := 334;
	
	
	// read system time
	#sfc1_ret_val := RD_SYS_T(#CDT_systemtime);
	#Year := BCD16_TO_INT(#systemtime.Year_CDT) + 2000;
	#Month := BCD16_TO_INT(#systemtime.Month_CDT);
	#Day := BCD16_TO_INT(#systemtime.Day_CDT);
	#Hour := BCD16_TO_INT(#systemtime.Hour_CDT);
	#Minute := BCD16_TO_INT(#systemtime.Minute_CDT);
	#Second := BCD16_TO_INT(#systemtime.Second_CDT);
	
	#Msecs := BCD16_TO_INT(SHR(IN := #systemtime.MSec, N := 4));
	
	// sum of leap years since 1979 (without current leap year)
	#Leapyears := ((#Year - 1) - 1968) / 4
	- ((#Year - 1) - 1900) / 100
	+ ((#Year - 1) - 1600) / 400;
	
	
	#Days_from_1970 := (#Year - 1970) * 365 + #Leapyears
	+ #days_from_BeginOfYear[#Month] + #Day - 1;
	
	IF ((#Month > 2) AND ((#Year MOD 4 = 0) AND ((#Year MOD 100 <> 0) OR (#Year MOD 400 = 0)))) THEN
	    #Days_from_1970 := #Days_from_1970 + 1; // + leap day, if year is leap year
	END_IF;
	
	// OUTPUT in s
	#l_unixtime := #Second + 60 * (#Minute + 60 * (#Hour + 24 * #Days_from_1970));
	
	
	// if error return 0
	IF #sfc1_ret_val <> 0 THEN
	    #UnixTimeStamp := '';
	ELSE
	    
	    CASE #Msecs OF
	        0..9:
	            #UnixTimeStamp := CONCAT(IN1 := DELETE(IN := DINT_TO_STRING(#l_unixtime), L := 1, P := 1),
	                                     IN2 := DELETE(IN := INT_TO_STRING(#Msecs), L := 1, P := 1), IN3 := '00000000');
	        10..99:
	            #UnixTimeStamp := CONCAT(IN1 := DELETE(IN := DINT_TO_STRING(#l_unixtime), L := 1, P := 1),
	                                     IN2 := DELETE(IN := INT_TO_STRING(#Msecs), L := 1, P := 1), IN3 := '0000000');
	        100..999:
	            #UnixTimeStamp := CONCAT(IN1 := DELETE(IN := DINT_TO_STRING(#l_unixtime), L := 1, P := 1),
	                                     IN2 := DELETE(IN := INT_TO_STRING(#Msecs), L := 1, P := 1), IN3 := '000000');
	            
	        ELSE
	            #UnixTimeStamp := '';
	    END_CASE;
	        
	        
	   
	END_IF;
	
	
	
END_FUNCTION
High met Henk

Special Member

Op 2 december 2021 17:12:22 schreef Jorn:
Als ik het goed begrijp wil je een date_and_time variabele uit elkaar trekken en opdelen in de afzonderlijke waarden?
Kan in SCL simpel door er met een AT instructie een masker van het gewenste type er overheen te leggen, in dit geval een struct met de losse waarden.

[bijlage]

De losse velden zijn in mijn voorbeeld te benaderen als DateTimeStruct.Jaar bijvoorbeeld.

Heb dit geprobeerd, maar zie het datatype AT niet en erbij tikken lukt niet

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Op 11 december 2021 16:07:14 schreef High met Henk:
[...]

Heb dit geprobeerd, maar zie het datatype AT niet en erbij tikken lukt niet

Waarschijnlijk heb je optimized block access aan staan?
Even rechtermuisknop op je fb/fc in het linker selectiescherm en dan properties, en optimized uitzetten.

https://www.youtube.com/watch?v=qHL1H0qsObk

High met Henk

Special Member

Dat filmpje heb ik gezien.
Optimized block access staat uit.
Let op is Tia Portal V14 en een cpu 314

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???