Skip to the content
2 layers80 × 60 mmMotor validation board, the printed circuit board in 3D

Arduino motor control and validation platform with INA219 sensing, Python logging and a KiCad carrier PCB

Size
80 × 60 mm
Copper layers
2
Thickness
1.6 mm
Parts
14
Nets
12
Pads
36
Tracks, vias
71, 3
Pours
1
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
22 Oct 2026
Updated
22 Oct 2026

Overview

Motor validation board is an open-source printed circuit board by damian-EE, from the damian-EE/motor-control-validation-platform repository on GitHub, published under the MIT licence. It is a 2-layer board of 80 × 60 mm with 14 parts on 12 nets, routed with 71 tracks and 3 vias.

It belongs with the robots and motor control boards of this library.

README

README.md

Custom PCB Motor Control & Validation Platform

A 2-layer KiCad carrier PCB for a small motor test platform (a 12 V DC gear motor with a Hall encoder), plus the breadboard prototype used to validate the circuit. The prototype drives the motor from an Arduino through an H-bridge, measures speed and supply current while it runs, and logs the data to CSV with a Python script. The PCB replaces the breadboard wiring.

PCB layout

What it does

  • Drives a 12 V gear motor with PWM speed and direction control (DRV8871 H-bridge).
  • Measures motor speed from the encoder (interrupt-based pulse counting).
  • Measures supply voltage and current with an INA219 sensor, averaging many readings per interval because the PWM chops the supply current.
  • Streams time_ms,pwm,rpm,current_mA,voltage_V every 500 ms over USB serial.
  • Runs an automatic PWM sweep, logs it to CSV, and produces time-series, response and run-to-run repeatability plots.

System overview

mermaid
flowchart LR
    PSU["12 V supply"] --> INA["INA219<br/>current / voltage"]
    INA --> DRV["DRV8871<br/>H-bridge"]
    DRV --> MOT["12 V gear motor<br/>+ Hall encoder"]
    ARD["Arduino Uno R3"] -- "D9 / D10 PWM" --> DRV
    MOT -- "encoder A (D2)" --> ARD
    INA -- "I2C (A4 / A5)" --> ARD
    ARD -- "USB serial, 9600 baud" --> PC["Python logger<br/>CSV + plots"]

Hardware used

PartNotes
Arduino Uno R3Motor control, encoder counting, sensor readout
DRV8871 breakoutH-bridge, PWM on IN1 (D9) / IN2 (D10)
INA219 breakoutHigh-side current/voltage sensing, I2C
12 V DC gear motor with Hall encoder (25GA370H type)45:1 gearbox, 12 pulses/rev on the encoder, 540 pulses per output revolution
12 V supplyMotor and driver

Pinout

Arduino pinSignalUsed for
D9PWM_IN1DRV8871 IN1 (forward)
D10PWM_IN2DRV8871 IN2 (reverse)
D2ENC_AEncoder channel A, rising-edge interrupt
D3ENC_BWired to the board, not read by the current firmware
A4 / A5SDA / SCLINA219
5V / GNDEncoder and INA219 supply, common ground

The INA219 sits in series on the high side: supply + goes to VIN+, VIN- goes to the DRV8871 VM pin.

Repository layout

text
firmware/
  motor_controller/      Final Arduino sketch (control + encoder + INA219)
  i2c_scanner/           Utility to confirm the INA219 is detected
  development/           Earlier steps: motor control only, then + encoder RPM
python_logger/
  motor_logger.py        Serial logger and automatic PWM sweep
  plot_results.py        Plots and steady-state table for one run
  compare_runs.py        Overlay and repeatability table for several runs
hardware/
  kicad/                 KiCad 10 project (schematic + PCB)
  gerbers/               Gerber and drill files (also zipped)
  schematic.pdf          Schematic
  bom.csv                Bill of materials
test_results/            Raw CSVs and steady-state summaries
media/                   Plots and board images

How to run it

1. Firmware. In the Arduino IDE install the Adafruit INA219 library (Library Manager), open firmware/motor_controller/motor_controller.ino, select the Uno and upload. If the Serial Monitor reports Failed to find INA219 chip, upload firmware/i2c_scanner to check the wiring (the INA219 normally shows up at 0x40). Close the Serial Monitor before using the logger, since only one program can hold the port.

2. Python setup. Run all Python commands from the repository root so the outputs land in test_results/ and media/.

text
pip install -r python_logger/requirements.txt
python python_logger/motor_logger.py --list     # find the serial port

3. Run a sweep. This steps through PWM 60, 100, 140, 180, 220, 255, then back down through 180, 100, 0, holding each level for 12 s (about 108 s total) and writing test_results/run_<timestamp>.csv:

text
python python_logger/motor_logger.py --port COM3 --sweep --hold 12

python python_logger/motor_logger.py --simulate runs the whole pipeline with a synthetic motor and no hardware. Simulated output is only for testing the software and is not real data.

4. Plot.

text
python python_logger/plot_results.py test_results/run_20261022_031935.csv
python python_logger/compare_runs.py test_results/run_20261022_030916.csv test_results/run_20261022_031231.csv test_results/run_20261022_031935.csv

Results

All results are no-load (the motor shaft was not loaded) on a 12 V supply, from three full sweeps on 2026-10-22. Each value is the mean over the second half of a 12 s hold, so the settling transient is excluded.

Run-to-run repeatability

Steady-state speed on the ramp up, three runs:

PWMRun 1 (cold start)Run 2Run 3Runs 2-3 differ by
6035.96 RPM45.0345.801.7 %
10079.8186.0385.970.1 %
140104.12108.62108.490.1 %
180116.17118.13117.920.2 %
220124.00125.22124.950.2 %
255135.02135.64135.340.2 %

