A weird For To Loop in Codesys - plc

I was trying to create a timed loop into an array but than I discovered something was not working right so I got back to a simpler example. Now I discovered that my loop skips all the time 1 index and places a value. So I get in index0, index1, index3 only values. I do not understand why this is happening, I'll show my code.
FOR vCount := 0 TO 9 DO
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount +1;
END_FOR
The result will be:
vVsample[0] = value vVin
vVsample[1] = did not change the value and is therefore 0
vVsample[2] = value vVin
vVsample[3] = did not change the value and is therefore 0
vVsample[4] = vVin
etc up to vCount = 10
I'm using Codesys V2.3 and tested this in simmulation mode

FOR loops already do increment the iterator, thus the vCount := vCount +1; line is the problem. Just remove it:
FOR vCount := 0 TO 9 DO
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_FOR
Or change to a while loop:
vCount := 0;
WHILE vCount <> 10 DO
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount +1;
END_WHILE

I have found the answer by myself allready it is not needed to count up vCount by 1.
When doing this it will skip always one index of the array.
Silly mistake by me

Related

Multi-variable assignment to an array in TwinCAT

How can assign a new variable to an array in TwinCAT?
in TwinCAT you can initialize all your array's argument directly for example for array a we can use:
a : ARRAY [1..3] OF INT := [3(0)];
or
a : ARRAY [1..3] OF INT := [0,0,0];
but if you want to assign the array in the main program(not initializing part) for example
a:=[2,8,5];
you will face this error tip: Unexpected array initialisation.
any help would be appreciated.
You cannot directly initialize arrays inside the program part.
That beeing said, the best option is porbably to define a constant containing the desired initialization values and then assigning the value of that constant to your array:
VAR
aiMyArray : ARRAY [1..2] OF INT;
END_VAR
VAR CONSTANT
aiInitializerMyArrayOptionA : ARRAY [1..2] OF INT := [1,2];
aiInitializerMyArrayOptionB : ARRAY [1..2] OF INT := [3,4];
END_VAR
IF bCondition THEN
aiMyArray := aiInitializerMyArrayOptionA;
ELSE
aiMyArray := aiInitializerMyArrayOptionB;
END_IF
The other option would be to manually initialize each index one by one which easily gets impracticale with decent array sizes:
IF bCondition THEN
aiMyArray[1] := 1;
aiMyArray[2] := 2;
ELSE
aiMyArray[1] := 3;
aiMyArray[2] := 4;
END_IF
Looping thorugh all elements and assigning values might be an option too. But that would only be usefull when the values are no arbitrary constatns but you are able to calculate the values from some formula.

What happens when I try to copy an object with `thecopy := object` instead of object.Clone()?

thearray := [6,77,4,3,66,11]
thecopy := thearray
MsgBox % thecopy.Length() ; 6
thearray := function(thearray)
MsgBox % thecopy.Length() ; 0
MsgBox % thearray.Length() ; 6
Why is thecopy "ruined" when thearray is changed by a function? My guess: The function changes the thearray. Therefor thecopy, which I guess is some kind of reference (?) to the same array as 'thearray' was, is invalid or something. Is this the right way to think about this? I'm all new to this reference thing or whatever it is.
And by the way, if .Clone() is added in the end of the second row thecopy remains intact.

How do I check if numbers are repeating in pascal?

