← SHEET 02 · ASSEMBLIES HW-001

Arduino PID Motor Rig: Sim-First Design

HWCONTROLS
PART NOHW-001
MATL / SYSTEMDC MOTOR + ENCODER
TOOLSPython · Arduino · L298N

A simulation-first closed-loop motor rig. A brushed DC-motor model and a discrete PID with anti-windup and a filtered derivative were tuned in Python (Kp=12, Ki=22, Kd=1) to a 90° step response of 13% overshoot, 1.45 s settling, and zero steady-state error, then mirrored 1:1 in Arduino firmware (encoder on D2/D3, L298N on D7–D9) so the control logic is validated before any purchase. The bill of materials is sourced locally for Uzbekistan, following a four-layer prototype plan from sim to hardware. Honest status: simulation, firmware, and BOM are complete; physical assembly is pending parts.

OVERVIEW & MOTIVATION

Most hobby PID builds start at the breadboard and discover the control problem by trial and error. This one inverts that order: design and tune the whole closed loop in software first, so that when parts are bought the gains and the wiring logic are already known to work. The plan (PROTOTYPE_PLAN.md) sets out four layers — control design in Python, firmware written in the same discrete-PID shape as the sim, a virtual-circuit check (Wokwi/Proteus/SimulIDE), then real hardware — and each layer is meant to de-risk the next before money is spent. The target plant is a closed-loop DC-gearmotor position control: drive a motor to a commanded angle, hold it there under load, using quadrature-encoder feedback.

HARDWARE & BILL OF MATERIALS

The BOM (PID_parts_uzbekistan.md, build_pid_bom.py) is priced against the Uzbek market (Tashkent OLX listings, Uzum/Glotr marketplaces, and the roboshop Telegram channel), compiled June 2026 at ~1 USD ≈ 12,800 so’m. The two parts that actually define the project — the encoder motor and the H-bridge driver — are flagged as not reliably stocked on OLX and sourced from marketplaces or Telegram sellers instead. Estimated total for individual parts: ~400,000–570,000 so’m (≈ $31–45); a bundled Arduino starter kit (192,216 so’m, Glotr) can replace the Uno + breadboard + jumpers + USB line items.

ITEMSPECROLE
Arduino Uno R3ATmega328-based, ~90,800 so’m confirmed (Glotr)controller, runs the discrete PID loop
DC gearmotor w/ encoderJGB37-520, 12 V, ~200,000–350,000 so’m (est)plant + feedback sensor — the essential, hardest-to-source part
L298N motor driverdual H-bridge, ~30,000–50,000 so’m (est)drives motor from PWM + direction pins
12 V 2 A power supply~32,130 so’m confirmed (sts-hik)motor power rail
Breadboard830-point, ~20,000–40,000 so’m (est)solderless wiring
Dupont jumper wires40+ M-M/M-F, ~15,000–30,000 so’m (est)interconnects
USB cable (A–B)~15,000–30,000 so’m (est), often bundledprogramming the Uno
Potentiometer (optional)~5,000–10,000 so’m (est)live setpoint knob

CONTROL DESIGN

The controller is a discrete PID with derivative-on-measurement and a low-pass filter on the D term, plus conditional integral anti-windup — the same structure in both sim/motor_pid_sim.py and firmware/arduino_pid.ino, running at a fixed 200 Hz loop (DT = 0.005). The sim models a brushed DC motor’s electrical (R, L, back-EMF) and mechanical (inertia, viscous friction, constant load torque) dynamics and steps P, PD, and full PID gain sets through a 90° position command under load. Anti-windup only integrates error while the output isn’t saturating in the same direction as the error; the derivative is filtered with time constant TAU_D = 0.02 s to avoid amplifying encoder noise. The firmware mirrors this line-for-line: encoder A/B on D2 (interrupt) and D3 (quadrature x2 decode), L298N direction pins on D7/D8 and PWM on D9, COUNTS_PER_REV left as a placeholder to be set from the actual encoder/gear ratio, output clamped to the 0–255 PWM range. The same repo also carries two adjacent control-system sims built with the same rigor: an LQR- balanced single-wheel inverted pendulum (balancer/balancer_pid.py, gains from a linearized continuous-time Riccati solve, not PID despite the filename) and a 2-link IK arm (arm/ik_arm.py) whose joint-angle profile was designed to drive a Fusion 360 animation.

STATUS & RESULTS

Simulated (verified): the step response comparison below, from sim/results/pid_step_response.png and the sim’s printed metrics, for a 90° step with a constant load torque:

CONTROLLEROVERSHOOTSETTLING (2%)STEADY-STATE ERROR
P (Kp=8)5.8%offset, no settle~2.9°
PD (Kp=12, Kd=0.8)0%offset, no settle~1.9°
PID (Kp=12, Ki=22, Kd=1.0)13%1.45 s~0°

Written, not yet bench-tested: firmware/arduino_pid.ino compiles against the same control logic and starts from the sim’s gains, but has not been run on real hardware — no encoder counts- per-rev has been measured, no real-motor step response has been logged. Planned: Layer 3 (virtual-circuit check in Wokwi/Proteus/SimulIDE) and Layer 4 (bench build, re-tuning, and a predicted-vs-measured step-response comparison) are both still ahead. Parts are priced and sourced but not confirmed purchased. This is honestly a software-verified control design with a firmware port awaiting hardware.

USE CASES & APPLICATIONS

PID position/speed loops are the default controller in industrial motion: servo axes on CNC machines and 3D printers, motor-speed regulation in conveyors and fans, robot-joint position control, and — cascaded into inner/outer loops — drone attitude and altitude hold. Temperature- control loops (ovens, 3D-printer hotends, HVAC) use the same three-term structure on a slower plant. The anti-windup and derivative-filtering details built into this sim and firmware are the same fixes production controllers need once output saturates or feedback is noisy.

FILES & REPRODUCTION

  • sim/motor_pid_sim.py — run python motor_pid_sim.py from sim/; edit gains/params at the top, re-run, inspect results/pid_step_response.png and the printed metrics table.
  • firmware/arduino_pid.ino — flash to an Uno/Nano once wired per the header comment (encoder A/B → D2/D3, L298N ENA/IN1/IN2 → D9/D7/D8); set COUNTS_PER_REV for the actual encoder/gearbox.
  • PROTOTYPE_PLAN.md — the four-layer plan and the sim-to-hardware parameter mapping.
  • PID_parts_uzbekistan.md, build_pid_bom.py — sourced BOM and the script that generates the priced, color-coded parts spreadsheet.
  • balancer/balancer_pid.py, arm/ik_arm.py — adjacent control-sim explorations (LQR balance, IK-driven arm animation) built with the same Python/matplotlib animation pipeline.

← BACK TO ASSEMBLIES

NAME ODILBEK MARIMOV
DWG NO. PF-2026
SHEET 01 / 07
DISCIPLINE ROBOTICS / MECHATRONICS
SCALE 1:1
REV A
THIRD-ANGLE PROJECTION
DATE 2026-07-11
UNITS mm