Skip to the content
2 layers50 × 34 mmPhotomarker, the printed circuit board in 3D

Data server system for data acquisition and control

Size
50 × 34 mm
Copper layers
2
Thickness
1.6 mm
Parts
31
Nets
12
Pads
71
Tracks, vias
92, 13
Pours
2
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
7 Jun 2024
Updated
3 Nov 2026

Overview

Photomarker is an open-source printed circuit board by SheinbergLab, from the SheinbergLab/dserv repository on GitHub, published under the MIT licence. It is a 2-layer board of 50 × 34 mm with 31 parts on 12 nets, routed with 92 tracks and 13 vias.

It is built around the OPT101P and LM393. Its parts include 14 resistors, 3 capacitors, 2 ICs, 2 connectors and 1 diode.

Main components

2

README

hardware/photomarker/README.md

Stimulus onset photo-marker

Sheinberg Lab — rev A

A per-rig photodiode board that timestamps stimulus light onset two ways at once: an analog waveform into an MCP3204 channel, and a comparator edge into a dserv DI pin (IRQ-latched with a box-clock stamp, so it beats the ~100 µs ADC scan quantization).

Wire both. The digital edge is your routine per-trial timestamp; the analog trace is how you verify the edge means what you think, because a fixed voltage threshold lands at a different fraction of the transition for black→white than for a gray-to-gray change.

  • 50 × 34 mm, 2-layer, M3 mounts on a 40 × 24 mm pattern
  • Silkscreen carries the lab name and rev; bump REV in gen_photomarker.py
  • DRC clean: 0 violations, 0 unconnected (KiCad 10.0.4)
  • Photodiode die centre is at board-local (14, 17) mm, marked with a crosshair on both silkscreens so an aperture or hood can be aligned to it

Regenerating

The board is generated, not hand-drawn. Edit gen_photomarker.py (placement table + routing table near the top) and re-run:

bash
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/python3 gen_photomarker.py

Two API gotchas baked into the script, both found the hard way: board.Add(fp) must precede fp.Flip() (flipping an unparented footprint segfaults), and the flip is an X-mirror — verified empirically rather than assumed.

Board sides

Top faces the screen. Only the OPT101 is up there, standing 4.19 mm proud so nothing shadows it.

Bottom carries all SMD — single-sided assembly at JLCPCB, and the board itself blocks the bring-up LED's light from reaching the photodiode.

Ordering

Upload fab/photomarker-gerbers.zip. For assembly add fab/photomarker-cpl.csv and fab/photomarker-bom.csv.

The BOM's LCSC Part # column is deliberately empty. Fill it from JLCPCB's parts search — do not trust a guessed C-number, it orders the wrong part.

JLCPCB places 10 parts: U2, R1–R5, R11, C1–C3. Everything else is DNP or hand-soldered. At that count, hand-soldering a SOIC-8 and nine 0805s may well cost less than the assembly setup fee — worth pricing both ways.

You solder these yourself

RefPartNote
U1OPT101, DIP-8Mount from the top. Strap pin 4 (1M) to pin 5 (OUT) is on the PCB already.
J1JST-PH B5B-PH-K, 5-pin verticalOn the bottom, so the cable exits away from the screen.

OPT101 handling: TI warns the clear plastic is moisture-sensitive and that rapid heating can stress the wire bonds. If the parts have sat in humidity, bake at 85 °C for 24 h first. Solder gently either way.

Connector J1

Pin 1 is leftmost. Silkscreen reads 3V3 GND AO DIb DIa.

PinNetTo the extio box
1+3V33V3
2GNDGND
3AOUTMCP3204 CH2 (CH0/CH1 are the joystick)
4DI-Bfree GPIO — optional second threshold
5DI-Afree GPIO — main onset edge

Free GPIOs per wiznet-io/PINMAP.md: 9–14, 26, 27.

Output goes LOW on light onset (signal on IN−), so configure that DI for the falling edge.

On the ain group carrying CH2: set deadband 0 and average 1. Both smear the edge, which is the one thing you are trying to measure.

Design values

Threshold network on 3.3 V, R1 = 39 k, R2 = 10 k, R3 = 270 k:

  • Onset threshold 0.749 V, release 0.654 V, hysteresis 94 mV
  • Input filter R4/C3 = 10 k / 3.3 nF → 4.8 kHz, τ = 33 µs

Because the signal is on IN−, the hysteresis lands entirely on the release side — it costs nothing on the onset edge, so be generous with it.

