How to Use Recipe and Log Handling in an Omron N Series PLC Program

My name is Ray Marquiss. I'm a senior application engineer with Valin Corporation. This video, is going to just show how to use recipe handling in the PLC program. This would be used in case you are using an HMI that doesn't have recipe handling or-and you'll have to remember this at the end of the video-you could use this to create your own user event log or user alarm log.  The concept’s the same. It's just that you don't add the elements or the recipes manually, if it's an alarm log, you would add them based on an event. So once you've done watching this you could apply this same concept to making an alarm or event log.

This is what we're going to achieve. And this is just a sample screen that I made pretty quickly to display a few recipes, have some buttons for manipulating the recipes, and then having some area here where we can actually add new recipes. Since this is just a demo program, I want to start out with a few recipes right away, so I'm going to go back to the program, and I have a section that just allows me to load 5 recipes and set the proper index for the array of recipes. So if I turn this button on and then turn it back off, you can see all these values populated, so now I have five recipes stored in PLC memory in an array.

If I go here to this screen. I can click on the next recipe, and it populates my display area with the recipes that I had, but I can only display 3 so I need to be able to scroll through them so you can see there's recipe 1..2..3. So I can scroll through up to the five that I have, and then if I click the button one more time, there's no recipe there. We'll go back up and I can use this area down here to create a recipe. We'll just call it “R6”, recipe 6, and I'll put some values in here. I always enter values that help me identify the recipe by number so that I can tell it's in the right order when I'm first starting to work with these.  You can see I'm putting sixes in in different places in the field so that I know that this is recipe #6 and it's in the right order and that the right data is associated with recipe name. I'll turn this guy on to say that we want that whatever that item is, it could be a valve or heater or whatever, I’m just going to make it on as part of the recipe, and then I'll add that by clicking this “add” button. And now when I click on “Next Recipe”, you can see that recipe 6 is there with the data in it. I made a mistake here and typed 500 in this field. But now I can scroll through the six recipes that I have. I started with five and now I have six.  That's the goal. That's what we're trying to do. Next part of this is that we want to be able to use a recipe that we've found, so we would scroll up and down through our recipes, and then we would have to pick one. So the way I've got it set up is that whatever recipe is in this box here, that's in a certain memory area in the PLC, and I can just click on the button to select that recipe. And it's going to put it into memory in a variable I called the “ProcessRecipe”. So now throughout the program while you're running the process, it will take the values from that process recipe and use them even if people are changing the screen here by going up and down looking at different recipes.

When we talk about recipes, let's focus on the things that we need to do.  Here are some notes that I've made that you can refer back to if you ever have to go through and create recipe handling in your PLC program. You need to be able to scroll up and down through a list of recipes. And you want to make sure that you stop at the first recipe. In other words, you can't scroll past that recipe, or you want to loop so that if you get to the up to the top of the list where the first recipe is, the next time you hit the previous button, it will take you to the last recipe in the list. And then you want to do the same thing for the last recipe as you're scrolling down. You don't want to just keep scrolling to through a bunch of zeros or empty recipe spaces. You want to stop at the last recipe that's been created, and then either stop there or loop to the first one again. You need to be able to edit and save a recipe. Either overwrite one or create a new one is what that comes down to.

The steps it takes to get this done is to make some notes of your ingredients and the data types that you're going to use for those variables that you create. You’ll create a user defined structure (see video about structured data types here) and each member in that structure is going to be an ingredient. And don't forget to include the recipe name as one of the members in that structure. You'll create a recipe variable for storing the recipes, and that's going to be an array, and the number of elements in the array is going to be however many recipes you think you are going to need to save. The recipe variable is going to be of the data type that you create when you create the structure from the previous step. You'll create a recipe variable for displaying the recipes on an HMI. You don't want to just display the variables in the array for recipes; you want to be able to leave that intact and all you do is add recipes to that particular array. But for the HMI display, you want to be able to move up and down through the list and change the index on it, and to be able to show all the different recipes in your array. And that's also going to be the data type that you create when you create your structure from above. You'll create a recipe variable for the selected recipe, the recipe that you use in the process. That's the one that when you're scrolling through the list and you find the one you want, you select it and then that's the one that's going to be used as the machine runs through the process. And that's also going to be of the data type that you create when you create your structure above. And then have some code for adding the recipe and creating variables for the array index numbers so that you can manipulate those index numbers to point to different elements in the array through the HMI buttons or the program.

