Skip to the content
2 layers48 × 38 mmBazauto block detection, the printed circuit board in 3D

Bazauto block detection

bazauto/block-detection

Two-channel active-high DCC block detector board (KiCad) for the Westgate Hollow layout

Size
48 × 38 mm
Copper layers
2
Thickness
1.6 mm
Parts
37
Nets
17
Pads
83
Tracks, vias
117, 38
Pours
2
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
14 Sep 2026
Updated
14 Sep 2026

Overview

Bazauto block detection is an open-source printed circuit board by bazauto, from the bazauto/block-detection repository on GitHub, published under the CERN-OHL-P-2.0 licence. It is a 2-layer board of 48 × 38 mm with 37 parts on 17 nets, routed with 117 tracks and 38 vias.

It is built around the TLV9002IDGKR-MS, 1N4148W and BAT54S. Its parts include 11 resistors, 5 capacitors, 4 diodes, 3 connectors and 2 ICs.

Main components

3

README

README.md

2-Channel DCC Block Detector (Active High)

CT-based occupancy detection for the Westgate Hollow layout. Two independent channels, each turning the current in an external current transformer into a push-pull logic level: HIGH (3.3 V) = block occupied, LOW (0 V) = clear.

Single +3.3 V rail, fed in through the output header. Board is 48 × 38 mm, 2 layers, four M2 mounting holes.

Why build this

So that a broken cable or connection under the layout doesn't register as a clear block.

The off-the-shelf detectors used so far are active low: they pull their output to 0 V when a block is occupied, and leave it open when clear. The feedback node's inputs are pulled up, so a broken wire floats high, and that reads exactly like a clear block, the permissive state (bazauto/layout-feedback#9).

This board is active high: occupied drives 3.3 V, clear drives 0 V. A broken wire into a pulled-up input now floats to the occupied side.

Status

Revision 1.0: 10 boards ordered from PCBWay, awaiting delivery. Nothing has been measured on hardware yet.


Files

FileWhat it is
bazauto-block-detection.kicad_schSchematic (KiCad 10 format)
bazauto-block-detection.kicad_pcb2-layer PCB, fully routed
bazauto-block-detection.kicad_symProject symbols: TLV9002IDGKR, TLV3212IDGKR
sym-lib-tableProject symbol library table. There is no project footprint table: every footprint comes from the stock KiCad libraries and is stored in the board file
bom.csvBill of materials, grouped
fab/rev-1.0/Revision 1.0 as sent to fab: Gerbers, drill files, Gerber job file, position file, the zipped Gerber set, and SOURCE.txt fingerprinting the board they came from. See Fabrication revisions
BOM_PCBWay_bazauto-block-detection.xlsxNot in the repo. bom.csv poured into PCBWay's template, ready to upload. Generate it locally; see Regenerating
scripts/Generators and checkers — see Regenerating

Everything else (resistors, caps, diodes, connectors, trimmers) comes from the stock KiCad 10 libraries, so the project opens on any standard install.


Circuit

Each channel is the same chain:

text
CT ─ terminal block ─ burden ─ ESD clamp ─ 1k ─ precision peak detector ─ comparator ─ OUT
     J1 / J2          R1,R2,R3  D1 / D2   R4/R5   U1 + D3/D4 + C3/C4 + R8/R9   U2      J3
                      + JP1

Burden. The CT secondary is loaded across the input terminals. Channel 1 is switchable, channel 2 is fixed:

ChannelJP1BurdenUse
1open1.1 kΩProgramming track (service-mode ACK pulse)
1fitted1.1 k ∥ 110 R = 100.0 ΩStandard track
2—100 Ω fixedStandard track only

The parallel combination is exact: 1100 × 110 / 1210 = 100.0 Ω.

Clamp. D1/D2 (BAT54S, series pair) clamp the input to roughly −0.3 V / +3.6 V. R4/R5 (1 k) then limit the current into the op-amp's input structure on the negative half-cycle — the CT output is bipolar and a single-supply op-amp input sits at the very edge of its absolute maximum without them.

Peak detector. The op-amp drives D3/D4 with the diode inside the feedback loop, so the forward drop is divided out by the loop gain — no 0.6 V loss on a signal this small. R6/R7 (100 Ω) sit between the op-amp output and the diode: they are inside the loop too, and stop the RRIO output from ringing into the 10 µF hold capacitor. C3/C4 hold the envelope, R8/R9 bleed it away.