Aim the threshold at ~50 % of your lit-state level, not 20 %. Mid-transition is steepest, so timing there is least sensitive to stimulus amplitude drift. The resulting latency to true onset is a constant: measure it once off the analog trace and subtract.

Retune by swapping R1 alone:

R1OnsetHysteresis
68 k0.513 V103 mV
39 k0.749 V94 mV
27 k0.955 V87 mV
18 k1.228 V77 mV
12 k1.536 V65 mV

C3 must be C0G/NP0, not X7R — X7R drifts with temperature and DC bias, which would move the filter corner and turn your calibrated constant lag into a drifting one.

U2: TLV3202 or LM393

The footprint is SOIC-8 and the two parts are pin-identical (1=OUT_A, 2=IN_A−, 3=IN_A+, 4=GND, 5=IN_B+, 6=IN_B−, 7=OUT_B, 8=VCC).

  • TLV3202 (recommended): push-pull, 5 mV max offset. Leave R7/R14 unfitted.
  • LM393 (fallback): open-collector — fit R7 (and R14 if using comparator B) as pull-ups to 3.3 V.

The LM393's common-mode ceiling (V+ − 1.5 V ≈ 1.8 V at 3.3 V) is not a problem at this operating point, since the threshold is 0.749 V and the lit level is ~1.5 V by design. There is no 5 V anywhere on the board, so nothing can put 5 V on a GPIO.

DNP options

RefPurpose
R6External gain resistor across the OPT101 feedback — fit this if you saturate, which is likely at 0.45 V/µW
R8Parallel with R1 for fine threshold trim
R7, R14Pull-ups, LM393 only
R9, D1Bring-up LED on the comparator output. D1 pin 1 = cathode (KiCad convention), so the anode faces R9 / +3V3 and the LED lights when the output goes low on light onset
R12, R13, R15Comparator B's second threshold → DI-B. Populate to time the 25 %→75 % crossing and measure the panel's transition slope in hardware, per trial
J20.1" alternative to J1, same pinout

R11 (10 k) is fitted, not DNP. With the B network unpopulated it pulls comparator B's IN+ to 3.3 V — definitively above IN−'s ~2.0 V ceiling — so that comparator parks HIGH instead of oscillating on a floating input, and DI-B carries a defined level. Re-value it into a real divider with R12 when you actually want the second threshold.

Bring-up

Test points: TP1 OPT_OUT, TP2 FILT, TP3 THRESH, TP4 CMP_OUT, TP5 GND.

  1. Cover the sensor. TP1 should read ~7.5 mV. Mid-scale or railed means the part is wrong or damaged.
  2. TP3 should read 0.749 V.
  3. Point at a white screen. If TP1 pins at ~2.0 V you are saturated — fit R6, mask down to a smaller aperture, or back off.
  4. Check for backlight PWM on the analog channel before trusting anything. A few-hundred-Hz chop cannot be filtered out without wrecking a 2 ms edge. Run the panel at 100 % brightness, where most panels stop PWM-ing. Only if you're stuck with it, raise C3 to 22 nF (720 Hz, τ = 220 µs) and accept the larger constant lag.

Schematic

photomarker.kicad_sch + schematic.pdf. ERC clean (0 violations), and verified against the board by check_netlist.py — which compares nets, refs, values, footprints and DNP flags, not just connectivity. All 12 nets match exactly; the only schematic-side extras are the OPT101's two NC pins, deliberately unconnected on both sides.

Run it before ordering and after any regeneration (exit status 0 = agreement):

bash
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/python3 check_netlist.py

It is generated by gen_schematic.py, which reads the netlist out of photomarker.kicad_pcb — so the schematic cannot silently drift from the board. Regenerate after any board change:

bash
/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/python3 gen_schematic.py

Connectivity is by net label rather than drawn wire, with components grouped by function. That is a deliberate choice for a generated schematic: label connectivity is verifiable by ERC and by netlist diff, where hand-computed wire geometry can look connected while being 0.01 mm short.

Custom symbols

KiCad ships neither part, so photomarker.kicad_sym defines both:

  • OPT101 — DIP-8, drawn as photodiode + transimpedance amp. Pins 6 and 7 are genuinely NC and carry no-connect flags.
  • TLV3202 — 3 units (A, B, power). Built on KiCad's LM2903 geometry, since the pinout is identical, but with output pins instead of open_collector.