I want to make a program which I will check if here are any Armstron numbers (numbers which are equal to the cubes of it's figures, for example 153).
Which are also perfect numbers (numbers equal to the sum of it's divisors, not including itself, for example 28 (1+2+4+7+14))
below 1000. So I made a program to see if a number is Armstrong number and to see if it's perfect number.
program Armstrong;
var i,n,j,d,s,p:integer;
begin
for i:=1 to 1000 do
begin
j:=i mod 10;
d:=i div 10 mod 10;
s:=i div 100;
n:=j*j*j+d*d*d+s*s*s;
if n=i then
writeln(i);
end;
end.
And for perfect numbers it's
program Perfect;
var n,s,i:integer;
begin
for n:=1 to 1000 do
begin
s:=0;
for i:=1 to n do
begin
if n mod i = 0 then
s:=s+i;
end;
if s=n then
writeln(n);
end;
end.
So I don't know how to merge them and see if any number I get from the first program appears in the second as well.
I did Pascal long time back. So assume I have used pseudo code for this answer.
Remove your loop from Armstrong and put the code in this function.
function Armstrong(i: integer): integer;
(* code goes here. And return 0 or 1 based on Armstrong *)
Remove your loop from Perfect, and put this code in this function
function Perfect(i: integer): integer;
(* code goes here. And return 0 or 1 based on Perfect *)
Then call it from a loop like this way:
for i:=1 to 1000 do
x = Armstrong(i);
y = Perfect(i);
if(x == 1 and y == 1) then
(* do something *)
end;

With Maple how can i prompt the user to answer a boolean expression?

The exact question would be "is the equation you want to use x=f(Xo)". This is in an if statement already so if true then continue if not then prompt user to enter a different function.
Your bit about its already being inside an if statement isn't very workable because that doesn't allow for an alternative value to be assigned to something in the case that the initial response is negative.
You should be able to work with something like this. Call p(), and assign its result to a ans, say, and then work with that value (and/or test it for some properties).
restart:
p := proc()
local answer, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf("Is the equation you want to use x=f(Xo)? (y/n)\n");
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
answer := x=f(Xo);
elif member(res1,{"n;","n","no;","no"}) then
printf("Enter your equation.\n");
res2 := readline(-1);
answer := parse(res2);
else
printf("Response not recognized\n");
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
if answer='answer' then NULL else answer end if;
end proc:
ans := p();
[edited below]
It is possible to get it a little closer to your original. With procedure p as below the returned result will be one of true/false/FAIL and could be used in a conditional. In the case that the return values if false (because of the response to the initial query) then a second query is made about the choice of another expression.
This version of p takes two arguments, the first is the suggested initial equation. The second is a name which can be assigned any alternative.
restart:
p := proc(candidate, resultvar)
local result, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf(sprintf("Is the equation you want to use %a? (y/n)\n",
candidate));
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
result := true;
assign(resultvar,candidate);
elif member(res1,{"n;","n","no;","no"}) then
result := false;
printf("Enter your equation.\n");
res2 := readline(-1);
assign(resultvar,parse(res2));
else
printf("Response not recognized\n");
result := FAIL;
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
return result;
end proc:
Now we can test it out.
p(x=f(X0), 'ans');
ans;
We could also use the call to p inside an if statement. Eg,
if p(x=f(X0), 'ans') then
"accepted";
else
"new choice made";
end if;
ans;
Here, answering "n" to the first query will make the conditional test see a false value, but the named argument ans will get assigned to as a side-effect.

For loops in Crystal Reports 2008

I'm trying to perform a very basic depreciation calculation based on the age of an asset using a For loop in Crystal 2008, and cannot get it working for the life of me.
The loop looks like this:
NumberVar AssetValue := {CIID.Currency4};
NumberVar DepreciationPercentage := {vw_DepreciationValues.Percent};
NumberVar AssetAge := DateDiff("yyyy",{CIID.Date4},CurrentDate);
Numbervar i := 0;
for i := 0 to AssetAge do
(
AssetValue = AssetValue - ((AssetValue/100)*DepreciationPercentage);
i = i + 1;
);
AssetValue;
For some reason, it always outputs AssetValue as the same number that went in....almost like it gets reset after being run.
I've tested the depreciation formula outside of the loop, and it works fine.
I've also verified that the i counter is getting incremented properly by the loop.
Anyone got a clue as to where I'm going wrong? I've even tried creating a custom function using private variables, but it made no difference.
Thanks in advance!
Typos:
AssetValue = AssetValue - ((AssetValue/100)*DepreciationPercentage);
^--- equality test
i = i + 1
^-- ditto
it should be := to do an assignment.