Building an automated, public-facing kiosk to distribute trade show items brings a unique set of integration opportunities. The goal is always to create a display that is robust, safe for public interaction, and visually engaging. Here is a high-level breakdown of how it functions, followed by a deep dive into the specific hardware, mechanical build, and programming strategies used to pull it off without relying on an external PLC.
What is it?
The core of the Swag Bot is an Omron TM5-700 cobot paired with a Robotiq 2F-140 gripper. To create a standalone kiosk, I attached a custom tabletop directly to the top of an Omron Mobile Work Station cart, mounting the cobot securely through the table using longer bolts, and additional brackets on the sides of the cart. I then added some T-Slot uprights to attach 4 sets of light curtains, completely surrounding the workspace. Then mounted a 6-button switch box on the front to make your selections, and added a space on the back side for the HMI, so I can access some of the controls when needed.
The Swag Bot Workflow
The front of the table features a row of six buttons, corresponding to six different swag items laid out in the display area. Here is what happens when a user walks up:
-
Selection: A user presses the button for the item they want (1 through 6).
-
The Pick: The robotic arm moves to position, uses its integrated vision system to pinpoint the item, moves down, and grips it.
-
The Hand-Off: The arm lifts the item, pulls back slightly, and pushes forward to present it to the user, holding it suspended just inside a light curtain beam.
-
The Release: Once the user reaches in to grab the item, the robot releases the gripper, then pulls back out of the way.
-
The Restock: The arm rotates 180 degrees to the rear staging side of the table, uses vision to locate a replacement for the exact item it just handed out, picks it up, and places it into the empty slot in the front display.
-
Ready: The robot returns to its home position, waiting for the next button press.