sym-lib-table maps photomarker: to the local library, so the project opens standalone.

What the schematic caught

Drawing it found a real bug in the board: KiCad's Device:LED has pin 1 = cathode, but D1 pin 1 had been wired to the resistor from +3V3 — the indicator LED was reverse-biased. Fixed by swapping the net assignment and flipping D1. Worth remembering if you add any other polarised part.

Parts

31
QtyValueFootprintReferences
5DNPR_0805_2012MetricR6, R8, R12, R13, R15
4M3MountingHole_3.2mm_M3_PadH1, H2, H3, H4
310kR_0805_2012MetricR2, R4, R11
2100nC_0805_2012MetricC1, C2
22k2R_0805_2012MetricR7, R14
1100RR_0805_2012MetricR5
1270kR_0805_2012MetricR3
139kR_0805_2012MetricR1
13n3 C0GC_0805_2012MetricC3
1CMP_OUTTestPoint_THTPad_D1.5mm_Drill0.7mmTP4
1DNP 1kR_0805_2012MetricR9
1DNP 1x05PinHeader_1x05_P2.54mm_VerticalJ2
1DNP LEDLED_0805_2012MetricD1
1FILTTestPoint_THTPad_D1.5mm_Drill0.7mmTP2
1GNDTestPoint_THTPad_D1.5mm_Drill0.7mmTP5
1JST-PH 5JST_PH_B5B-PH-K_1x05_P2.00mm_VerticalJ1
1LM393SOIC-8_3.9x4.9mm_P1.27mmU2
1OPT101DIP-8_W7.62mmU1
1OPT_OUTTestPoint_THTPad_D1.5mm_Drill0.7mmTP1
1THRESHTestPoint_THTPad_D1.5mm_Drill0.7mmTP3

More from SheinbergLab/dserv

1
  • 2 layers75 × 55 mmPhotomarker tht, the printed circuit board in 3D

    Photomarker tht

    SheinbergLab/dserv

    Data server system for data acquisition and control

    29 parts2MIT

Similar boards

  • 2 layers37.5 × 99 mmDiy oled 3d controller, the printed circuit board in 3D

    Diy oled 3d controller

    open3doled/open-3d-oled

    If running windows 11 or 10 with DPI scaling be sure to disable it as follows. 1) Right click properties on 3dplayer.exe in the 3DPlayer folder 2) Click on "Compatability" tab then click on the button at the bottom…

    42 parts98
  • 2 layers70 × 80 mmPpg panel, the printed circuit board in 3D

    Ppg panel

    nguyenhuy0426/PPG_simulator

    The PPG Signal Simulator is a portable device that generates synthetic PPG (photoplethysmography) waveforms with physiologically accurate morphology.

    70 parts2MIT
  • 2 layers52 × 81 mmPhotodiode Led Circuit, the printed circuit board in 3D

    Photodiode Led Circuit

    AlessandroLovo/T-junction

    Analysis of data from a Microfluidic T-juction. Course of Advanced Physics Laboratory @ Università degli studi di Padova

    14 parts1
  • 4 layers72 × 44 mmDevice, the printed circuit board in 3D

    Device

    jayis1/hardware-design-lab

    Full-cycle hardware device designs — each device in its own subfolder with architecture, schematics, PCB layout, and software stack

    21 parts
  • 2 layers231.1 × 106.7 mmSnark barker, the printed circuit board in 3D

    Snark barker

    schlae/snark-barker

    A 100% compatible replica of the famed SB 1.0 sound card

    199 parts687
  • 2 layers130 × 80 mmSmu main 1, the printed circuit board in 3D

    Smu main 1

    jaromir-sukuba/J-SMU

    DIY source-measure unit

    210 parts244
  • 2 layers100 × 85 mmVNA, the printed circuit board in 3D

    VNA

    profdc9/VNA

    Vector Network Analyzer based on the STM32F103C8T6 bluepill

    178 parts93
  • 4 layers292.1 × 88.3 mmSnark barker mca, the printed circuit board in 3D

    Snark barker mca

    schlae/snark-barker-mca

    A Sound Blaster compatible sound card for Micro Channel bus computers

    177 parts69

Questions

How big is the Photomarker PCB?

It measures 50 × 34 mm and has 2 copper layers, 1.6 mm thick.

What parts does the Photomarker use?

31 parts, built around the OPT101P and LM393. 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 Photomarker KiCad files?

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

Can I use the Photomarker 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).