Quick start
- Step 1 — Load: drop your PnP file (
.mnt,.mnb,.pos, or CSV from any supported CAD tool) onto the dropzone, then Continue. Or click Load demo data to walk through with a synthetic board (5 components plus 3 fiducials). - Step 2 — Feeder Mapping (optional): for each unique Value+Package, assign a Feeder ID and nozzle. Save the mapping to JSON to reuse on future boards. Skip this step entirely on a first pass and the converter will auto-assign sequential feeder IDs in Step 3.
- Step 3 — Assign Feeders: per-placement table where mapped feeder/nozzle defaults appear. Adjust feeder, nozzle, tape pitch, height, speed, vision per part type; X/Y/rotation per individual placement; tick Skip on any placement to leave it out of the run (skipped rows are omitted from the DPV entirely).
- Step 4 — Board / Calib: set X/Y offset if your file's origin isn't the PCB's lower-left corner. Fiducial dropdowns auto-detect
FID*-style refdes, or fall back to placements whose Value/Package starts withFID. - Step 5 — Export: review the DPV preview, click Download. Copy the
.dpvfile to a USB stick and load on the CHM-T36VA. Calibrate fiducials on the machine before running.
That's the whole flow for a typical board. The rest of this help expands on each piece.
Supported file formats
Fusion 360 / EAGLE .mnt and .mnb
The .mnt / .mnb format comes from EAGLE's classic mountsmd.ulp script, which both EAGLE and Fusion 360's Electronics workspace ship with. Generate it via:
- Fusion 360 (Electronics): Utilities → Automate → Run ULP → mountsmd.ulp
- EAGLE: File → Run ULP → mountsmd.ulp from the board editor
The script writes one file per side: .mnt = top, .mnb = bottom. The column layout is fixed:
RefDes LocationX LocationY Rotation Value Package
Whitespace-delimited, no header line, comments starting with # / ; / * are stripped. The converter recognizes the extension and skips column-detection automatically.
mountsmd.ulp path instead.KiCad .pos and .csv
Generate via File → Fabrication Outputs → Component Placement (.pos) File in the PCB Editor. Both KiCad output formats are supported:
- CSV format (
.csv) — comma-separated with headersRef,Val,Package,PosX,PosY,Rot,Side. Recommended for new projects. - Plain Text / ASCII format (
.pos) — whitespace-aligned columns with metadata header lines (### Module positions,## Unit = mm) and a#-prefixed column header. The parser recognizes this format and uses it directly.
Use millimeters as the unit. Set the board origin via Place → Drill/Place File Origin at the lower-left corner of your board before exporting — otherwise placements will be relative to the page origin (typically far off the board) and you'll need a large X/Y offset on Step 4 to compensate.
EasyEDA pick-and-place CSV
Generate via File → Export → Pick and Place File (Std edition: Top Menu → Fabrication → Pick and Place File). EasyEDA exports as UTF-8 with a BOM and tab delimiters — the parser handles both transparently. The Mid X/Mid Y columns are used as the placement coords; Ref X/Y and Pad X/Y are ignored (they reference the part's library origin, not the placed centroid). Bottom-side parts are filtered out by default; change the Side dropdown on Step 1 if you need them.
Generic CSV / TXT
Any comma/tab/semicolon-delimited file with a header row works. Column detection is case-insensitive and scans for these names:
| Field | Recognized header names | Required? |
|---|---|---|
| Reference | Designator, RefDes, Reference, Ref, Name, Part, Component | Yes |
| Value | Value, Val, Comment, Description | No |
| Package | Package, Footprint, Pattern, Pkg | No |
| X coord | Mid X, X, Center X, Loc X, Pos X, PosX, Ref X | Yes |
| Y coord | Mid Y, Y, Center Y, Loc Y, Pos Y, PosY, Ref Y | Yes |
| Rotation | Rotation, Rot, Angle, Orientation, Theta | Yes |
| Side | Side, Layer, TB, Mirror | No |
| DNP | DNP, DNI, Do Not Place/Populate/Install, Populate | No |
The first data row is detected automatically — preamble lines like [COMMENT], Centroid Data for…, and [PLACEMENT] are skipped before the header is identified.
Coordinate units
The unit is read from the file whenever the file states one. Three things count as a statement, checked in order:
- A metadata line — KiCad's
## Unit = mm, Angle = deg., or anyUnit: <name>in the first 40 lines - A unit on the X/Y column header — Altium's
Center-X(mm), orMid X (mm),PosX [mil] - A unit suffix on the values — EasyEDA's
12.5mm
mm, mil/thou and in/inch/" are all recognized. A header carrying a unit is matched to its field with the annotation removed, so Center-X(mm) is found as an X column instead of going undetected.
Only when the file declares nothing does the converter fall back to the magnitude of the coordinates, measured across every row:
- Max coordinate < 13 → inches
- Max coordinate ≤ 300 → millimeters
- Max coordinate > 300 → mils (1/1000 inch)
That fallback still gets an undeclared board under about 13 mm across wrong, reading it as inches. The Step 1 summary names the unit, says where it came from, and prints the resulting board size, so you can see it before continuing. Correct it with the dropdown and the summary updates as you change it.
Feeder mapping
Step 2 shows a table with one row per unique Value+Package pair found in your file. For each, you can optionally set a Feeder ID (the station number on your machine where that reel is loaded) and a Nozzle (N1 or N2). Leave blank to skip — those parts will get auto-assigned defaults on the next step.
Why this step exists
Most physical reels on the CHM-T36VA stay in the same station across multiple boards. Once you've loaded a reel of 10k 0402 at station 5, every future board with that part should use station 5 too. The mapping step lets you record those assignments once and reuse them on every subsequent board via Save Config / Load Config.
What the mapping affects
On Step 3, every placement of a mapped part type starts with the mapped feeder ID and nozzle as its default. You can still change those defaults on Step 3 — the mapping is a starting point, not a lock. Unmapped part types get the existing auto-guess: a sequential feeder ID and a nozzle picked from the package name (small SMD → N1, larger ICs → N2).
Avoiding feeder collisions
The Step 3 auto-assigner skips any feeder ID claimed by your Step 2 mappings. So if you map 10k 0402 → 5, no unmapped group will get auto-assigned to feeder 5. This means the duplicate-feeder warning at Step 3→4 only fires for actual conflicts you created intentionally.
Save / Load Config
The buttons live on Step 2 and operate on the current mapping. Save writes only the rows you actually filled in (blank rows are not stored). Load applies a saved JSON to the current board: any Value+Package matches get the saved feeder/nozzle; unmatched entries are reported in a summary alert.
Saved configs are portable across boards: the same mapping works on any future board that includes those parts. Per-placement coordinates and rotations are not in the config — those are board-specific.
Workflow walkthrough
Step 1 — Load file
Drop or click to browse. After parsing, you'll see file stats and an "Auto-detected — override only if wrong" panel with three dropdowns and a one-line summary. The summary names the column each field mapped to, then states which unit the coordinates were read as and the board that produces: overall size, plus the X and Y range. Most boards just need Continue.
When to touch the overrides:
- Heuristic picked the wrong units (small mil-units board misread as mm)
- File has both top and bottom parts and you want both — change Side filter to "All rows"
- You want to include parts marked DNP — set DNP filter to "Include them"
Step 2 — Feeder Mapping (optional)
One row per unique Value+Package pair, with two optional inputs: a Feeder ID and a Nozzle toggle. See the Feeder mapping section above for the full rationale.
The toolbar has three buttons:
- ↓ Save config — write the current mapping to a JSON file (only the rows you've filled in are stored)
- ↑ Load config — apply a saved JSON to the current board's mapping table (case-insensitive Value+Package match)
- Clear all — wipe the current mapping (useful before loading a different config from scratch)
The Feeder ID input has a color-coded left edge so you can see at a glance which entries share a feeder number — the color is computed from the ID, so same number = same color across the whole table (and on Step 3).
The table paginates at 20 rows per page for large projects. Editing a row on a non-first page commits the change in place without resetting your position.
Skip this step entirely on a first pass — the mapping is optional, and unmapped part types just get auto-assigned defaults on Step 3.
Step 3 — Assign Feeders
The table shows one row per placement on your board. Identical part types share most settings — editing them on one row updates every row of that part type, with sibling inputs visually synced. Editable per row:
- X / Y — placement coordinates in mm (per-placement)
- Rotation — placement angle in degrees, CCW positive (per-placement)
- Skip — flags this individual placement as "don't place" — skipped rows are omitted entirely from the DPV output, not flagged for skip (the machine's documented skip flag is unreliable across firmware versions). Per-placement; ticking on R1 doesn't affect R2.
- Feeder — station ID where the reel for this part type is loaded (1–99) — shared across same-type parts
- Nozzle — N1 (left) for small parts, N2 (right) for larger ones — shared
- Tape pitch — physical reel spacing in mm; see tape pitch reference — shared
- Height — physical thickness of the part (mm) — shared
- Speed — 0 means use machine default; raise above 0 only if the part needs slower handling — shared
- Vision — on for ICs and fine-pitch; can turn off for very small passives — shared
The Feeder column has color-coded left edges — same color = same feeder ID, computed from a golden-angle hue formula so even adjacent IDs (5, 6, 7) are visually distinct. Same color carries over from Step 2's mapping table.
Defaults: feeder/nozzle come from your Step 2 mapping if set; otherwise auto-assigned. Tape pitch, height, and nozzle (when not mapped) are guessed from the package name. The auto-assigner skips feeder IDs claimed by mappings, so no collisions sneak in.
Click RefDes, Value, or Package column headers to sort. Click again to reverse, third time to return to insertion order. RefDes uses natural sort (R1 < R2 < R10). X / Y / Rotation columns are not sortable. Skipped placements always partition to the end of the table regardless of sort.
The table is paged at 20 rows per page. Use Prev / Next or the jump-to-page input. Sorting jumps you to page 1 with the new top of the order. A subtle background tint clusters same-part-type rows visually even when sorted by RefDes.
Step 4 — Board / Calib
Set the X/Y offset if your file's origin isn't the PCB's lower-left corner; see board origin for details.
Fiducials: three cards (UL, LR, LL), each with a dropdown listing every RefDes plus (none) and (custom — type X/Y manually). Selecting a RefDes auto-fills X/Y from that placement with the board offset already applied; the X/Y inputs become read-only. (custom) lets you type values manually. (none) zeroes the slot.
The converter auto-detects fiducials on first arrival at Step 4 and shows an auto-detected badge next to each card's label until you change the selection. See fiducials & calibration for the detection rules.
Step 4b — IC tray geometry
If any part sits on a station in the 80–99 range, a card appears for it below the fiducials with six fields: first and last cavity centre, columns, rows and start cavity. A live readout compares cavities against the parts that need them. The block stays hidden when no tray station is in use. See IC trays for what each field means.
Step 5 — Review & Export
The DPV preview shows exactly what will be written. Filename is editable. Download saves a plain-text .dpv file you can copy to a USB stick and load on the CHM-T36VA.
If your job has fewer than 2 active placements (after skip-filtering), an amber notice appears above the preview explaining that phantom DUMMY rows were added — the machine requires at least 2 EComponent rows for fiducial calibration to work.
Feeders & nozzles
CHM-T36VA station ID ranges
| Range | Type | Notes |
|---|---|---|
| 1–29 | Reel feeders | Standard SMD tape reels — most parts go here |
| 30–59 | — | Not used / reserved |
| 60–74 | Front IC trays | For tubed ICs and small trays at the front of the machine |
| 75–79 | — | Not used / reserved |
| 80–99 | IC trays | For matrix-tray ICs (waffle pack) |
Use any unused number — the converter validates that each non-skipped part group has a unique feeder ID and warns about duplicates before generating the DPV. Stations in the 80–99 range also need a tray definition; see IC trays.
Nozzle selection
The CHM-T36VA has two nozzles mounted side by side, named N1 (left) and N2 (right). Each can be a different physical nozzle (CN040, CN065, CN140, etc.) — you switch nozzles on the machine when changing what's mounted.
- N1 (left) — typically a smaller nozzle for 0201, 0402, 0603, SOT-23. Default for passives.
- N2 (right) — typically a larger nozzle for SOIC, QFP, QFN, BGA, electrolytics. Default for ICs.
The converter auto-picks based on package name. If you only have nozzles loaded for one head and want everything on N1, edit each row or sort by Package and bulk-edit (one row at a time — bulk editing isn't a feature yet).
Tape pitch reference
Tape pitch is the distance the reel advances between picks. It must match the physical spacing of parts on your reel — too short picks the same pocket twice; too long skips parts.
| Pitch (mm) | Typical packages | Reel widths |
|---|---|---|
| 2 | 0201 | 8 mm |
| 4 | 0402, 0603, 0805, 1206, SOT-23, SC-70/75 | 8 mm |
| 8 | 1210, SOT-223, SOIC-8 | 8 mm or 12 mm |
| 12 | SOIC, TSSOP, small QFN | 12 mm |
| 16 | QFP, larger QFN, BGA | 16 mm or 24 mm |
| 24 | Large ICs, connectors, modules | 24 mm or 32 mm |
The DPV format calls this field "FeedRates" but it's a single value, not a rate.
Board origin & rotation
The CHM-T36VA places parts using coordinates relative to the PCB's lower-left corner. After fiducial calibration, the machine knows where that corner is in machine coordinates and translates accordingly.
Most modern CAD tools export with the lower-left convention, so X/Y offsets of 0,0 work in most cases.
You'll need to set offsets when:
- Your design uses board-center origin instead of corner origin
- Negative X or Y values appear in the placements (the machine's origin must be set so all placements are positive)
- You're panelizing one-up boards into a larger panel and want to shift the placements into the panel's coordinate system
Quick test: after Step 3 the table displays placements in the order they'll be made. If the smallest X/Y values are near zero — good. If they're at, say, X = −18 to +18 — the file uses a centered origin and you need an offset of about +18 mm.
Global rotation offset (Step 4) rotates every placement by the same angle. Useful if you want to run the same DPV on a board mounted in a different orientation; rare otherwise. For individual reel-vs-footprint orientation mismatches, edit the affected placements' Rotation column directly on Step 3.
Fiducials & calibration
Fiducials are reference marks on the PCB that the machine's camera uses to figure out exactly where your board is sitting on the bed. The CHM-T36VA expects three:
- UL — upper-left fiducial
- LR — lower-right fiducial
- LL — lower-left fiducial
The dropdown picker (Step 4)
Each fiducial has its own card on Step 4 with a dropdown that lists every RefDes in your file plus two special options:
- (none) — leaves X/Y at zero. Use this if your file has no fiducials at all and you'll calibrate entirely on the machine.
- (custom) — enables manual X/Y entry. Use this if you have fiducial coordinates from another source (e.g. a Gerber file) but they're not in the placement file.
- Any RefDes — auto-fills the X/Y display from that placement's coordinates, with the board X/Y offset already applied. The X/Y inputs are read-only when a RefDes is selected; selecting a different RefDes or
(custom)changes that.
Auto-detection
If your file has refdes matching FID1 / FID2 / FID3 (also MARK* or F1/F2/F3), the converter pre-selects them as UL/LR/LL on first arrival at Step 4 and shows a small auto-detected badge next to each card's label. The badge disappears once you change the selection.
If no refdes matches that pattern, the converter falls back to checking the Value and Package columns — any placement whose Value or Package starts with FID (case-insensitive: FIDUCIAL, fid-1mm, FID-2MM, etc.) is treated as a fiducial candidate. This catches CAD libraries that mark fiducials by component type instead of refdes convention. Refdes matches always win when both kinds of hints are present in the same file.
Auto-detection won't override choices you've already made — if you go back and forth between steps, your manual selections stick.
Coordinates & the X/Y offset
Coordinates flowing into the DPV's CalibPoint section are the placement's raw X/Y plus the board offset above. Changing the offset live-updates the displayed fiducial coordinates so what you see on Step 4 is what gets written.
IC trays
Two station ranges hold trays, and they work differently.
60–74 — the fixed front tray. Built into the machine, one part per station ID. A station ID here is a single pocket, not a grid, and the machine already knows where its own pockets are. Nothing extra goes in the file: the Station row is the whole story. Parts on these stations export completely with no further setup.
80–99 — trays you supply. You position these yourself, so the machine cannot know their layout. One station ID is one whole tray, a grid of cavities, written to the DPV's ICTray table from the cards on Step 4.
| Field on the card | DPV column | Meaning |
|---|---|---|
| First cavity X / Y | CenterX, CenterY | Centre of cavity 0 |
| Last cavity X / Y | IntervalX, IntervalY | Centre of the last cavity |
| Columns / Rows | NumX, NumY | Grid size |
| Start cavity | Start | First cavity to pick from — row major, left to right, bottom to top |
IntervalX and IntervalY hold the last cavity centre, not a spacing between cavities. The machine interpolates the grid between the first and last centres. The card labels say first and last to keep this straight.Tray values are machine coordinates. The board X/Y offset on Step 4 moves placements and fiducials; it deliberately leaves tray coordinates alone.
As with fiducials, what gets written is a starting hint — calibrate on the machine under Run → Edit → IC Trays → First/Last Position. One physical tray can also be split into several virtual trays with separate station IDs, so more than one card may describe one piece of plastic.
Before export the converter checks each tray. A start cavity outside the grid blocks the export. A tray with no positions set, a tray whose first and last cavity are the same point, or a tray with fewer usable cavities than parts to pick all raise a warning you can accept or go back and fix.
Tape pitch is meaningless on any tray station, front or rear, so Step 3 disables that input for those rows rather than showing a guess the machine ignores.
DPV file format
The .dpv file is plain text, CRLF line endings, structured as labeled sections. The CHM-T36VA reads it from a USB stick. Generated files have these sections in order:
separated+ header (FILE, PCBFILE, DATE, TIME, PANELYPE)Stationrows — one per non-skipped part groupPanel_Array— single board (1×1) by defaultEComponentrows — one per placement (RefDes-level)ICTrayrows — one per tray station in 80–99, omitted entirely when none is usedPcbCalib— placeholder (set on machine)CalibPointrows — three fiducial entriesCalibFator— placeholder (computed by machine)
Coordinates are written with 2 decimal places (the machine truncates further digits anyway). Angles are normalized to (−180°, 180°].
DUMMY rows to satisfy this requirement. Step 5 displays a notice when this happens so you don't get confused by the extra rows.Column → DPV field map
What each column in the Assign Feeders table corresponds to in the generated DPV file:
| UI column | DPV section | DPV field |
|---|---|---|
| RefDes | EComponent | Explain |
| Value + Package | Station, EComponent | Note |
| X (mm) | EComponent | DeltX (+ board X offset) |
| Y (mm) | EComponent | DeltY (+ board Y offset) |
| Rotation (°) | EComponent | Angle (+ global rotation offset, normalized to ±180°) |
| Feeder | Station, EComponent | ID, STNo. |
| Nozzle (N1/N2) | EComponent | PHead |
| Tape pitch | Station | FeedRates |
| Height | Station, EComponent | Height |
| Speed | Station, EComponent | Speed |
| Vision | Station, EComponent | Status (bit 4) |
| Skip | (EComponent omitted) | Skipped placements aren't written to the DPV at all |
Saving feeder configs
Saved configs carry IC tray geometry alongside the feeder and nozzle mapping. Tray layout describes your machine rather than your board, so every tray the tool knows about is written, not just the ones the current board uses. Configs saved before tray support still load; they simply carry no trays.
On Step 2, the ↓ Save config button exports your current Value+Package → Feeder/Nozzle mapping to a JSON file. The ↑ Load config button applies a saved JSON to the current board's mapping table.
What's stored
Only feeder ID and nozzle, keyed by Value+Package. Tape pitch, height, speed, and vision are not saved — they're auto-guessed from package names on every board, which is the right behavior since they depend on the part footprint, not the project. Per-placement coordinates and rotations are also not stored — those are board-specific.
How matching works on Load
- If the new board has a part type with the same Value+Package (case-insensitive), the saved feeder/nozzle is applied to its mapping row.
- If the new board has a part type not in the config, its mapping row stays blank (and Step 3 will auto-assign a feeder when you continue).
- If the config has entries for parts not on the new board, they're listed as "unused" in the summary alert that pops up after Load.
Old config compatibility
Configs saved by older versions of this tool included tape pitch, height, speed, vision, and skip — those fields are silently ignored when loading. The feeder ID and nozzle still apply correctly.
Workflow suggestion
Tune your feeder assignments carefully on your first board (in Step 2). Save the config. On every subsequent board with the same physical reel layout, load the config first and tweak only the parts you've added. Per-placement rotation tweaks (for reel-vs-footprint orientation fixes) can be applied directly on Step 3 — but those are placement-specific, so if every R1/R2/R3 of a reel needs the same +90° fix, set it once in your CAD library footprint instead so it comes through correctly from the .mnt.
Troubleshooting
"Couldn't find required column(s)"
Auto-detection couldn't identify a required column (RefDes, X, Y, or Rotation) from the header row. Most common causes:
- File has no header row — open in a text editor and check.
- Headers use unusual names — supported names are listed in file formats.
- File has a long preamble that's confusing the header detector. The detector scans the first 15 non-comment lines and picks the most header-like row, but unusual structures can trip it.
"After filtering, 0 placements remain"
The diagnostic alert breaks down where every row went. Most common causes:
- Side filter mismatch — your file uses Side values like
F.Cuor unusual numbers. Set Side filter to "All rows" or set the Side column to "none". - All rows have non-numeric coordinates — file might have units appended (
"12.5mm"); the parser strips common unit suffixes but not all.
Rotations are off by 90° or 180° on certain parts
Almost always a reel-vs-footprint orientation mismatch. Two ways to fix:
- Best (permanent): fix the footprint in your CAD library so future boards come through correctly.
- Quick (per-board): sort the table by Value or Package, edit the Rotation column on each affected row to add 90 / 180 / -90 as needed. Tedious for many placements, fine for a few.
The machine reports placements off the board
Usually a coordinate origin issue. Check Step 4's X/Y offset. If your CAD file uses board-center origin, the offset should be about (half board width, half board height).
KiCad placements are wildly off (thousands of mm)
You forgot to set Place → Drill/Place File Origin before exporting. KiCad uses the page origin (top-left of the sheet) by default, which is typically ~150mm to the upper-left of your board. Re-export after setting the origin to your board's lower-left corner.
"Duplicate feeder IDs assigned"
You've assigned the same feeder number to two different part groups. The DPV will still be generated but the machine will physically only have one reel at that station — the second part group will pick the wrong reel. Re-assign one of them to an unused feeder ID.
Splash screen sticks around forever
The splash auto-fades after 5 seconds. If it doesn't, JavaScript may have errored before the timer fired — open the browser console (F12) and check for errors. Hard-refresh the page (Ctrl+Shift+R / Cmd+Shift+R) if a previous load left things in a weird state.
Tips & shortcuts
- Hover any ⓘ icon in column headers for a per-field reference card.
- Tab moves between input fields on Step 3 — useful for quick keyboard entry of feeder IDs down a column.
- Click "Load demo data" on Step 1 to walk through the workflow without your own file. The demo includes 3 fiducials so you can preview Step 4's auto-detection.
- Color-coded feeders: the Feeder ID column on Steps 2 and 3 has a left-edge color stripe tied to the ID number. Same number = same color, so you can scan a long list for duplicates or sanity-check reel groupings at a glance.
- Sort by Package on Step 3 to group similar parts together — useful for spotting inconsistencies in tape pitch or nozzle across rows of the same package.
- Pagination: Steps 2 and 3 show 20 rows per page. Sorting always jumps to page 1 so the top of the new ordering is visible.
- Skipped placements always partition to the end of the Step 3 table regardless of sort order. Skip is per-placement (per-row), not per-part-type.
- Auto-detected fiducials: if your file has
FID*-named refdes (or values/packages starting with "FID"), Step 4 picks three automatically and shows an auto-detected badge on each card until you change the selection. - Skip Step 2 entirely on a first pass — feeder mapping is optional. The auto-assigner on Step 3 will give every part type a unique feeder ID.
- Esc closes this help panel.
Privacy & how this runs
This is a single static HTML page. Open it in any browser. Everything runs locally:
- No file you load is uploaded anywhere.
- No analytics, no telemetry, no remote calls.
- The page only fetches Google Fonts on load (you can replace those with system fonts by editing the HTML).
- Your saved feeder config JSON files are also entirely local — nothing leaves your machine.
You can run this offline. Save the HTML file to disk and open it directly. If your browser blocks fonts when offline, the page still works — it just falls back to system fonts.