top of page

MODULAR ROBOT
my master's project

Executive Summary:

During my fall 2023 semester, I designed, developed, and manufactured a modular kit of low-impedance precision robot joints and links.  The aim was to provide future robotics and controls students a clear bridge between control theory and implementation, as hardware and fabrication troubleshooting have historically formed a demoralizing and time-consuming bottleneck in introductory controls courses. 

 

With this kit, a robust kinematic chain can be assembled in minutes with minimal tooling, and the accompanying software is streamlined and simple to use, meaning that a robot can be designed, built, and controlled in a matter of hours instead of days or weeks. Furthermore, the modularity of the kit means that many different robot architectures can be constructed, and designs can be reconfigured and adapted extremely quickly.

The precise tolerances and rigid construction, coupled with high-resolution encoding built directly into the joints and smooth brushless actuators with zero-backlash capstan cable drives, allow both simple and advanced control methods to be demonstrated with great fidelity. To reach as broad of an audience as possible during my research showcase, I kept things simple with a proportional vs. proportional-derivative comparison, but for more advanced students or researchers, the ceiling of possible project complexity is quite high.

 

Observer control, rendering of haptic environments, and adaptive trajectory planning via computer vision (albeit with an external camera module) are all well within the electromechanical capabilities of this kit. With so little dry friction and such precise encoding and actuation, the differences between control methods become strikingly visible and tangible, something which is often lost in the classroom when cheap, high-friction gear motors are used for lab work.

As much as possible, I designed the kit with economy in mind. All the core electronics are under $50, and each motor and encoder pair is an additional $70 or so. The joints are 3D printed with carbon fiber reinforced nylon, and I designed them around the most common (cheapest) sizes of precision bearings and shoulder bolts available to keep the per-joint cost to around $15. The links are standard mass-produced carbon fiber tubes for hobby quadcopters, and the majority of the hardware consists of inexpensive nylon bolts. This means that the entire kit shown in the video above would cost around $400 to produce, easily within the budget of a university. 

Overall, this was an incredible experience to put together, and I'm eager to see future students push the limits of this project and use my work in new and exciting ways. That's about all for the high-level overview! For a more in-depth write up, keep reading.

Motivation:

 

In many introductory controls and robotics courses, students face significant hardware obstacles when building kinematic chains: revolute joints may lack sufficient off-axis stiffness, actuators may be underpowered, encoders may be inaccurate and/or imprecise, and shaft couplings may be loose, to name a few. Attempting to address these issues in an ad-hoc manner with in-house fabrication and prototyping inevitably costs time, as does waiting for off-the-shelf components to arrive from suppliers. This time could be better spent on the broad storytelling of the controls and robotics discipline. Not only is repeated hardware iteration often demoralizing to new students, but it also muddies the clear connection between the mathematical model and the physical system.

A solution which abstracts the necessary fabrication into a simple, intuitive assembly process with minimal component modification creates an efficient bridge between the modeling and the physical testing. In this way, new students can more succinctly “get the point” of controls and robotics, following the full process from idea to finished kinematic system in a reasonable timeframe for a one-semester course. This accelerated, intuitive approach will build confidence, minimize frustration and self-doubt, and give students a holistic understanding of the scope of controls which will better prepare them for more complicated builds in future coursework.

 

Problem Statement:

Design a modular kit of robotics components which will enable students to solve a variety of problems with the same basic parts, mitigating the hardware bottleneck and bridging the gap between mathematical modeling and physical testing.

Solution Overview:

 

The kit is centered around a robust revolute joint with built-in encoding (exploded view below right). The joint can be wired to a microcontroller and passively report its angle as it is moved by the student (for example, to validate the predicted inverse kinematics of a chain as calculated by the student), or it can be actuated via a removable pulley and capstan assembly connected to a BLDC gimbal motor.​

Final Explosion (2).png

