Jump to content

List of structs into ForEach loop


Recommended Posts

Is it possible to execute ForEach loop on a list of structs?

What I'm looking to do:

  • For every motor element I have a "run" struct (run, feedback, hours counter, wye-delta soft timers...) and a "settings" struct (power-up time, setting bits, preset times, etc).
  • This way I have a neat "motor object" for every motor, without having to take care of 100s of individual bits and integers everywhere.
  • Instead of manually calling a function for each motor, I'd like to have it somehow automated.

I made a list of "run" structs and "setting" structs for each motor. Number of list elements of run and setting structs is the same.

But when I create a ForEach loop, I can't choose any of the lists I made. Only way I can feed a list into a ForEach loop is if that list consists of primitive data types, that is: bits, integers, reals, etc. Not structs!

Is this possible in any way?

Link to comment
Share on other sites

Ah yes, that's it. Thank you @Saragani! ❤️

Why I couldn't do it, is that I forgot the "Properties Window" on the right, I have to select proper data type in there. Otherwise it won't work!

Now I have additional question: can I have multiple struct types as inputs to a for-each loop? Because I've defined one struct for "current" data which isn't retained, and other one with different settings data which *is* retained. For example: Run, Feedback, RPM, CurrentLoad... are stored in a non-retained struct, and data like WorkingHours, OnDelayTime, IsMonitored, ... are stored in retained struct. I've done this to save memory space, because max space for retained vars is less than non-retained.

If this isn't possible then,... I might have to merge these two structs into one which is wholly retained. Or are there any other workarounds? Can I have structs within structs? Or an array of structs?

Link to comment
Share on other sites

10 hours ago, kvlada said:

Ah yes, that's it. Thank you @Saragani! ❤️

Why I couldn't do it, is that I forgot the "Properties Window" on the right, I have to select proper data type in there. Otherwise it won't work!

Now I have additional question: can I have multiple struct types as inputs to a for-each loop? Because I've defined one struct for "current" data which isn't retained, and other one with different settings data which *is* retained. For example: Run, Feedback, RPM, CurrentLoad... are stored in a non-retained struct, and data like WorkingHours, OnDelayTime, IsMonitored, ... are stored in retained struct. I've done this to save memory space, because max space for retained vars is less than non-retained.

If this isn't possible then,... I might have to merge these two structs into one which is wholly retained. Or are there any other workarounds? Can I have structs within structs? Or an array of structs?

unfortunately, you can't have a struct in a struct.... nor an array of structs 😒

Link to comment
Share on other sites

  • 2 months later...

You need to set the type of the foreach loop to match the type of the list.

When you select the foreach function in the solution tree, then in the property grid, you can select the type of the list:

image.png

 

See the video I posted like 7 posts up.

 

Link to comment
Share on other sites

Great, thanks! This is what I was looking for! :) And than the variables are listed as Local Tag.

One last question:
Using a Data Table this way it is easy (with store) to read and write cell values. Is this correct?

Or is it better to use a List and read and write the row back to the data table seperately? (Is there a difference in speed/ cpu usage)

DataTable.png

Link to comment
Share on other sites

When you work with a data table as List parameter inside a "For Each" function, then you don't need to use Read Row and Write Row.

The whole point of the For each function is that it accepts Arrays, Data Tables and Lists, and it iterates the items one by one as the "Current Item".

 

In fact, it accesses the row directly, in case of a Data Table, so altering a member of the current item, immediately affects the value inside the data table.  

Link to comment
Share on other sites

Ok, I understand. And there no speed difference, because everything is in the same memeory area?

The reason why I'm looking for this is to improve our PLC software.
Please find attached 2 videos.
The first one is UniLogic version 1.33.161. With the bit "Tag: Data Entry Complete" the read row command of the data table is locked. I think in Versions up 1.33.161 the timing of the "Tag: Data Entry Complete" is different and the read row lock is not working anymore?

Link to comment
Share on other sites

I don't exactly understand what happens in the video. I see only a portion of the screen of the PLC, and I don't know what is expected to happen.

I know that there is an open issue about Numeric Box, that the Data Entry Complete bit is being set about 500ms after the edit was actually completed. What do you mean by read row lock?

Link to comment
Share on other sites

OK, this is a know issue, and it has a high priority.

Just for curiosity, how does the delay in the bit affects your code?

 

As far as I understand from the issue description, the numeric value is being set to the tag, and 500ms later the Data Entry complete bit is set.

In the ladder, if the code checks for the Data Entry Complete for being 1, and only then performs something, then it shouldn't care if the bit is being set 500ms later.

I understand that your case is different because you check for the Data Entry Complete being 0 (I'm not sure what AI.Aktive[23] is and what it does). 

 

Is your code constantly reading the current row from the Data Table into the struct (I assume that it's AI23_Ist.....), and only on the cycle that the Data Entry Complete is set it doesn't?

 

Do you have a global struct per row of the data table? (So if your table has 50 rows, then you have 50 instances of the same struct), and if you read row 1 you read it to Instance1 and if you read row 2 then you read it to Instance2, etc. ?

Link to comment
Share on other sites

Currently the data table for the analog values has 121 rows. The data table contains the current values of the sensor data and settings (e.g. linearization and threshold for process and alarm triggering). We use data tables for all digital and analogue values to be independent of the hardware I/O address. The configuration of the facility setup is done in this data table. Typically our facilities only have about 30 analogue sensors out of the option pool from 121. “Aktiv” = Active just means that the sensor is relevant for this facility.

So we read – manipulate – and write back each active row of the data table in one PLC cycle. We can modify the setting data in the data table. If the modification of settings is done on the HMI we use the “Data Entry Complete” bit to lock the read row operation for this cycle.

Only for the analogue data we have for each row a global struct containing the row data. This data is used for the program and HMI.

For digital IO’s we us an array and tag aliasing. Tag aliasing for analogue data would be possible but it is faster to have a struct because the name is inherited for all tags within this struct.

Maybe everything is realised too complicated. However, it brings flexibility.

The foreach loop and lists definitely bring new options. However, I will still keep the data table because of the overview and the easy import/ and export of data.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

This site uses cookies. By clicking I accept, you agree to their use.