Our project consists of a lot of function blocks (CM’s) which all contain an settings input. In the settings consists of severeval types, for example:
When we use several of the same function blocks, we want declare the settings only once and make them into an array, like this:
But for easy access we want to show the values inside the settings into a table on the HMI: an column for Speed, one for Acceleration and one for deceleration.
Currently we do that by reading/writing the values into a new array structure, like this:
The downside of this is dat we need to have all the values twice and you need a button on the HMI to read/write the values.
What would be nice to have is a function that can write the values from a structure into an array, as if it are pointered values. Basically sometime like:
But this does not work, because you cannot access the seperate values into an array with the access function.
Is there anybody with a solution for this problem?
an asorted list of things I am wondering about and recommending:
a) Why do you basically have the same structure array twice? If you map the “ValueSettings” to the visu directly, any read and write do directly modify the structure as expected - no need for a dedicated button to read and/or write
b) Using VC4 (I am quite sure mappView allows for similar things but am not familiar with it) you could use the Completion Datapoint on the text fields, and any time it’s set, you refresh the Set data, otherwise you read the data:
IF SettingsChanged THEN
SettingsChanged := FALSE;
// we copy the data from the Visu to our local structures
brsmemcpy(ADR(ValueSettings), ADR(HMISettings), SIZEOF(ValueSettings));
ELSE
// we copy the local structure to the HMI
brsmemcpy(ADR(HMISettings), ADR(ValueSettings), SIZEOF(ValueSettings));
END_IF
Note: even when not going with this solution, I recommend the use of brsmemcpy instead of iterating the arrays manually
SettingsChanged would be mapped to ALL fields on the visu that this specific structure is representing (you don’t need to distinguish, which field was changed - the info THAT it changed is enough)
a) The problem with mapping the structure directly into the visu is that we want to use an table. The input of a table is always an array with one type. e.g. real[0…2], so ValueSettings cannot be mapped directly to a table.
b) That could be a nice solution, but the problem with that is that ValueSettings and HMISettings do not have the same structure:
Variables.var:
Types:
The suggestion b) would then still work, just not with using brsmemcpy
IF SettingsChanged THEN
SettingsChanged := FALSE;
// we copy the data from the Visu to our local structures
FOR i := 0 TO 2 DO
ValueSettings[i].Speed := HMISettings.Speed[i];
...
END_FOR
ELSE
// we copy the local structure to the HMI
FOR i := 0 TO 2 DO
HMISettings.Speed[i] := ValueSettings[i].Speed;
...
END_FOR
END_IF
I also didn’t look close enough, your initial screenshot already would have shown that these are different types…
Probably it would still work with memcopy, but then one array value at the time. But your solution will work aswell. I’m now looking if the ‘value change’ works on a table, but it still feels like a ‘dirty’ solution.
One where I can use a pointered value between the ‘ValueSettings’ and ‘HMIsettings’ would be a much more cleaner solution and then I also don’t have to declare the memories twice.
Well, using memcpy for one value at a time doesn’t make sense anymore. This was just a "i want one structure content to be the same as another one - which with your datatypes won’t work.
“Array of reference to” doesn’t work unfortunately, only “Reference to array of”, so what you suggest is not possible.
What you could do is to abandon the ValueSettings structure and use the HMISettings one, then, only. This will then work for your tables, and the code is more flexible in that regard so you can adapt to change ValueSettings[index]. to HmiSetting.[index]
“Array of reference to” doesn’t work unfortunately, only “Reference to array of”, so what you suggest is not possible.
Yes, that is also my understanding after testing a lot of combinations with ACCESS and ADR(). Too bad.
What you could do is to abandon the ValueSettings structure and use the HMISettings one, then, only. This will then work for your tables, and the code is more flexible in that regard so you can adapt to change ValueSettings[index]. to HmiSetting.[index]
The suggestion is the first thing that we tried, and generally that works, but the rest of our project structure and code becomes a real mess with that solution, so that is the reason why we went back to a seperate structure.
Yes that would be a great solution, and something we are also investigating currently. The tools which are available for that are unfortunally not very user friendly, so this will take some time to get to know this.