The rationale behind this particular modular design language is twofold. For one, modularity allows the complex task of building a robotic system to be discretized into smaller, more digestible steps: First, the rough geometry of the kinematic chain is determined by the carbon fiber tubes, which form the links of the robot. Relative movement between links is permitted by the revolute joints, to which the carbon fiber tubes are bolted. Some of the joints in the kit have built-in encoders to facilitate positional sensing, while other joints are completely passive, illustrating to students that not every joint needs a sensor in certain robotic schemes, such as a parallel five-bar linkage. In this way, the geometry, degrees of freedom, and sensing all build on each other to create a holistic understanding of the form and logic of the robot, allowing students to internalize its passive behavior completely independently from the task of actuation. Only once the kinematics have been validated and understood are the motors attached, allowing the robot to not just know where it is, but to move to where it needs to be.​

However, this would all be possible with a fixed, predetermined robot architecture. Indeed, there are many products on the market that consist of, for example, a robot arm kit which students can assemble and control. Thus, the second reason behind this particularly modular design language is to foster the creativity of students to build diverse kinematic chains and solve a much broader set of controls problems while pursuing their individual interests. The components which are more or less invariant across the majority of kinematic chains–namely the revolute joints, encoders, and motors–are ready to use out-of-the-box. Coincidentally, these are also the components which often prove most difficult to work with in conventional controls and robotics classes, so this rapid deployment alleviates major student pain points. Meanwhile, the carbon fiber tubes can be cut to any length to facilitate different scales and geometries of robot designs, preserving some degree of fabrication responsibility for the students to make the assembly feel less rigidly predetermined.

Key Features and Development Milestones:

Technical architecture:

Microcontroller: Raspberry Pi Pico

IDE: Arduino (using Earle Philhower’s Arduino Pico library)

Serial Communication: RS-485 protocol using modified code from CUI Devices

Encoder: CUI Devices AMT213-B Absolute Capacitive Encoder

Motor: OT-EM3215D2450Y1R-BEZE (BLDC gimbal motor, item ROB-20441 from Sparkfun)

Motor Driver: TMC6300 (ROB-21867 from Sparkfun)

Motor Control Code: SimpleFOC (open-source field oriented control library)

1. First "smart joint" prototype

Truthfully, this is already a few milestones rolled into one. Ample discussion between Felix and myself, using decision matrices to better crystallize and compare our ideas, ultimately resulted in the plan to design a joint that would be a self-contained assembly to which links could be attached. Any alternatives, like having each link terminate in half of a joint, would have required a daunting amount of precise assembly by the students using the kit.

 

As it is, it took me a long time and multiple failed attempts to figure out how to embed an encoder within the joint, accurately couple the encoder to the shaft without putting any pressure on the delicate encoder wheel, press fit the shaft into the outer half of the joint, and ensure tight alignment and tolerances of the bearings, all while being able to dismantle the joint for any future troubleshooting.

 

However, by leveraging the accuracy and repeatability of 3D printing, I came up with this proof of concept, which achieves excellent off-axis stiffness and smooth rotation thanks to the wide spaced bearing pair. In fact, this bearing pair trick (along with decent quality bearings and shafts that fit together with minimal play) is one of the most crucial design elements for the overall quality and feel of the kit. These bearings are only about $4 each and have some noticeable angular play individually, but together they feel like a million bucks.

2. First successful encoder reading

Again, this a highly composite milestone--a lot went into this! The encoder I sourced for this project (CUI Devices AMT213-B Absolute Capacitive Encoder) uses the RS-485 serial protocol to  send and receive data. Far more sophisticated than simple high or low voltages on a quadrature encoder, this device requires a command byte to be sent over serial requesting position. If the leading bits of the command byte match the encoder's unique ID, the encoder will send back a two-byte position response.

 

This response includes a checksum for error detection, so only 14 bits are reserved for the position itself, but this still yields a whopping 16,384 pulses per revolution. Coupled with the fact that the encoder reports absolute position, it's a perfect fit for highly precise robots that require no calibration on startup to know where they are, making the mental leap from manipulator geometry/design to physical implementation as small and intuitive as possible. Additionally, the use of RS-485 means that multiple encoders can share a bus without any extra wires allocated for additional devices, so an arbitrarily long robot snake of daisy-chained encoders would still only use the same four wires as a single encoder. Great news for simple assembly!

