Multi-Axis Block Stacker

by NHAN NGUYEN & ANDREW KUTSARNov. 20, 2019

Summary

This was a class final project for Automation at Washington State University Vancouver (WSUV) Our assignment was to program the multi-axis motion controller (Gantry machine) to dispense and stack a set of blocks in any instructed order (e.g stacking in 3x2 or 2x1 formation). It was also required that we would perform the operation without brute-forcing each given order, instead, the controller could perform the calculation of the rows by columns prompted by the user and stack the blocks accordingly. The motion of the conveyer and the solenoid on the dispenser was controlled by a PLC program, and the motion of the 3-axis arm was controlled by a motion program.

The laboratory systems use Geo Brick Drives by Delta Tau Data System, Inc. which only permitted teams a single entry a week. Each station has a control panel, which contains the motion controller, power supplies, I/O terminals, buttons and indicator lights. This meant that the machines are miniaturized versions of the real industrial machines. Industrial grade components such as sensors, motors, bearings, cabling, etc. were used in the designs. As such, each station contains the same industrial control panel that would be found in industry but interfaced to a miniaturized industrial machine.

The biggest challenges within this project were to learn the programming language and the system's limitation. Unlike typical coding languages provide by computer science courses, this language was intended to be a higher-level language aimed towards mechanical engineers. Because no one had experience with programming PLC and given the limited lab availability, we had to learn as quickly as we could to understand start programming our project. When I and my partner understood our objected and the machine's abilities, we quickly began pseudo coding an algorithm to help us simulate the machine's operation so that it could meet the criteria.

Pseudo code:

upward: how
tall we want it (H)
right: how
wide we want it (W)
 
Stacking:
Height x Width
 
for (each
row, we start at 0 and stack to upward):
    for (each column, we start at the most
left, and stack right):
        stack a block
        increment
        stack until the condition is met
(stack up to width amount)
    increment
    move onto the next row and loop back
stack until
both width and height condition is met

From the pseudo code, we prototype it in C with numerous print statement to get a visual representation of what our code was actually doing, compared to what we thought it was doing. The C code translated over extremely easy after we've familiarized with PLC, and all objectives and criteria were met.

In-depth of the process

While it might not be possible to operate your machine with this code, given the circumstances of different systems, I would still like to present the code.


We first worked on the PLC portion of the project. PLC 1,
which initializes the project, was already completed, so we had to work on PLC
10. The first portion of PLC 10 that we had to work on was the stop state. We
had to complete substates 0, 3, and 4. The goal of substate 0 was to bring the
conveyor to a stop. This was achieved by checking to see if the conveyor, or
motor 4, was moving and if the latch was set to 0. Then a few parameters for
the motion profile of the conveyor were set, the latch was set to 1, so the
command wouldn’t be executed more than once, and a stop command was sent to the
controller to stop the conveyor. After the conveyor stops, the latch is reset
and the next substate is selected.

Substates 3 and 4 were very similar. The goal of the
substates was to stop axis y and z, respectively. This was done by mirroring
the code of Substate 2, where the x-axis was stopped. If the axis was still
moving and the latch was set to 0 then a few motion parameters for the axis
were set, the latch was set to 1, and the stop command was sent for that axis. Once
the axis came to a complete stop, then the latch was reset and the next
substate was selected. Once Substates 0, 3, and 4 were completed we were done
with the stop state.

Our next step in the project was to complete the run
state. This involved finishing Substates 1 and 2. Substate 1 involved feeding
the cube onto the conveyor and setting a timer once the block crossed the path
of the light sensor. First, we waited for the conveyor to get started, then we
extracted the arm of the solenoid to push a block out from the stack. After
waiting for a second, the solenoid’s arm was retracted. After the light beam
was broken by the block travelling down the conveyor, a three-second timer was
started, the latch was reset, and the next Substate was selected.

For Substate 2 of the run state, the PLC waited for the
timer set by Substate 1 to end then it set a few parameters for the motion
profile of the conveyor before sending the stop command to the conveyor’s axis.
After the conveyor came to a stop, the latch was reset to 0, the next Substate
was selected, and the P_BoxArrived was set to 1. The P_BoxVariable was used to
communicate between the PLC program and the motion program. When that variable
was set to 1, then the motion program knew that the next block was ready to be
picked up.

After completing the stop
and run states of PLC 10 we worked on the motion program that took the blocks
from the conveyor and stacked them in the specified arrangement on the pallet.
To be able to stack the blocks in any arrangement specified by the user, we
used an algorithm that included two for loops, one inside the other, that were
implemented using while loops. The outer while loop controlled the vertical
placement of the blocks, which correlates to the different rows. The inner while
loop controlled the horizontal placement of the blocks on the pallet, which
corresponds to the different columns of each row. This way each block in a row
would be placed before proceeding to the next row. The horizontal placement was
offset incrementally by the length of the block after each block was placed and
the vertical placement was offset incrementally by the height of the block
after each row was placed. The Pseudocode of the motion program is shown below