Skip to content

Releases: medinstech/perfboard-studio

Perfboard Studio v0.19.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 15:08

Added

  • A solderless breadboard is a board type. File ▸ Board Setup ▸ Type ▸ Breadboard, in
    the three sizes they are sold in: full (830 points), half (400) and mini (170, no rails).
    The pattern is the real one -- five holes to a clip up each half of a column, a groove down
    the middle for a DIP to straddle, and on the larger two a + and a − rail along each long
    edge -- and it is the board's shape rather than anything new in the file, so a .perf from
    an earlier release opens exactly as it did. Two parts of different nets in one clip are a
    short, and LVS says so; a pin where the board has no hole is a DRC error.

  • Every hole on a breadboard is named as the board prints it: e12, the row letter and
    then the column, and T+12 or B-3 for a hole on a rail. The guide, DRC, LVS, the
    router's explanations, the window and the MCP server all say it that way, and an agent
    addresses a breadboard's holes the same way.

  • Place on the Board and Autoroute work on one. The placer keeps two nets out of one
    clip, puts a chip across the groove because nowhere else separates its pins, and keeps
    everything but ground off a − rail and everything but power off a + rail. Autoroute plans
    jumpers into free holes -- one lead to a hole -- runs ground and power down the rails with a
    short jumper from each clip that needs them, bridges a rail pair once at the end of the
    board when both halves carry a net, and reports anything it cannot do. All six examples
    place and wire on a full-size breadboard with LVS clean.

  • It looks like one, in both views and in STEP: white plastic with square openings, the
    groove, a blue line beside each ground rail and a red one beside each power rail, and the
    column numbers and row letters it prints. Leads go into the plastic and stop there; nothing
    is soldered underneath.

  • Its build guide is a building guide. No iron, no solder and no flux on the bench --
    unless a chip has to go onto its adapter first -- and solid-core wire, because a stranded
    end frays in a clip. The jumpers go in first, flat on the plastic, cut to their length and
    two 6 mm stripped ends; then the flat parts; then each IC across the groove, pin 1 named by
    the hole; then everything else, shortest first. Each continuity check comes once the parts
    it probes are in. In Turkish too.

  • File ▸ New Board from This Design takes the circuit to another board as a new
    document -- every part back in the design, the nets and the schematic carried, nothing of
    the old board's -- and asks which board to put it on. A circuit tried on a breadboard goes
    on to perfboard this way, and the breadboard's own file stays as it was.


Windows - PerfboardStudio_..._Setup.exe. It is unsigned, so SmartScreen will
warn on first run: More info -> Run anyway. A signed build is planned.

Linux - perfboard-studio-...-x86_64.AppImage. chmod +x and run it; it needs
glibc 2.35 or newer. If it will not start, the machine has no FUSE 2: install
libfuse2, or run the file with --appimage-extract-and-run, which unpacks it
instead of mounting it.

macOS - perfboard-studio-...-arm64.dmg, Apple silicon. Drag it to Applications,
then run this before opening it:

xattr -dr com.apple.quarantine /Applications/PerfboardStudio.app

It is signed ad-hoc but not notarized, so Gatekeeper blocks the first launch.
On macOS 15 and later the dialog it raises defaults to Move to Trash, which
deletes the install. Clearing the flag first avoids the dialog entirely. On an
Intel Mac, install from source.

Anywhere with Python 3.12+: pip install -U perfboard-studio, then perfboard-studio.
Same release, no installer and no SmartScreen warning; Qt and VTK are most of a
400 MB download the first time.

Checking your download - SHA256SUMS carries the SHA-256 of all three
files. sha256sum -c SHA256SUMS on Linux, shasum -a 256 -c SHA256SUMS on
macOS, Get-FileHash <file> in PowerShell. Perfboard Studio does this for you when it
fetches an update itself: Help - Check for Updates. It proves the file
arrived intact, not who built it - that second claim needs the code signing
this project has not bought yet.

This is pre-alpha software. Nobody has yet built a real board by following a
generated guide - check every measurement against the part in your hand.

Perfboard Studio v0.18.0

Choose a tag to compare

@github-actions github-actions released this 16 Oct 12:01

Added

  • A part on the panel is wired to the board, not placed on it. A pot, a jack, a
    footswitch, a DC socket or a bezel LED that lives in the enclosure is taken off the board
    with Mount on the Panel, on its right-click menu on the board or on the schematic. On
    the board it becomes the row of pads its wires land in -- where its pins were when they
    stood in a row, so the copper already laid still reaches them -- and it keeps everything its
    package used to say: an LED its A and K, a pot its symbol on the sheet. One undo step takes
    it back. Such a part can also be asked for directly as wire-<n>, with -p<step> for pads
    further apart and -l<mm> for how long each wire is cut, or from Custom Part; KiCad's
    SolderWire and SolderWirePad footprints import as one, and a KiCad potentiometer
    symbol on one stays a potentiometer.

  • The build guide wires it in with the long wires (phase 7): which pad goes to which lug
    of the part, named as the part names it, and over which edge of the board the wires leave.
    Every wire is on the cut list, in its net's colour and gauge, cut to the length the part
    gives or marked "cut to fit"; the bench list counts them with the hookup wire. A continuity
    check on a net that reaches the part waits until its wires are in, rather than failing
    before they are.

  • Both views draw the wires leaving, and the same wires. Each runs from its pad over the
    nearest edge in its net's colour, dressed like an insulated wire on the board, with its
    tinned end showing at the pad; in 2D it fades out past the edge on its way to the panel, and
    in 3D it rises out of the pad and drops away past the edge. A row of pads pointing at its
    edge is laid in lanes side by side, rather than every wire on top of the one in front.

  • Every such wire says where it goes. It carries a marker just past the edge, as a
    harness wire does -- "RV1·2", or "J1·T" once the jack's leads are named -- in both views:
    printed on the wire in 2D, on a white sleeve in 3D. The part's tooltip lists each wire with
    its pad, the lead at the other end, its net and its colour, and the guide's step says the
    same of each one: "H24 to RV1 pin 1 — GND, black wire". A part off the board no longer
    prints its pin names beside its pads, where they lay on top of its own wires, and other
    parts' names stop short of those wires.

  • Two more symbols a part can declare: a potentiometer, and an LED once its leads are
    named A and K. In the part's properties, and as potentiometer and led for an agent.

  • A surface-mount chip goes on the board on a DIP adapter. A SOIC, SSOP, TSSOP or MSOP
    is soldered onto a small adapter board that stands on two rows of header pins, numbered as
    the DIP of the same pin count -- so the netlist drawn for the SOIC lands on the board
    without a pin moving. Asked for as adp-soic-8, adp-tssop-20 and so on, or from
    Custom Part. The board is the size the makers sell (rows 0.3 inch apart for eight pins
    and 0.6 above, half a pitch of board round the holes), and the part is as tall as the chip
    on it or the header's tails, whichever stands higher. Both views draw the chip on its
    adapter, legs and pin-1 dot included.

  • A KiCad netlist's SOIC, SSOP, TSSOP and MSOP footprints import on an adapter instead
    of being refused as surface-mount, and a part the catalog knows keeps its pin names in the
    smaller package: an LM358 in a SOIC-8 is the catalog's LM358. A footprint with an exposed
    pad, a SOT-23 or a QFN is still refused, because no DIP adapter brings it out pin for pin.

  • Three more parts in the catalog: the DHT11 and DHT22 humidity and temperature
    sensors, pinned from Aosong's datasheets, and Pololu's A4988 stepper motor driver carrier.
    The carrier is drawn as what is on it in both views -- the chip, the sense resistors, the
    capacitor and the current-limit trimmer, from Pololu's own photograph -- but only for a
    part named Pololu: the StepStick boards sold as "A4988" share its pins and not its parts,
    and keep the plain block.

  • Pololu's DRV8825 carrier and the Seeed XIAO ESP32C3 in the catalog, each drawn as what
    is on it: the DRV8825's chip across the lower half of its purple board, the XIAO's USB-C
    socket, shield can, buttons and antenna socket -- placed from Seeed's own board file. On
    these two, and on the A4988, the real parts stand where the names beside the pins would
    go (their makers print the names on the back), so the names are printed over the parts on
    the same dark tag the names on the board wear, and every part is where it really is.

  • The build guide has the chips soldered onto their adapters first, in phase 0 while the
    bench is clear and the legs can still be reached, and then fits each adapter as the DIP it
    stands in for: a socket in phase 2 if there is one, the adapter with the other ICs at the
    end. The bench list counts the header pins and asks for a magnifier.

Changed

  • The phenolic board is a quieter orange. Still the hue of the boards in the photographs
    it was measured from, at less saturation: a whole board of flat orange was the loudest thing
    in the window, and an orange film capacitor all but disappeared into it.
  • update_part takes off_board, which is Mount on the Panel for an agent, on the board
    or in the design. Any other new footprint for a part already on the board is still refused.

Windows - PerfboardStudio_..._Setup.exe. It is unsigned, so SmartScreen will
warn on first run: More info -> Run anyway. A signed build is planned.