Direct I/O Integration
All logic for the TM5-700 is handled by the Control box, offering 16 digital inputs and outputs, 2 analog inputs and outputs, 4 pairs of safety inputs, 1 pair of safety outputs, and integrated supply power up to 2.0A, with inputs to add external power.
The six selection buttons are housed in a physical Siemens 6-button switchbox utilizing non-illuminated, normally open (NO) contacts tied to a common ground. I wired each button directly into the back of the TM5 Control box, utilizing digital inputs DI0 through DI5. DI6 and DI7 were left open to allow for easy future expansion.
Dual-Purposing Safety as a User Interface
When you put a robot in front of a crowd, safety is the top priority. The perimeter is guarded by four independently controlled SICK light curtains mounted to T-slot aluminum extrusion and wired into a Schneider XPSMCM safety controller.
The TM5 Control box will accept the OSSD signal directly from the light curtain, but since I am trying to run 4 light curtains independently, I opted to use an external safety controller. The Schneider XPSMCM simply handles the logic from the 4 light curtains and outputs a single pair of OSSD signals to the safety input of the TM5 Control box.
If a user’s hand breaks any of the light curtains while the robot is moving, the arm immediately drops into a safe, slow collaborative mode. Moving your hand in and out of any of the beams, you can seamlessly see it speed up and slow down.
The reason I wanted each curtain independent is because I’m actually doubling the front light curtain as a functional gripper release trigger. To do this, I programmed a separate output in the Schneider safety relay just for the front light curtain, which is wired directly into DI8 on the TM5 Control box. When a user reaches into the front drop-zone, the XPSMCM verifies that only the front curtain is interrupted, triggering both the safety output and the gripper to release at the same time. I wanted to make sure the gripper isn’t falsely triggered by a hand in one of the other light curtains.
Deep Dive: To see exactly how to wire these curtains and program the logic tree using SoSafe Configurable software, check out the dedicated guide: [Getting Started with the Schneider XPSMCM Modular Safety Controller].
Solving Constant Power Issues with an External Supply
As mentioned, the internal power supply only handles up to 2 amps. Exceeding that triggers a warning and stops your running process. During early testing, I was running a single light curtain and a large dual-color LED strip, only to find I would overload the internal supply when actuating the gripper while the LED strip was on. I initially programmed additional nodes to turn the LEDs off intermittently while the gripper actuated. This worked, but it required a lot of extra programming and wasn’t sustainable, especially as I was planning on adding more light curtains.
The solution was adding an external power supply. Any 24V supply will work, but I opted for the Omron S8VK-C12024. Plugging in the external supply causes the control box to internally reroute power, meaning all 24V ports and Digital Outs are now supplied by the S8VK.
One unexpected side effect: when using external power, the 24V ports stay active even when the TM5-700 is shut down. My safety controller and light curtains were staying on all the time, so I needed to figure out a way to switch it automatically. To fix this, I wired a relay to supply the power to the XPSMCM, then used Digital Out (DO15) from the TM5 control box to activate the relay when I start a program. Now, I simply add a node to enable the DO15 pin, so when I run the project, it turns that specific output on, powering on the XPSMCM, which then turns all the light curtains on as well. Upon shutdown, all DO pins turn off, ensuring all peripherals power down smoothly.
The Teach Pendant
The TM5-700 control box is essentially a computer; you need a monitor, keyboard, and mouse to set it up. For initial programming, that works great, but it isn’t very portable. That is why the Omron Teach Pendant (RT6-A000020) is critical. It’s designed to wire directly into the ports of the control box, providing a dedicated, rugged touchscreen interface.
Just under the screen are physical control buttons (Start, Stop, Speed +/-, and M/A), an E-stop at the top, a power button on the back, and two expandable USB ports on the bottom. I connected a wireless keyboard/mouse and a game controller to these ports. At a show, I can use the touchscreen as an HMI, have quick access to physical controls and the E-stop, and can instantly dig in to make changes if needed.
Remote Interfacing
You can also remote into the TM5 using a separate computer, connected through a networking cable. Plug a networking cable from one of the 2 RJ45 ports next to the USB ports, then plug the other end into your computer. On your computer, you must install the exact version of software that the TM5 has installed, otherwise it will not work.
Once you have the TM5 powered up, do not log in or get control of your robot. Instead, open TMflow on your remote computer, double click the TM5-700, log in, then click Get Control. Now your computer has full control of the TM5, just as it would be if you were directly on the TM5 Control box.
Note: Only one device can have control at a time. If you can’t get control of the robot, it is likely because you already have control elsewhere. For example, if you want to remote in, you first need to release control directly on the TM5 Control box, then also log out. Now you can gain access through the remote computer. If you want to switch back to the TM5 Control box, you must first release control on the remote computer and log out, then you can log back in and gain control directly on the TM5 Control box.
First Time Boot & Getting Control
When you power up a brand-new TM5-700, you have to officially take command of the system through the TMflow software:
-
Log In: Launch TMflow. The default account is Administrator and the password field is completely blank. Do not type anything in, just click OK.
-
Setup: Follow the setup process, setting your language, time, etc.
-
Get Control: As an observer, you can see system status but cannot make changes. Click the Get Control button (the robot arm/lock icon) to gain write access.
-
Switch to Manual Mode: The robot cannot be programmed in Auto mode. Toggling into Manual Mode unlocks the TMflow programming interface and enables the physical “Free” button on the robot’s wrist for hand-guiding. To do this, use the M/A button on the wired remote, or on the Teach Pendant.
-
Start a Project: Open the left menu, select Project, and click the folder icon with a “+” to start.
Block Logic & Hand-Guiding
Now that you have gained control, let’s do some programming. TMflow uses a block logic style program. You create points, add gripper actions, and add inputs by dragging nodes from the left side into the project and connecting them with lines. You edit the parameters of each node by highlighting it and clicking the pencil icon.
For physical positioning, press and hold the “Free” button on the arm, then physically move it to your desired position, and release. Now press the point button on the robot to create that waypoint in your workflow. If you have a gripper installed, press the gripper button to add a gripper node.
(I’m not going to dive too much into the basics as Omron already has great tutorials explaining this, such as TM Collaborative Robots Tutorial 2 – Programming the Basic Motions).
Subflows
As you start to build your logic, you will notice it gets cluttered fast. The best way to keep the program readable is by utilizing a Subflow node. Whenever there is a repetitive task, I tend to design it within a Subflow, so instead of repeating the logic over and over, I can just drop that Subflow in instead.
To do this, drag a Subflow node in
, select create a Subflow page, which moves you to a new tab. You can hit the edit icon and rename your Subflow so you know how to identify it later. Now you can design your flow inside here without cluttering up the main flow. If you want to use this flow in multiple areas, you can add a flow, hit cancel so you don’t create a new one, then hit the edit icon and select the Subflow you want it to reference.
Gripper Set
When using a gripper, you need to first initiate it and set the parameters before it functions. So that is one of the first steps you want in your main flow. In this case, since I am going to have multiple Gripper set widths, I am going to utilize a Subflow.
I dragged in a Subflow and named it GripperStart. Next, I need to tell the robot to enable it, define the communication type, and set the open/close settings. I drag in a Gripper Set Node, click the edit button, and set those four settings. To do that, click the first one, click variables, select the variable below, and hit the edit icon to change it. It will bring you to another menu where you only need to change the right side, and when you click that, another menu opens where you can type the correct setting.
Here is a breakdown of the variables you need to change:
-
Active_or_not:
true(This activates the gripper). -
Close_Settings:
-
var_close_pos: 98% (Optimal for detecting if nothing was gripped). -
var_close_speed: 100% (Maximum speed). -
var_close_force: 30% (Adjust lower for fragile items, higher for heavy items).
-
-
Open_Settings:
-
var_open_pos: 40% (For some narrower profiles, I created a separate subflow set to 60%). -
var_open_speed: 100% (Maximum speed). -
var_open_force: 50% (Standard open force).
-
-
ComPort-Settings: Set to Com port 3. If this is incorrect, you will have no communication to the gripper.

