I am wondering if anybody has a sample program for recipe control. We need to select and manage up to 100 recipes each with 100 words/variables. I am new to CoDeSys programming and appreciate your help.
Any ideas are welcomed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Finally you need code to move the current recipe back into the main storage array (in case it changed) and also to move the new recipe from the main storage area into the current area. Something like this....
ifiSelectRecipe<>iCurrentRecipethen
  fori :=1to100do
   awMyRecipeArray[iCurrentRecipe,i] :=awCurrentRecipe[i];
   awCurrentRecipe[i] :=awMyRecipeArray[iSelectRecipe,i];
  end_for;
  (*UpdatetheCurrentRecipenumbersoitdoesn't get loaded again *)
  iCurrentRecipe :=iSelectRecipe;end_if;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have the following suggestion assuming that your recipe are stored in memory some where. I like to reference structures so that you can give the variables of the recipes descriptive names. I also believe it's faster than for loops by passing pointers. I included the project so you can play with it. But here is the jist of the code.
Create a structure
TYPERECIPE:STRUCT  wPorportional    :WORD;  wIntergral      :WORD;  wDerivative    :WORD;  wScale      :WORD;  wOffset      :WORD;END_STRUCTEND_TYPE
Create some variables in your program:
VAR  bNewRecipe      :BOOL;          (*Whentriggeredcausesamemoryread*)  dwSelection      :DWORD;          (*Selectionofwhichrecipe,visualizationlimitsitfrom0to3*)  dwOffset        :DWORD  :=16#A;    (*Offsetsincethereare5words=10bytes=16#Atomovebetweeneachrecipe*)  tCurrentRecipe    :RECIPE;          (*Currentlystoredrecipe*)  tRecipeMemory    :POINTERTORECIPE  :=16#82DCA0;  (*Baseaddressoffirstrecipeinmemory*)  tTempRecipe      :POINTERTORECIPE;  (*Usedasatemporaryvariable*)END_VAR
Now change the contents of the structure each time the button is pressed and the index changes. Hope you get the idea.
IFbNewRecipeTHEN
  (*Movetheaddresstothetemprecipe*)
  tTempRecipe  :=tRecipeMemory+(dwSelection*dwOffset);
  (*Storethecontentsofthememoryintothecurrentrecipe*)
  tCurrentRecipe  :=tTempRecipe^;END_IF(*Nowyoucanreferencevariablelikethisinyourcode*)(*  tCurrentRecipe.wDerivative
  tCurrentRecipe.wIntergral
  tCurrentRecipe.wOffset
  tCurrentRecipe.wPorportional
  tCurrentRecipe.wScale*)
That's it on an operator display as the user presses an arrow or something to scroll through the recipes he changes the index and selects accept. That was easy!!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Your PLC of choice will have some way of accessing memory. Whether it is by using addressing like in my example, a FB provided by your PLC vendor or something. The example was trying to reflect that you can read the contents of memory and store them in a consistent interface that makes it not only easy to read but can also have data that has varying variable sizes and it still works. The pressing of buttons only skips to the next structure in memory. I do not know the Moeller PLC but I would have to ask you the question how do you store retained data? Is it by R/W files (Windows CE)? Directly in some EEPROM/FLASH? If you have a FB that reads and writes to memory if you want to post a project with the FB I can give you back an example with your particular PLC vendor. Once you have the method of retrieving stored data you can apply the principals in this example. Let me know if you need further help.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The ADR operator is for returning the pointer to a CoDeSys variable in memory. Can you use it to access Memory that CoDeSys is unaware of I'm not sure. I am not sure what your confusion is? You said you used the ADR operator but to do what? What are you trying to accomplish? If you can help me understand your situation I may be of better help.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The pointer to memory address 16#82DCA0 was just an arbitrary number it didn't mean anything. I guess I could have just used 0 as well. Recipes are normally stored in some type of non-volatile memory. You can change my example around to make it match your situation. I have assumed here that the structures are stored together in memory.Take for instance I have a manufacturer specific FB to read and write to FRAM memory on my PLC. I give it a starting address in bytes from 0 and the length in bytes to read it will return the bytes using the ADR operator. By knowing this initial offset in memory I know know where all the Recipes are stored because I know the size of the structure. It will work for RAM memory as well. So each time a user requests a different recipe I call FRAM_READ with the base address plus the users offset of which recipe and the number of bytes to read, the FB will pass it back into the structure.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You said >Zitat:
"By knowing this initial offset in memory I know know where all the Recipes are stored because I know the size of the structure."
. My question: Is there an list of used adresses in RAM in Codesys that you have an review of adresses, else how do you know where to set the adress and if it is already used by system?
regards
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm not really sure of your question? Can you explain further? If I define a structure of structures or in this case:
TYPERECIPES:STRUCT RECIPE1:RECIPE; RECIPE2:RECIPE; RECIPE3:RECIPE; RECIPE4:RECIPE; RECIPE5:RECIPE;END_STRUCTEND_TYPERETAIN  MyRecipes:RECIPES;                                 (*Defineitasretainmemory*)END_VARORMyRecipesAT%MW0:RECIPES;                             (*Defineitasamemoryaddress*)ORMyRecipes:RECIPES;                                    (*DefineitinRAM*)ORFRAM_READ(NumBytes:=50,StartAdr:=101,DST:=ADR(MyRecipes));(*ReaditfromsomecustomspecificPLCmemorylocation*)CurrentRecipe:RECIPE;wSelected_Index:word:=0;(*Zerobasedtoreachthefirststructure*)wRecipeOffset :=10;(*5words*2=10bytes*)dwRecipeIndex   :=ADR(MyRecipes)+(wRecipeOffset *Selected_Index);CurrentRecipe   :=dwRecipeIndex^; (*Deferencethecurrentlyselectedstructure*)
Does this help?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think you miss typed? You stated 100 but it is 10? It is the number of bytes that each structure holds based on the data types that are in the structures. You are referring to my comment 5 words * 2 bytes = 10 bytes?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi All,
I am wondering if anybody has a sample program for recipe control. We need to select and manage up to 100 recipes each with 100 words/variables. I am new to CoDeSys programming and appreciate your help.
Any ideas are welcomed.
I have not done one in CoDeSys but in general, recipe systems involve arrays. Structured Text seems to be the easiest language to accomplish this.
First you need a place to store the recipe information:
Then you need a place to hold the current (active) recipe and the number of the current recipe
Finally you need code to move the current recipe back into the main storage array (in case it changed) and also to move the new recipe from the main storage area into the current area. Something like this....
Thanks Mate. With a few mods, this done the job well. Stay tuned for more questions as we blunder our way through codesys.
Also, this is on an ABB PLC so many new adventures ahead.
Thanks,
Rob.
I have the following suggestion assuming that your recipe are stored in memory some where. I like to reference structures so that you can give the variables of the recipes descriptive names. I also believe it's faster than for loops by passing pointers. I included the project so you can play with it. But here is the jist of the code.
Create a structure
Create some variables in your program:
Now change the contents of the structure each time the button is pressed and the index changes. Hope you get the idea.
That's it on an operator display as the user presses an arrow or something to scroll through the recipes he changes the index and selects accept. That was easy!!
Some how the file didn't get uploaded. Dummy me again no .pro allowed!!!
RecipeManager.zip [8.85 KiB]
Hello,
What I dont't understand in this program is how do you know the base address (82DCA0), is it a byte address like %MB100 ?
I work with Moeller XC201 MIPS III
tRecipeMemory :POINTER TO RECIPE := 16#82DCA0; ( Base address of first recipe in memory )
Thanks
Gildas THOMAS
Your PLC of choice will have some way of accessing memory. Whether it is by using addressing like in my example, a FB provided by your PLC vendor or something. The example was trying to reflect that you can read the contents of memory and store them in a consistent interface that makes it not only easy to read but can also have data that has varying variable sizes and it still works. The pressing of buttons only skips to the next structure in memory. I do not know the Moeller PLC but I would have to ask you the question how do you store retained data? Is it by R/W files (Windows CE)? Directly in some EEPROM/FLASH? If you have a FB that reads and writes to memory if you want to post a project with the FB I can give you back an example with your particular PLC vendor. Once you have the method of retrieving stored data you can apply the principals in this example. Let me know if you need further help.
Hi,
isn't the CoDeSys instruction ADR whitch can do that ?
It doesn't seem to work...
Thanks
Gildas
The ADR operator is for returning the pointer to a CoDeSys variable in memory. Can you use it to access Memory that CoDeSys is unaware of I'm not sure. I am not sure what your confusion is? You said you used the ADR operator but to do what? What are you trying to accomplish? If you can help me understand your situation I may be of better help.
The pointer to memory address 16#82DCA0 was just an arbitrary number it didn't mean anything. I guess I could have just used 0 as well. Recipes are normally stored in some type of non-volatile memory. You can change my example around to make it match your situation. I have assumed here that the structures are stored together in memory.Take for instance I have a manufacturer specific FB to read and write to FRAM memory on my PLC. I give it a starting address in bytes from 0 and the length in bytes to read it will return the bytes using the ADR operator. By knowing this initial offset in memory I know know where all the Recipes are stored because I know the size of the structure. It will work for RAM memory as well. So each time a user requests a different recipe I call FRAM_READ with the base address plus the users offset of which recipe and the number of bytes to read, the FB will pass it back into the structure.
Maybe an old converstion but....
You said >Zitat:
"By knowing this initial offset in memory I know know where all the Recipes are stored because I know the size of the structure."
. My question: Is there an list of used adresses in RAM in Codesys that you have an review of adresses, else how do you know where to set the adress and if it is already used by system?
regards
I'm not really sure of your question? Can you explain further? If I define a structure of structures or in this case:
Does this help?
Hi
I think you miss typed? You stated 100 but it is 10? It is the number of bytes that each structure holds based on the data types that are in the structures. You are referring to my comment 5 words * 2 bytes = 10 bytes?