Comparator. The envelope goes to +IN, the trimmer wiper to −IN, and the push-pull output drives the header directly. R10/R11 (10 M) add positive feedback so the output does not chatter as the envelope crosses the threshold.


Setting up

Time constants and tuning, all measurable on the board:

  • Release time. R8/R9 × C3/C4 = 100 kΩ × 10 µF ≈ 1 s to decay. That doubles as debounce for dirty wheels. For a faster release drop the bleed resistor — 10 k gives ≈ 100 ms.
  • Hysteresis. V_hyst ≈ 3.3 V × R_bleed / R_hyst = 3.3 × 100 k / 10 M ≈ 33 mV. Lower R10/R11 for more.
  • Threshold. With the block clear, turn RVn until OUTn just goes low, then back off about 10 %.

Test points, all on the top side:

TPNetUse
TP1 / TP3VREF1 / VREF2Trimmer wiper — the threshold you have dialled in
TP2 / TP4ENV1 / ENV2Peak-detector output — the rectified envelope
TP5GNDScope ground

⚠ Known concerns with revision 1.0

1. The signal chain has no gain, and that makes the threshold hard to set.

This is the one thing worth changing. The detector is a unity-gain rectifier, so the comparator threshold has to be set in the millivolt region. With a 1:100 CT and a 100 Ω burden, 10 mA of track current gives about 10 mV at the envelope node. The trimmer spans the full 0–3.3 V across 10 kΩ, so 10 mV is 0.3 % of its travel — a fraction of one turn on a 12-turn trimmer — and it is the same order as the comparator's own input offset voltage. Setting it repeatably will be unpleasant, and it will drift.

The cheap fix is one resistor: put ~330 kΩ in series between +3V3 and the top of each trimmer (RV1 pin 1, RV2 pin 1). The wiper then covers roughly 0–100 mV instead of 0–3.3 V, giving about 30× the resolution and swamping nothing else. The alternative is to give the op-amp stage gain instead of running it at unity.

Revision 1.0, as ordered, does not include this change (there is no 330 kΩ part in bom.csv). Sizing it properly needs the CT's actual turns ratio. It affects two nets and about 4 mm of track.

2. Verify the TLV3212IDGKR pinout against the datasheet. The comparator symbol uses the industry-standard 8-pin dual layout — 1=OUTA, 2=INA−, 3=INA+, 4=GND, 5=INB+, 6=INB−, 7=OUTB, 8=V+ — which is what TLV3202IDGKR uses in the same DGK package. I could not confirm TLV3212's pin assignment from a datasheet in this session. TLV3202IDGKR is a verified drop-in if you would rather not check. Same for TLV9002IDGKR, though that one follows the universal dual-op-amp pinout and is not in doubt.

3. AGND is the plane, not a separate net. The spec asked for the filter returns to go to AGND and for a solid, unbroken ground plane. Those pull in opposite directions — a genuine second net needs a split, and a split is exactly what section 6 forbids. I used one continuous GND pour and kept the analog returns physically local instead: C3/C4 and R8/R9 ground through their own vias straight into the plane, a few millimetres from the op-amp's own ground via.


Layout

  • B.Cu is a ground pour. F.Cu carries the signals plus a second GND pour in the gaps. 30 ground vias tie the two together: 16 taking SMD ground pads straight down to the plane, 14 stitching the pours across the board.
  • +3V3 runs as a perimeter ring (top edge, right edge, bottom edge) with a spine threaded through the gap between the two pad rows of U1 and U2, so it never crosses a channel's signal path.
  • The two channels are mirrored top and bottom about the board centreline, with the shared dual op-amp and comparator between them. Both ICs are rotated so channel A faces the top band and channel B the bottom.
  • 0.1 µF decoupling (C1, C2) sits against each IC's V+ pin; C5 is the 10 µF bulk.

Where the ground plane is interrupted. Four short bottom-layer hops let crossing nets pass each other, 8.60 mm of track in total on a 1824 mm² board:

NetFrom → toLength
+3V3(20.20, 22.00) → (20.20, 24.00)2.00 mm
/OUT1(42.20, 18.30) → (43.80, 18.30)1.60 mm
/OUT2(31.90, 22.60) → (33.45, 22.60)1.55 mm
OA2 out(21.50, 22.75) → (21.50, 26.20)3.45 mm

