I have a question regarding the UDT Structure vs heap-item in the recipe example of the pdf. I see that the RecipeStruct becomes the structure for the CurrentRecipe heap item, but I don't think I fully get the difference. I can address the RecipeStruct structures directly via RecipeStruct1.itemname or indirectly via RecipeStruct[V100].itemname so the heap-item benefits me how? I'm not sure I am seeing the benefit other than no array designation.
Let's look at it using a built-in structure, PID. I can create a block of 16 PID Structs, called MyPID. I can address MyPID0..MyPID15 in a PID instruction. I can even use a FOR/NEXT loop with V0 0..15 with PID instruction with MyPID[V0] (this is how we tested 1000 PID loops without needing 1000 PID instructions - HA!)
I can also create PID heap-items. CookerABC. ChillerXYZ.
I can look at MyPID4.PV or MyPID[V100].PV or CookerABC.PV or ChillerXYZ.PV.
I did all this with the structure definition PID Struct. 1 data block of 16, and 2 heap-items. I could actually create another data-block of 100 PIDs called MyOtherPID, and now I have MyOtherPID0..MyOtherPID99, in addition to the other block of 16 and 2 heap-items.
Back to RecipeStruct. I defined a User Data Type structure definition called RecipeStruct. That just defines the data-type, not a data-block or heap-item. I can then create a data-block of 100 of them called Recipe, so I have Recipe0..Recipe99. But I then also create a heap-item of a RecipeStruct called CurrentRecipe. This heap-item is what my program actually uses for control. So, at the beginning of the batch, I use V42 as my recipe selector, where V42 equals 0..99. Say I picked recipe #11 (so my HMI stuck 11 in V42). I then MEMCOPY RecipeStruct[V42] into heap-item CurrentRecipe. After the MEMCOPY, CurrentRecipe contains the values that were in Recipe11. CurrentRecipe.CookTime is what I use in my TMR.
Heap-Items are just single instance (non-ID, non-array) structures. Program Structs, Task Structs, PID Structs, RampSoak Structs and many system structures are typically heap-items. But you could create a data-block of PID structs or RampSoak structs, or even Program Struct or Task Struct data-blocks.
Sometimes you want a block of 100. Sometimes just a bunch of single ones. But you can do both, or even multiples of both (e.g. have internal subroutine structure names called MySubRecipe, then pass in the CALL Recipe11 into MySubRecipe heap-item, then the Subroutine MySub uses MySubRecipe to generate a STRING describing that recipe into MySubString that is a STRING heap-item, and then move MySubString into SS100 in the CALL Output parameter list.
This is advanced stuff, but heap-items are good for well-named single instance data items. Data-blocks are good for having a block of something, like Timers or Counters, or especially where you want to do array indexing, like Recipe[V42].