Skip to content
Voltomni
← Rotary inverted pendulum kit (Furuta pendulum)

Build guide: Rotary inverted pendulum kit (Furuta pendulum)

A stepper motor swings a horizontal arm; a free pendulum hangs from the arm's end. The firmware swings the pendulum up and balances it upright. Build time: 3–4 hours. Level: intermediate.

1. What's in the box

PartQtyUsed for
Arduino Nano (CH340)1Controller
NEMA 17 stepper motor, 40 mm1Turns the arm
TMC2209 stepper driver1Drives the motor quietly and smoothly
AS5600 magnetic encoder with magnet1Measures the pendulum angle
608 ball bearings2Pendulum pivot
12 V 5 A power supply1Power
M3 screw and nut kit1Assembly
Printed parts: base with motor tower, arm, pendulum, magnet cap4Structure
Wiring harness, power lead with DC jack, encoder cable1 setWiring
M8 × 50 bolt, 2 washers, 2 nuts; M3 grub screw1 setPivot shaft, arm hub

You also need: a computer, a USB Mini-B cable, the Arduino IDE (free), and a 2.5 mm hex key and a small screwdriver. Python 3 with numpy is optional (for designing your own controller).

2. Assembly

  1. Motor into the tower. Feed the motor cable down through the tower and out of the side window. Push the motor's round boss up into the hole in the tower's top plate, shaft up, and fix it with four M3 × 8 screws from above.
  2. Bearings into the arm. Press one 608 bearing into each end of the arm's round housing until it stops against the lip in the middle. Use a vice or press on the outer ring only.
  3. Pivot bolt. From the encoder-bracket side, pass the M8 bolt through the bracket opening and both bearings. On the far side, add a washer and one nut and tighten until the bolt turns freely with no play (not tight: the inner rings must still spin).
  4. Magnet. Press the magnet cap over the bolt head and glue the round magnet into its pocket with a drop of superglue, centred. The magnet must be the diametric one from the encoder bag.
  5. Encoder. Screw the AS5600 board to the bracket, chip facing the magnet, with M3 screws and nuts. Slide it in the slots until the chip is centred on the bolt. Gap between chip and magnet: 1–3 mm (use washers as spacers). Wire the board's DIR pin to GND (the harness does this).
  6. Pendulum. Slide the pendulum's hub onto the bolt after the nut, so it hangs straight down, and tighten the pinch screw. Lock with the second nut.
  7. Arm onto the motor. Push the arm hub onto the motor shaft, flat side towards the grub screw, about 2 mm above the tower. Tighten the M3 grub screw onto the flat.
  8. Check: the pendulum swings freely for 20+ seconds after a push. If it stops quickly, loosen the pivot nut slightly.

3. Wiring

The harness is pre-wired. Connect it as follows (Nano pin → device):

NanoConnects to
D2TMC2209 STEP
D3TMC2209 DIR
D4TMC2209 EN
5V, GNDTMC2209 VIO and GND; AS5600 VCC and GND
A4AS5600 SDA
A5AS5600 SCL
  • TMC2209 MS1 and MS2 → GND (1/8 microstepping). VM → 12 V, GND → supply GND (the 100 µF capacitor across VM/GND is on the harness: never run the driver without it).
  • Motor coils to the driver's A1/A2 and B1/B2 (the harness plug only fits one way).
  • The Nano is powered from USB while you program it; the motor needs the 12 V supply plugged in.
  • Never unplug the motor while the 12 V supply is on: it can destroy the driver.

4. Firmware

  1. Install the Arduino IDE. Download the firmware (pendulum.ino, linked at the top of this guide) into a folder named pendulum and open it.
  2. Tools → Board: Arduino Nano; Processor: ATmega328P (Old Bootloader) for most CH340 boards.
  3. Upload. Open the Serial Monitor at 115200 baud, line ending Newline.

5. First run

  1. Plug in the 12 V supply. Let the pendulum hang still. Hold the base down with one hand.
  2. Type s and press Enter. The arm makes a small jog (this finds the encoder direction), waits, then swings the pendulum up and balances it, usually within 2–5 seconds.
  3. Type x to stop at any time. The firmware also stops by itself if the arm turns more than 2.5 rad (about 140°) either way, to protect the encoder cable.

If it doesn't balance, see Troubleshooting. Most rigs balance with the default gains.

6. Logging and tuning

  • l streams ms,theta,phi,dtheta,dphi,u,mode at 100 Hz (copy from the Serial Monitor into a CSV).
  • p prints the current gains and angles.
  • g k1 k2 k3 k4 sets the balance (LQR) gains; e ke kc kd sm sets the swing-up gains.

Design your own controller. python/furuta.py holds the model of this rig. Weigh your pendulum and put its mass in Rig, measure the friction from a free swing (time how long the swing takes to halve, then fit b), and run:

python3 furuta.py

It prints LQR gains for your rig as a g … line to paste into the console, and simulates a swing-up and balance (it saves a plot if matplotlib is installed). Try different weights Q and R and see how the real pendulum's behaviour changes.

7. Experiments

  1. System identification: fit the pendulum's natural frequency and damping from a free swing.
  2. Pole placement vs LQR: design both from the same model and compare disturbance rejection.
  3. Swing-up: change ke and sm and see how fast and how violently it swings up.
  4. Robustness: add a small weight (a nut) at the tip and see which controller still balances.
  5. Sim-to-real: compare logged data with the simulation from the same starting point.

8. Troubleshooting

SymptomFix
"Encoder didn't see the pendulum move"Magnet glued off-centre or the gap is over 3 mm; check SDA/SCL and 5 V
Motor buzzes but doesn't turnSwap one coil pair; check the 12 V supply is on
Swings up but overshoots and fallsReduce ke (try e 0.6 80 5 60)
Balances but the arm drifts to the limitMake k1 and k3 more negative (stronger arm centring)
Jitters while balancingIncrease the encoder gap slightly, or reduce k4
Arm slips on the shaftTighten the grub screw onto the flat of the shaft

9. Safety

The arm moves fast. Keep fingers, hair and cables clear while it runs, and stop with x before touching it. Use only the supplied 12 V supply.


© 2026 Voltomni. The firmware and Python model are free to use, change and share for learning and teaching. Questions: [email protected].