Linux - perfboard-studio-...-x86_64.AppImage. chmod +x and run it; it needs
glibc 2.35 or newer. If it will not start, the machine has no FUSE 2: install
libfuse2, or run the file with --appimage-extract-and-run, which unpacks it
instead of mounting it.

macOS - perfboard-studio-...-arm64.dmg, Apple silicon. Drag it to Applications,
then run this before opening it:

xattr -dr com.apple.quarantine /Applications/PerfboardStudio.app

It is signed ad-hoc but not notarized, so Gatekeeper blocks the first launch.
On macOS 15 and later the dialog it raises defaults to Move to Trash, which
deletes the install. Clearing the flag first avoids the dialog entirely. On an
Intel Mac, install from source.

Anywhere with Python 3.12+: pip install -U perfboard-studio, then perfboard-studio.
Same release, no installer and no SmartScreen warning; Qt and VTK are most of a
400 MB download the first time.

Checking your download - SHA256SUMS carries the SHA-256 of all three
files. sha256sum -c SHA256SUMS on Linux, shasum -a 256 -c SHA256SUMS on
macOS, Get-FileHash <file> in PowerShell. Perfboard Studio does this for you when it
fetches an update itself: Help - Check for Updates. It proves the file
arrived intact, not who built it - that second claim needs the code signing
this project has not bought yet.

This is pre-alpha software. Nobody has yet built a real board by following a
generated guide - check every measurement against the part in your hand.

Perfboard Studio v0.17.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 13:45

Added

  • The board view draws a module as what is on it too, from above, for every module the
    3D view knows: the WROOM's can and antenna, the Nano's chip on its corner, the USB socket,
    the buttons, the cans of a buck module. The dark block across the middle said nothing about
    which way round a module was -- an ESP32 devkit's antenna end and its USB end looked the
    same -- and the pin names stopped short of parts this view did not show; now they stop at
    parts both views show, in the same colours.

  • A module's board is the colour its maker makes it: a Raspberry Pi Pico is green and the
    Espressif devkits black, in the board view, the 3D view and the STEP export alike. Every
    other module keeps the blue most of them are made on.

  • The build guide keeps your place. Each step in the Build Guide panel has a tick, and a
    ticked step is remembered for that board: the phase headings and the summary count what
    is done, and Next Step to Do picks the first step without a tick -- shown on the
    board, and in 3D when the 3D view is open -- which is where somebody coming back to the
    bench left off. The ticks live in the application's settings, not in the board file, so
    ticking one off does not mark the board modified or join the undo stack; a board saved
    under a new name takes them with it, and Clear Progress takes them all off, asking
    first.

  • A click in the 3D view selects what it lands on. A part clicked there is selected on
    the board, which scrolls to it, and on the schematic, and the Build Guide goes to the step
    that fits it; a wire or a solder run clicked lights its net everywhere, as clicking a wire
    on the schematic does; a click on the bare board puts the selection down. What is selected
    anywhere -- on the board, on the schematic, in the Nets panel -- is tinted in 3D, so the
    three views side by side show one selection. Dragging still turns the camera: only a
    press and release in the same place counts as a click.

  • The 3D view steps through the build one step at a time, as well as playing it. Two
    arrows either side of Play go back and forward a step -- and so do the left and right arrow
    keys while the 3D view has the focus (only then, because on the board they nudge parts).
    Playing is for watching the build go by; somebody following it at the bench wants the next
    step when they have done this one, and dragging the slider a pixel at a time on a 40-step
    board was the only way to ask for it. A step asked for stops the playing, and the Build
    Guide beside the view moves to the same step, as the view already followed a step picked
    in the guide.

Changed

  • Board, Schematic and 3D stand side by side. The 3D view used to open split off to the
    right of the board as a strip about 190 px wide -- it is shut on every start, so the
    window's opening proportions never reached it -- with the build guide stacked behind it
    as a tab, both their names cut short. Now a view opened takes its place beside the others
    and the middle is shared out equally between them; one closed gives its room back. The
    window opens on the board, the schematic and the 3D view come up beside it when they are
    asked for, and the build guide stands down the right, given room to be read when it opens.
    Because this is a new opening layout, a panel arrangement saved by an earlier version is
    set aside once and the window opens on the new one.
  • The Board, Schematic, 3D and Guide buttons are at the start of the toolbar, as
    switches.
    They sat at the far end of the row, where they read as one more tool rather
    than as what is on screen; now each opens or closes its panel and is lit while it is
    open. Ctrl+1 to Ctrl+4 still only ever bring a view forward.
  • The 3D view carries its own tools. Exploded View and Reset Camera are on a bar across
    the top of the 3D panel, as the schematic panel carries its own; they lived in the View
    menu, three menus away from the view they work on, and they are still there too.
  • The Turkish interface calls the 3D view one thing. The toolbar button, the workflow
    bar and four tooltips said "3B" while every menu, dialog and the README said "3D"; it is
    "3D" throughout now.
  • An LM2596 buck module and an SN65HVD230 CAN breakout are drawn as what is on them. A
    module's id carries its board and the height of its tallest part and nothing else, so in
    3D every module was its blue board with one dark block standing on it. A module whose value
    names one of these two -- LM2596, SN65HVD230, VP230, CJMCU-230 -- now shows its
    parts at their datasheet sizes: the buck its two cans, the D2PAK regulator with its legs,
    the shielded inductor, the Schottky diode and the blue multi-turn trimmer with its brass
    screw; the breakout its SO-8 chip with its legs and marking, its 0805 resistors and
    capacitors and its silkscreen. The layout turns with the part and follows the pins' names
    (an LM2596 described with IN on the right has its regulator on the right), stays on the
    module's own board and clear of the pin names printed on it, and no part stands taller
    than the id says -- the height DRC measures. A value nobody wrote a layout for, or a board
    of another size, keeps the block, and the STEP export is still the envelope. Every module
    also shows the tinned pad each of its pins comes up through.
  • The five modules in the catalog are drawn as what is on them too -- the ones most
    boards will carry. The ESP32-DevKitC is its WROOM-32 with the shield can and the antenna
    past the board, the regulator, the USB bridge, EN and Boot either side of the micro-USB
    socket; the ESP32-C3-DevKitM-1 its C3-MINI-1, the RGB LED and Boot and RST; the Arduino
    Nano its ATmega328P turned on its corner, the reset button, the four LEDs, the mini-USB
    socket and the unfitted ICSP holes; the Raspberry Pi Pico its RP2040, the flash and
    crystal, BOOTSEL and the green LED; the WEMOS D1 mini its ESP-12F and the reset button in
    its side. Positions come from the makers' own drawings -- Espressif's dimension drawings,
    Arduino's datasheet -- and from KiCad's models of the Pico, the D1 mini and the radio
    modules, measured rather than eyeballed. A module described with its pins the other way
    round is turned by their names, so the USB socket stays at the USB end, and a Nano Every,
    a Pico W or an ESP32-S3 DevKitC on the same footprint keeps the block rather than being
    drawn as a board it is not. The README's close-up of nano-relay is redrawn, with the
    Nano on it.
  • A module's pin names stop at the first part standing in their way, in both views. A
    WROOM can is 18 mm wide between pin rows 25.4 mm apart, so no fixed strip beside the pins
    could be kept clear on a real devkit; the names now run until they meet a part, which is
    how the module's own silkscreen is printed, and every layout leaves each name room to be
    read. Where a real board puts a small part closer to its pins than that, the part is drawn
    a fraction of a millimetre in, and the layout says which. A module drawn as the block
    prints its names exactly as before.
  • A vertical terminal is drawn as KiCad's header with a screw plug standing in it. It was
    one green block with the wire openings and the screw heads side by side on its top, which
    is no part anybody sells. The header is now KiCad's own Phoenix MSTBVA model -- the open
    pocket, the locking lip and its notches, the ends past the pins -- cut into ways like the
    side-entry block, so a header of any length is drawn. The plug is drawn from Phoenix's MSTB
    2,5/..-ST-5,08 sizes and stands IN it: its foot down in the pocket, its body resting on
    the rim with no gap between. On a vertical header the plug stands on end, so the wires go
    in from above -- each entry a real hole with a funnelled mouth and the clamp's metal cage
    down in it, straight over its pin as the 2D view draws it -- and the screws are in its
    side, slotted heads in round pockets, on the face a side-entry terminal's mouth would be
    on. Each way is its own cap with a groove between, the back carries grip ribs, and the
    edges are broken. The nylon and the metal are the side-entry block's, so the two kinds
    look like one family. The plug is narrower than Phoenix's 15 mm so it stays inside the
    footprint's 12 mm, which DRC and the placer measure; neither moved.

Windows - PerfboardStudio_..._Setup.exe. It is unsigned, so SmartScreen will
warn on first run: More info -> Run anyway. A signed build is planned.

Linux - perfboard-studio-...-x86_64.AppImage. chmod +x and run it; it needs
glibc 2.35 or newer. If it will not start, the machine has no FUSE 2: install
libfuse2, or run the file with --appimage-extract-and-run, which unpacks it
instead of mounting it.

macOS - perfboard-studio-...-arm64.dmg, Apple silicon. Drag it to Applications,
then run this before opening it:

