Performing a Shift Register operation on an array in TwinCAT3 using SHL/SHR - plc

I am very new to PLC programming. Can anyone help with explaining how I can perform a SHR/SHL operation on an array of INT of lets say 10 elements using TwinCAT3. They way I thought I would do this is by moving the shift register one place so that Element 0 becomes Element 1, Element 1 becomes Element 2 ..etc. and the last Element is lost.
Thank you in advance for your help.

Lets say you are working with:
VAR
aiElements : ARRAY[0..uiElementsCount-1] OF INT;
i : INT;
END_VAR
VAR CONSTANT
uiElementsCount : INT := 10;
END_VAR
To move each value one index forward (0 -> 1, 1 -> 2, etc.) you can do the following:
FOR i := uiElementsCount-1 TO 1 BY -1 DO
aiElements[i] := aiElements[i-1];
END_FOR
To move each value one index backward (1 -> 0, 2 -> 1, etc.):
FOR i := 0 TO uiElementsCount-2 DO
aiElements[i] := aiElements[i+1];
END_FOR

Related

Converting an integer to binary

I am using Connected Components Workbench V12 with a Micro850 PLC
I am trying to take an input from a barcode scanner and convert the scanned integer input to a 8-bit binary number to use each bit as a boolean to trigger outputs on the PLC.
I am expecting the FOR loop to get the remainder for the input/2 and repeat for the remaining bits.
for example I input 21 and expect a 0,0,0,1,0,1,0,1 but only get a 1 on the 8th bit
Here's a Screenshot of the Variable Monitor
out_Complete := in_Enable;
IF in_Enable THEN
B[8]:= ANY_TO_DINT(in_Integer_Input); //convert input to DINT
Ba[8]:= ANY_TO_DINT(in_Integer_Input);
FOR X := 1 TO 8 BY 1 DO
B[X]:= MOD(Ba[X],2); //get remainder for [x] bit
Ba[X]:= B[X] / 2; //divide by 2
OutputBit[X]:= ANY_TO_BOOL(B[X]); //set output bit
END_FOR;
END_IF;
Ba[X] is always zero, except for index 8, because that is the one you set.
Another way to check the bits would be try bit access. Or bit shifting combined with AND, something like this
FOR X := 0 TO 7 BY 1 DO
B[X]:= SHR(in_Integer_Input, X) AND 1;
END_FOR;

Instantiating of numerous function block in CODESYS (IEC61131)

I have made a function block using CODESYS to perform energy metering. The inputs of the function block is current and voltage and the output is energy.
Now, we need to have 1000 instances of this function block to run the code for 1000 meter we have. Writing (and possibly copy and pasting) of these instances doesn't seem to be the most interesting work.
Wondering if anybody has a smarter way of doing this numerous instantiation.
For example, here is how the code (in CODESYS) looks like for 2 instances:
meter_instance1(CURRENT:=I1, VOTAGE:=V2);
Energy1:= meter_instance1.ENERGY;
meter_instance2(CURRENT:=I2, VOTAGE:=V2);
Energy2:= meter_instance2.ENERGY;
And we like to have 1000 instances of it.
Any idea is highly appreciated.
Just make an array of the function block:
aEnergyMeter : array [0..999] of FB_EnergyMeter;
Also make arrays of the voltage and the current:
aVoltage : array [0..999] of INT; //if you use INT as type
aCurrent : array [0..999] of INT;
Then you can use it like that:
aEnergyMeter[0](CURRENT:= aCurrent[0], VOLTAGE := aVoltage[0]);
As you use different arrays with the same size, I would prefer to define some global constant:
VAR GLOBAL CONSTANT
firstDevice : UINT := 0;
lastDevice : UINT := 999;
END_VAR
Then you can define the array like that:
aEnergyMeter : array [firstDevice..lastDevice] of FB_EnergyMeter;
I agree with Arndt that you should use an array of function blocks and an array for voltage and current. Depending on your scan rate of your task you should be able to use a for loop to scan through all of your function blocks in a couple lines of code
var
meterInstance : array[1..1000] of FB_EnergyMeter;
voltage : array[1..1000] of int;
current : array[1..1000] of int;
energy : array[1..1000] of int;
end_var
for i:=1 to 1000 by 1 do
meterInstance[i](Voltage := voltage[i],Current:= current[i]);
energy[i] := meterInstance.Energy;
end_for;
in that for loop you could also combine some error checks while you're at it
for i:=1 to 1000 by 1 do
meterInstance[i](Voltage := voltage[i],Current:= current[i]);
if meterInstance.Energy > MaxEnergy then
//sound alarm
end_if;
end_for;
The only caveat with this approach is if the scan time is too fast for your task. You could possibly get a watch dog error as the task would overrrun. However since you are only doing 1000 elements and I am assuming your function block is not extremely complex you should be ok with this approach. If you have problems try extending scan time or watch error time.

Randomize order of a MongoDB query in Go

