Forum Replies Created
-
AuthorPosts
-
manjey73ParticipantSetVal(500.34) does not work, presumably because the Val() formula cannot display the channel value without a status. I also came across this. There is also the Data() formula, but I haven’t tried it yet, somehow it wasn’t necessary. It works a little differently, if I understood correctly.
You can change the values from the range directly in the channel formula, try using the combined CheckComm formulas inside the SetVal formula as shown above.If you plan to use formulas inside other formulas, make it a rule to convert to double yourself, even if returning bool is enough for you. Then it becomes possible.
manjey73ParticipantCheckComm – The multiplier formula
CheckComm1 – The formula is without using a multiplier, in fact, the multiplier is 1 if you use the first one
manjey73Participantpublic double CheckComm(double min, double max, double mult, string str = "" ) { if (Cmd < min || Cmd > max) throw new Exception($"The value must be within {min} - {max} {str}"); return Cmd*mult; } public double CheckComm1(double min, double max, string str = "" ) { if (Cmd < min || Cmd > max) throw new Exception($"The value must be within {min} - {max} {str}"); return Cmd; }You can also use formulas with verification to control the input parameters.
I’ve been making universal ones for myself here.The method of application in the output formula of the channel
Output channel
CheckComm(16, 32, 10, "degrees")Calculated/Output
SetVal(CnlNum, CheckComm(16, 32, 10, "degrees"))
manjey73ParticipantTry different options, as different channel processing scripts are required for different tasks.
manjey73ParticipantAn example of using formulas in Calculated channels
The Val() formula allows you to show the value after you enter it, but it will reset on reboots.
There is a formula that allows you to use the default value for reboots, suggested by Mikhail.// Set the default setpoint value. // For channels of the Calculated/output type public CnlData GetDefaultData(double val) { return Stat() > 0 ? Data() : NewData(val, 1); }
manjey73Participantyou need to use formulas in channels. the simplest is Val() for input and SetVal(CnlNum, Cmd) for output formulas.
well, there is also the possibility of using more complex formulas. The channel must be Calculated/Output
manjey73ParticipantStart with scripts in which you read or write to files, and the like. That is, some more complex scripts that you use.
manjey73ParticipantYou’ve voiced the problem, but you haven’t provided a single script that you think could lead to this.
manjey73Participantso 10 times per second is about a 100ms cycle 🙂
manjey73ParticipantPlease show me your script.
When calling the script directly, it should run faster than when called through EverySec.
manjey73ParticipantI don’t understand how your script works fast when using the limit of once per second (everysecond) and at the same time runs for 10 seconds with a direct call?
Show your script that behaves this way.
manjey73Participant1. How does your script run for a few seconds without using EverySec?
How did you determine that?
manjey73ParticipantYou can use it inside your scripts. Someone also has to set the timer so that it starts working.
manjey73ParticipantWhat’s wrong with processing a script in a loop, which also requires a timer of less than a second?
To be honest, I haven’t implemented timers for such a task. I usually use them for other purposes, for example, to delay triggering the device status.
What exactly is your goal? Can you draw a flowchart for understanding?An example of a TON timer from CodeSys or similar.
// IEC timers and others public static long Ticks() { DateTime now = DateTime.Now; long time = now.Ticks/10000; return time; } protected class UtilTimer { public long et; public bool flag; public bool q; } protected Dictionary<string, UtilTimer> TonTimer = new Dictionary<string, UtilTimer>(); protected Dictionary<int, UtilTimer> TofTimer = new Dictionary<int, UtilTimer>(); protected Dictionary<int, UtilTimer> TpTimer = new Dictionary<int, UtilTimer>(); // Timer with a delay of turning on TON public double TON(double IN, double PT, double Q, string str = "", int idx = 0) { var ut = new UtilTimer() {et = 0L, flag = false, q = false}; string keys = $"{CnlNum}_{idx}"; // The key is the channel number plus the timer index, zero by default. Allows you to use multiple timers inside a formula. long ET = 0L; long _pt = Convert.ToInt64(PT); bool q = Q > 0; bool _in = IN > 0; string s = str.ToLower(); if (s == "s" || s == "sec") _pt = Convert.ToInt64(PT) * 1000; if (s == "m" || s == "min") _pt = Convert.ToInt64(PT) * 60000; if (s == "h" || s == "hour") _pt = Convert.ToInt64(PT) * 3600000; if (!TonTimer.ContainsKey(keys)) { TonTimer.Add(keys, ut); } if (!_in) { TonTimer[keys].q = false; TonTimer[keys].flag = false; TonTimer[keys].et = 0L; } else { if (!TonTimer[keys].flag) { TonTimer[keys].flag = true; TonTimer[keys].et = Ticks(); } else { if (!q) ET = Ticks() - TonTimer[keys].et; } if (ET >= _pt) q = true; TonTimer[keys].q = q; } q = TonTimer[keys].q; return Convert.ToDouble(q); } // -------------------------------------------- // Timer with delayed shutdown of TOF public double TOF(double IN, double PT) { var ut = new UtilTimer() {et = 0L, flag = false}; long ET = 0L; long _pt = Convert.ToInt64(PT); bool q = Val(CnlNum) > 0; bool _in = IN > 0; if (!TofTimer.ContainsKey(CnlNum)) { TofTimer.Add(CnlNum, ut); } if (_in) { q = true; TofTimer[CnlNum].flag = true; TofTimer[CnlNum].et = 0L; ET = 0L; } else { if (TofTimer[CnlNum].flag) { TofTimer[CnlNum].flag = false; TofTimer[CnlNum].et = Ticks(); ET = 0L; } else { if (q) ET = Ticks() - TofTimer[CnlNum].et; } if (ET >= _pt) q = false; } return Convert.ToDouble(q); } // -------------------------------------------- // Pulse Timer TP public double TP(double IN, double PT) { var ut = new UtilTimer() {et = 0L, flag = false}; long ET = 0L; long _pt = Convert.ToInt64(PT); bool q = Val(CnlNum) > 0; bool _in = IN > 0; if (!TpTimer.ContainsKey(CnlNum)) { TpTimer.Add(CnlNum, ut); } if (!TpTimer[CnlNum].flag) { if (_in) { TpTimer[CnlNum].flag = true; TpTimer[CnlNum].et = Ticks(); if (ET < _pt) q = true; } } else { if (q) { ET = Ticks() - TpTimer[CnlNum].et; if (ET >= _pt) q = false; } else { if(!_in) { TpTimer[CnlNum].flag = false; ET = 0L; } } } return Convert.ToDouble(q); }
manjey73ParticipantAll formulas in the channels are executed in a cycle from the smaller channel to the larger one. If you don’t specify every second, then it’s about 10 times per second. And the more channels there are, the longer the pause time will be.
Or don’t use the every second wrapper, or use your own timer for example. -
AuthorPosts