Building an AI Powered Follow Trolley Part 3: Hardware Assembly & TestFollow article
Assembling the follow trolley frame, interface PCB & writing some Python to verify correct hardware operation.
In part two of this series, we designed the aluminium extrusion frame of the follow trolley. We also took a look at the electronic components that make up the control system of the trolley. In this post, we’ll be assembling the interface PCB and frame, and testing all the components.
We started the trolley assembly by cutting down the aluminium extrusion that forms the frame. A cut list was drawn up based on the CAD model we had previously designed. With a liberal application of measure twice cut once, the aluminium extrusion was cut-to-size ready to be bolted together. As usual, a file was used to break any burrs left on the edges of the cut extrusion.
As we had picked the Rexroth extrusion system to use, a wide variety of accessories were available for us to use. Instead of using gusset corner pieces to fasten the extrusion together, we opted to use a profiled round corner that matches the extrusion profile and looks neater.
These are sold as a kitthat includes the corner itself, and three self-tapping M8 screws — making installation quick and easy as no preparation of the extrusion has to be done. We used a cordless drill to screw in the self-tapping screws, as our little cordless screwdriver did not have enough torque.
Coverswere also purchased to complete the corners. These are a press-fit into a small hole in the centre of the corner piece, and nicely finish off the look of the extrusion.
The top and bottom frames were assembled first as two separate components, ready to have the four corner extrusion lengths screwed into them to form the frame. Before the frame could be fully assembled, we installed the aluminium plate that acts as the base of the trolley — this holds all the wiring, controls and batteries in place.
With the plate in place, we screwed in the corner pieces and then installed the basket base plate. This then allowed us to install the top frame, which completes the follow trolley chassis.
PCB Design & Assembly
As the GPIO on the Jetson Nano is at a 3.3V level and the componentry we have picked out operates on higher voltages (mostly 24V), a board needed to be designed that provides buffering and level shifting of signals.
We started this process by looking at all the inputs and outputs that will be needed — the Electromen motor drives need a 0-5V analogue speed signal and a 4-28V digital input for direction control. The stack light has three 24V inputs for the three lights and a common ground connection. Next to be connected is the two IFM proximity sensors — we picked the PNP output version which sources 24V to a load.
A schematic was started in DesignSpark PCB, consisting of the 40-pin header that matches the Jetson Nano GPIO header pinout, a number of high-side 24V and 5V switches, and an op-amp circuit.
The three 24V high side switch circuits differ slightly from the ones for 5V due to the addition of an extra resistor. This is necessary as most MOSFET devices will not tolerate much beyond a 20V difference on the gate pin — hence the two resistors form a resistor divider, providing a 12V difference between the gate and source, which is sufficient to turn the device on.
An op-amp circuit provides low-pass filtering for the PWM signal coming from the Jetson Nano, and also then level shifts the signal from 0-3.3V to 0-5V, suitable for feeding into the motor controller. Low pass filtering was necessary as the motor controller expects an analogue input rather than a PWM signal — and since we did not know how it would react to a PWM signal, for the sake of a few more components we opted to err on the side of caution and implement the LPF and buffer.
A quick simulation of the buffer circuit was run, to ensure that resistor values were selected to provide the correct gain and that the circuit would behave as expected.
The 24V signals from the proximity sensors were handled with a resistor divider, with resistor values calculated to give a 3.3V output to the GPIO pins.
With the schematic designed, we moved on to the PCB layout. This was a relatively simple board to layout, and ended up being fairly compact; the bulk of the board size is due to the 40-pin header, and the numerous connectors that run off to various components on the trolley. We picked the smaller Phoenix Contact MC series headers to connect wires to the board, as we did not need a high current capacity and the pluggable style offers ease of wiring.
Assembly of the PCB was a quick affair, taking no longer than an hour. At this point, we could move onto testing the various inputs and outputs.
Jetson Nano Setup and Testing
With the frame & interface PCB assembled, we moved on to setting up the Jetson Nano and then testing the GPIO interface.
We started by ensuring that J48 was jumpered to enable the external 5V barrel jack input — which enabled us to bench test everything easily. The GPIO header on the Jetson was then connected to the header on our interface board using a 40-pin ribbon cable.
Setting up the Jetson PWM interface
In part one we set up a Linux image on the Jetson Nano, so we already had a working system to carry on with. Before the hardware PWM peripheral can be used, it has to be configured through the Linux Device Tree.
Conveniently, Nvidia has provided a Python script that provides a terminal-based UI for configuring the GPIO header pins. To get started, we ran the command
sudo /opt/nvidia/jetson-io/jetson-io.py in a maximised terminal window (it is important to have a maximised window, otherwise, the tool does not display properly).
With the tool running, we selected the “Configure 40-pin expansion header” option, then turned on “pwm0” and “pwm2”. The tool then generated a device tree overlay, then compiled it into a device tree blob which was applied upon rebooting.
The “Jetson.GPIO” Python library was installed next, which is as easy as running
sudo pip install Jetson.GPIO. We also cloned the accompanying Github repository as this contains a set of “udev” rules that need to be applied, and also some sample Python applications. To start, we first created a new user group called “gpio” and then added our user to it, by running
sudo groupadd -f -r gpio && sudo usermod -a -G gpio jetson.
With this done, we then installed the udev rules by running
sudo cp lib/python/Jetson/GPIO/99-gpio.rules /etc/udev/rules.d/ from within the root of the repository. The rules then needed to be applied, either with a reboot or by running
sudo udevadm control --reload-rules && sudo udevadm trigger.
Testing the GPIO Interfaces
At this point, we could now run the PWM sample — to ensure that the PWM output works and that our interface board successfully generates a 0-5V analogue output. The script had to be modified slightly, to change both the output pin number and to bump the PWM frequency up; in the example, this is set to 50Hz but the low pass filter needs at least 1kHz to produce a nice smooth DC voltage.
Probing the output of the op-amp channel showed a nice, smooth 0-5V output as the sample code ramped the PWM value up and down. The sample code was then adjusted to test the other PWM output pin, and again the same behaviour was noted — exactly as the simulation that was run during the design phase had shown.
With the PWM confirmed working, we moved onto testing the output channels. This was again done by modifying the sample output script that was provided to have the correct GPIO pins set. Again, this was a success with the stack light blinking as the script toggled the outputs on and off.
Only the two proximity sensor inputs were left to test. This was initially done using a multimeter to double-check the resistor divider voltage output was within the 3.3V limit of the Jetson GPIO pins. With this confirmed, the provided “simple_input.py” script was modified to watch the input pins and we were greeted with a stream of “HIGH” and “LOW” in the terminal as we wiggled the pin.
The final set of tests consisted of wiring up the motor drive, emergency stop button, and motor as if the motion controls were installed onto the follow trolley frame. A small Python script was written that runs the motor in one direction and then the other in a loop until terminated.
The above video demonstrates the Jetson Nano controlling the speed and direction of the motor, verifying that the control system does work as intended.
In this post we’ve taken a look at the frame assembly, the interface board and theory of operation, set up the Jetson Nano and tested the system for correct functionality. The next step is to finish off the mechanical side, wire the system and connect the output from the AI model demonstrated in the first post to the motion system, so that the trolley can then steer to follow a person.