xattr -dr com.apple.quarantine /Applications/PerfboardStudio.app

It is signed ad-hoc but not notarized, so Gatekeeper blocks the first launch.
On macOS 15 and later the dialog it raises defaults to Move to Trash, which
deletes the install. Clearing the flag first avoids the dialog entirely. On an
Intel Mac, install from source.

Anywhere with Python 3.12+: pip install -U perfboard-studio, then perfboard-studio.
Same release, no installer and no SmartScreen warning; Qt and VTK are most of a
400 MB download the first time.

Checking your download - SHA256SUMS carries the SHA-256 of all three
files. sha256sum -c SHA256SUMS on Linux, shasum -a 256 -c SHA256SUMS on
macOS, Get-FileHash <file> in PowerShell. Perfboard Studio does this for you when it
fetches an update itself: Help - Check for Updates. It proves the file
arrived intact, not who built it - that second claim ...

Read more

Perfboard Studio v0.16.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 14:23

Added

  • The board leaves as a STEP model, to draw its enclosure round. File ▸ Export 3D
    Model (STEP)…
    writes the finished board as solids a mechanical CAD program can measure
    and cut a box round: the board at its real size with every drilled hole and mounting bore
    through it, every part as the room it takes -- the very outline and height DRC's
    overhang and too-tall rules measure, a cylinder for a can, a barrel lying along its leads
    for a resistor -- every lead down through its hole and a millimetre past the solder
    side, and every wire along its path on the face it is laid on, as thick as the gauge the
    cut list prints plus its sleeve, lifted over whatever it crosses as the 3D view lifts it.
    Each part is its own named component (Board, R1, U1..., and Wires) in the colour the 3D
    view gives it. Written by the application itself (ISO 10303-21, AP214), so it needs no
    graphics driver and no new dependency; checked against OpenCASCADE, the kernel FreeCAD
    and KiCad read STEP with. A project save writes -board.step beside the other outputs,
    and the headless run writes board.step. Copper and solder traces are left out, as
    KiCad's own STEP export leaves copper out by default: an enclosure needs the room, not
    the solder.
  • export_step, the MCP server's 54th tool, writes the same STEP model for an agent:
    asked to design the case, or only whether the board fits the one it has, it can now hand
    the board to the program the case is drawn in. It takes a file path and is refused
    without one, like every tool that writes, and needs neither Qt nor GL.

Windows - PerfboardStudio_..._Setup.exe. It is unsigned, so SmartScreen will
warn on first run: More info -> Run anyway. A signed build is planned.

Linux - perfboard-studio-...-x86_64.AppImage. chmod +x and run it; it needs
glibc 2.35 or newer. If it will not start, the machine has no FUSE 2: install
libfuse2, or run the file with --appimage-extract-and-run, which unpacks it
instead of mounting it.

macOS - perfboard-studio-...-arm64.dmg, Apple silicon. Drag it to Applications,
then run this before opening it:

xattr -dr com.apple.quarantine /Applications/PerfboardStudio.app

It is signed ad-hoc but not notarized, so Gatekeeper blocks the first launch.
On macOS 15 and later the dialog it raises defaults to Move to Trash, which
deletes the install. Clearing the flag first avoids the dialog entirely. On an
Intel Mac, install from source.

Anywhere with Python 3.12+: pip install -U perfboard-studio, then perfboard-studio.
Same release, no installer and no SmartScreen warning; Qt and VTK are most of a
400 MB download the first time.

Checking your download - SHA256SUMS carries the SHA-256 of all three
files. sha256sum -c SHA256SUMS on Linux, shasum -a 256 -c SHA256SUMS on
macOS, Get-FileHash <file> in PowerShell. Perfboard Studio does this for you when it
fetches an update itself: Help - Check for Updates. It proves the file
arrived intact, not who built it - that second claim needs the code signing
this project has not bought yet.

This is pre-alpha software. Nobody has yet built a real board by following a
generated guide - check every measurement against the part in your hand.

Perfboard Studio v0.15.0

Choose a tag to compare

@github-actions github-actions released this 06 Oct 09:33

Added

  • Every wire in the build guide is drawn at 1:1, to cut and bend it on. Each wire step
    shows the wire twice: bent to its shape over the board's holes -- a solid ring where it
    goes down through the board, a dashed one at each corner, the copper-coloured ends to
    strip -- and straight, with every mark's distance from the left-hand tip. Both are drawn
    as seen from the face the wire lies on, because a bent wire turned over is its own mirror
    image, and each tip is named by the hole it goes into. The guide ends with all of them at
    real size beside a 50 mm ruler: print at 100 %, check the ruler, cut, mark and bend. Tip
    to tip each drawing is exactly the cut list's length, because both come from the same
    numbers. A point a hand-laid wire runs straight through is not marked as a bend, and a
    shape too wide for an A4 page is turned a quarter -- a turn, never a flip. The guide's
    JSON gains each conductor step's side.

Changed

  • The build guide's pictures come in close on what each step is about. They were framed
    on the whole board, so on a 9 × 15 cm board a resistor was a few pixels of highlight and
    the picture said nothing a builder could act on. Each step is now framed on its own part
    or conductor with at least 30 mm round it to count holes from -- centred even at the
    edge, where the edge itself is the landmark -- and seen from the same direction as every
    other step on that face, so the pages still read as one board being built. A subject
    that needs the whole board gets the whole board.

  • The board question builds your circuit on the boards before it suggests one. It used to
    lay the circuit out quickly on every stock size and suggest the first it filled to a third
    or less -- a rule set by looking at where the examples sat on the boards that same rule
    had picked for them, and a board and a half too big: the 24-part atmega328-relay was sent
    to 9 × 15 cm, most of it bare, and it builds just as cleanly on 7 × 9. Now the circuit is
    placed, wired and checked on that roomy board and on each size below it, and the suggestion
    is the smallest that builds as well -- every part placed, every connection made, no DRC
    error, no placement warning the roomy board does not have, and at most 20% dearer to wire.
    Each tried board in the dialog shows the placement it was judged by and what was found
    ("builds as well, at 104% of its wiring cost", "warns: Too close to a mounting hole"); the
    progress dialog names each board as it is tried, and Cancel keeps the answer so far. It
    takes a few seconds on a small circuit and about half a minute on a 24-part one -- once per
    design, since the answer is remembered until the design changes.

  • The examples moved onto the boards the application recommends for them, placed exactly
    as the window places them. The sizes used to be written into the build script by hand,
    and each placement was the cheapest of a sweep of seeds -- a little better than anybody
    pressing the same buttons would get. Now the script asks the Board step's own question and
    commits the placement that board was judged by, at seed 0:

    was now
    atmega328-relay 9 × 15 cm 7 × 9 cm
    nano-relay 9 × 15 cm 6 × 8 cm
    lpb1-booster 7 × 9 cm 5 × 7 cm
    lm317-supply 6 × 8 cm 4 × 6 cm
    arduino-io-shield 5 × 7 cm 2 × 8 cm
    ne555-astable 4 × 6 cm 2 × 8 cm
    ne555-blinker (suggested) 6 × 8 cm 2 × 8 cm

    The README's pictures of nano-relay and the assembly animation are redrawn from them, and
    the animation lays a board taller than it is wide across its frame rather than upright.

  • Place on the Board after choosing a board puts down exactly what the dialog showed,
    at once. The board was tried with the circuit placed on it, so that placement is committed
    rather than worked out a second time, which took as long again and could come out
    different from the picture just approved. An edit in between makes it place afresh.

  • Auto-place keeps parts out from under the corner screws, and keeps a regulator or a
    relay away from the electrolytics as a matter of course.
    DRC has always warned about
    both, and the placer only ever priced the second, by millimetres, behind the cost of
    routing -- so on a small board it would hand back a capacitor under a screw head or
    beside the regulator whenever that routed a little cheaper. Both are now counted by the
    same predicate DRC uses and ranked ahead of the routing cost, the way a part hanging off
    the edge or standing in a terminal's wire entry already was, and the summary says when a
    part was moved out from under a screw head or a hot pair moved apart. It matters most on
    the smaller stock boards, where the corners are where the room runs out first: measured
    on the examples, it is what separated a board one size down from the one they had room
    on. None of the fifteen golden fixtures has a mounting hole or a part that runs hot, and
    all of their placements came out byte for byte the same.