The caveat is that these serial messages must be extremely precisely timed, since both incoming and outgoing messages are sent on the same differential wire pair. Improper timing will result in meaningless nonsense. Furthermore, if multiple encoders are sharing a bus, they need to be addressed sequentially, so there is a practical upper limit for how many encoders can realistically be used before the necessarily slower sample rate becomes an issue. However, with a 2Mbps transmission speed, a handful of encoders pose no issue for real-time control (around 22µs per encoder, or >10kHz control loop with four encoders on a bus).

I'd never worked with RS-485, but thankfully CUI sent me some thorough sample code for an Arduino Mega that I was able to reference and adapt to work on the Pi Pico. I initially began rewriting the entire thing in MicroPython, as it seemed like a better fit for the hardware. While it was a great coding exercise, it ultimately proved to be far more hassle than it was worth, since the majority of the CUI code was very idiomatically tailored to the Arduino language. Transcompiling it to MicroPython would have resulted in much less readable code overall, and I feared this would be more intimidating to students who would likely be more familiar with Arduino anyway.

 

Thankfully, Earle Philhower’s Arduino Pico library was easy to set up in the Arduino IDE. After lots of debugging and poring over the RP2040 documentation to recreate all of the bitbashing tricks necessary for such data transmission rates, I was finally able to send position commands. However, getting any meaningful response back from the encoder took a few solid hours of probing with an oscilloscope, manually adjusting the timing and delays down the microsecond, and debugging my code line-by-line. After much trial and error, I was elated when it finally worked. Sound on for my narration.

 

3. First successful motor control (open-loop)

I was quite relieved to discover how simple this milestone actually was! Control of BLDC motors is notoriously fickle due to the complicated phase math required to convert an equivalent

control voltage into three separate PWM signals, but the open source SimpleFOC library made the whole process quite painless.

 

Furthermore, I knew this motor had great potential for precise haptics because of Scott Bezek's SmartKnob project. However, I'd never seen anyone use it with my encoder. For the first tests, this didn't yet matter, since I was running the motor in isolation anyway without an encoder attached. This meant that closed-loop control was impossible, but I set up a quick open-loop velocity control test to see how well it would track the position of the joint by simply trying to match its velocity to the discrete derivative of the encoder position. I was absolutely stunned at how well this worked without any discernible drift, even rendering collisions and rapid acceleration quite accurately.

4. Designing the Capstan

To couple the motor to the joint, I opted for a capstan cable drive. Felix is a huge fan of these, as their essentially backlash-free and zero-cogging power transmission makes them excellent for haptics applications. Furthermore, since the BLDC motor is quite limited in terms of torque, the mechanical advantage of the capstan is necessary to enable the movement of larger payloads. And lastly, by spatially separating the motor from the joint/encoder, students will be able to better compartmentalize sensing and actuation as two distinct tasks in robotics (which are often blurred together by the use of cheap magnetic encoders attached directly to hobby DC motors). 

 

However, capstans are a nightmare for students to build. I wanted to design a capstan that would be extremely easy to set up and tension, giving students exposure to this beautifully elegant alternative to gears without the usual pain and troubleshooting involved in making one from scratch.

While steel Sava cable is a standard choice for such applications, I wanted to try the vastly cheaper option of low-stretch Dyneema cord, usually used by sailors. Tying a knot in a cord is easier, faster, cheaper, and less permanent than applying copper crimps to a steel cable, and the lack of stiffness makes the capstan far easier to wind and tension as well, especially around very small pulleys that would be an issue for the springy steel.

I first made an extremely quick plywood mockup of the basic concept just to make sure my method of securing the cord would work properly. This early demo heavily influenced my subsequent 3D-printed design, as shown below.