Supply current at full PWM was about 58 mA (roughly 0.72 W electrical input) in the two warm runs and 61 mA in the cold run, and about 0.05 mA with the motor stopped. Bus voltage stayed between 12.45 V and 12.53 V in all three runs.

Time series of the third run:

Run 3 time series

Steady-state response of the third run (ramp up solid, ramp down dashed):

Run 3 response

Raw data and per-run summaries are in test_results/, and the three-run comparison is in media/repeatability_summary.csv.

Notes and limitations

  • Run 1 is a cold start. The gearbox was cold, so at the same PWM it ran slower and drew roughly 5-11 % more current than runs 2 and 3. Runs 2 and 3 agree to within 0.3 % at PWM 100-255. The speed also creeps up slightly during a hold, which is consistent with warm-up.
  • The up/down difference is not cleanly separable from warm-up. At PWM 100 the ramp-down speed is higher than the ramp-up speed (2.9 % in run 2), but because the motor is warmer by then this is not evidence of true hysteresis.
  • Low PWM is the least repeatable region. Near PWM 60 the motor is close to the point where friction dominates, so run-to-run differences are largest there.
  • Speed resolution is about 0.22 RPM. One encoder pulse in a 500 ms window is 1/540 of a revolution.
  • No load, no torque measurement. Only electrical input power was measured, so this data does not give efficiency or torque.
  • Direction is not sensed. Only encoder channel A is counted.
  • Discarded runs. Earlier attempts were excluded and not included: two runs where the logger saved no data or the supply connection dropped out, and one run taken with a loose 12 V connection (bus voltage sagging to 11.6 V, with a dip to 10 V). The connection was fixed before the three runs above.

PCB

A 80 x 60 mm, 2-layer carrier board (KiCad 10.0.6) that connects the Arduino, the DRV8871 and INA219 modules, the power input and the motor/encoder connector through headers instead of breadboard wires.

3D render

  • Signal traces on the top layer, with vias to the bottom layer where needed, and a ground zone on the bottom layer.
  • Two net classes: default signals (0.4 mm tracks) and a power class (1.0 mm tracks) for the 12 V and motor-output nets.
  • Six through-hole test points: +5V, GND, +12V_MOTOR, ENC_A, ENC_B, PWM_IN1.
  • Two M3 mounting holes.
  • Design rule check was clean (no violations, warnings or unconnected items) at the time of the Gerber export.

Files: hardware/schematic.pdf, hardware/bom.csv, hardware/gerbers/, hardware/kicad/.

Status

The board is designed and passes DRC, but it has not been fabricated or tested. All measurements above were taken on a breadboard prototype with the same circuit. Before ordering the board, check that the socket pin order on J4 (INA219) and J5 (DRV8871) matches the actual breakout modules in use, since module pin orders vary between vendors.

Project scope

The focus of this project is PCB design and hardware validation: the KiCad schematic and board, the breadboard prototype of the circuit, and the test runs and data shown above.

License

MIT, see LICENSE.

Parts

14
QtyValueFootprintReferences
6TestPointTestPoint:TestPoint_THTPad_D2.0mm_Drill1.0mmTP1, TP2, TP3, TP4, TP5, TP6
1ARDUINO_LINKConnector_PinHeader_2.54mm:PinHeader_1x08_P2.54mm_VerticalJ1
1DRV8871_MODULEConnector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_VerticalJ5
1DRV_OUTConnector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJ6
1INA219_MODULEConnector_PinSocket_2.54mm:PinSocket_1x06_P2.54mm_VerticalJ4
1MOTOR_ENCConnector_PinHeader_2.54mm:PinHeader_1x06_P2.54mm_VerticalJ3
1POWER_INTerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-2-5.08_1x02_P5.08mm_HorizontalJ2

The 12 most common of 14 parts.

Similar boards

  • 2 layers116.8 × 30 mmType d, the printed circuit board in 3D

    Type d

    google/mozc-devices

    Circuit diagrams and firmware source code for Gboard DIY keyboards

    14 parts3kApache-2.0
  • 2 layers32 × 22 mmDiff driver, the printed circuit board in 3D

    Diff driver

    rene-dev/stmbl

    AC Servo Driver for STM32F4

    14 parts990GPL-3.0
  • 2 layers34 × 45 mm2032Charger, the printed circuit board in 3D

    2032Charger

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    14 parts915
  • 2 layers34 × 109.9 mmTdisplay s3, the printed circuit board in 3D

    Tdisplay s3

    landonr/homeThing

    Wifi Smart Home Remotes that run on ESPHome

    14 parts551GPL-3.0
  • 2 layers45.3 × 42.7 mmMainPcb, the printed circuit board in 3D

    MainPcb

    adamb314/ServoProject

    Getting the most out of your hobby servo

    14 parts545
  • 2 layers42.5 × 28.8 mmC5VRX JACK DIY, the printed circuit board in 3D

    C5VRX JACK DIY

    Twotoz/C5VRX

    Ultra-minimal, zero-CPU 5.8 GHz analog FPV video receiver using ESP32-C5 Wi-Fi 6 PHY MODEM_DIAG, BitScrambler WBFM demodulation & resistor DAC CVBS

    14 parts515GPL-3.0
  • 2 layers62 × 24 mmMai button, the printed circuit board in 3D

    Mai button

    whowechina/mai_pico

    Pico controller for Maimai

    14 parts475

Questions

How big is the Motor validation board PCB?

It measures 80 × 60 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Motor validation board use?

14 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Motor validation board KiCad files?

From the damian-EE/motor-control-validation-platform repository on GitHub, at the commit this page was made from: the board is hardware/kicad/motor-validation-board.kicad_pcb and its schematic hardware/kicad/motor-validation-board.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Motor validation board design in my own project?

Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).