Fixed

  • The board's tools left the toolbar when the 3D view or the build guide was opened.
    The window kept ONE note of which panel was in front, for two groups of tabs -- the board
    with the schematic, the 3D view with the guide -- so pressing 3D, Build Guide or the step
    bar's "Open the Build Guide" made the board count as behind while it was showing: Delete,
    Rotate, Autoroute and the drawing tools disappeared until its tab was clicked, and a
    schematic in front stopped redrawing after edits the same way. Each group now keeps its
    own, and opening a panel in one says nothing about the other.
  • The schematic could hang the window by fitting itself for ever. The sheet is drawn
    with a small margin round it, so fitting the sheet left that margin overflowing; a scroll
    bar came in, which made the panel smaller, which fitted the sheet again, which took the
    bar away -- over 8000 fits in 50 ms in a small panel, and no frame drawn. A paste that
    widened the sheet was enough to start it. A fitted sheet now shows no scroll bars at all;
    zooming or panning brings them back. A sheet that grows while it is fitted -- a paste, a
    new part parked past the edge -- is fitted again, rather than left with the new part
    off the edge of a view nothing can scroll.
  • The welcome window's "Draw a New Circuit" button lost its style. Its stylesheet ended
    in one brace too many, Qt refused the whole of it, and every start printed "Could not
    parse stylesheet" three times. A test now reads the source for that mistake's shape --
    a plain string glued onto an f-string, still holding a doubled brace -- and this was the
    only one.
  • Opening the 3D view hung the window on macOS with Qt 6.10 or newer. Every frame the
    panel drew asked Qt for another, so the window stopped answering the moment the panel
    opened. On that combination the panel no longer paints on screen itself; everywhere else
    it is drawn exactly as before.
  • The build guide gave bare wire its net's insulation colour. A ground run of bare wire
    was "Cut 30 mm of black AWG 24", the cut list's colour column had red and orange in it
    for wires with no insulation at all, and the bench list asked for hookup wire in colours
    only the bare runs had been given. Bare wire is now "tinned copper", and the bench list
    asks for hookup wire and bare wire on two lines, each with its own gauges and length.
  • A wire given its own colour was cut from the net's. A document can colour a wire
    itself, and the board view drew that colour while the build guide's cut list, step and
    bench list named the net's -- the screen said blue and the bench was told black. The
    guide now names the colour the wire was given: a stocked name as it is, a hex as the
    stocked colour it would be called ("#ffa500" is orange), any other word as written. The
    3D view read only "#rrggbb" and drew a wire called "red" in its net's colour; it now
    reads the colour exactly as the board view does, and a colour neither can read falls
    back to the net's in both instead of the board view painting it black.
  • Place on the Board left parts off a board that had room for them. It laid the design
    out in lanes with a hole between parts and a row between lanes, and whatever the lanes had
    no room for stayed in the design with a count in the status bar -- a 24-part circuit on a
    7 × 9 cm board came back five parts short. Those parts are now put down where they overlap
    least and the placer works them clear; only a board that really is too small leaves any
    behind, and it says which.
  • The board-size question counted the finger strips as room. Each stock board was laid
    out as a bare grid, so the two edge strips a board is sold with -- holes nothing can be
    soldered into -- and the pads its corner screws take were counted as space for parts, and
    a board could be called a fit that placing on it would then fall short on. They are
    reserved now, as they are when the design is placed for real.
  • DRC measured a screw head from the wrong point when the hole was moved off its grid
    position.
    It took the nearest point of a part towards the hole's grid address and then
    measured from where the screw actually is, which agree only while the offset is zero: a
    head standing over the middle of a part could be measured to its far corner and pass.
    Every stock board's corner holes sit on the grid, so no board shipped with the tool was
    affected.
  • The Turkish README said the whole project was Apache-2.0. Since 0.12.0 the 3D package
    meshes borrowed from KiCad are CC-BY-SA 4.0, and the English README's licence section
    says so and answers the two questions people have about it; the Turkish one was never
    given that paragraph. It has it now...
Read more

Perfboard Studio v0.14.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 22:06

Added

  • A step bar: Circuit, Board, Placement, Wiring, Check, Build — and Next. The window
    had every tool and no order: nothing said the circuit comes first, that a board is
    chosen before the parts go on it, that routing joins them, that DRC says it can be built,
    or that the guide and the 3D view are what it is built from. A row under the toolbar now
    shows the six steps, where this board stands on each ("8 parts · 7 nets", "5 x 7 cm",
    "8/8 on the board", "3 connections left", "0 errors · 1 warning"), and a Next button that
    does whichever is next — a DRC error or an open net first. Pressing a step goes where it
    is done. Choosing the board is a step of its own.

  • Boards chosen by looking at them. The question of which stock board a circuit goes
    on is now a grid of pictures, each board with the circuit actually arranged on it, the
    suggested one starred and the too-small ones greyed; and New Board and Board Setup draw
    the chosen product — finger strips, corner holes, printed legend — beside the questions,
    redrawn as the size changes. The pictures are drawn by the board view itself.

  • A welcome that has somewhere to begin. Draw a New Circuit, the shipped examples by
    name with what each one is ("11 parts on a 6 x 8 cm board", the drawn-but-not-built one
    first), Import a KiCad Netlist, and the six steps named once.

  • A wire on the sheet can be dragged from pin to pin, as well as clicked at both ends.
    A drag used to take the first pin and do nothing when let go -- the gesture everybody
    tries first. The pin under the pointer is ringed before the click, and a pin is a target
    of at least eight pixels at any zoom (it was 1.2 mm: five pixels on a fitted sheet).

  • Ground and power from a pin's right-click. A pin on nothing offers the sheet's rails
    by name, and GND and +5V when there are none — where it used to take the Label tool and
    typing the name.

  • part.addMany: several parts into the design as one undo step, all or nothing.

  • The build guide in Turkish. The guide is what this application is for — the thing a
    person follows with an iron in their hand — and it was English in a Turkish window: every
    step, every check, the cut list, the parts list and the page they are printed from. It is
    now written in the window's language: "D1 1N4007 — I32 → E32, 4 delik ara", "Katot —
    bantlı uç — I32 deliğine", "K32 ↔ L32 açık devre olmalı", down to the column headings of
    the CSVs and the progress counter on the page. The panel, the exported files and a saved
    project's outputs agree, --headless --lang tr writes it too, and an agent asks for it
    with language on generate_guide. English is unchanged, word for word. The
    translation lives in the engine (phrasebook.py) because the sentences are built from
    the board rather than looked up, and a test builds every board in the repository in both
    languages and searches the Turkish for English left in it. Part names are said the same
    way in the Parts panel and the guide, from one table.

  • Route ▸ Crossings: routing with no wire at all. The engine could always be told what
    a solder trace does where it meets something it may not cross, and nothing let anybody
    tell it. A short jumper over the crossing stays the default; "one wire for the whole
    connection" and "never use wire" are the other two. The last uses solder traces only,
    whatever connection is preferred, and names each connection a trace cannot make rather
    than laying wire nobody asked for. It is remembered with the other routing choices, and
    an agent asks for the same thing with crossings on autoroute and reroute.

  • File ▸ Open Example. The examples ship with the application and nothing in the
    window pointed at them. They open as new, untitled boards — the file lives inside the
    application, so saving over it would change the example for everybody — and the empty
    board's hint mentions them when there are any.

  • Wires laid along the grid. Every wire the router laid was one straight run between
    its two ends, so a routed board was a cat's cradle of diagonals crossing each other, and
    a straight bare wire could pass 0.2 mm from another net's pad. Route ▸ Lay Wires Along
    the Grid
    (on by default) runs them square to the rows and columns of holes with as few
    bends as the board allows, keeps a bare wire off every pin, joint and run of copper, and
    keeps wires from lying on top of one another. On the shipped examples, stripped and
    routed again: no diagonal wire, nothing unrouted, no short, no DRC error, for about a
    fifth more wire. The engine's default stays straight, so every golden route is
    unchanged; RouterOptions.wire_path chooses. The MCP server's autoroute and reroute
    take the same choice as wires and default to the grid too, so an agent's board comes
    out like a person's.

  • DRC: wire-over-joint. A bare wire or a bent lead lying across a pin of another net,
    or across the soldered end of an insulated wire, is a short at the bench that neither the
    netlist nor LVS can see, because a wire is joined only at its two ends. The router already
    refused to lay one; a wire drawn by hand, or a part moved under an existing one, now gets
    an error. Six of the fifteen golden fixtures carry one, which the original engine never
    checked, so the rule joins PYTHON_ONLY_RULES and is pinned there.

