Published: Sept 7, 2025
With robotics quickly growing—especially in areas like humanoid robots—the need for compact, efficient, and precise drive systems is bigger than ever. Cycloidal gearboxes stand out because they deliver high torque density and virtually zero backlash in a very compact package, making them ideal for robotic joints and other demanding applications.
With my interest in robotics and wanting to learn more about actuator design, I challenged myself with the design of such gearbox. In this project, I designed, analyzed and built a cycloidal gearbox from the ground up, developing the CAD model, running stress simulations, and validating its performance with a prototype. The result is a high-precision gearbox that demonstrates the key benefits of cycloidal drives while achieving a compact form factor and designed for 3D printing.
The final gearbox design achieved a 29:1 reduction, with the final dimensions being 100 x 52 mm (Outer Diameter x Thickness).
When starting personal projects like this, I’ve realized how important it is to hold myself accountable to clear design goals and performance specifications. The best way to do this—just as in any professional engineering project—is by drafting an Engineering Design Specification (EDS). An EDS defines what a product or system must achieve in measurable, testable terms, guiding both the design process and its validation. In practice, it acts as a contract between what is needed and what will ultimately be built.
The table below highlights a selection of key design specifications, many of which mirror the functional requirements (FR) commonly used to market commercial gearboxes. For the complete EDS and the corresponding verification plans, please see the reference at the bottom of this page.
Note: ' is arcminutes, NFR = Non-Functional Requirement, C = Constraint
One key constraint I established for this project was that the primary manufacturing method would be 3D printing, since I have ready access to a Bambu Lab P1S. Fortunately, the curved nature of cycloidal geometry is particularly well suited to 3D printers, unlike traditional involute gear designs (spur, helical, etc.), which rely on sharp corners that are more challenging to produce accurately on a printer.
To understand the fundamentals of a cycloidal gearbox, it's first important to understand the cycloid shape. A cycloid is the curve traced by a fixed point on the circumference of a circle as that circle rolls along a straight line without slipping. This geometry is then adapted for a cycloidal disc, with the point being traced as the circle rolls along the diameter of another circle (base circle). This can be seen in the below video.
Figure: Path of cycloid [1]
Figure: Tracing of cycloidal disc [2]
Key components of a typical cycloidal gearbox are shown in the image below, with their respective roles described as follows:
Input Shaft with Eccentric Cam: The input shaft drives an eccentric cam, which causes the cycloidal disc to orbit.
Cycloidal Disc: A disc based on cycloid geometry. This disc does not simply rotate—it follows a combination of rotation and orbital motion.
Fixed Ring Pins: Circular pins arranged around the inside of a housing. The lobes of the cycloidal disc push against these pins.
Output Mechanism (Pins + Output Disc): Holes in the cycloidal disc engage with output pins attached to the output shaft/disc. These convert the orbital motion into smooth rotation at a reduced speed.
Figure: Typical Structure of Cycloidal Disc [2]
One key performance specification for any gearbox is the reduction ratio (i). It outlines the relationship between the speed of the input shaft and speed of the output shaft. In cycloidal gearbox design, the reduction ratio is a function of the number of fixed ring pins (N) and number of lobes on the disc (n), with the equation listed below. The number of lobes on the disc is (1) one less than the number of fixed ring pins (n = N - 1).
Motion transmission through a cycloidal gearbox occurs through the following three steps:
Input: The motor drives the eccentric cam, which makes the cycloidal disc orbit inside the ring of fixed pins.
Disc Behavior: The cycloidal disc’s lobes engage with the fixed pins. Because there is one more pin in the ring than lobes on the disc, the disc rotates slowly in the opposite direction of the input orbit.
Output: Holes in the disc drive output pins connected to the output shaft. This transforms the orbital motion into high-torque, reduced-speed rotation.
TLDR: The cycloidal disc orbits around the center point of the fixed ring pins + rotates around its own center. This combination of motion is what allows us to achieve high reduction ratios in compact forms as opposed to involute gear systems (spur, helical, etc).
The first step of my gearbox design was to generate the cycloidal disc geometry. The geometry can be defined by the parametric equations listed below, along with a helpful visualization of each of the variables. All the variables listed can be set arbitrarily while following some key rules explained below.
Figure: Diagram of Key Disc Parameters
Figure: Key Disc Parameters Used
I've listed out the values I used in my disc design in the table above. The values can largely be set arbitrarily, but there are some key rules I followed to make the design easier. I will list out the values I had chosen and their reasoning below:
Pitch Circle Diameter of Fixed Ring Pins, D
D = 80 mm
Based on my EDS, I set the maximum outer diameter of the gearbox at 100 mm. To stay within this envelope, I selected an 80 mm disc diameter, which ensured a consistent 10 mm radial clearance for the housing. This choice also provided enough wall thickness to accommodate features like heat-set threaded inserts, which I anticipated using later in the design. Going smaller than 80 mm would have introduced risks—both in terms of efficiency (more on that later) and the added difficulty of sourcing appropriately sized bearings and off-the-shelf components, which quickly becomes more costly at very small scales.
Fixed Ring Pin Diameter, dr
dr = 5.0 mm
This value dictates the diameter of the fixed ring pins. In commercial-grade cycloidal gearboxes, a ring of bearings are used to make up the fixed ring pins, known as a free rolling configuration. Some obvious benefits are low friction, better load distribution and lower operating noise. The downside is that it can be extremely costly with number of bearings = N. Additionally, they increase the part count and assembly time, while also introducing a tolerance stack-up to ensure the pin the bearing sits on is correctly positioned.
For my application, cost and ease of assembly were higher priorities, so I pursued a solid pin design with the pins integrated directly into the 3D-printed housing. To maintain flexibility, I selected a round 5.0 mm diameter—large enough to print reliably, yet also compatible with a potential upgrade to 5 mm OD bearings should I revisit a free-rolling configuration in the future
Eccentricity, e
e = 1.0 mm
Eccentricity (e) is the single most critical parameter in cycloidal gearbox design, influencing both the geometry of the disc and the shaft configuration. Its value directly shapes the trade-off between efficiency and torque capacity.
Smaller e → The disc profile becomes closer to a circle, with shallower lobes. This reduces contact stresses and friction, but limits overall torque capacity.
Larger e → The lobes become deeper, creating greater engagement between disc and pins. This improves torque transmission but increases stresses, making the system more sensitive to deflection and wear.
One major drawback of introducing eccentricity is the resulting shaft imbalance, which can cause noticeable vibrations during operation. A common solution is to use a two-disc configuration, where identical discs are positioned 180° out of phase. This arrangement cancels out imbalances, ensures continuous contact with the fixed ring pins, and improves both load sharing and backlash performance. For my design, I adopted the two-disc approach to minimize vibrations and enhance load distribution—an especially important choice given the added variability and tolerance limitations inherent in 3D printing.
For the initial design, I chose an eccentricity of e = 1.0 mm as a starting point. After comparing multiple disc profiles with different eccentricities, I found that 1.0 mm offered a good balance, which I later confirmed through pressure angle analysis (more on that later). Another design decision was whether to use an ordinary cycloid or a contracted cycloid profile. The contracted form is defined by the conditional equation shown in the second equation below. To highlight the difference, I’ve included short descriptions of both approaches alongside a visual comparison.
Figure: Ordinary vs. Contracted Cycloid [2]
An ordinary cycloid produces larger, more bulged lobes that contact the ring pins over a broader area, but this geometry requires greater eccentricity and results in more sliding, friction, and lower efficiency. In contrast, a contracted cycloid forms tighter, pinched lobes that engage in a more rolling-like manner with less sliding, allowing for smaller eccentricities at the same reduction ratio and ultimately delivering higher mechanical efficiency.
I opted to go with the contracted cycloid mainly due to the smoother lobe profiles that would be easier to produce through 3D printing as opposed to the sharper corners provided by the ordinary version. If you would like to learn more about the rolling circle diameter, δ, please visit this website.
Additional Parameters
The last 2 parameters related to the disc design are the output pin diameter (dpin) and output pin hole diameter on the disc (dhole). The pin diameter can be chosen arbitarily, with dhole computed using the equation below. Given that the pins orbit inside the hole, its common to use bushings or bearings whose inner diameters match dhole, to reduce friction. For my design, I chose the following parameters:
dpin = 4.0 mm
dhole = 6.0 mm
I opted to go for a standard metric pin size so that I can purchase them instead of having to 3D print them. Given my e = 1.0 mm, this led to a standard metric size of the output pin hole diameter, which can easily be achieved by a bushing or bearing. Note, if I had chosen an eccentricity or pin size combination that resulted it a non-standard metric hole size, it would've been much harder to source bearings/bushings, forcing me to go a custom route.
Once I settled on these profile parameters, I decided to write a Python tool to help visualize the key disc and gearbox geometry before putting them into CAD. This would also be a space for me to play with the parameters and brush up on my Python. I've provided a link below to my GitHub repo, which contains both a folder for all Python code (visualization, force analysis, verification data, etc) and one for my embedded C code, which was used to run the Nucleo during testing (more on that later).
Below are two plots generated from profileGenerator.py. Both of the profiles in the two plots were generated by iterating through φ from [0, 2π] and computing the equations listed above. The left image below shows the cycloidal disc profile centered at (0,0) with the red dotted line representing the fixed ring pin diameter (D). The right image below showcases the full static gearbox, complete with both discs 180° out of phase of each other (blue & gold), along with their accompanying output disc holes and mutual output disc pins (red). The black circles represent all 30 fixed ring pins.
Figure: Static Cycloidal Disc Profile
Figure: Static Gearbox Diagram
I then wanted to make a dynamic visualization of the gearbox to showcase the disc's interaction with the ring pins given a input shaft speed. I attempted this using matplotlib's Animation classes, where I used a 2D rotation matrix to rotate each point of the profile by the disc's current spin angle and translate the center position using simply trigonometry for each frame update. For some reason, I couldn't get it to work accurately (lobes were crossing the ring pins), so conscious of time, I opted to utilize this great online simulator made by ME Virtuoso. The below video is my gearbox design animated!
In this project, I focused on analyzing and optimizing two key areas of the cycloidal gearbox: pressure angle behavior and force distribution. The pressure angle analysis helped me evaluate how efficiently the discs transmit motion through the pins, while the force analysis looked at the mechanical loads inside the system—covering shaft torsion, root stresses, and the per-lobe forces acting on the cycloidal disc. Together, these studies guided my design decisions and informed the trade-offs between strength, efficiency, and durability.
Pressure Angle Analysis
The pressure angle (α) is a key measure of transmission performance in cycloidal gears, governing how efficiently force is transmitted through the lobes. It is defined as the angle between the line of action (the direction of the contact force between the cycloidal disc and the ring pins) and the tangent to the path of motion.
A lower pressure angle directs more of the force tangentially, improving torque transmission and reducing stress.
A higher pressure angle increases the radial component of force, which pushes components apart instead of rotating them.
TL;DR: Aim for a lower pressure angle for smoother, more efficient gear operation.
The following image showcases the derived closed-form pressure angle equation (ɑk) with its intermediate equations, which I used in a Python script (PythonCode/PAcompute_cf.py) to compute pressure-angle plots given my cycloid parameters.
Figure: Closed-form Pressure Angle Equations [3]
The following plot shows how the pressure angle of a single lobe varies with input shaft rotation, given my cycloid profile parameters from above. For cycloidal gears, a lobe only contributes to torque transmission between 180° and 360°, with performance judged by the minimum pressure angle in this range — lower values mean greater component of the force is tangential, leading to more efficient transfer.
Between 0° and 180°, the lobe does not transmit torque. It’s in contact with a pin, but the pressure angle is ≥ 90°, so the force direction does not contribute useful tangential torque. Instead, the force is mostly radial — effectively pushing the lobe into place and setting up the geometry for when it will engage. At 0°, 180°, and 360°, the pressure angle is 90°, corresponding to the dead points where no torque is delivered [3].
The following plot depicts PA curves for all lobes as a function of input rotation angle. At any given input rotation angle, multiple lobes of the cycloidal disc are engaged with different pins. Each lobe follows the same pressure angle curve (as above) but is phase-shifted according to its position on the disc, shown by all 29 colored lines below. This means that while one lobe might be in its non-transmission phase (0°–180°), another is in its active phase (180°–360°), contributing useful torque.
Because of this phase staggering, there are always several lobes transmitting torque simultaneously, with their tangential force components adding together. The result is load sharing across multiple lobes and pins, which reduces stress on any single contact point, improves durability, and smooths out torque ripple.
The plots compare how eccentricity (e) and ring pin circle diameter (r_PCD) affect pressure angle trends:
Eccentricity (top): Higher e lowers the minimum PA but raises the early peak; lower e reduces the peak but increases the minimum. At e = 1.0, the curve is well-balanced with a moderate peak and a low enough minimum, providing smooth transmission over the active range.
Ring pin diameter (bottom): Smaller r_PCD deepens the minimum but creates very high peaks, while larger r_PCD reduces the peak but raises the minimum. At r_PCD = 40, the trade-off is ideal—avoiding excessive peaks while keeping a low minimum pressure angle.
My chosen parameters (e = 1.0, r_PCD = 40) strike an effective balance, minimizing the worst-case loading while ensuring efficient torque transfer through low minimum pressure angles.
Force Analysis
This part of the analysis examined how forces are shared across the lobes and pins as the disc turns. I used the input torque, shaft radius, and eccentricity to evaluate force transmission and stress.
Calculated radial (Fr), tangential (Ft), and normal (Fn) forces acting on each lobe
Tracked force distribution across active lobes over the full shaft rotation
Visualized loading with a normal force heat map to highlight peak regions
Overlaid force vectors on active lobes to clearly show directions and magnitudes
Design takeaway: By comparing the computed stresses against Von Mises, I was able to evaluate safety margins and verify that the chosen geometry and material could withstand peak loading conditions.
All force-related solvers and plotting functions are stored in a single Python script that I have written: PythonCode/FA.py
The following image summarizes the equations I used to evaluate the factor of safety (FOS) for the 3D-printed gearbox shaft under torsional loading from the maximum motor torque (Tin = 16 Ncm). A shoulder stress-concentration factor (Kts = 2.2) and a safety factor (SF = 2.0) were applied to account for geometry effects and shock loads [4]. Using the Von Mises criterion, I derived the allowable shear stress from the tensile strength of PETG-CF and compared it to the maximum torsional shear stress. This resulted in a calculated FOS of 6.38, confirming that the shaft can withstand peak motor loading with ample margin.
Figure: Shaft Torsion Equations [4]
While the Von Mises criterion is commonly used for predicting failure in ductile materials, it can be slightly inaccurate for 3D-printed parts because of their anisotropic nature, where strength depends heavily on print orientation, layer adhesion, and infill type/percentage. Given that I would print my shaft with the axial length in the z-axis, the limiting factor is z-layer adhesion. To validate my assumptions, I carried out a light empirical test using a jig and a printed shaft at my chosen nominal diameter & design. Known weights (water) were hung at a 150 mm long lever arm to apply torque until the shaft failed in torsional shear.
The results, shown in the graph below, confirms a near-linear relationship between applied mass and resultant torque. Failure occurred at just over 0.918 Nm torque for the tested shaft geometry, leading to a FOS of 5.73.
The following equations were used to compute the radial (Fr), normal (Fn), and tangential (Ft) forces acting on each lobe as the input shaft rotated through 0–360°. The full solver and plotter exists in PythonCode/FA.py. The analysis starts with the input torque (Tin = 16 Ncm), which is converted into a total shaft radial force (FcamT) based on the eccentricity (e). This load is then distributed across the number of discs (Ndisc) and the lobes that are active at each angle (Nactive). Active lobes are based on the instantaneous pressure angle (ɑk) being ≤ 90°, which I set using a mask in my Python Code:
mask = (alpha <= (np.pi/2))
counts = mask.sum(axis=0)
The per-lobe radial force is then resolved into normal and tangential components, which directly govern torque transmission and local stresses.
Assumptions:
The radial load is evenly shared among active lobes.
Contact between lobes and pins is rigid (no compliance or deformation).
The pressure angle (ɑk) fully defines the direction of the contact force.
Effects of friction, backlash, and print-induced imperfections are neglected.
Note: Improvements to this force analysis model could include the integration of Hertzian Contact Theory, which relaxes assumption #2 by accounting for elastic deformation at the lobe-pin interface. This allows for more realistic predictions of contact area, constact stresses, and load distribution. For simplicity, I decided to leave it out for now.
Figure: Per-lobe Force Equations
The following plot is a heat map of the normal force (Fn) acting on each lobe over one full input shaft revolution. The diagonal bands highlight how different lobes engage and disengage sequentially as the shaft rotates. Only a subset of lobes carry load at any given angle, with forces peaking around 9 N. This confirms the expected load-sharing mechanism of a cycloidal drive: torque is not concentrated on a single lobe but distributed across several active lobes that cycle in and out of engagement.
The following plot gives a snapshot of the force distribution at a specified input angle of θ = 90°. Here, approximately 15 lobes are active, each carrying a share of the applied load. Among these, the normal force (Fn) is the largest component, followed by the tangential (Ft) and radial (Fn) contributions (constant given my assumption). The variation in bar heights reflects how the load is not perfectly uniform — some lobes experience higher tangential force due to their pressure angle position. Lobes with higher Ft correspond to lower pressure angles, meaning more of the contact force is directed tangentially and actively driving the output. This plotter works for any input angle, θ, and you can see the force distribution move along at varying angles.
This last diagram overlays the radial (Fr), normal (Fn), and tangential (Ft) force components on the cycloidal disc at a input shaft angle of 90°. 15 lobes are actively engaged with the ring pins, each carrying part of the applied load. The green arrows show the total contact force on each lobe, which resolves into radial (blue) and tangential (orange) components, with the same trend regarding magnitude as in the plot above.
To make it to the final design of the cycloidal gearbox as shown in the exploded view above, I started by modelling the key components in SolidWorks given the parameters I had listed earlier in the webpage.
Cycloidal Disc
The core component of the gearbox would be the cycloidal disc, which I sketched in SW using the Equation Driven Curve tool. This tool takes a parametric equation and iterates t through limits set by the user. To make it easier to input the relevant cycloidal parametric equations, I wrote a small function in PythonCode/profileGenerator.py that outputs the equations that can directly be pasted into the dialog boxes:
X_eq = "({}*cos(t)) - ({}*cos(t+arctan( sin({}*t)/(({}) - cos({}*t))))) - ({}*cos({}*t))".format(R,Rr,n,R/(e*N),n,e,N)
Y_eq = "(-{}*sin(t)) + ({}*sin(t+arctan( sin({}*t)/(({}) - cos({}*t)))))+({}*sin({}*t))".format(R,Rr,n,R/(e*N),n,e,N)
The central ball bearing is a 15 x 24 mm (ID x OD) bearing which rides on the cam of the central shaft, giving the disc its eccentric motion (e = 1 mm). A circular array of eight 6 x 12 mm (ID x OD) ball bearings are used to make up dhole, which accommodates the output pin diameter, dpin= 4.0 mm. The number of ball bearings is entirely dependent on the number of output pins I chose, which is completely arbitrary. A greater number of pins means greater load distribution but also requires greater space.
Central Shaft
The central shaft is a critical component in the gearbox. My design incorporates two Ø15 mm cams positioned 180° out of phase to enable the two-disc cycloidal configuration. Several shoulders were built into the shaft to precisely locate both the shaft within the housing and the discs onto the shaft. The smallest diameter section is Ø8 mm, which defined the baseline geometry.
Because of the sharp shoulders and the limitations of 3D printing, I carried out empirical testing (described earlier in the Force Analysis section) to evaluate strength. Across multiple print iterations, I adjusted the outer diameters of certain regions to achieve reliable interference fits between the shaft and its bearings to minimize disc wobble during operation.
Output Disc & Pin Support Disc
The output disc (left) and pin support disc (right) work together to locate and support the output pins, which engage with both cycloidal discs to generate the reduced motion at the output. Both components are mounted on the central shaft but remain mechanically isolated from the input shaft’s rotation and speed through central 10 x 12 mm (ID x OD) ball bearings.
Each output pin orbits within a 6 mm bearing seated in the cycloidal discs, producing the 29:1 reduction ratio and the corresponding torque multiplication. To ensure proper alignment, the holes in the output disc were sized for an interference fit with the pins, locking them rigidly in place. In contrast, the pin support disc uses clearance-fit holes, which prevent the pins from being squeezed or bent axially, ensuring smooth rotation of the pins inside the cycloidal discs.
For structural support, the output disc incorporates a 55 mm ring that seats into a 55 × 72 mm (ID × OD) bearing located in the housing lid. This outer bearing supports bending moments transferred through the output arm, reducing loads on the central shaft by minimizing lever arm effects. Finally, the output disc includes a circular pattern of four clearance holes for M3 heat-set threaded inserts, providing a robust interface for attaching the output arm.
Housing
The gearbox housing is split into two parts: the main housing (left) and the top lid (right). The main housing contains the solid ring pins, sketched as a circular pattern of (30) Ø5 mm semi-circles on an 80 mm PCD, with a 0.50 mm clearance. It also includes a recess for an 8 × 12 mm (ID × OD) ball bearing to support the central shaft, as well as M3 clearance holes for heat-set threaded inserts and a rear fixture point for the motor mount.
The housing lid is designed to mount directly to the main housing with up to 10 M3 screws, secured in M3 counterbore holes. A 72 mm seat is integrated into the lid as an interference fit for the 55 × 72 mm bearing, which supports the output disc and helps transfer any external bending moments into the full housing. In addition to sealing the gearbox interior, the lid seals the internal components from exposure to the environment.
The cross-section view below highlights the major components of the cycloidal gearbox (left) and the motor housing (right). The two cycloidal discs are driven in an eccentric path by the central shaft, with motion transferred through the output pins, supported by the output disc and pin support disc. The main housing and housing lid secure the assembly with M3 screws, while a 55 × 72 mm bearing in the lid supports the output disc. On the input side, a NEMA 17 stepper motor couples to the central shaft using an 8-to-5 mm shaft flexible coupling, mounted within a two-piece motor housing. Together, these features form a compact, serviceable design that provides the 29:1 speed reduction.
To bring the design into reality, I began by 3D printing numerous test pieces to validate critical fits and clearances. All parts were produced using FDM 3D printing on a Bambu Lab P1S, with PLA+ used for early prototypes and PETG-CF chosen for the final build due to its improved strength and stiffness. Assembly involved the press-fit of bearings and output pins and installation of heat-set inserts, ensuring that the gearbox components were properly aligned and mechanically robust.
A light coating of Super Lube 21030 Synthetic Grease was added to the solid ring pins of the gearbox housing and cycloidal gears to reduce friction.
Testing began with the motor bring-up, where I wrote custom firmware and developed the necessary electrical diagrams to verify basic functionality. Once the motor was operational, I tested the initial gearbox performance using both speed ramping and constant motor RPM control. With the system running reliably, I progressed to formal verification of the Functional Requirements (FRs) outlined in the Engineering Design Specification (EDS).
FRs Verified:
✅ Absolute accuracy
✅ Repeatability
✅ Backlash
✅ Efficiency
Electrical & Firmware Bring-up
Given my prior experience using an STM32 Nucleo to control stepper motors in my SCARA project, it was the natural choice for this build. I based the control firmware on a stripped-down version of the SCARA code, which provided a reliable foundation for motor bring-up and testing.
For verification, I selected measurement tools tailored to the Functional Requirements: a dial indicator for assessing absolute accuracy, repeatability, and backlash, and a load cell to measure output torque for efficiency calculations.
On the electrical side, I developed a simple circuit with the Nucleo at its core, shown by the schematic below. It interfaced with an A4988 stepper driver to control the NEMA 17 motor and an HX711 breakout module to read a 5 kg load cell. During testing, the Nucleo was powered via U5V, supplying +5 V to both the A4988 and HX711, while the motor was driven by an external +24 V desktop power supply. In the schematic below, I also included an LM2596 buck converter to demonstrate how the entire system could be powered from a single supply.
This diagram below illustrates the firmware architecture for the gearbox controller, showing how hardware, HAL modules, and functional processes interact under the supervision of the main program. At the hardware level, the load cell is read through the LoadCell_HAL module, while the stepper motors are driven through Motor_HAL. In the functional layer, Calibration handles tare and scaling of the load cell, and Filtering conditions raw measurements into stable force/torque data for use in verification. Motion Control manages motor behavior, including speed ramping and constant-RPM commands, which are controlled through Motor_HAL. A dedicated Scheduler/Timing process ensures that both motion updates (e.g., step pulses at 1 kHz) and sensor reads (e.g., 100 Hz samples) occur at consistent intervals. At the top level, Main.c orchestrates these processes, coordinating calibration, motion routines, and data collection to carry out the testing and verification of the gearbox.
The following images show the StepMotor() (left) and MoveByAngleConst() (right) functions, which are core logic of the Motor_HAL. MoveByAngleConst() was used extensively in all the verification tests.
StepMotor()
Purpose: Interrupt-driven routine that executes one step pulse and updates motor state.
Key Steps:
Checks for stop condition (target steps reached).
Implements gain scheduling (acceleration/deceleration) if enabled.
Recomputes the timer period each interrupt to match current RPM.
Toggles the step pin, decrements remaining step count.
Role in system: Core ISR routine that guarantees precise step timing and smooth motion, even under acceleration or deceleration profiles.
MoveByAngleConst()
Purpose: Initiates a motor move by a specified output angle at a fixed RPM.
Key Steps:
Sets rotation direction (CW/CCW).
Converts target angle into step count, accounting for motor steps per revolution and gearbox reduction.
Configures the timer period to generate step pulses at the required RPM.
Starts the timer interrupt that drives step generation.
Role in system: Provides deterministic motion over a defined angle, used for tests where a constant step rate is sufficient (e.g., gear reduction verification).
If you would like to see the full details of the firmware used in this project, please have a look through the code in the GitHub repository or details provided by the README.md file.
Gearbox Testing
Once the gearbox was assembled and the wiring was done, I ran some initial tests using a MoveByAngle() function in Motor_HAL.c, which is similar to MoveByAngleConst(). MoveByAngle() commands the motor to rotate by a specified angle using a trapezoidal speed control profile: it accelerates linearly from a minimum RPM over the first 1/4 of total steps, maintains the target speed through the midsection, and then decelerates linearly over the last 1/4 of steps before stopping. The function computes the total step count, sets acceleration/deceleration regions, initializes the timer period for step generation, and starts the interrupt-driven motion.
The following video shows the gearbox running its speed-ramping profile at 1/16th micro stepping (achieved by pulling MS1, MS2 & MS3 to HIGH on the A4988), with the housing lid removed to be able to see the movement of the discs.
Absolute Accuracy Verification
Question: How accurate is the output angle vs command (e.g., 1–5°)?
Setup: Dial indicator mounted tangentially to lever arm, at a measured radius, r = 150 mm, from the output shaft; probe preloaded and zeroed against the lever arm
Procedure (ran using MoveByAngleConst() in Motor_HAL.c):
Command an output angle of 1° from the starting position
At each landing, record dial travel, s (mm).
Zero dial indicator in-between angles.
Repeat steps 1-3 for series of angles (1–5°, in 1° increments)
Repeat step 4 for 3 total sets of 1–5° commands
Results: Measured vs Commanded (with ideal y=x) and residuals
Summary table: slope & intercept (scale/offset), R2 , RMSE/MAE (arcmin), max |error|.
Conversion used:
I completed the results analysis using a Python script I had written, which can be found in TestingAnalysis/AccuracyTesting.py. The following chart plots the error (') between the commanded and measured output angles, with the table below summarizing the results from the absolute accuracy testing. Residuals stay within about ±9′ across 1–5° commands, with typical scatter around 4–5′. All three sets show the same pattern: small positive error at 1–2°, a negative dip at 3–4°, and near-zero by 5°—i.e., showing repeatable, mild scale/nonlinearity rather than random noise.
Accuracy is within ±9.1 arcmin at worst (±0.15°), with an average 4 arcmin typical error.
Backlash Verification
Question: What is the lost motion between opposite approach directions (CW vs CCW) at the same commanded angle?
Setup: Same tangential dial setup at r = 150 mm; ensure consistent preload. Use two approach directions to the same target.
Procedure (ran using BacklashTest_FixedRPM() in Motor_HAL.c):
For a chosen target (ex. 2°), command a CW approach and record landing, A (mm)
Return to start, command a CCW approach to the same target and record, B (mm).
Repeat CW/CCW pairs across trials and across targets
Results: Feed paired arrays A (CW) and B (CCW) to Backlash.py (mm). The script computes:
Directional bias: d=A−B (arcmin), with mean ± σ to show which side lands deeper.
Backlash magnitude (spec): ∣A−B∣ (arcmin), summarized by mean / median / max and p95, plus plots of paired A/B (with connectors) and a scatter of ∣A−B∣ per trial with a mean line.
The following plot shows paired CCW (blue) and CW (orange) landings across 10 trials, with light-grey connectors highlighting the lost motion gap for each pair. The consistent vertical separation between paired markers indicates a measurable backlash. CW landings consistently sit “shallower” than CCW landings, showing a clear directional bias.
From 10 paired trials, the mean backlash magnitude was 0.25 arcmin, with a maximum of 0.35 arcmin. The 95th percentile stayed below 0.30 arcmin, showing that the backlash is both low and tightly bounded. In practice, this means the gearbox shows minimal backlash and a predictable directional bias, both of which are important for precision positioning.
Notes: Given the measurements observed, the limiting factor was the resolution of my dial indicator, which was 0.01 mm.
Repeatability Verification
Question: When approaching from the same direction, how tightly do repeated landings cluster at the target?
Setup: Same tangential dial-indicator setup at r = 150 mm; probe preloaded and zeroed at the target landing.
Procedure (ran using RepeatabilityTest_OutputCW_FixedRPM() in Motor_HAL.c):
Command a prescribed 45° move to engage the dial indicator probe.
Record the dial reading at each landing position.
Return to the start position and repeat for a total of 20 cycles.
Results: The spread in measured landings quantifies repeatability. Results are summarized by mean error, standard deviation (σ), RMSE, and max |error| in arcminutes, with plots showing the clustering of all landings around the mean
The following plot shows the distribution of 20 landings, with most clustered tightly around the mean (–0.18 arcmin). The short error bars confirm the low variance, while the single outlier near –0.47 arcmin represents the worst-case but still within sub-arcminute repeatability. Across the 20 cycles, the standard deviation was 0.13 arcmin, and both MAE (0.1778 arcmin) and RMSE (0.2186 arcmin) confirm that the scatter was very tight.
Efficiency Verification
Question: How efficiently does the gearbox convert input torque into output torque at the designed reduction ratio?
Setup: Input torque measured from motor specifications and shaft radius; output torque measured using a lever arm with a load cell. Output speed assumed to follow the theoretical reduction ratio (29:1).
Procedure (ran using LoadCell_ReadNewton() in loadcell_hall.c):
Run the motor at a constant RPM with the gearbox driving the lever arm towards the fixed 5kg load cell.
Record output force (N) from the load cell and convert to output torque (Tin) using known lever arm length
Calculate efficiency from the following torque ratio (assuming ideal speed reduction):
Results: Achieved a 86.5% (Tout = 4.01 Nm) efficiency based on the input torque being a maximum of 16 Ncm (as per stall torque of NEMA 17 motor).
Note: For higher fidelity, true efficiency would be calculated using power in/out (P=T⋅ω), but torque ratio provides a practical and reliable estimate given the test setup.
Speed Reduction Verification
Question: Does the gearbox achieve the designed 29:1 reduction ratio between motor input speed and output speed?
Setup: Motor run at a commanded constant RPM. Output disc rotation tracked using video analysis / stopwatch timing (full revolutions)
Procedure (ran using MoveByAngleConst() in Motor_HAL.c):
Command the motor to run at a target RPM for a set duration (e.g., 20 s)
Compute the expected number of output revolutions
Compare actual vs. expected revolutions to quantify error.
Repeat across multiple input speeds and durations for validation.
Results: The gearbox closely followed the intended 29:1 reduction ratio across all tested input speeds (100–500 RPM). The slope of the measured output speed vs. theoretical was nearly 1.0, with only minor deviations (<0.25 RPM residual). This confirms that the gearbox maintains its designed kinematic ratio consistently.
The top plot below shows measured output RPM almost perfectly overlapping the theoretical prediction, with the adjusted values further improving alignment. The bottom plot highlights residuals, which remained small (generally within ±0.2 RPM) across all speeds. Slight positive bias appeared at higher speeds, likely due to measurement tolerance or timing error.
To close out this project, I revisited the Engineering Design Specification (EDS) after validating the gearbox, with results summarized in the verification matrix below. Testing confirmed that the design met all major requirements, including achieving the intended 29:1 transmission ratio, maintaining sub-arcminute repeatability, and operating with high efficiency (~90%). The design also satisfied key non-functional and constraint targets for weight, cost, and serviceability. Overall, the project demonstrated that a 3D-printed cycloidal gearbox can achieve both precision and efficiency while remaining lightweight and manufacturable without fancy equipment.
Throughout this project, I prioritized sourcing components from readily available vendors. The final BOM below includes both component costs and filament usage for the standalone cycloidal gearbox, with additional R&D filament costs included for transparency. The total came to $95.60. Additionally, the project demanded 38 hours of 3D printing.
A few notes on costing:
The BOM reflects unit prices only for the final build and does not scale for full bundle quantities (e.g., Amazon often provides more parts than needed at lower unit cost).
For precise quantities & higher quality parts, McMaster-Carr is a reliable option, though at significantly higher costs (ex. Same BOM sourced from MMC is $435.77, 15mm ID bearing is $9.47/EA on MMC as opposed to Amazon's $1.15/EA, 55mm ID bearing is $67.53/EA on MMC).
Electrical components required to operate the gearbox (e.g., STM32 Nucleo, A4988 driver) were excluded, but would add approximately $30+ to the total.
The BOM Excel file can be found in the GitHub repo for easy access to the hyperlinks.
Thoughts
This project came together really well, and I’m pleased with the performance of the prototype. It not only validated the feasibility of a 3D-printed cycloidal gearbox but also demonstrated my ability to take an idea from concept through to tested hardware. At the same time, I see plenty of room for refinement—given more time and iteration, I believe this design could be pushed toward a production-ready solution for additive manufacturing.
A key choice I made was to keep the design as a gearbox rather than a full actuator, which provides flexibility for different motor integrations. For testing, I used a NEMA 17 stepper motor, since it was a reliable option that allowed me to focus on proving the gearbox mechanics. Importantly, I also kept the application of this design open-ended, positioning it as a general gearbox platform rather than tailoring it to a single use case.
Learnings
One of the biggest takeaways from this project was how deep the analysis side went. What began as a straightforward design exercise quickly grew into a detailed exploration of pressure angles, force distributions, and stress concentrations within a cycloidal drive. I likely went further than necessary for a prototype, but diving into this “rabbit hole” gave me a much stronger foundation in gearbox mechanics—and learning at that level of detail is something I enjoy. Beyond the mechanical design, I also pushed myself to strengthen my mechatronics and software skills, developing firmware, wiring, and Python tools to complement the build. Drawing from my experience on Weed Warden, I recognized the importance of thorough verification against specifications—not only to validate performance but also to keep myself accountable and ensure the project was truly worthwhile.
Future Ambitions
Looking ahead, I see several ways to build on this project:
Immediate design improvements: integrated grease channels in the ring pins to improve lubrication.
Performance testing: expand verification to include longevity and endurance testing, which was not covered in my current EDS.
Motor integration: move beyond stepper motors to BLDC motors, enabling higher-speed testing and laying the groundwork for actuator-level applications.
Next step: design not just a gearbox, but a cycloidal actuator—building my own BLDC motor alongside a refined gearbox, bridging the gap between mechanical and electrical design.
[1] “Cycloid,” Wikipedia, Mar. 28, 2020. https://en.wikipedia.org/wiki/Cycloid
[2] tec-science, “Construction of the cycloidal disc of a cycloidal drive,” tec-science, Jan. 14, 2019. https://www.tec-science.com/mechanical-power-transmission/planetary-gear/construction-of-the-cycloidal-disc/
[3] X. Huang and J. Zhang, “Analysis of Geometric Characteristics of Cycloidal Transmission,” IOP Conference Series: Materials Science and Engineering, vol. 751, no. 1, p. 012059, Jan. 2020, doi: https://doi.org/10.1088/1757-899x/751/1/012059.
[4] R. Budynas and K. Nisbett, Shigley’s Mechanical Engineering Design Eleventh Edition in SI Units. London: McGraw-Hill Education (Asia), 2020.