scripts/check_plane.py audits this and reports which analog nets pass over a void. Current result: the CT input rails, both op-amp inputs, ENV1 and VREF1 have completely unbroken copper beneath them. Four crossings remain, all in channel 2's middle band — ENV2 twice, VREF2 once, channel 2's op-amp output once — and in each the trace crosses a void under 1 mm wide. Those nets carry a rectified DC envelope and a DC threshold reference, where a sub-millimetre detour in the return path at DCC frequencies is not a real effect. If you want them gone, the honest fix is a 4-layer stack-up, not more clever 2-layer routing.

One placement change from your version: C1 moved 0.65 mm right (to x = 23.45) so that channel 2's feedback trace and op-amp output each get their own corridor past it. Everything else is where you left it.


Regenerating

Run with KiCad's bundled Python, from the project directory:

sh
K="C:/Program Files/KiCad/10.0"

python scripts/gen_schematic.py         # schematic + project symbol lib
python scripts/verify_netlist.py        # netlist vs. design intent
"$K/bin/python.exe" scripts/route_pcb.py    # routing + pours (placement is preserved)
"$K/bin/python.exe" scripts/check_board.py  # placement + board-vs-schematic nets
"$K/bin/python.exe" scripts/check_plane.py  # ground-plane audit

route_pcb.py loads the existing board, so hand-adjusted placement and silkscreen survive; it only rebuilds tracks, vias and zones.

ScriptDoes
gen_schematic.pyBuilds the schematic from real KiCad library symbols; wires are computed from actual pin coordinates
kicadlib.pyS-expression reader/writer and symbol-library helpers
probe_transform.pyDerives KiCad's symbol placement transform empirically from its own demo files
verify_netlist.pyCompares the extracted netlist against the intended one, net by net
route_pcb.pyRouting, ground pours, silkscreen legends
check_board.pyCourtyard overlaps, off-board parts, board nets vs. schematic
check_plane.pyBottom-layer voids and which analog nets cross them
make_pcbway_bom.pyFills PCBWay's BOM template; fails if it has drifted from bom.csv. Needs PCBWay's sample BOM template saved locally as Sample_BOM_PCBWay.xlsx. It's PCBWay's file, so it isn't committed, and neither is the output.
check_fab_outputs.pyChecks the newest fab/rev-X.Y/ against the board it was generated from; --record writes that revision's SOURCE.txt. Plain Python, needs kicad-cli on PATH or KICAD_CLI set

Fabrication revisions

Each set of files sent to a board house lives in its own fab/rev-X.Y/ folder and is never regenerated in place, so the repo always holds exactly what a revision was. Each revision is also tagged in git (rev-1.0).

fab/rev-X.Y/SOURCE.txt records the SHA-256 of the board file (line endings normalised) that its outputs came from. CI runs scripts/check_fab_outputs.py:

  • Board unchanged since the newest revision: it regenerates the outputs and fails if the committed ones differ. That catches Gerbers left stale after a board edit, and a zip that disagrees with the loose files. Gerbers are compared by the geometry they draw, because KiCad doesn't write primitives in a stable order.
  • Board changed: work on the next revision is under way. It reports a notice and passes.

To cut a new revision, for example 1.1:

  1. Plot Gerbers, drill files (Excellon, PTH and NPTH separate) and the position file (CSV, mm, both sides) into fab/rev-1.1/, and zip the Gerbers, the Gerber job file and the drill files as bazauto-block-detection.zip there.
  2. python scripts/check_fab_outputs.py --record rev-1.1
  3. python scripts/check_fab_outputs.py, which must report all outputs matching.
  4. Land it through a PR, then tag the merge commit rev-1.1.

Verification

Everything below was run against the files in this directory:

text
kicad-cli sch erc            0 errors, 0 warnings
verify_netlist.py            all 17 nets match design intent, no unconnected pins
kicad-cli pcb drc            0 violations, 0 unconnected items
check_board.py               37 footprints, 0 problems (no overlaps, nets match schematic)
check_plane.py               8.60 mm bottom-layer track; 4 analog crossings (see above)

CI re-runs the two kicad-cli checks and check_fab_outputs.py on every pull request (see .github/workflows/ci.yml). DRC there runs with --schematic-parity at error severity. At warning severity the parity check reports 80 cosmetic mismatches: footprints saved without their library prefix, and field text such as a Datasheet of '' against ~. None is a net or connection mismatch.