Changed

  • A netlist is imported into the design, not onto whatever board is open. Its parts
    used to land on the board after a question, beside what they connect to — skipping the
    choice of board and leaving a first-pass placement nobody would keep. They now arrive in
    the design with their values and pin names, the sheet comes forward, and Choose a Board
    and Place on the Board take them from there.

  • Add a Part offers the catalog first, from the Parts panel's own tree: typing 555
    finds the NE555 and gives it its value, its pin names and U as its letter, where it used
    to list sixty-one packages with a crystal first and Y1 in the reference box. A value that
    names a catalog part in the chosen package brings its pinout too.

  • The board's tools are on the toolbar only while the board is in front. With the
    sheet in front the bar offered solder-trace and jumper tools, and a Rotate and a Mirror
    that acted on the board's selection beside the sheet's own.

  • A net is classed by its name until somebody picks a class: GND typed in New Net, a
    pin labelled GND, or N3 renamed GND is a ground net and drawn as ground symbols, where it
    used to be a signal wired to every part.

  • References on the board sit over their part, on a plate, instead of at the corner of
    the courtyard across the next row's pads -- and over every part, so a crowded board no
    longer prints "X12" as "X1" with the next part across the rest.

  • The schematic keeps its lanes out of the text. Every row has room above for its
    references and below for its values, so no trunk runs through "NE555" or "10nF"; net
    names are placed clear of each other and of the parts' text; every power glyph says which
    supply it is; and the panel draws text at the size the layout left room for, re-fitting
    the sheet as the panel finds its size until somebody zooms (it used to fit once, while
    the panel was still small, and stay there).

  • What just happened is said in the window's language. A command describes itself in
    English -- that sentence is the undo label, the journal line and what an agent reads -- so
    a Turkish window's status bar said "Add J1 PWR to the schematic" and its Edit menu "Geri
    Al Place and arrange 8 part(s)". Every sentence the commands, the planners and the
    window's own labels produce is now recognised where it is shown and said in Turkish
    ("Şemaya J1 PWR ekle", "7/7 nette 14 bağlantı yönlendirildi"), a conductor in the guide's
    own words. A test runs a session of nearly every command and fails on any sentence that
    comes back untranslated.

  • Qt's own buttons speak the window's language: OK, Cancel, Close, Yes and No are
    Tamam, İptal, Kapat, Evet and Hayır in Turkish.

  • The example boards are routed the way Ctrl+R routes, and the README shows the
    application as it is.
    tools/build_examples.py routed with the engine's default, which
    lays each wire as one straight run because that is what every golden route records — so
    the first boards a stranger opened from File ▸ Open Example were the cat's cradle of
    diagonal wire the window itself stopped producing when wires were laid along the grid.
    All six are rebuilt with the window's settings and the current router: no diagonal wire,
    every net closed, no DRC error, LVS clean. Three carry one R5' warning each, a trace laid
    beside another net's pin, which the guide turns into a check. The README's pictures and
    the assembly animation are regenerated from them, so they show wires along the grid and
    solder drawn as solder.

  • The potentiometer and the relay look like the parts in the bag in 3D. Neither has a
    borrowed model, and the generated bodies were a blue disc with a peg on it and a plain
    box. The potentiometer now has its steel cover crimped over the housing, a threaded
    bushing and a knurled shaft with a screwdriver slot; the relay a case with rounded
    corners standing on its feet. Both carry their value in print, as the real ones do —
    across the relay's top, stamped into the potentiometer's cover.

  • Solder and wire look like solder and wire in 3D. A run of solder was a round grey
    tube with bulges, a wire's end a ball on its pad, an insulated wire a coloured pipe with a
    mitre at every corner, and the leads came out of bare rings as if nothing had been
    soldered. A run is now a low bright ridge swelling into a dome on each p...

Read more

Perfboard Studio v0.13.0

Choose a tag to compare

@github-actions github-actions released this 26 Sep 15:55

Added

  • An example that is a real part list: examples/nano-relay. An Arduino Nano switching
    a 12 V relay through a BC547, fed by a 7805, with a push button and an LED -- imported
    from its KiCad netlist exactly as File ▸ Import KiCad Netlist does, with no footprint
    named for it: the catalog's parts by their values, the rest by their KiCad footprints, the
    Nano's and the LED's pins renumbered by name. It is on the README's new Real parts
    pictures, and tools/build_examples.py builds it through the importer, so it is the
    end-to-end check of that path too. The other examples were rebuilt with this release's
    placer; tools/screenshots.py now takes its pictures with a settings store of its own
    rather than the user's, which it used to rearrange.

  • A T on the sheet. A drawn wire went from a pin to a pin and nowhere else, so a net
    reaching four pins was three wires from pin to pin -- nothing like the one run with
    branches off it that a person draws. The wire tool now takes a drawn wire as either click:
    a pin and then a wire, or a wire and then a pin, and the pin branches off it in a T, with
    a dot where it lands and its last run across the wire rather than along it. A T can land
    on a T. The circuit is still doc.nets: a T joins its pin to the net of the wire it lands
    on, exactly as a wire to one of that wire's pins would. It is stored as the wire it is
    plus the far end of the wire it lands on (SheetWire.tap, written only when set, so
    every sheet drawn before is byte for byte what it was), and where it lands is laid back
    onto that wire each time the sheet is drawn -- a symbol drags only the end runs of its
    wires, so a T in the middle of one stays where it was put. Rubbing a wire out takes the
    T's off it with it, in one undo step; a T whose wire is no longer drawn (its net lost an
    end) goes to its pin instead.

  • A KiCad netlist's parts arrive as what they are. The importer kept the nets and threw
    away everything else a netlist says about a component, and guessed each part from its
    reference letter and pin count: a 7805 in a TO-220 ("U1", three pins) became a DIP-8,
    every electrolytic a disc capacitor, and every part came with no value. Now
    parsers.kicad_parts reads, in order: the value against the catalog ("BC547B", "L7805CV",
    "NE555P" -- with the part's pin names and symbol, when the KiCad footprint is the same
    package); the KiCad footprint name, which KiCad writes as the package's measurements
    (resistors and diodes by span and body, electrolytics and discs by can and lead spacing,
    DIPs, headers, IDC, Phoenix and bornier terminals, LEDs, TO-92, TO-220, HC-49); and only
    then the old guess. A surface-mount footprint, a relay, a push button and a module are
    not mapped and say why. The parts are placed beside what they connect to
    (placer.arrange) rather than in a grid in reference order, with their values, as one
    undo step. Over MCP, import_netlist returns suggested_parts and notes, and
    place_missing=true places them.

  • Which leg is which, from the schematic's pin names. A netlist's pin numbers are the
    symbol's, and they are not always the part's: KiCad's LED is pin 1 = cathode where this
    library's is pin 1 = anode, and a generic Q_NPN_EBC given "BC547" as its value is pin 1 =
    emitter where a BC547's pin 1 is its collector. Taken at its numbers, either netlist wires
    a board for a part that does not exist, and no check can see it, because the netlist is
    what every check is measured against. The netlist now carries each pin's name
    (pinfunction, which the parser used to drop); where every named pin matches exactly one
    pin of the real part, the import renumbers it to the part's own numbers and says so, and
    a transistor or diode whose names cannot be settled is reported instead. An LED with no
    names in the netlist is read by KiCad's own numbering of its footprint. A module comes
    through the same way: KiCad numbers an Arduino Nano, a Pico or a D1 mini down one side
    and up the other, the catalog's are numbered across their rows, and every pin is found by
    its name -- KiCad's overbar markup off (~{RESET} is RESET), a Pico's GPIO26_ADC0 read
    as its silkscreen's GP26, and a name on several pins (two GNDs) matched in order when
    every one of them is in the same net, and never otherwise. A part that has no
    catalog entry but three or more named pins -- a 2N5088, an IC -- gets the schematic's
    names printed beside its pins.

  • Labels written on the board. A perfboard has no silkscreen; what a builder writes on
    one with a marker -- "MOTOR 24V" beside the terminal that takes it, "CAN ->" where the
    chain goes -- is now part of the board: Edit ▸ Add Label…, or Add Label Here… on a
    right-click, dragged into place, double-clicked to change, Delete to remove. A label is
    on the top or the solder side, turns by 90°, is printed on the 1:1 sheet and in the
    guide's pictures, and in 3D is drawn by Qt so a Turkish "ALT YÜZ" or an arrow comes out
    whole (VTK's vector text knows ASCII only). Stored as boardNotes, addressed like a
    mounting hole -- a hole and millimetres off it -- and omitted when there are none, so no
    existing board changes by a byte. Nothing derives anything from a label: DRC, LVS and
    the router ignore it. View ▸ Show Labels on the Board hides them; over MCP,
    add_board_label (the 53rd tool) and remove_board_feature. A label stays on the board:
    a drag stops at its edge, and one whose offset would carry it past the substrate -- on
    adding, editing, or narrowing the border under it -- is refused (off-board,
    would-strand-label).

  • A push button as made: sw-tactile-6x6 and sw-tactile-12x12. A 6 x 6 mm button's
    legs stand 6.5 x 4.5 mm apart -- three holes by two on a perfboard, across the gutter on a
    breadboard -- and the registry's sw-tactile is two holes by one, which no such button
    is. Which legs are which matters more: the pair straight across is one strip of metal,
    the pair down one side is what pressing it joins, and sw-tactile calls the pair its
    pins 1 and 2 stand on one node -- so a KiCad switch guessed onto it was a button pressed
    for ever. The new ones are numbered as KiCad's SW_PUSH footprints are (pins 1 and 2 the
    switched pair, 3 and 4 joined inside to them, named A B A B), have KiCad's models on
    their holes, are in the catalog under Switches, and are what a netlist's SW_PUSH_6mm
    and SW_PUSH-12mm, and a guessed SW, now become. sw-tactile is unchanged, for the
    boards that have it.

  • Real parts by name: the catalog. The library is sixty-one packages, and a package is
    not a part -- a TO-92 is a BC547 or a 2N7000 or a 78L05, and which leg is the base is the
    fact the board depends on. perfboard_studio.catalog lists 60 parts a perfboard is
    actually built from -- bipolar and MOSFET transistors, regulators and references, diodes
    and zeners, a PTC, sensors, DIP ICs, push buttons and five dev boards -- each with its
    package, what its datasheet calls every lead, its symbol, its value and its reference
    letter, and
    source saying whose datasheet that is. They head the Parts panel, grouped by kind and
    found by what they are ("p-channel", "esp32"); picking one places it with all of that
    filled in, dragged or clicked, on the board or the sheet. Nothing in the document refers
    back: what lands is an ordinary part, so a board opens the same anywhere. Over MCP,
    list_catalog lists them and place_component / add_part take part="bc547". In
    Turkish, what each part is and what to check on it are in Turkish, and the filter finds
    a part in either language ("regülatör" or "regulator"); the datasheet citations stay as
    written.

  • A module on header pins: mod-<cols>x<rows>-p<c>-r<r>-<W>x<D>x<T>-s<seat>[-o<X>x<Y>].
    A devkit or a breakout is a board of its own standing on its pins, and box- described
    it as a solid block from the board up. The new module-board archetype knows its pins,
    its own board, how high that sits -- 8.5 mm in a female header, 2.5 mm soldered on its
    own pins -- and the height of what is on it. 3D draws the board on its header strips
    with its pins through it; the guide says to solder the headers and plug the module in
    last. The catalog's ESP32-DevKitC V4 is measured from Espressif's own DXF; the
    ESP32-C3-DevKitM-1, Arduino Nano, Raspberry Pi Pico and WEMOS D1 mini from KiCad's
    footprints. Custom Part… has a module family that takes the pin names too.

  • Pin names on the board, and a switch for them. A part's pin names are printed beside
    its pins in 2D and 3D: on a module's own board as its silkscreen is, and on this board
    just outside anything else -- a DIP's down either side, a terminal's behind it rather
    than across its mouth -- on a dark tag, since white ink across white pad rings cannot
    be read. Only names a part declares are printed off a module. View ▸ Show Pin Names
    turns them off for a crowded board being placed or routed.
    The names are laid out for the whole board, not part by part: on the first real board two
    terminals stood side by side and each one's names ran under the other's body. A name now
    stops at whatever is in its way -- a body, a terminal's mouth, a screw head, a label, the
    board's edge, another name. A part with its pins in one row prints them on its other side
    when that is clear; a name short of room is narrowed, down to 60 % of its width; one with
    none is left off, and the part's tooltip lists it. Both views ask
    bodies.lay_out_pin_names, so they print and leave off the same names, and 3D draws each
    one with Qt, as it does a board label, so "GİRİŞ" keeps its dots.

  • A screw terminal whose wires go in from above: screw-terminal-<n>-v. The pluggable
    bloc...

