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.
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.
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
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 (15%)]
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 (21%)]
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.
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.
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 (18%)]
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
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
TYPE UDT77
// header
STRUCT
DeurStatus : BOOL; //open dicht
DeurTijd : TIME;
tekst : STRING[30]:='' ;
END_STRUCT;
END_TYPE
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!
Heb je hier wat aan?
https://support.industry.siemens.com/cs/document/21222026/how-can-you-…
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.
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
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.
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
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
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.
Importeer mijn voorbeeld en kijk of Tia het accepteert in je cpu.
[Bericht gewijzigd door Peter112 op (19%)]
Op 11 december 2021 21:13:09 schreef High met Henk:
Dat filmpje heb ik gezien.
Optimized block access staat uit.
Let op is Tia Portal V14 en een cpu 314
Klopt, mijn voorbeeld heb ik ook met een 314 CPU gemaakt omdat inderdaad een 300 serie niet alles kan wat met een 1500 wel kan.
Enige verschil is dat ik Tia Portal V17 gebruikt heb.