Gerbers and drill files for revision 1.0 are in fab/rev-1.0/, and regenerating them from the current board reproduces them exactly. Nothing has been measured on hardware yet. The threshold-resolution concern above is analysis, not a bench result.


Licence

Copyright © 2026 Paul Barrett.

MaterialLicence
The hardware design: schematic, board, project symbol library, BOM, Gerbers and drill files, and the enclosure model (enclosure/, except check_fit.py)CERN-OHL-P-2.0
Software: everything in scripts/, and enclosure/check_fit.pyMIT

Source location: https://github.com/bazauto/block-detection

Third-party material, notably the KiCad library symbols the project symbols are derived from, is listed in THIRD-PARTY-NOTICES.md.

Parts

37
QtyValueFootprintReferences
4M2MountingHole_2.2mm_M2H1, H2, H3, H4
310uFC_0805_2012MetricC3, C4, C5
2100RR_0805_2012MetricR6, R7
2100kR_0805_2012MetricR8, R9
2100nFC_0805_2012MetricC1, C2
210MR_0805_2012MetricR10, R11
210kPotentiometer_Bourns_3269W_VerticalRV1, RV2
21N4148WD_SOD-123D3, D4
21kR_0805_2012MetricR4, R5
2BAT54SSOT-23D1, D2
11.1kR_1206_3216MetricR1
1100RR_1206_3216MetricR3
1110RR_1206_3216MetricR2
1CT1TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_HorizontalJ1
1CT2TerminalBlock_Phoenix_PT-1,5-2-3.5-H_1x02_P3.50mm_HorizontalJ2
1ENV1TestPoint_Pad_D1.5mmTP2
1ENV2TestPoint_Pad_D1.5mmTP4
1GNDTestPoint_Pad_D1.5mmTP5
1MODEPinHeader_1x02_P2.54mm_VerticalJP1
1OUTPinHeader_1x04_P2.54mm_VerticalJ3
1TLV3212IDGKRMSOP-8_3x3mm_P0.65mmU2
1TLV9002IDGKRMSOP-8_3x3mm_P0.65mmU1
1VREF1TestPoint_Pad_D1.5mmTP1
1VREF2TestPoint_Pad_D1.5mmTP3

Similar boards

  • 4 layers137 × 79.5 mmTGX4, the printed circuit board in 3D

    TGX4

    hexeguitar/TGX4

    Teensy 4 based guitar amp emulator

    297 parts66
  • 4 layers106 × 63.5 mmBrineomatic, the printed circuit board in 3D

    Brineomatic

    hoeken/brineomatic

    Open Source Watermaker Controller.

    323 parts47LGPL-2.1
  • 2 layers115.2 × 78.6 mmL0destar, the printed circuit board in 3D

    L0destar

    m4rkw/l0destar

    l0destar open-source tracker project

    164 parts43
  • 2 layers200 × 120 mmPlytka v2, the printed circuit board in 3D

    Plytka v2

    tmierzwa/WICI

    Otwarty system łączności awaryjnej (Reticulum/LXMF, 869 MHz)

    152 parts4
  • 2 layers100 × 102 mmMpair, the printed circuit board in 3D

    Mpair

    marpi82/mpair

    Advanced Air Quality Monitoring Station based on ESP32's

    198 parts2
  • 4 layers99.9 × 99.9 mmEcu dev board, the printed circuit board in 3D

    Ecu dev board

    D3stan/ecu-dev-board

    265 parts1
  • 2 layers262.2 × 100 mmHandcart, the printed circuit board in 3D

    Handcart

    eagletrt/handcart-hw

    🛒 Hardware for Fenice's charging handcart

    215 parts1
  • 2 layers100.6 × 131 mmHabitat V5, the printed circuit board in 3D

    Habitat V5

    machadoleonardo94/HabitatControl-hardware

    Hardware files for HabitatControl, designed on DipTrace

    161 parts1

Questions

How big is the Bazauto block detection PCB?

It measures 48 × 38 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Bazauto block detection use?

37 parts, built around the TLV9002IDGKR-MS, 1N4148W and BAT54S. 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 Bazauto block detection KiCad files?

From the bazauto/block-detection repository on GitHub, at the commit this page was made from: the board is bazauto-block-detection.kicad_pcb and its schematic bazauto-block-detection.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Bazauto block detection design in my own project?

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