Read more

Perfboard Studio v0.12.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 13:58

Added

  • The schematic is an editor now. Symbols are dragged where you want them, turned a
    quarter at a time and flipped; wires are drawn from pin to pin by hand; a pin can be
    joined to a net by NAME instead, with a label at the pin, which is how every schematic
    ever drawn handles a reset line reaching six parts; and text, boxes, lines and circles can
    be put on the drawing. Parts are dragged onto the sheet out of the Parts panel, and
    Delete takes what is selected out of the design. The sheet's own toolbar carries the
    tools; Escape always comes back to the pointer; the middle button pans in every tool.

    PLAN.md D3 is reversed on purpose, and only half of it. D3 declined to write a
    geometric schematic editor because that is a year of work whose output this tool already
    accepts from KiCad. What it did not weigh is that a tool which can capture a circuit and
    cannot DRAW one sends people back to KiCad anyway. So there are two kinds of sheet and the
    document decides which: with doc.sheet empty the whole drawing is derived exactly as
    before — symbols in cells, wires in the channels between them, no wire able to cross a
    symbol — and that is still what every imported netlist, every fresh document and every
    press of Arrange produces. The moment anything is moved, turned or wired, every symbol
    gets a position of its own in one command, and from then on the sheet is the drawing
    somebody made.

    The netlist is still the one answer to what is connected. A drawn wire carries no net
    id: which net it belongs to is whichever net holds both of its ends, looked up every time.
    That is what makes a wire left over from a connection somebody has since removed stop
    being drawn instead of quietly asserting a join that no longer exists — and it is what
    keeps LVS, the router, the placer, the build guide and the board from having to learn
    anything about geometry.

    Arrow keys nudge the selection one grid square, through the same command a drag ends in,
    so it undoes as one thing. A selection survives the redraw every command causes — turning
    a symbol twice takes one click on it.

    Right-clicking a wire offers Rub Out This Wire, which takes the line off the sheet
    and leaves the pins connected — the net says so by name instead. It is a separate entry
    from Delete Net on purpose: deleting the picture of a join is not the same decision as
    taking a pin off one.

    .perf files are untouched by all of this unless somebody draws on the sheet: sheet,
    sheetWires and sheetNotes are omitted when empty, so all fifteen golden fixtures
    serialize to exactly the bytes they did before and DOCUMENT_FORMAT_VERSION has still
    never moved.

  • Parts are dragged out of the Parts panel onto the board. Picking a part and then
    clicking where it goes is still the way to put down a run of them — five 10k resistors,
    one after another, without going back to the list — and it was the ONLY way, which is the
    problem: dragging is what everybody tries first, and there was nothing to discover that it
    was not supported. The row simply did nothing. The drop goes through the same arming the
    list has always used, so the next free reference, the typed value and the "this hole is
    already taken" warning are all the ones that were already there, and the part stays armed
    afterwards.

  • The board is a panel now, and so is the schematic. Everything else in the window
    could be moved, floated, stacked or closed; the two views this application exists for
    were the one pair nailed down — a central widget with a tab beside it — so "board on the
    left, sheet on the right" was not something anybody could ask for, and wanting both at
    once meant a second window built by a button. They are dock widgets like the 3D view and
    the build guide: side by side is a drag, a window of its own is the title bar's float
    button, stacked is a drag onto the other one, and Qt remembers whatever it was left as.
    The toolbar carries a button per panel beside 3D, and View ▸ Reset the Panel Layout
    puts everything back where a new installation opens it.

    The panel shortcuts are renumbered around the four views of the design: Ctrl+1 Board,
    Ctrl+2 Schematic, Ctrl+3 3D, Ctrl+4 Build Guide, then Ctrl+5 Parts, Ctrl+6 Nets
    and Ctrl+7 DRC / LVS. Saved window layouts from before this are ignored once, on
    purpose: restoreState puts back the docks it knows and leaves the ones it has never
    heard of wherever the constructor put them, which landed the two new panels off the side
    of the window.

  • A tactile switch is drawn as a pushbutton and a relay as a coil and a contact block,
    instead of both being boxes with numbered pins. Both shapes come from what the PACKAGE
    says about itself — a 6 mm switch's four legs are two bonded pairs, and a relay's winding
    is the pair of pins along one side — read off the footprint's own geometry rather than
    assumed. The relay deliberately stops there: which contact is common is a fact about the
    part and not the package, so the contacts stay numbered leads out of a block. A TO-92 and
    a TO-220 stay boxes for the same reason, and there is now a test saying so for each.

  • Right-click the sheet to edit the circuit. A symbol offers its properties, a rename
    that carries every net it is wired into, a duplicate, and either Remove from the Design
    or Take off the Board depending on which of the two it is in; a pin under the pointer
    offers to come off its net, named in full — Disconnect U1.3 from VOUT; a wire offers its
    net's name, its class, the full net dialog and delete. All of it existed already, in a
    tree of twenty net names or behind a dialog with three fields — except taking one pin off
    a net, which had no door on the sheet at all. A symbol somebody has dragged also offers to
    go back to the layout on its own, without undoing an afternoon of other drags.

  • The Part Properties dialog no longer apologises for a bug that was fixed. It said
    renaming a part takes it off the nets that name it and to rename before importing a
    netlist rather than after; rename_in_nets has carried the wiring for some time.

  • A symbol can be dragged to another cell on the sheet, and it stays there. The
    drawing is still derived: what the document carries is a CELL per part, not millimetres,
    so the layout keeps every position and keeps its guarantee that no wire crosses a symbol —
    which is what lets this exist without reversing PLAN.md D3. Positioning one symbol leaves
    every other one exactly where it was, Arrange the Sheet hands the whole lot back to the
    layout in one step, and a document nobody has rearranged serializes to exactly the bytes
    it did before, so all fifteen golden fixtures are untouched and the format version has not
    moved.

  • Drag a symbol onto the board to place that one part. "Place on the Board" moves the
    whole design; until now there was no way to put down a single part from the sheet at all
    — double-clicking a symbol opened its properties. Dropping one whose part is already on
    the board moves it instead, because that is the only thing the gesture can mean. Dragging
    onto the Board tab switches to it and lets the drag carry on, so it works whether the
    sheet is a tab or a window of its own.

  • A fifth, much larger example: atmega328-relay. An ATmega328 with a 7805, a
    crystal, a relay and four connectors — 24 parts, 24 nets, 52 conductors and a 76-step
    guide with 104 checkpoints, on a 9 × 15 cm board. The four existing examples are between
    8 and 12 parts, which is the size at which everything works; this is the size at which
    the interesting rules all fire at once, and it is what the placer, the router and the
    build guide now have to keep working against.

  • geometry.unusable_holes — every hole nothing can be soldered into, which is a
    mounting bore that has taken the pad or an edge-connector finger that is solid copper
    with no bore. One fact with three consumers that were not allowed to disagree and did:
    DRC reported a pin or a run on one as an error while the placer and the router happily
    produced them.

  • A project is a folder, and the board inside it is still an ordinary .perf.
    File ▸ New Project… names the board, asks what it is built on, makes the directory and
    saves it immediately — so it has somewhere to autosave to, somewhere to put a build guide
    and something to put in the recent list from the first minute rather than from whenever
    it was first saved. File ▸ Save Pro&ject (Ctrl+Alt+S) writes the board and rewrites
    everything generated from it — the 1:1 sheets, the schematic as SVG/PDF/PNG, the build
    guide, the bill of materials, the cut list — into outputs/ beside it. File ▸ Open Project… opens the board inside one, and refuses a folder with two boards in it rather
    than guessing which was meant.

    Not an archive, not a manifest, not a new format. The byte-for-byte .perf does not
    move, the document still opens in a text editor and an agent's file tools, and throwing
    the folder away loses nothing but files the tool can write again. project.py decides
    what a project contains without a filesystem and ui/project.py has the disk, the same
    split as recovery.py/ui/autosave.py.

  • A welcome dialog offers the way back to last night's board, over a window that is
    already up rather than instead of one. Everything on it was already reachable; none of
    it was reachable in the two seconds after a launch, which is when it is wanted. Skipped
    entirely on a document that has anything in it — one opened from the command line, or
    handed back by crash recovery — and it has a checkbox that means what it says.

  • **The schematic panel opens by itself on a doc...