If you want to get advanced, I'm not going to show this in the video, but you can prevent duplicate recipe names-you could try to prevent duplicate recipe names.  You can provide for deleting recipes and then shuffling the recipes to pack the empty spaces. So if I delete a recipe in the middle of my array as I'm scrolling through, I don't want to see that empty space. I would rather have all the other recipes collapse in the array to fill that space. And then the last thing that you could try is to search for a recipe by name. Like I said, I don't have code shown for doing this, but these are things that operators or users might request and you would have to work out a way to do it.
Let's get busy with the first step of creating the data type that we need. The way that we do that is to go to the data section of the program. Select data types. And then make sure that the tab for structures is selected over here as opposed to unions or enumerated. I've got the structure that I wanted here. I've named the structure “Ingredients”, and then I've added members to that structure called Name, Ingredient1Amount, Step1Time, CycleCount, ItemSelect1 and ItemSelect2.  You can see that each member has its own data type.

The way that we create these from scratch is to right click in the in the blank area here, select “create new data type”. I'm just going to call this Junk. Then I'll right click on Junk and create a new member, and here's where I would create my members that I want to have in that structure. And then I'll select the data type for those over here from the normal data types. I'm not going to go through the process of creating the whole thing, but. You can see what I did here. I'm just going to delete this to get it out of my project.

The next step is to create the global variables that use this data type by clicking on “global variables”. Once again, you can right click in the blank space and create a new variable. This is going to be a junk one again because I've already created the variables. I'll show you those in a second, but you just create Junk. And we said in the beginning that we wanted it to be an array, so the way I do that is I'll type here array and enter and that shows me the format that I want to use for creating an array. So I need to tell the beginning index, which I'll say is 1, the end index-and for this program we're only doing 10, but you could make that 99 or 100 or 1000 whatever you want. I deleted the bracket by accident so I'll put it back and then “Of” and the “of” is what data type is this variable? I'm going to give you a minute. Yeah, you probably got it right, its “Ingredients”. That was the structure that we created.  When we create a structure, we're creating a data type, a user defined data type. So what I just did is I created an array of those ingredients.  There are 10 elements in the array. That's basically saying I've got 10 variables and then each one of those has…if we go back to the data types…1,2,3,4,5, 6 members, so essentially I've created 60 variables here.

Now I'm going to delete that. I just wanted you to see the process.

Here are the variables that I created to actually use. Here's the main one for recipes. And notice that I checked that it's retained. That means that when I cycle power on the PLC, it's not going to lose the values that are in there. Let's sort my global variables by data types so that you can see the ones that I created that are of that data type. I've created the one called “Recipes”. That is an array of Ingredients. I've created one called “DisplayRecipe”. Remember, I said we want to create one that will let us display or scroll through the recipes there and you'll see how I use that in a little bit. And it's also an array of Ingredients. Going down the list I can see other variables that have the same data type Ingredients, but they're not arrays.  Going down the list I can see other variables that have the same Ingredients data type. That's the data type that I created. The first one that we see in the list is process recipe. That's the recipe that I use for my actual process when the machine is running. Once DisplayRecipe is selected, those contents of that particular recipe, or that element in the array, are copied to the process recipe to be used. There's a “NewRecipe”, so on the screen I can type in new values, and then once I click a button on the screen, it's going to take those values and copy them into the Recipes array.  On my screen I display 3 lines which is showing three recipes out of the array. And so they have the data type “Ingredients”. And there's line one line 2 and line 3, so as I'm scrolling up and down, these variables are populated with recipes out of the array, so that's how I'm using the data type that I create for the recipe.

Next, we're going to talk about arrays and array indexes. An array is just a collection of variables of the same data type. The formats for selecting one element, which is one of the things in the array. Is to put the element number in brackets, so when you define the array, you say how many elements there are, you're going to say it's 1 to 10 of bool, or one to 10 of integer type. Or zero to 10 or 1 to 9000, whatever you want it to be.  Then when you want to select one element in the array, then you will pick a number and that's the element number. In this case, we're selecting the third element in the array. 3 is what we call the index or pointer in this case. So whatever is in those brackets, that's the pointer or the index. Therefore, you can store unique data in temperature 3. Which means it'll be different from what's in temperature[4], temperature index 4, for example.

