Pepperoni Bot
Making pizza is a process that requires many steps and different tools. The stretching of dough, the application of sauce and cheese, and the addition of various layers of toppings are usually performed manually by an employee, but can be automated quite easily.
This example details an automated placement of pepperoni on a square sheet pizza.
Reasoning & Prerequisites
Prerequisite Knowledge
- Safety
- Teach Pendant Navigation
- Jogging and Clearing Alarms
- Creating Programs
- Motion Instructions
- Tool and User Frame
- Non-Motion Instructions
Required Preliminary Setup
- A stack of poker chips representing pepperoni.
- A Box
- Robot at HOME Position
Reinforced Concepts
- Counters and Register Instructions
- User Frame Use
- Offsets
- Palletizing (Stack Tracking)
All labs assume HandlingTool software.
Planning Your Cell
Program Requirements | Program Name |
The robot will need to pick up a pepperoni piece from the pepperoni stack | Pick_Pepperoni |
The robot will need to place the pepperoni at the next available space on the pizza. | Place_Pepperoni |
The robot will need to reconfigure the position registers so the offsets reflect the reducing height of the pepperoni stack, as well as the next location for placement on the pizza. | Pepperoni_Bot |
We have determined the main motion tasks required for the robot’s function. This is picking up the pepperoni, and then placing the pepperoni. These will be separate programs, to make our process easier to manage and understand.
We have added a main program as well that will do all the math and set up all the registers for us, before calling each of the motion programs.
Frames
Requirement | Frame Type | Name |
The robot will need to know where the center of the vacuum gripper tool is, relative to TCP. | Tool | VacuumTool |
The robot will need to know where the pizza is placed to properly determine rows and columns for the intended pepperoni. | User | PizzaFrame |
Tool Frame
Since we will be using a tool on the robot, we will need to tell the robot exactly where the tool’s effective end is. Due to the fact we will be working entirely within X, Y, and Z (no rotations needed) the tool frame 3-point method will suffice. Set up your tool frame with the 3-point method, name it VacuumTool, then change your selected frame to the number of the frame you made.
*SHIFT+COORD, select Tool, type your tool frame number.
User Frame
The pizza could be placed anywhere within the robot’s work envelope. We need to create a user frame that is aligned with the first pizza we will be teaching, so any new ones can simply be adjusted later. Again, since we will just be working in X,Y,Z with no need of precision, you can use the 3 point method for the user frame you create. Create your user frame for the box. Use the name PizzaFrame. Make the Y axis align with pepperoni rows and the X axis align with pepperoni columns.
Before you begin programming, change your coordinate system to the user frame you created.
*SHIFT+COORD, select User, type your user frame number.
Just in case the robot was left in a state where it is locked by another task, go ahead and hit FCTN and select Abort All.
Programs
Motion Program: Pick_Pepperoni |
While there only actually needs to be one point taught, as the “Above_Stack” height could just be an offset of the “At_Piece” position, it’s just simpler to use the two. We will have to organize our motion and IO instructions to move above the stack, then move down to the current height of the top pepperoni, turn the vacuum on, then move back above the stack. J P[1:Above_Stack] 100% FINE L P[2:At_Piece] 100mm/s FINE Offset PR[17:Stack_Height] RO[1:Vacuum] = ON L P[1:Above_Stack] 100mm/s FINE Note: The choice of motion types is important. The Joint motion to get to the stack will ensure the robot can get from the stack to the pizza, regardless of position. The linear moves down to/up from the stack ensure the stack won’t be disturbed in the XY directions. | ||||||||||||||||||||||
Motion Program: Place_Pepperoni |
We will be using the position register PR[18:Pizza] to offset our destination positions. The contents of PR[18:Pizza] will be written ahead of time in the Pepperoni_Bot program. J P[1:Above_Pizza] 100% FINE OFFSET PR[18:Pizza] L P[2:At_Pizza] 100mm/s FINE OFFSET PR[18:Pizza] RO[1:Vacuum] = OFF L P[1:Above_Pizza] 100mm/s FINE OFFSET PR[18:Pizza]
| ||||||||||||||||||||||
Main Program: Pepperoni_Bot |
PR[17:Stack_Height] = PR[17:Stack_Height] - PR[17:Stack_Height] PR[18:Pizza] = PR[18:Pizza] - PR[18:Pizza] RO[1:Vacuum] = OFF Note: You may not know all the registers and position registers you will use in programs you create before you start writing them. This is fine, as you can always add more to your setup section later. Keep track of them on paper as you use new ones. Additionally: The robot could be in any position when the program first starts. Many of these positions could cause issue if care is not taken before running. To ensure the trajectory of the first motion is always consistent, we add an instruction to go home at the start: J PR[1:Home] 100% FINE The above instructions so far won’t be part of our main loop, so it will only run through them once, when the program is first started. Everything we want as part of the main loop will have to be below the label chosen to mark the main loop’s beginning: LBL [1:Loop] The rest of this program will exist within the loop, except for our program END and an instruction to go HOME.
CALL Pick_Pepperoni Every time this is called, we need to reconfigure the offset register to reflect that the stack is a bit lower now. We’ve chosen 3.3mm as the height of the pepperoni because that’s the height of our poker chips, so the stack is reduced in height by 3.3mm each time: PR[17,3: Stack_Height] = PR[17,3: Stack_Height] – 3.3 Now it is time to place the pepperoni. Since nothing has yet been written to PR[18:Pizza], nothing will be added to the placement position and it will place it at our originally taught first position. Call Place_Pepperoni Every time this is called, we need to reconfigure the offset register to reflect the next desired placement position. This is +45mm in the Y axis. PR[18,2: Pizza] = PR[18,2: Pizza] + 45 After it has placed 5 pepperonis, we don’t want it to place another in that row or it will be outside the pizza crust, so we’ll add a conditional to check the position and alternatively start a new row entirely. This means starting from the original 0mm Y position but 45mm further in the X axis IF PR[18,2: Pizza] < 181 JMP LBL [2: SKIP] PR[18,2: Pizza] = 0 PR[18,1: Pizza] = PR[18,1: Pizza] + 45 LBL [2: SKIP] Now we have it making new rows every time one is finished, but there’s nothing yet stopping it after it makes all 5 rows. We add another conditional to check this and keep looping if it isn’t outside the limit we set. Once it is outside this limit, it will go home and END. IF PR[18,1: Pizza] < 181 JMP LBL [1:Loop] J PR[1:HOME] 100% FINE END |
Going Further
This program is just an introduction to what the robot would be capable of. The sections below are overviews of what additional features could be added to our system.
Application of Sauce
The robot is capable of moving around an applicator for pouring sauce on the pizza. With the rate of flow regulated, the robot would only need to move in a back-and-forth sweeping pattern so the whole area becomes covered in a uniform layer of sauce. A circular instruction with points that increase in distance from the center every 360 degrees would be ideal.
Resume Function
If the robot is rebooted halfway through a pizza and the program were to start again, it would start to lay pepperoni over the pizza from the beginning. Consider how a digital input may used to disable the lines of code that set offsets back to zero at the beginning. In reality, this would be triggered by a connected PLC or HMI, where an operator is prompted with the choice to resume where it left off.
Additionally, if power was lost mid-pizza, it is likely the air was shut off (which is often tied to the master control relay) and the pepperoni it was holding has fallen off. It would need to resume from the beginning of the pick operation!
Pepperoni Error Correction
This program works in concept but relies entirely on perfectly uniform food products. In reality, this doesn't happen and you will need sensors to adjust for errors. On your own, think about how you could add these error correcting features:
- Pepperoni Height Adjust - We used 1.8mm as a constant but it could instead be taken from a laser distance sensor above the stack.
- Gripper Error - A fiber optic reflective photoelectric sensor can be placed inside the vacuum cup brass piece to sense if a pepperoni is loaded, to "redo" a pickup when a piece is dropped. A vacuum pressure sensor can also be used, although a clogged cup will trigger it.
- Stack Empty - Multiple stacks can be used, letting the cell run longer without human intervention. In industry, a feeder system is often established to allow production operators to refill empty stacks of consumables while the robot works on others, so the robot never has to wait for a stack to be replenished. A door interlock would prevent it from switching stacks while an operator is working on it and prevent an operator from beginning work while stacks are switching.