Read more

Perfboard Studio v0.11.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 09:28

Changed

  • The application is called Perfboard Studio; its package and command are
    perfboard-studio and its Python module is perfboard_studio.
    It was PerfStudio
    through ten releases. Two things were wrong with that name, and the second is the one
    that decided it. The first is how it reads: one letter separates "perf" from "perv",
    and not every eye lands on the right one. The second is what the abbreviation already
    means in software — "perf" is performance. It is the name of Linux's profiler, and
    AMD shipped a graphics profiler called GPU PerfStudio for years. PLAN.md §12 picked
    "perf" for open-source discoverability, and discoverability is exactly what it cost:
    a search for "perfstudio" lands among profiling tools, not among perfboard.

    The identifier is perfboard-studio rather than the bare perfboard, and that is
    a second decision rather than a longer spelling of the first. perfboard is the name
    of the board, not of this program; taking the generic word as a package name confuses
    the product with the material it works on. It is also a word this repository writes in
    prose on nearly every page, which would have made the name impossible to change again
    without reading every line by hand.

    What it means for an existing install:

    • uv tool install perfboard-studio, or pipx install perfboard-studio. The old
      perfstudio distribution is not renamed in place — PyPI has no such operation — so
      it stays where it is and stops at v0.10.0.
    • The command is perfboard-studio and the MCP server is perfboard-studio-mcp. A
      client configured with python -m perfstudio.mcp has to be pointed at
      python -m perfboard_studio.mcp.
    • The environment variables are PERFBOARD_STUDIO_LANG, PERFBOARD_STUDIO_DOCUMENT,
      PERFBOARD_STUDIO_LOG and the three PERFBOARD_STUDIO_BLESS_*.
    • The window's stored settings are keyed on the application name, so the first start
      after upgrading comes up with the default layout, the default board colour and an
      empty recent-files list. Nothing on disk is lost; the old keys are simply not read.

    The document format did not move. DOCUMENT_FORMAT_VERSION is still 1, the
    extension is still .perf — it was always short for perfboard, never for the
    application — and every golden fixture in tools/diffcheck/golden/ is byte-identical
    across the rename. A board written by v0.10.0 opens in this build unchanged, and the
    differential proof against the TypeScript engine is untouched.

  • The board is the board people actually buy, checked against a photograph of one.
    Somebody held a 5 × 7 cm double-sided board up against the screen and asked whether it
    matched. The geometry did — 70 × 50 mm, the grid, the four corner screw holes in the
    border, the finger strips down both short edges — and two things did not:

    • The pads are TINNED, not gold. _GOLD claimed to be "what the green, blue and
      black prototyping boards are finished with", and on the photograph they are plainly
      not: the pads there are neutral and light, at a blue/red ratio of about 1.0 where
      gold's is 0.4. It is HASL — hot-air levelled solder over copper. _TINNED replaces it
      for every masked scheme, kept warmer and lighter than the grey a solder run is drawn
      in, because those two are nearly the same metal on a real board and telling them apart
      is what this application is for. The 2D render signatures were re-blessed after
      reading the diff: ink coverage identical to three decimals, every cell moved about ten
      levels — a colour change and not a geometry one, which is exactly what it should be.
    • The legend was taken off the green board in the same pass and put straight back:
      the 400-pixel product shot resolved no printing, a photograph of the same product at a
      usable size shows the column letters plainly along the border under the bottom row,
      beside the part number and "5X7CM". A thumbnail too small to resolve a print is
      evidence that the print cannot be SEEN, not that the board has none — which is now
      written at board_from_preset and in the test, because the same mistake is available
      to anyone reading the same photograph.
  • The corner screw hole is AT the corner position, centred, and the pad it replaces is
    gone.
    It used to be pushed as far diagonally into the printed border as it would fit,
    to spare that pad — and one offset was used for both axes, so on a 5 x 7, whose two
    borders are 3.41 and 5.79 mm, the bore ended up 0.20 mm from one edge of the board and
    floating 2.6 mm from the other, with the corner pad jammed against it. Nothing was
    centred in anything, and it is the corner somebody looking at the board looks at first.

    • The board is manufactured with a screw hole at that position INSTEAD of a pad, so the
      pad is consumed — through consumed_holes, which DRC, both renderers and the guide
      already read, with no special case for corners.
    • A board whose border is too thin to hold a screw steps the hole one position inward
      rather than drilling a notch out of its own edge: CORNER_HOLE_WEB_MM is 1 mm of board
      and the corner position leaves 0.31 mm of it on the 20 x 30 and 0.88 mm on the 7 x 9.
      Both are now measured by a test rather than left to the eye. It also means every
      double-sided preset gets its four screw holes; the six largest boards used to get none
      at all, because the old arithmetic gave up and returned zero.
    • The finger strip already trimmed itself clear of the screws, but by taking the run
      from the first clear finger to the last — which assumed the obstruction is always at an
      END. An inset screw obstructs one in the middle, and first-to-last quietly put it back;
      it takes the longest contiguous clear run now.
  • A mounting bore takes the copper it is drilled through, including a finger. A hole
    put one position in from the corner — which is what Board Features offers by default —
    reaches the edge-connector strip, and the finger it went through was still drawn intact
    in both views: a 3.2 mm hole sitting on top of a contact the board no longer has. A bore
    does not distinguish between the two shapes of copper it destroys, so
    geometry.surviving_finger_holes answers that for both renderers the way
    consumed_holes already answered it for a round pad.

  • The printed legend is not printed into a hole. Ink goes ON the substrate and a bore
    takes the substrate away, so a letter under one is not faint, it is absent — which is
    what a real board shows. geometry.printed_label_is_clear is asked by the 2D legend and
    the 3D one, in the same units, because a legend that agreed with the board in one view
    and not the other is the disagreement this pair keeps producing.

  • The board in 3D has holes in it. Which sounds like a statement of the obvious and
    was not true: the substrate was one solid cube and every hole on it was faked by laying
    a dark cylinder over the top. A dark disc on green reads as a mark printed on the board,
    not as something you can push a lead through — and it was worst on a mounting bore,
    which has no copper ring around it to explain the darkness, so a screw hole read as a
    sticker. The plate is punched now: both faces, every hole, and the wall of the bore
    visible inside it.

    • Affordably, which is why the fake existed. A boolean subtraction per hole is
      nearly two thousand of them on a 945-hole board, and that argument still holds. This
      is neither: a face is ONE TILE — a pitch square with its hole taken out — glyphed at
      every hole, so both faces of any board cost one source and two actors. The tiles are
      exactly a pitch across, so neighbours share an edge and the surface is watertight;
      what is left between the outermost tiles and the board's edge is the printed border,
      drawn as rectangles, and a bore in it is cut out of them.
    • A mounting bore takes whole tiles and lays one patch over them, and the tiles it
      takes are exactly the holes geometry.consumed_holes reports the copper gone from —
      one bore, one answer, in the renderer and in DRC. It was also being drawn at its hole
      ADDRESS rather than at mounting_hole_centre_mm, so every corner hole appeared back
      on the grid in the middle of four pads that are perfectly intact. CLAUDE.md has said
      not to do that since the feature was written.
    • An edge-connector finger keeps a solid tile: it is a contact with no bore, and
      drilling through it is what made a finger look like a long pad.
  • The parts look like the parts. Every model was looked at on its own, close up, which
    is how most of these were found: at the whole-board zoom a wrong shape reads as a small
    coloured blob and nothing more.

    • A resistor was a flat-ended tube; it has the moulded shoulder at each end now,
      with the barrel shortened by what the domes add back so the part still measures the
      length its footprint says it does.
    • A film capacitor was a plain orange brick. The dipped case is a slab with
      half-round ends, so it is one now.
    • A disc ceramic was a coin with a sharp rim; the dipped case is a lens, thicker in
      the middle, and that is the same one solid.
    • A TO-92 was a squashed cylinder — which is an ellipse, so it has two flats and
      marks nothing. It is the D-shaped case now, with the flat facing its row of pins, and
      getting a transistor round the wrong way is the classic way to spend an evening.
    • A TO-220's tab was a slab the width of the package sitting on top of it. The tab
      is sheet metal the plastic is moulded around: thin, flush with the back face, and with
      the bolt hole through it — the side a heatsink goes on.
    • An HC-49 crystal was a flat-topped tube. It ...