The high responsiveness and incredible smoothness of the capstan make for a fascinating sensation. Even with relatively little tension on the cord, movement is snappy and faithfully transmitted. It definitely felt more polished than I was expecting!

 

A motorized test with a simple open-loop sine wave pattern also proved quite promising. With the encoder, motor, and capstan all working well on their own, feedback control was just one integration step away... but it's never that easy, is it?

 

5. Closing the Loop

The glaring issue with the open-loop velocity control I'd previously used for motor testing was that deviations from the setpoint caused the rotor to violently skip. This makes sense, as open-loop velocity control of a BLDC just involves creating a constantly rotating magnetic field. If the rotor "misses the train" so to speak, it will be rudely jolted when the next one approaches. By contrast, proper field-oriented control maintains a 90 degree phase angle between the rotor's and the stator's magnetic fields, enabling smooth torque control. However, this requires feedback of the position of the rotor relative to the stator. That's where the encoder comes in.

Alas, it ended up taking an obscene number of hours over the course of multiple days to get this to work. I tried everything I could possibly think of, debugging with the oscilloscope and asking extensive questions on the SimpleFOC forum (shoutout to runger for all the help), but I was just becoming more and more perplexed: The motor seemed to be initializing correctly, since it would move slowly back and forth during startup as per the SimpleFOC code, but it would never recognize the encoder and thus stopped moving altogether after initialization, despite the fact that I was getting clean command and response bytes on the scope. ​

 

It took me embarrassingly long to figure this out, but the culprit was a single line of code that wasn't being executed early enough, so the encoders weren't being read during startup. With that resolved, I was ecstatic to see that my closed-loop proportional torque control demo was working perfectly.

 

6. Assembling the first five-bar linkage

With a single joint working well, I went into production mode and made nine more for my two parallel five-bar linkages. Four out of the ten joints have embedded encoders, while six are completely passive, since the base angles of the parallel five-bar linkage completely determine the end effector position (given that the range of motion of the joints prevents positional ambiguity).

I also cut the carbon fiber tubes down to length on the table saw before drilling holes in them to accept the locking bolts which would secure them to the joints. Since the whole point of this project was to develop modular components that could be assembled quickly and easily, I wanted to see how well I was meeting this goal. Once I had finished making the joints and preparing the links, I timed myself to test how fast I could assemble one of the five-bar linkages. On my first and only timed trial, I finished the assembly in under 12 minutes.

 

I was relieved to see how straightforward it was to work with the kit components. My plan of spending months developing these parts so that future students could put them together in minutes was certainly coming to fruition.

7. Preparing the showcase

I've saved my most egregious lumping of milestones for last! I put an enormous amount of work into tying up all the project's loose ends ahead of the showcase, but it all happened within such a short timeline that I think it makes sense to consider it a single sprint.

For starters, I had to get all the encoders working on the same bus, and my wiring scheme was not the recommended configuration for RS-485. According to the protocol specifications, there should be a single twisted wire pair running throughout the entire setup with very short stubs branching off to each device. This aims to minimize signal reflections which could make the crisp square waves of the bits too fuzzy to read properly.

 

However, I knew it would be vastly easier to troubleshoot and take things apart if each motor had its own wire bundle which plugged into screw terminals on a breadboard. I figured if it didn't work, I could quickly redo the wiring according to specs. To my delight though, despite flying in the face of stub length limits, I was able to get clean results from all four encoders, albeit after fiddling with the signal delays as well as fixing various unrelated issues (like insufficient encoder power leading to meaningless gibberish being transmitted).

By the way, I think those ugly spikes are an artifact of the Arduino plotter when the encoder read fails on occasion. Due to the extremely high sample rate of the realtime control loop, these occasional misreads are completely harmless physically: the stored position value in the Arduino code only changes after a successful read, so a failure would simply result in the previous position value being used for another 100µs or so.

Finally, after countless hours developing this kit, and with a single day before the showcase, I coded a quick proportional controller, filmed this leader-follower control demo, and went to bed.

© 2024 by Andrew Daetz. Powered and secured by Wix

bottom of page