Here is my query :
c := session.DB("searchV").C("video")
var results []BadVideo
err5 := c.Find(nil).All(&results)
fmt.Println("request done")
if err5 != nil {
panic(err5)
}
var i = 0
for _,badvideo := range results {
}
I would like to randomize the order of browsing the items of the query for making operation on each item of the request ...
So each time I run it, I browse it in a different order.
Manual shuffling
Here's a simple shuffle algorithm, which shuffles (randomizes) a []BadVido slice:
func shuffle(r []BadVideo) {
for i := len(r) - 1; i > 0; i-- {
j := rand.Intn(i + 1)
r[i], r[j] = r[j], r[i]
}
}
So after you loaded your results, simply call shuffle(results) on it.
For testing, I will use a simple BadVideo type:
type BadVideo struct {
Name string
}
func main() {
rand.Seed(time.Now().UnixNano())
results := []BadVideo{{"a"}, {"b"}, {"c"}, {"d"}, {"e"}}
shuffle(results)
fmt.Println(results)
}
Output (try it on the Go Playground):
[{c} {d} {b} {e} {a}]
How it works:
To shuffle a slice, the shuffle() function randomly selects one element from the slice for each index. It does it like iterating over all elements downward, and selects a random element from the remaining slice (including index of the element we're currently selecting, because random orders also include ones where an element "stays in place"), and using a random index to swaps the element with the chosen random one. The loop goes until i > 0 (and not until i >=0), because if only 1 element left, no need to swap it with itself.
Using rand.Perm()
Another variant of shuffle() could take advantage of rand.Perm() which returns a slice containing shuffled numbers. We can use these random numbers to tell how to reorder the results:
func shuffle(r []BadVideo) {
r2 := append([]BadVideo(nil), r...)
for i, j := range rand.Perm(len(r)) {
r[i] = r2[j]
}
}
Try this variant on the Go Playground.
One thing to note here: before we do the reordering, we have to save the original slice (make a copy of it), so we can select the original elements specified by random indices when writing the results in the slice. I created a copy by appending the complete slice to a nil slice.

safely remove item while iterating backward in Swift 3

When I want to pass through and remove an item or items from an array (when certain conditions are met), I typically iterate backward in the C-style for-loop and remove the item by index, avoiding the problem of index numbers being changed of the next item to be processed, or the changing size of the list affecting how many times the loop is passed through. But the C for-loop has been removed in Swift 3.
Here is my Swift 2.3 code for the initialization of the loop:
for (var i = allowedItems.count - 1; i > -1; i -= 1)
Here is the monstrosity created by the Swift 3 converter:
for (i in ((-1 + 1)...allowedItems.count - 1).reversed())
This version does not compile however. ("Expected ',' separator" at the "in" operator).
I simplify the "-1 + 1" bit to zero:
for (i in (0...allowedItems.count - 1).reversed())
Now the error is "Expected Sequence expression for for-each loop".
What is the safe and hopefully reasonably elegant way of iterating backward in Swift 3, in which an index or counter variable is made available for use in specifying which item should be removed? This type of logic appears a number of places in my code so I want to make sure to find the best solution.
Thanks.
What is the safe and hopefully reasonably elegant way of iterating backward in Swift 3
The built-in way is:
for i in (0 ..< allowedItems.count).reversed()
The elegant way is:
for i in allowedItems.count >>> 0
(where >>> is the custom operator that I define here).
Use stride:
for i in stride(from: allowedItems.count - 1, through: 0, by: -1) {
}
What is the safe and hopefully reasonably elegant way of iterating
backward in Swift 3, in which an index or counter variable is made
available for use in specifying which item should be removed?
This doesn't answer the technical question, but possibly the underlying XY problem: have you considered simply filtering your array based on the criteria "when certain conditions are met"?
func certainConditionsForKeepingAreMet(_ element: YourElementType) -> Bool { /* ... */ }
allowedItems = allowedItems.filter(certainConditionsForKeepingAreMet)
E.g.
var allowedItems = [1, 3 ,6, 2]
func certainConditionsForKeepingAreMet(_ element: Int) -> Bool { return element < 3 }
allowedItems = allowedItems.filter(certainConditionsForKeepingAreMet)
print(allowedItems) // [1, 2]
If you'd like to remove and use the removed elements (on-the-fly), you could simply pipe the elements that are to be removed to some "use this element" function, in the course of checking the conditions for the elements.
func doSomethingWith(_ element: Int) { print("Removed", element) }
func certainConditionsForKeepingAreMet(_ element: Int) -> Bool {
if element >= 3 {
doSomethingWith(element)
return false
}
return true
}
var allowedItems = [1, 3 ,6, 2]
allowedItems = allowedItems.filter(certainConditionsForKeepingAreMet)
/* Removed 3
Removed 6 */
print(allowedItems) // [1, 2]

how can I count the number of set bits in a uint in specman?

I want to count the number of set bits in a uint in Specman:
var x: uint;
gen x;
var x_set_bits: uint;
x_set_bits = ?;
What's the best way to do this?
One way I've seen is:
x_set_bits = pack(NULL, x).count(it == 1);
pack(NULL, x) converts x to a list of bits.
count acts on the list and counts all the elements for which the condition holds. In this case the condition is that the element equals 1, which comes out to the number of set bits.
I don't know Specman, but another way I've seen this done looks a bit cheesy, but tends to be efficient: Keep a 256-element array; each element of the array consists of the number of bits corresponding to that value. For example (pseudocode):
bit_count = [0, 1, 1, 2, 1, ...]
Thus, bit_count2 == 1, because the value 2, in binary, has a single "1" bit. Simiarly, bit_count[255] == 8.
Then, break the uint into bytes, use the byte values to index into the bit_count array, and add the results. Pseudocode:
total = 0
for byte in list_of_bytes
total = total + bit_count[byte]
EDIT
This issue shows up in the book Beautiful Code, in the chapter by Henry S. Warren. Also, Matt Howells shows a C-language implementation that efficiently calculates a bit count. See this answer.