It is often the case were certain variables need to be adapted depending on the hardware configuration that is being used.
Example: A FB is using the DeviceName information for a communication library and the address is changing depending on the hardware configuration.
For that kind of situations we often use something called “Preprocessor statements” (code that is executed while the project is being compiled).
The first step would be to create a constant for each hardware configuration that will allow us to know which of the configurations is active. This can be done from Project → Change Runtime Versions… → Build.
After that, using preprocessor instructions we will be able to generate code such as:
It really does not matter where this piece of code is placed because as I mentioned before, it will be only executed during the project compilation and it will not affect to the other cyclic tasks.
Lastly, make sure to have the option “Allow preprocessor directives” from Project → Settings activated. That will allow you to use preprocessor instructions during the project build.
Using this strategy there is no need to worry about changing certain variable values everytime that you switch between different configurations.
In case you want to know more about preprocessor instructions you can check this AS help link.
I really like this approach but do have one question.
Is there any advantage with using this method instead of using the ArProjectGetInfo function block to read the ConfigurationID?
A similar if statement could be used to then determine the DeviceName.
One disadvantage I see using the function block is the determination is made at runtime so there is a very small increase in CPU usage compared to using the preprocessor. Even on low end systems I don’t think the increase would be noticeable however.
To be honest, (when using AR versions greater than 4.33) I do not see any significant advantage on using this method compared to the one you mention using the information provided by the ArProjectGetInfo FB.
One small advantage that I can think about is that you do not have to worry where you place this piece of code because it will be for sure executed before any code has been transfered to the PLC.
Maybe someone else can give their opinion based on some experience.
I think that the advantage lies within the fact that this lets you determine what code will be compiled at compile time. If you have one function block that needs to switch between a handful of devices, there probably isn’t a major difference either way. However if you have many devices using one code base, and you need to change more than just function block inputs (e.g. you need to modify entire sections of code) this can help you both by saving time during builds and by not including unused/conflicting code on the target.
Of course, in many cases there might be cleaner ways to handle such a scenario (such as action files or functions). But it’s handy to have the ability to control which code is compiled without commenting out entire sections, especially if there is a lot going on in a particular project.
One advantage of the preprocessor statements is, that you can have multiple configurations that have the same ConfigID and still treat them differently.
I often have configurations that use the same hardware and only differ by software. So they use the same, referenced .hw file. As the ConfigID is also stored in the .hw file (I’m not sure if that was a good decision, but that is, how it is), therefore they also share the ConfigID.
The preprocessor defines however are stored in the PLC/Cpu.pkg and therefore independent of the hardware.