I created multiple other Gripper Subflows for various open widths which I use throughout my flow. As you can see, there is a lot of control built into this specific gripper.
(For more information on how to install and set up a gripper, check out TM Collaborative Robots Tutorial 4 – How to Attach a Gripper to the Cobot).
Routing Logic: The M-Decision Hub and Action Paths
To allow a user to choose between the six different swag items, you need a way to route the program based on which button is pressed. This is where the M-Decision block comes in.
Think of the main M-Decision node as the Primary Hub. It sits and actively monitors all the selected digital inputs from the switchbox. Connected to this Hub are individual Action Paths (e.g., the specific flows for the Duck, the Lego, the Robot). When the Primary Hub detects that a button was pressed, it branches the block logic down that specific Action Path to retrieve the requested item.
I also added extra virtual Action Paths to this hub that are not tied to any physical buttons. These specific paths—used to reload individual items or perform a “reload all” sequence—are triggered exclusively through variables on the touchscreen HMI once the project is running.
M-Decision Pro Tip: You can also set the Primary Hub to automatically force the logic down a specific Action Path after a set wait time. This became handy as I found the system would sometimes crash if it waited at the M-Decision Hub for extended periods with no interaction. To fix this, I made a “Timeout” Action Path that automatically activates after 2 minutes of inactivity. It routes to a short flow that simply flips the status light color for a second, then loops right back to the M-Decision Hub to wait again. It was a simple way to fix a big issue, yet leaves the opportunity to make the robot wave or perform an idle animation when sitting for extended periods.
Vision Training & Calibration
The integrated vision system works really well, but not all objects are created equal, and swag items are not the most consistent. The major thing to keep in mind about the vision system is that it is 2D, and it is calibrated to the base height (distance from the table). So taller objects can be an issue as you move farther from center. Here are a few different vision task types I found worked best, depending on the object:
-
Fixed-Point: Most flat, shorter than 40mm objects work perfectly with fixed-point vision. Generally the fastest to pick as well.
-
Part-Based: For taller objects, I had to utilize part-based calibration, otherwise positioning may be off as it gets farther from center. The added logic tends to slow the pick process down some.
-
Servoing: For irregular objects that the camera struggled to pick up consistently, utilizing the servoing function allowed the arm to dynamically adjust its approach. This adds quite a bit of time to the pick process, as it needs to align directly above the part before picking.
-
Lighting: Lighting is critical. I found that setting the lighting slider to about 30% yielded the most consistent results when dealing with the highly variable lighting conditions of a show floor.
Note: Every project is different, so you need to play around with the different options to find what works for you. You can even prop the base height up when calibrating if you are mainly working with taller objects, allowing you to use Fixed-Point instead, which can simplify some of the training processes. There is no limit to the number of bases you can set up; for this project, I have 5 separate bases it is switching through depending on the item it is picking up.
(For more information on how to calibrate bases check out TM Collaborative Robots Tutorial 5 – Vision Calibration and Vision Node).
The Glow Stick Tray Workaround
I found that the Glow sticks were difficult to detect visually on a flat table. They show up almost clear in the vision task. To solve this, I designed and 3D printed a custom hanging tray. Instead of using vision, I used the palletizing feature, where the robot uses a hard-coded precision pick, but knows to move to the next spot for the next pick. When a glow stick is selected, the robot narrows the gripper, moves in precisely, grips the hanging stick, lifts slightly to clear the tray, and pulls straight back. Despite the glow stick being a less desired item by nature of being 1-time use, the extreme precision of picking from this rack is a massive crowd-pleaser. Also found out it works for Flashlights, as shown below.