Read more

PerfStudio v0.10.0

Choose a tag to compare

@github-actions github-actions released this 02 Sep 09:20

A polish release: nothing new to learn, and a long list of things that were almost right.
Four audits — the window, the three views, the engine's own prose and the loader's
tolerance for bad files — each came back with what they found, and what follows is what
survived being checked.

Added

  • The three panels that had no way back. Parts, Nets and DRC / LVS can be closed from
    their title bars, and the only route back was a right-click on the menu bar, which nobody
    finds. View ▸ Show Parts (Ctrl+1), Show Nets (Ctrl+2) and Show DRC / LVS (Ctrl+6)
    join the three toggles the other panels already had.
  • Right-clicking a conductor. The menu over a trace was the bare-board menu — Paste,
    Connect, Fit — with no way to delete the trace under the pointer. It now selects the
    conductor and offers Copy, Duplicate and Delete, the way a right-click on a part already
    selects the part.
  • Ctrl+0, Ctrl++ and Ctrl+- follow the keyboard focus. Over the schematic panel
    they fit and zoom the sheet, which had a Fit button and no key; over the board they do
    what they always did. The sheet's zoom also gained the board's limits — a few trackpad
    flicks used to leave a blank field or one pin, with nothing but the button to recover.
  • Undo and Redo say what they will do. The Edit menu read "Undo" and "Redo" and the
    answer was one hover away; it now reads "Undo Move R4 to C7", and Redo — which never
    named anything, because the bus had no way to ask — reads the same. CommandBus gained
    redo_history() for it.
  • Load warnings are shown, not counted. Opening a file that was read differently from
    how it was written — a diagonal solder-trace step, an unknown property, a duplicated
    reference — put "(2 warning(s))" in the status bar and nothing else anywhere. They are
    listed in a dialog now. And a duplicated reference IS a warning now: every net node
    names a part by reference, so two R1s is a netlist that cannot say which one it wired.
  • Two DRC rules for the file only a hand can write. conductor-off-board (a conductor
    with a hole outside the grid, the twin of component-off-board) and unknown-footprint
    (a part whose footprint neither the library nor the id grammar can produce). No command
    can create either state, so both only ever fire on a document edited by hand or written
    by another tool — which is exactly the file that must still open and be told what is
    wrong with it. Both are Python-only (PYTHON_ONLY_RULES); the second turned out to fire
    on eight of the fifteen golden fixtures, all on one id, c-disc-1, which exists in
    neither engine. The fixtures are dumps of the original and are left as they are; the
    rule is excluded from the differential comparison and pinned by its own test.
  • The interface is Turkish where it was still English. The status bar's DRC, LVS and
    ratsnest fields, the Nets panel's "done", the DRC panel's summaries, the schematic
    panel's summary, the three file dialogs, the progress dialog's five labels, the
    confirmations' bodies, the "select a part first" line and its five verbs, the Board Setup
    material list, and the board's own prose while measuring, picking pins and joining them.
    tests/test_i18n.py now also checks the View menu for accelerator clashes, which found
    one in each language.

Changed

  • A group moved together is one undo step. Five parts dragged or nudged at once used
    to be five component.move commands, so five Ctrl+Z presses to put them back — and a
    refusal part-way through left the group torn apart. The scene dispatches one
    component.moveMany, which is all-or-nothing: a locked part in the selection refuses the
    whole move and says which part.
  • Every destructive question puts Cancel under Enter. Delete parts, delete conductors,
    delete a net and reload from disk all used QMessageBox.question with no buttons named,
    which puts Yes under Enter — so a confirmation answered by reflex was a deletion. They
    share one box now, MainWindow._confirm, whose button carries the verb ("Delete") and
    whose default is Cancel. Tests that used to stub QMessageBox.question stub _confirm.
  • Deleting a mixed selection deletes all of it. A rubber band that took a part and the
    two traces on it used to delete the part and keep the traces without a word; the
    question now says the conductors go too, and they do.
  • The loader refuses what board.set refuses. A .perf with "pitch": 0, no columns,
    or a drill wider than its pad used to load without a word, and then every repaint divided
    by it — in the pure render path, a segfault. Two components sharing an id (a part no edit
    could ever reach, and one the placer refused the whole board over) and a formatVersion
    below 1 (no such version has existed) are refused too, with the same codes and paths the
    other load errors carry. Missing required field "cols" now says "board.cols", the
    path every neighbouring message already quoted.
  • CommandBus.dispatch never raises, as its contract says. A payload of the wrong
    shape — a dict where a dataclass was expected, a tuple where a HoleCoord was — used to
    surface as an AttributeError out of the command; it is {ok: false, code: "invalid-payload"} now, which is what an agent on the far side of the MCP server needs.
    The undo stack is bounded at a thousand entries, where it had no bound at all.
  • Save is enabled only when there is something to save. Ctrl+S on an unmodified
    board rewrote the file — a new modified stamp, a new mtime — for nothing. An untitled
    board can always be saved somewhere, so Save stays live there.
  • The Downloaded strip has a Close button. Its only button was Hide, which skips that
    version for good — so closing the strip after a successful download told the application
    never to mention the release the user had just fetched. Hide stays on the announcement,
    where it means what it says.
  • board.set names every stranded part, and refuses to strand a track cut. Shrinking a
    board with three parts outside the new size used to name the first, so the refusal
    repeated once per part, each discovered only after the previous one had been moved. A
    cut off the board was kept silently — and if the board was grown again, it broke a strip
    nobody remembered cutting. A component also needs a non-empty reference now; the wiring
    cannot name one without.
  • MCP results mean one thing by ok. run_lvs returned ok: false when the board
    did not match the schematic, while everywhere else ok: false means the call was
    refused; it returns ok: true with matches_schematic now, and run_drc carries
    ok: true too. autoroute on stripboard returned cuts: 0 for an empty plan and
    cuts: [...] for a committed one; it is always a list, with cut_count and
    link_count beside it. export_pdf with no directory wrote two PDFs into the
    server's working directory, against the instructions' own promise that nothing writes to
    disk unless a path is named — it refuses with no-directory. Paths accept ~, and an
    empty path is refused rather than blamed on permissions. The server's instructions now
    list all six connection kinds (not four), give the design-first working order
    docs/MCP.md gives, say what plain is as a board type, and send an agent to reroute
    after optimize_placement rather than to autoroute, which only adds.
  • The KiCad importer says what it was handed. A .kicad_sch given to it — the
    schematic instead of the netlist exported from it, which is the first-time mistake — got
    "no export form found"; it now says it is a schematic and where the netlist comes from.
    Two nets sharing a code (a broken export, but the user's export) used to refuse the
    whole import as a duplicate id; they are imported with a suffix and a warning. A
    component with no footprint is warned about, since it is what forces the host to guess
    one.

Fixed

  • Measuring, then flipping the board, broke every tool. The measurement marker is an
    item like the others and a rebuild destroys it, but the mode kept a wrapper for it — so
    the next click, or the next arming of any tool (all of which disarm measuring first),
    raised from removeItem and left every board mode unreachable until the window was
    reopened. test_measuring_survives_a_flip is the reproduction.
  • Three more things a rebuild lost. A half-drawn trace kept its path and lost its
    picture, so after a flip or an undo the tool was armed with nothing on the board and
    Enter committed an invisible chain. The placement ghost came back at A1 after every
    placement — at exactly the moment the next part was being lined up. And a conductor
    selected to be deleted was deselected by whatever unrelated command came first, while
    parts had always been re-selected by id.
  • Picking a part mid-trace armed both. Clicking the Parts panel while a trace was being
    drawn left the ghost following the pointer while every click still extended the trace,
    so the part could never be placed. The board modes are mutually exclusive and placement
    now disarms drawing, as drawing already disarmed placement.
  • The solder side and the keyboard disagreed. The arrow keys moved a part one column in
    the document, which on the mirrored solder side is a step to the LEFT under Right;
    Rotate Clockwise turned the other way there for the same reason; and the placement ghost
    painted a DIP's pins running one way while the placement put them the other. A drag was
    right all along, because it round-trips through screen_to_hole. All three now correct
    for the side, and test_arrow_keys_follow_the_screen_on_the_solder_side holds it.
  • Flipping the board flips the view and the camera with it. The scene is ...
Read more