The array index can be a variable too, so I could make my structure look like “Temperature[myIndex]”. Whatever number’s in my index is the element number. So by manipulating the variable with the index number in it, it's a handy way to automatically select elements in the array based on the program requirements. When I say automatic, I mean programmatically.

So here's a little example of an array index variable being used. Suppose you have a process that requires a different temperature setpoint at each of 10 steps. You could create 10 variables to store the set points.  Call them Temp1, Temp2, Temp3. Something like that, and that's OK if you only have 10 or five or whatever. But what if you had 100? You know that's a lot of variables. The other way to do it is you create an array of 10 elements and manipulate the index in each step. So temp[1] for step one, temp[2] for Step 2, etc. Then you can replace the index with a variable, something like a variable named “myIndex”, which would be an integer type, just a number. Now you can manipulate the index to point to whichever temperature setpoint you need. So, for example, you might have part of your code in the process that says if the step number is one, make myIndex 1.  That would point to temp[1], which ostensibly would be for step one. If you'd have code that then later on that says if step number equals 2. Then make myIndex 2 and so on. Or you could even just have code that when this step is over, you'd increment the index to go to the next variable, which would potentially be the next step. And then you might have another line that in that process code that says that the step one temp setpoint is equal to the temp[myIndex].
Keeping in mind that there's always more than one way to write a program, this is the way I've done mine. This is the code to do the increment part. So basically there's a button on the HMI. That when they push it, it increments “DisplayIndex” which is a variable for the index of the display array variable. This one basically just takes whatever is in the Recipes array and puts it into the DisplayRecipe array. That way I can manipulate and move around all through the display recipe and not be changing the index for the recipes. I need to display a few lines on the screen from the display recipe, so whatever the display index is if you look here, I will show that element from the array on line one, and then here's the really cool thing about using arrays and indexes is if I want to look at the next element in the array. I can make the index look like this “[(DisplayIndex+INT#1)]”.  If I want to do another line, I repeat the code again, and then the index is DisplayIndex+INT#2. I could create multiple lines on the display with this one simple code here. So every time the button to increment the number, the recipe number, is pressed or decrement the recipe number is pressed, then I move these values into these variables in line 01 line O2, line 03. If you look in the beginning of the video, those are variables that I made and they are of the same data type as the display recipe variable: they’re of the ingredient data type.

This is how I stop incrementing.  If the DisplayIndex is equal to 0 then I turn on a bit that says stop, decrementing, and then you can see I've used it here. The stop decrement will keep this button press from actually performing this code. I have it up here too, so once I reach zero, I will push this button again and it won't decrement the display index again. And then similar code for the incrementing of that index number. And then I have simple code for adding a recipe, so there's a button on the screen to push that says “Add” and I take the recipe index and I add one to it and then store it back in the recipe index, so I've increased the recipe index. That means I've increased the number of recipes that are in my array. I have this code which is executed when the same button is pressed. All it does is we add to the most recent spot in the array or the slot in the array which is pointed to by the recipe index, which I've increased up here when they push the add button. And then I add new recipe name, new recipe ingredients, new recipe cycle count and so on. I could have done this in one move. I could have just said Recipes[recipeIndex]=NewRecipe and that would have done everything that I just did in all of these lines of code here.  I just did this to kind of show what was going on.  Newrecipe.name, newrecipe.ingredientamount, newrecipe.cyclecount; those are fields on my HMI down here so this is newrecipe.name, so if we look at the properties of this field I'll drag this over so you can see it is newrecipe.name. This one is newrecipe.ingredientoneamount. This one's newrecipe.steptime.  That's why we're taking these values and then moving them into our stored recipe.

This is a little bit of code to save an edited recipe, so whatever the recipe is being displayed on line one. When I hit this button, it's going to save it again in the same spot, so it's going to overwrite, so it says Recipes[displayindex].Name = line01.Name, and remember at the beginning of the video I said that line 01, this is where you're going to either edit or select the recipe.  Finally, this is where we select the recipe. There's a button on the screen for select recipe and it takes line 01, which is a variable of the type Ingredients, and moves it into ProcessRecipe. I could have done code like I have here which says process recipe = line01, but I chose to use a ladder instruction instead just to show the different ways to do things.

Request Sysmac Studio Recipes Sample Code

Hopefully you find this helpful. I'm going to make the sample code available as well. It should be on the same page where you found this video. If you have questions you can reach us easily using information on the screen thanks a lot and have a great day.

If you have questions, you can reach us at (855) 737-4716 or fill out our online form.