Restocking & The Operator HMI
As I mentioned earlier, I added additional M-Decision nodes for restocking items on the front side, which are only accessible through the HMI. Each of the reload nodes are simply jumping to a section of the flow where it does that specific reload, so you don’t need to duplicate everything. So, setting up for the day, I start the project in auto mode, I stage up to three of each item on the back of the table. When selecting reload all, the robot sequentially finds, picks, and populates the entire front display on its own. I also added individual reload buttons for each of the six items, which is an absolute necessity for when an attendee manually snags an item without using the robot!
Programming Strategies and Setup Challenges
Once the hardware was mounted and communicating, the actual motion programming inside TMflow brought its own set of unique challenges.
Light Curtain Clearance
When adding in the light curtains, it brought on other challenges, as I now needed to try to keep the arm within the beams so it didn’t constantly put itself into collaborative mode. This was mainly an issue when reloading items from the back of the table to the front. The easiest solution was adding a few extra waypoints, making sure the arm tucks in far enough so that even the item it picks up doesn’t break the beam. (Note: There is a way to do this automatically using the “Operation Space” feature in TMflow, but I have not tried this yet for this first build).
Pro Tip 1: Getting Smooth Movements (Blending)
After you make several points and run your project for the first time, you will notice that the arm pauses at every single point, which is not ideal. To fix this, click the edit icon on any specific point you want it to flow through without stopping. Look for the Blending section (by default, “no blending” will be highlighted). Click By percentage, and move the slider to 100%. Now it will not slow down at all before moving to the next point. You can play with this slider to find the sweet spot if you just want a slight deceleration.
Note: I recommend not using Blending right before or right after a pick or place, as it will sometimes cause an issue by either missing the pick, or not making the gripper action in time.
Pro Tip 2: Point-Specific Speed Control
Inside that same edit menu, you can also control your overall speed at that specific waypoint. This comes in handy when you want your project’s global speed at 80%, but need to pick up an object more carefully. Under Motion Settings, click on the highlighted motion profile. From there, you can lower the local percentage. Note that this acts as a multiplier of your global speed limit. If your project is set to 80%, a node set to 100% still only moves at 80%. But moving that node’s slider to 50% means it will move at 50% of the 80% limit (effectively 40% of the arm’s maximum physical speed).
Managing Legacy Hardware Constraints (HW 3.2)
If you are replicating this build, note that there may be some hardware constraints depending on the hardware version of the arm. My TM5-700 is Hardware Version 3.2, which caps the software at TMflow 1.88.2700. Currently, there is no workaround to update the firmware. If you are on the newer 5.0 hardware running the 2.x software, you gain some features that make this easier:
-
Symmetrical Objects: With highly symmetrical swag items, TMflow 1.88 required me to manually set joint rotation limits to prevent the arm from over-rotating. HW 5.0 / TMflow 2.x introduces built-in settings to automatically handle symmetrical object orientation.
-
Game Controllers: Handheld controllers are great for precise jogging. On HW 3.2, you are strictly limited to the Logitech F310 (wired) or F710 (wireless) controllers. TMflow 2.x adds native support for Xbox controllers.
-
Offline Programming & Simulation: TMflow 1.88 requires a direct connection to the robot to program. TMflow 2.x includes the TMflow Simulator, allowing you to view, edit, and develop project files offline, and even import 3D CAD models to simulate motions virtually without taking the physical machine offline.
Deep Dive: If you need to update your firmware, see the step-by-step guide: [How to Update TMflow Software on Your Omron TM5-700]
Full Flow Walkthrough (Example: The Duck)
Now that you have some of the basics, let’s do a full walkthrough of how this project flow operates, tracing the exact path the robot takes from powering on to handing out a rubber duck.
Startup & Initialization When the program begins, the very first action is the Turn_on_XPSMCM I/O node. This triggers the DO15 pin to activate the relay, powering on the safety controller and all four light curtains. Immediately after, it calls the GripperSet40 subflow to initialize the Robotiq gripper and set the default open/close parameters.
The M-Decision Node The program then hits the M-Decision node, essentially pausing at a series of Action Paths (e.g., Pick_Robot, Pick_Duck, Pick_Lego) to monitor the digital inputs from the physical Siemens switchbox on the front of the table, or from the HMI.
The Pick (The Duck Path) If a user presses the button for the duck, the logic branches down the Pick_Duck path.
-
It hits a
GreenOffI/O node to disable the indicator light, and switch it to Yellow. This is to indicate it is busy. -
It moves into position for the LFBase (This is a waypoint that matches the base location).
-
It executes the
LFront_Duckvision node to visually locate the exact position of the toy on the display. -
If it fails to find the Duck, it routes out the Fail path, which takes you to the go-to node that simply speaks “Not Found”, then opens the gripper and goes back to the M-Decision Node.
-
If found, coordinates are locked, and it moves through fine-alignment points P223 and P225 to pick the part. (Notice the eye symbol on those pick nodes, indicating they are following the vision base, and are not normal points. The points vary based on where the vision is located.)
-
It triggers the
ADG_V001_CLOSE1command to grip the duck. -
If the gripper detects the object, it will move up 100mm; if not, it moves to the “not found” path again.
The Handoff (Pass_Toy Subflow) To keep the main flow clean, the handoff sequence is grouped into a subflow. The arm moves to its safe presentation points (P13 and P14), turning on a green status light (Green1). It hits a WaitFor2 Node, which is set to wait for the light curtain trigger. Once the front light curtain is blocked, it turns the LED off (LEDoff) and the ADG_V001_OPEN2 command to release the duck into the user’s hand.
The Restock (Duck Subflow) After handing the item away, the main flow calls the Duck restocking subflow. The arm swings 180 degrees and starts with the RRear_Duck vision node to scan the rear staging area for a replacement.
-
If Pass (Duck Found): It moves to approach points P184 and P185, closes the gripper (
ADG_V001_CLOSE1), and executes a move command (Move4) to bring the fresh duck to the front display. It sets the item exactly where the original one was, then moves back to the starting point to wait for its next M-Decision. -
If Fail (Empty Table): If the camera sees nothing, it branches down a failure path. It triggers a Voice node (
Voice6), pauses for 5 seconds (WaitFor5), then searches again. This gives us time to add a duck back in the staging area if we are not keeping up.
Below is what the full flow looks like for picking a DigiKey Duck.
Pro Tip: Configuring the Voice Node (Text-to-Speech)
To add some personality to your kiosk, or to handle errors gracefully (like when the vision system fails to find a restock item in the rear staging area), you can utilize the Voice node to have the TM5 speak out loud. You simply plug a standard 3.5mm speaker or a USB audio device into the control box.
However, the text formatting inside the node is incredibly specific. You cannot just type a normal sentence into the text box. Because the system parses it as a raw string variable, you must place quotation marks around every single word and manually connect them with plus signs (+).
For example, if you want the robot to say “Not Found”, you cannot type it normally. You must type exactly: "Not"+" "+"Found"
Notice that you even have to hard-code the blank space between the words as its own string (" "). If you forget the spaces, the robot will read it as one jumbled word. Inside the Voice node edit window, you will also see radio buttons that dictate how the robot behaves while speaking. You can select Speak, then Move (which halts all arm motion until the audio clip finishes playing) or Speak and Move (which allows the arm to continue its workflow while simultaneously talking).
Full System Bill of Materials
-
End Effector: Robotiq 2F-140 Gripper Kit Part # 236-AGC-OMRON-KIT-140-ND
-
Infrastructure: Mobile Work Station (236-RT6-A000010-ND), Landmark (236-RT6-A000021-ND), Teach Pendant (236-RT6-A000020-ND)
-
Safety Controller: Schneider XPSMCM Part # 4008-XPSMCMCP0802G-ND
-
Safety Perimeter: SICK Light Curtains (Parts #1882-1211496-ND and #1882-1211497-ND)
-
External Power: Omron Z5294-ND External Power Supply
-
User Interface: Siemens 6-Button Switchbox part # 3473-3SU18060AA000AB1-ND
-
Push Buttons: Body 3473-3SU10000AB100AA0-ND, Holder 3473-3SU15500AA100AA0-ND, and Contacts 3473-3SU14001AA101BA0-ND
-
Status Indicator: Banner Tower Light part # 2170-TL50PS3AQ-ND










