Giter Site home page Giter Site logo

adamws / kicad-kbplacer Goto Github PK

View Code? Open in Web Editor NEW
330.0 6.0 23.0 13.69 MB

KiCad plugin for automatic keyboard's key placement and routing

License: GNU General Public License v3.0

Python 95.63% CSS 0.07% Dockerfile 3.12% PowerShell 0.19% Shell 0.99%
kicad mechanical-keyboard action-plugin pcbnew keyboard kicad-plugin

kicad-kbplacer's Introduction

icon kicad-kbplacer

KiCad Repository Downloads CircleCI PyPI Coverage Status Weblate

KiCad plugin for mechanical keyboard design. It features automatic key placement and routing based on popular layout descriptions from keyboard-layout-editor and ergogen.

Table of Contents

Motivation

All PCB's for mechanical keyboards shares common properties which creates great opportunity for scripting. Although this project does not aim to provide complete automatic PCB generation tool it speeds up development process by reducing tedious element placement and routing tasks.

Features

  • Automatic keys and diodes placement
  • Track routing and track template replication
  • Support for KLE, VIA, QMK and ergogen inputs
  • User selectable diode position in relation to key position
  • Configurable additional elements placement
  • Board outline generation

Warning

Ergogen support is new experimental feature and it has not been tested extensively

demo

Some examples can be found in examples directory.

See also:

๐Ÿ”— Keyboard PCB design with ergogen and kbplacer

Installation

As KiCad plugin

To install release version of this plugin, use KiCad's Plugin and Content Manager and select Keyboard footprints placer from official plugin repository.

pcm

To install development version, see how to use custom plugin repository. Custom repository is automatically updated with latest master branch builds and it is available here.

For development activities, it is recommended to checkout this repository and copy (or link) content of kbplacer directory to one of the KiCad's plugin search paths. For more details see this guide.

After installation, plugin can be started by clicking plugin icon on the toolbar:

plugin-icon-on-toolbar

or selecting it from Tools -> External Plugins menu. For more details about plugin usage see Use from KiCad section.

As python package

The kbplacer can be installed with pip:

pip install kbplacer

When installed this way, it can't be launched from KiCad as KiCad plugin. This option exist for usage via command line interface or for integrating with another tools.

Command line interface provides more options but generally it is recommended for more advanced users. For example it allows to create PCBs without schematic, which is non-typical KiCad workflow. For details see Use from CLI or from another tools section.

Important

Most of the kbplacer python package functionalities depends on pcbnew package which is distributed as part of KiCad installation. This means, that on Windows it is required to use python bundled with KiCad. On Linux, pcbnew package should be available globally (this can be verified by running python -c "import pcbnew; print(pcbnew.Version())") so it may not work inside isolated environment. To install inside virtual environment created with venv it is required to use --system-site-package option when creating this environment.

Note

Both installation methods can be used simultaneously. When installed as KiCad plugin, some scripting capabilities are still available, but in order to use kbplacer in another python scripts, installing as python package is required.

Use from KiCad

This is traditional way of using this tool. Before it can be used on kicad_pcb project file, user needs to create it and populate with footprints. In typical KiCad workflow this is started by creating schematic. When PCB file is ready, user can start kbplacer plugin in GUI mode from KiCad and run it with selected options. To use this tool in this way, it needs to be installed following plugin installation guide.

  • Create switch matrix schematic which meets following requirements:

    • Each switch has connected diode

      • Diodes can be connected in either direction. Track router attempts to connect closest (to each other) pads of switch and diode as long as both have same netname, i.e. are connected on the schematic
      • Each switch can have multiple diodes
    • Symbols are ordered by Y position.

      • โš ๏ธ This annotation scheme might not work well for certain 'ergo' layouts.
      • Annotation order is ignored when using layout with mapping to matrix defined (see VIA specification).

      To learn more see annotation guide.

    schematic-example

  • Create new PCB and load netlist

  • Obtain json layout file from keyboard-layout-editor or convert ergogen points file to json

    keyboard-layout-editor details

    kle-download

    Plugin supports internal kle-serial layout files and via files. Detection of layout format will be done automatically. Conversion between layout downloaded from keyboard-layout-editor and its internal form can be done with https://adamws.github.io/kle-serial or keyboard-tools.xyz/kle-converter

    [!NOTE] When using via layouts, switch matrix must be annotated according to via rules. If layout supports multiple layout of keys only the default one will be used by kicad-kbplacer.

    ergogen details
    • open your design in https://ergogen.cache.works/ and download points.yaml

      ergogen-points

    • convert yaml to json (this operation is not integrated with kicad-kbplacer source because it would require installation of third-party pyyaml package and there is no good way to manage plugin dependencies yet)

    • converted file should be automatically recognized in next steps

  • Run kicad-kbplacer plugin

  • Select json layout file and plugin options and click OK.

    plugin-gui

It is possible to run this plugin from command line. Everything which can be done via GUI can be also achieved using command line. Execute following command (in the directory where plugin is installed) to get more details:

python -m com_github_adamws_kicad-kbplacer --help

Important

On windows, use python bundled with KiCad

Options overview

Section Label Description
Switch settings Keyboard layout file Layout file path. Supports keyboard-layout-editor json layouts in both raw and internal form, via and qmk json layouts and ergogen canonical yaml points files converted to json.
Can be empty to run without switch footprints placement.
Step X / Step Y Distance (in millimeters) of 1U between two switches in X and Y directions.
Footprint Annotation The switch footprint annotation format with single replacement field {} which will get replaced with incremented footprint number. This string is internally used by python's str.format function.
Orientation Angle (in degrees) of switch footprints.
Side Selects Front or Back side of the board.
Switch diodes settings Allow autoplacement Enables automatic diodes positioning. When turned on, each diode will be placed next to the switch footprint with common net, according to the position settings. When disabled, diodes will not be moved.
If any switch has more than one diode, then Default and Custom position options are not supported.
Route with switches Enables automatic routing of switch-diode pairs. If user manually route first pair, then it replicates the connection for remaining pairs. If not, uses automatic internal router. When automatic router used, attempts to connect only two closest pads of the same net.
Automatically adjust orientation Enables automatic diode orientation adjustment based on distance between diode and corresponding switch. Useful for some key matrix types, for example Japanese duplex matrix, where diodes are connected with alternating directions.
Footprint annotation The diode annotation format. Same rules as for switch footprint annotation applies.
Position Diode position option with three possible choices:
โ€ƒDefault - positions diodes to default position
โ€ƒCustom - positions diodes based on user defined values
โ€ƒRelative - uses first switch-diode pair to get relative position between them and uses that as reference position for remaining pairs
โ€ƒPreset - uses provided kicad_pcb template file to get relative position and tracks for replication for all switch-diode pairs
Offset X/Y Distance (in millimeters) from the center of switch footprint to the center of diode footprint. Accepts floating values with . (dot) decimal separator.
Applicable only for Custom position option.
Orientation Angle (in degrees) of diode footprint. If switch is rotated it will be automatically adjusted to match switch rotation
Applicable only for Custom position option.
Side Selects Front or Back side of the board.
Applicable only for Custom position option.
Load from
/
Save to
The preset kicad_pcb file path to use when position option is equal Preset or optional file path to store current position and tracks when position option is equal Relative.
Additional elements settings - This is equivalent of Switch diodes settings section with these exceptions:
1) It is possible to add/subtract elements from the list using +/- buttons
2) Allow autoplacement option is missing, footprints which should not be moved should not be added to the list
3) Footprints from this sections are not routed
Other settings Route rows and columns Enables/disables automatic routing of keyboard switch matrix. Works by finding all pads with nets matching COL(\d+) and ROW(\d+) regular expressions (ignoring case) and connecting them using simplified internal router. Configuration of row/column naming scheme is not yet supported.
Controller template circuit file Path to kicad_pcb template file which can be used for placing/routing repetitive parts of the PCBs. It is expected that user creates own templates.
This is optional and not very well documented process.
Build board outline Enables/disables board outline creation based on selected footprints (if any) or all switch footprints.
Using selected footprints is supported only for KiCad 7 or above.
Outline delta The amount (in millimeters) to inflate/deflate generated outline shape.

Diode placement and routing

By default diodes are placed like shown below. This placement may not work for all switch and diode footprints combinations.

Before After
default-before default-after

To use custom diode position there are two available options. Either select Custom in Position dropdown and define X/Y offset, Orientation and Front or Back side:

custom-position-example

or manually place D1 diode to desired position in relation to first switch and run plugin with Relative Position option selected.

current-relative-position-example

Remaining switch-diode pairs will be placed same as the first one. To save current template, set Save to path. This can be later re-used with Preset Position option.

Before After
custom-before custom-after

Some custom diodes positions may be to difficult for router algorithm. In the above example it managed to connect diodes to switches but failed to connect diodes together.

Switch-to-diode routing is not done with proper auto-routing algorithm and it is very limited. It attempts to create track in the shortest way (using 45ยฐ angles) and doesn't look for other options if there is a collision, leaving elements unconnected.

Diode automatic orientation adjustment

Some key matrix types use diodes in alternating directions (see The (Japanese) duplex matrix), making it undesirable to use a single Position value for all of them. When Automatically adjust orientation is enabled, kicad-kbplacer will choose between two positions: the one defined by the Position controls values and another with the orientation rotated by 180 degrees. It then selects the position where the distance between the switch and diode pads is shortest.

Consider following example:

Schematic Automatic adjustment disabled Automatic adjustment enabled
japanese-matrix-schematic japanese-matrix-no-adjustment japanese-matrix-adjustment

Track templating

If first switch-diode pair is routed before plugin execution, as shown below, kicad-kbplacer instead of using it's built in routing algorithm, will copy user's track. This allow to circumvent plugin's router limitations. This is applicable only for Relative Position option or when diode placement disabled (with Allow autoplacement unticked). The latter is suited mostly for routing boards generated with ergogen. When using Relative Position and Save to path defined, tracks will be stored in template. Then it can be re-used when using Preset Position option.

Before After
custom-with-track-before custom-with-track-after

Note

Track templating is recommended for more complicated switch footprints, for example reversible kailh. When switch footprint has multiple pads with the same net name, automatic router would try to connect only the two closest pads between diode and switch.

Below example shows more complicated custom diode position with track template pre-routed by the user. Manual work needs to be done only for first switch-diode pair, plugin will replicate layout for the remaining pairs:

track-template-comples

Warning

All footprints for diodes and switches must have same pad layouts, otherwise connection replication may yield unexpected results

Additional elements placement

In case additional elements need to be automatically placed next to corresponding switches (for example stabilizer footprints if not integral part of switch footprint, or RGB LEDs), define entries in Additional elements settings section. It behaves very similarly to switch diodes options with few exceptions:

  • corresponding switch is matched based on annotation number and not net code
  • there is no default position defined
  • there is no track routing

Building board outline

The kicad-kbplacer plugin is capable of generating board edges around selected footprints or all switches footprints (matched using Switch Settings - Annotation Footprint value). It uses convex hull algorithm to calculate outline and allows to specify additional increase/decrease amount by Outline delta value.

Outline delta 2.0mm Outline delta -1.0mm
board-outline-plus2 board-outline-minus1

Important

To build outline using selected footprints, selection must be done before launching plugin and KiCad 7 or above must be used

Run without layout

Creating tracks, placing switch associated elements (like diodes) or building board outline does not require layout file. With empty Keyboard layout file field, switch placement is simply skipped. Placing and routing of other elements will use already placed switches as reference points and won't move them. This might be useful for PCB files generated by other tools, for example ergogen.

This works with custom diode positions and track templating.

Use from CLI or from another tools

Run as a script

The kbplacer module might be executed as a script using python's -m command line option.

python -m kbplacer

This is command line equivalent of running this tool as KiCad plugin but without GUI interface. Run it with --help option to get more details about options and CLI usage.

Layout format conversion script

The kbplacer is capable of converting layouts between various formats. For example, to convert ergogen point file to KLE layout file:

python -m kbplacer.kle_serial \
  -in tests/data/ergogen-layouts/absolem-simple-points.yaml -inform ERGOGEN_INTERNAL \
  -out $(pwd)/absolem-kle.json -outform KLE_RAW

This command generates this file which can be loaded by keyboard-layout-editor website.

In case of VIA-like annotated layouts there is an option to perform 'collapse' operation.

python -m kbplacer.kle_serial \
  -in tests/data/via-layouts/wt60_d.json -inform KLE_VIA \
  -out $(pwd)/wt60_d-internal-collapsed.json -outform KLE_INTERNAL -collapse
Before collapse After collapse

Layout collapsing moves keys to theirs final physical position and removes duplicates. Key is considered duplicate when there is another key of same matrix position and size.

Extra tools

The kbplacer is used by additional tools available in tools directory.

Tool Example result
layout2image.py - generates KLE-like image for layout
layout2schematic.py - generates KiCad schematic file with switch matrix
layout2url.py - small utility to generate KLE url To open new firefox tab with layout using keyboard-layout-editor run
python layout2url.py -in kle.json | xargs firefox
Example result: url

Use in python projects

Some kbplacer functionality might be reused in another projects. For example, to parse raw KLE data to it's internal form run:

from kbplacer.kle_serial import parse_kle
keyboard = parse_kle([["", ""]])
print(f"This keyboard has only {len(keyboard.keys)} keys")

The kbplacer API is used in following projects:

  • keyboard-pcbs (repository) - benchmark for kbplacer - website with collection of pre-generated KiCad projects (both schematics and PCB files) based on via layouts. Combines usage of kbplacer KiCad plugin and accompanying tools.
  • keyboard-tools (repository) - website for generating PCB files from user uploaded layout files, combines kbplacer plugin with skidl and aims to introduce no-schematic workflows or provide decent starting point for traditional KiCad projects.

Creating keyboard PCB file from scratch (without skidl or using schematic generated with layout2schematic tool) is also possible using kbplacer CLI interface although it is currently considered experimental.

Demo keyboard project

For example keyboard project see demo directory. This project contains 4x4 switch matrix with layout json files in raw (kle.json) and internal (kle_internal.json) formats. It requires keyswitch-kicad-library to be installed. Use this project to validate plugin installation.

Troubleshooting

Plugin does not load

If plugin does not appear on the Tools -> External Plugins menu and its icon is missing on toolbar, launch python scripting console Tools -> Scripting Console and type:

import pcbnew; pcbnew.GetWizardsBackTrace()

This should return backtrace with an information about the fault. Include this information in bug report.

Plugin misbehaves or crashes

  • Read stacktrace in error pop-up
  • See kbplacer.log file, created in PCB directory

For bug reports please use this template.

kicad-kbplacer's People

Contributors

adamws avatar ceoloide avatar weblate avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

kicad-kbplacer's Issues

python KeyError: 1 when loading JSON file

Describe the bug
When trying to load a .json file pulled from keyboard-layout-editor.com, I get the below error. This error also happens when I try to load any json from the examples folder you've provided.

Traceback (most recent call last):

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/kbplacer_plugin_action.py", line 90, in Run
    placer.run(

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/key_placer.py", line 880, in run
    self.place_switches(keyboard, key_matrix, key_info.position)

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/key_placer.py", line 588, in place_switches
    offset = self._calculate_reference_coordinate(keyboard, key_matrix)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/key_placer.py", line 576, in _calculate_reference_coordinate
    first_key, _ = next(key_iterator)
                   ^^^^^^^^^^^^^^^^^^

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/key_placer.py", line 216, in __next__
    return key, self.__get_footprint(key)
                ^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/key_placer.py", line 207, in __get_footprint
    sw = self._key_matrix.switch_by_number(self._current_key)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "/home/nf3985/.var/app/org.kicad.KiCad/data/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/key_placer.py", line 121, in switch_by_number
    return self._switches_by_number[number]
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^

KeyError: 1

KiCad version info

Application: KiCad PCB Editor x86_64 on x86_64

Version: 8.0.1, release build

Libraries:
	wxWidgets 3.2.4
	FreeType 2.13.2
	HarfBuzz 8.1.1
	FontConfig 2.15.0
	libcurl/8.7.0-DEV OpenSSL/3.1.5 zlib/1.3.1 libidn2/2.3.4 libpsl/0.21.2 nghttp2/1.58.0

Platform: Freedesktop SDK 23.08 (Flatpak runtime), 64 bit, Little endian, wxGTK, X11, i3, x11

Build Info:
	Date: Apr  7 2024 13:02:50
	wxWidgets: 3.2.4 (wchar_t,wx containers) GTK+ 3.24
	Boost: 1.84.0
	OCC: 7.7.2
	Curl: 8.6.0-DEV
	ngspice: 42
	Compiler: GCC 13.2.0 with C++ ABI 1018

Build settings:

Unexpected behavior: diode "relative" place method rotates diodes

Describe the bug
What it says in the title. When I use diode autoplacement relatively to the first switch-diode pair, all switches are rotated to a certain degree. I expect that diodes should remain square to switches in this case. Plugin does not crash though.

Additional context
I observe this behavior on switches which are not square to the PCB drawing. I assume it is connected to the layout I am building?

Screenshots
First I was like
Plugin window
But then
diode_bug.zip

KiCad version info

Application: KiCad PCB Editor x86_64 on x86_64

Version: 7.0.9-7.0.9~ubuntu22.04.1, release build

Libraries:
	wxWidgets 3.2.1
	FreeType 2.11.1
	HarfBuzz 6.0.0
	FontConfig 2.13.1
	libcurl/7.81.0 OpenSSL/3.0.2 zlib/1.2.11 brotli/1.0.9 zstd/1.4.8 libidn2/2.3.2 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.9.6/openssl/zlib nghttp2/1.43.0 librtmp/2.3 OpenLDAP/2.5.16

Platform: Ubuntu 22.04.3 LTS, 64 bit, Little endian, wxGTK, ubuntu, x11

Build Info:
	Date: Nov  8 2023 19:01:25
	wxWidgets: 3.2.1 (wchar_t,wx containers) GTK+ 3.24
	Boost: 1.74.0
	OCC: 7.5.2
	Curl: 7.88.1
	ngspice: 38
	Compiler: GCC 11.4.0 with C++ ABI 1016

Build settings:
	KICAD_SPICE=ON

Does not start with pre-relase builds

Describe the bug
Plugin release v0.8 does not work with KiCad release candidate due to failing KiCad version parsing:

from .board_modifier import (
  File "/home/aws/.local/share/kicad/8.0/3rdparty/plugins/com_github_adamws_kicad-kbplacer/board_modifier.py", line 14, in <module>
    KICAD_VERSION = tuple(
                    ^^^^^^
ValueError: invalid literal for int() with base 10: '0~rc1'

KiCad version info

Application: KiCad PCB Editor x86_64 on x86_64

Version: 8.0.0-rc1-67-g7b24167398-dirty, release build

Libraries:
	wxWidgets 3.2.4
	FreeType 2.13.2
	HarfBuzz 8.3.0
	FontConfig 2.15.0
	libcurl/8.5.0 OpenSSL/3.2.0 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.4 libpsl/0.21.2 (+libidn2/2.3.4) libssh2/1.11.0 nghttp2/1.58.0

Platform: Arch Linux, 64 bit, Little endian, wxGTK, X11, , tty

Build Info:
	Date: Jan 18 2024 11:44:15
	wxWidgets: 3.2.4 (wchar_t,wx containers) GTK+ 3.24
	Boost: 1.83.0
	OCC: 7.7.2
	Curl: 8.5.0
	ngspice: 42
	Compiler: GCC 13.2.1 with C++ ABI 1018

Build settings:
	KICAD_USE_EGL=ON

GUI state tests fail randomly

Some of the tests, for example test_gui_state_restore are flaky and fail on circleci randomly, with errors like this:

tmpdir = local('/tmp/pytest-of-root/pytest-0/test_gui_state_restore_no_addi0')
screen_manager = <tests.test_gui.LinuxVirtualScreenManager object at 0x7faae1481410>
window_name = 'kbplacer'
gui_callback = <function test_gui_state_restore.<locals>._callback at 0x7faae147a7a0>

    def run_gui_test(tmpdir, screen_manager, window_name, gui_callback) -> None:
        is_ok = True
        # for some reason, it occasionally may fail with
        # 'wxEntryStart failed, unable to initialize wxWidgets!' error, most likely
        # this is not related with plugin's code - try to get screenshot 3 times
        # to limit false positives
        max_attempts = 3
        for i in range(0, max_attempts):
            with screen_manager as mgr:
                p = gui_callback()
                is_ok = mgr.screenshot(window_name, f"{tmpdir}/screenshot.png")
                try:
                    outs, errs = p.communicate("q\n", timeout=1)
                except subprocess.TimeoutExpired:
                    p.kill()
                    outs, errs = p.communicate()
    
                assert outs == "Press any key to exit: "
>               assert errs == ""
E               AssertionError: assert 'double free ...ion (!prev)\n' == ''
E                 + double free or corruption (!prev)

tests/test_gui.py:224: AssertionError

This can be reproduced when running tests in docker container (just like circleci does it).
Most likely this is the problem with tests because no problems has been observed when running this directly on host.

Can't get plugin to work

Hi,

I'm trying to use the plugin but i can't get it to work, it just shows the following stack trace:

image

I've tried it both on Windows (Kicad 7.0) and on Linux (Kicad 7 and Kicad 6).
This happens on both the example files and my own json files converted with https://adamws.github.io/kle-serial/ as the instructions say. Do you know what I might be doing wrong?

Deprecated python list calls

Python 3.8.10 Kicad Version: 7.0.2-6a45011f42172ubuntu20.04.1, release build

The version of the plugin that can be downloaded from the plugin editor will not run by default as the list[item] calls used in board_modifier.py and key_placer.py are deprecated, causing an error and the plugin to fail to import. A solution was add from __future__ import annotations at the beginning of both of these files and then the plugin shows up on the toolbar and in the external plugins menu

Split `Route tracks` option to `Route switch-diode pairs` and `Route matrix`

Main router use case is routing diodes with switches (which is often repeatable because diodes are usually at fixed position in relation to corresponding switch). Having columns/rows routing is byproduct of that feature and it works 'ok' only for simple layouts (ortholinear, simple staggered) but falls short for complex 'ergo' ones with lots of rotations etc.
Let the user choose which types of routing shall be run. This is already pretty well separated in placer class, need to update GUI and CLI interfaces.
Route switch-diode-pairs should be located in Switch diodes settings section, Route matrix should remain in Other settings.

Stuck with commandline use

Describe the bug

The KiCad plugin crashes and leaves me without a lot of usable information about what happened. So I thought I try the CLI version.

I didn't want to build my Matrix by hand so I annotated my KLE with the column and row positions and used tools/layout2schematic.py to generate the schematic.

[nix-shell:~/git/kicad-kbplacer]$ python3 -m kbplacer --board ~/Documents/KiCad/typematrix\ monolyth/typematrix\ monolyth.kicad_pcb -l ~/Downloads/typematrix-2020-lookalike-with-small-enters\(2\).json --build-board-outline --key-distance "17 18" --log-level DEBUG 
15:25:32: Set key 1U distance: 17000000/18000000
15:25:32: Switches by nets: defaultdict(<class 'list'>, {frozenset({'ROW4', 'COL8'}): ['SW69'], frozenset({'ROW6', 'COL11'}): ['SW89'], frozenset({'ROW6', 'COL14'}): ['SW92'], frozenset({'ROW6', 'COL2'}): ['SW88'], frozenset({'ROW0', 'COL5'}): ['SW6'], frozenset({'COL14', 'ROW3'}): ['SW60'], frozenset({'COL12', 'ROW4'}): ['SW73'], frozenset({'COL5', 'ROW2'}): ['SW36'], frozenset({'COL2', 'ROW2'}): ['SW33'], frozenset({'COL14', 'ROW5'}): ['SW85'], frozenset({'COL13', 'ROW2'}): ['SW44'], frozenset({'COL11', 'ROW4'}): ['SW72'], frozenset({'COL7', 'ROW0'}): ['SW8'], frozenset({'COL9', 'ROW3'}): ['SW55'], frozenset({'COL12', 'ROW5'}): ['SW83'], frozenset({'COL14', 'ROW4'}): ['SW75'], frozenset({'ROW0', 'COL1'}): ['SW2'], frozenset({'COL11', 'ROW0'}): ['SW12'], frozenset({'COL12', 'ROW2'}): ['SW43'], frozenset({'COL4', 'ROW3'}): ['SW50'], frozenset({'COL1', 'ROW3'}): ['SW47'], frozenset({'COL1', 'ROW2'}): ['SW32'], frozenset({'ROW0', 'COL6'}): ['SW7'], frozenset({'COL12', 'ROW1'}): ['SW28'], frozenset({'COL3', 'ROW2'}): ['SW34'], frozenset({'COL4', 'ROW0'}): ['SW5'], frozenset({'COL9', 'ROW5'}): ['SW80'], frozenset({'ROW6', 'COL1'}): ['SW87'], frozenset({'COL10', 'ROW1'}): ['SW26'], frozenset({'COL2', 'ROW4'}): ['SW63'], frozenset({'COL0', 'ROW3'}): ['SW46'], frozenset({'ROW6', 'COL13'}): ['SW91'], frozenset({'ROW4', 'COL13'}): ['SW74'], frozenset({'COL13', 'ROW3'}): ['SW59'], frozenset({'ROW0', 'COL8'}): ['SW9'], frozenset({'COL1', 'ROW1'}): ['SW17'], frozenset({'COL11', 'ROW3'}): ['SW57'], frozenset({'COL9', 'ROW0'}): ['SW10'], frozenset({'COL7', 'ROW1'}): ['SW23'], frozenset({'COL14', 'ROW1'}): ['SW30'], frozenset({'COL11', 'ROW1'}): ['SW27'], frozenset({'COL0', 'ROW4'}): ['SW61'], frozenset({'COL0', 'ROW0'}): ['SW1'], frozenset({'COL4', 'ROW2'}): ['SW35'], frozenset({'COL0', 'ROW1'}): ['SW16'], frozenset({'ROW1', 'COL6'}): ['SW22'], frozenset({'ROW1', 'COL5'}): ['SW21'], frozenset({'COL7', 'ROW2'}): ['SW38'], frozenset({'COL9', 'ROW4'}): ['SW70'], frozenset({'COL10', 'ROW0'}): ['SW11'], frozenset({'COL11', 'ROW2'}): ['SW42'], frozenset({'ROW2', 'COL6'}): ['SW37'], frozenset({'COL3', 'ROW3'}): ['SW49'], frozenset({'COL9', 'ROW2'}): ['SW40'], frozenset({'COL13', 'ROW5'}): ['SW84'], frozenset({'COL14', 'ROW0'}): ['SW15'], frozenset({'COL12', 'ROW0'}): ['SW13'], frozenset({'COL0', 'ROW2'}): ['SW31'], frozenset({'ROW3', 'COL8'}): ['SW54'], frozenset({'ROW1', 'COL8'}): ['SW24'], frozenset({'COL11', 'ROW5'}): ['SW82'], frozenset({'COL2', 'ROW5'}): ['SW78'], frozenset({'ROW3', 'COL5'}): ['SW51'], frozenset({'COL2', 'ROW0'}): ['SW3'], frozenset({'COL10', 'ROW3'}): ['SW56'], frozenset({'COL3', 'ROW4'}): ['SW64'], frozenset({'COL10', 'ROW4'}): ['SW71'], frozenset({'ROW0', 'COL13'}): ['SW14'], frozenset({'COL7', 'ROW4'}): ['SW68'], frozenset({'COL4', 'ROW1'}): ['SW20'], frozenset({'COL0', 'ROW6'}): ['SW86'], frozenset({'COL3', 'ROW1'}): ['SW19'], frozenset({'ROW6', 'COL12'}): ['SW90'], frozenset({'COL2', 'ROW1'}): ['SW18'], frozenset({'COL2', 'ROW3'}): ['SW48'], frozenset({'ROW4', 'COL6'}): ['SW67'], frozenset({'COL12', 'ROW3'}): ['SW58'], frozenset({'COL0', 'ROW5'}): ['SW76'], frozenset({'COL4', 'ROW4'}): ['SW65'], frozenset({'COL3', 'ROW5'}): ['SW79'], frozenset({'ROW4', 'COL1'}): ['SW62'], frozenset({'COL1', 'ROW5'}): ['SW77'], frozenset({'ROW4', 'COL5'}): ['SW66'], frozenset({'COL14', 'ROW2'}): ['SW45'], frozenset({'ROW1', 'COL13'}): ['SW29'], frozenset({'COL10', 'ROW5'}): ['SW81'], frozenset({'COL7', 'ROW3'}): ['SW53'], frozenset({'COL10', 'ROW2'}): ['SW41'], frozenset({'ROW3', 'COL6'}): ['SW52'], frozenset({'COL8', 'ROW2'}): ['SW39'], frozenset({'COL3', 'ROW0'}): ['SW4'], frozenset({'COL9', 'ROW1'}): ['SW25']})
15:25:32: Diodes by switch: {'SW79': ['D79'], 'SW55': ['D55'], 'SW62': ['D62'], 'SW87': ['D87'], 'SW71': ['D71'], 'SW18': ['D18'], 'SW45': ['D45'], 'SW67': ['D67'], 'SW78': ['D78'], 'SW6': ['D6'], 'SW43': ['D43'], 'SW73': ['D73'], 'SW9': ['D9'], 'SW2': ['D2'], 'SW33': ['D33'], 'SW49': ['D49'], 'SW80': ['D80'], 'SW26': ['D26'], 'SW88': ['D88'], 'SW12': ['D12'], 'SW38': ['D38'], 'SW23': ['D23'], 'SW28': ['D28'], 'SW72': ['D72'], 'SW85': ['D85'], 'SW13': ['D13'], 'SW56': ['D56'], 'SW52': ['D52'], 'SW22': ['D22'], 'SW81': ['D81'], 'SW58': ['D58'], 'SW91': ['D91'], 'SW61': ['D61'], 'SW69': ['D69'], 'SW30': ['D30'], 'SW40': ['D40'], 'SW63': ['D63'], 'SW75': ['D75'], 'SW19': ['D19'], 'SW34': ['D34'], 'SW53': ['D53'], 'SW39': ['D39'], 'SW50': ['D50'], 'SW5': ['D5'], 'SW57': ['D57'], 'SW86': ['D86'], 'SW92': ['D92'], 'SW42': ['D42'], 'SW83': ['D83'], 'SW24': ['D24'], 'SW68': ['D68'], 'SW21': ['D21'], 'SW60': ['D60'], 'SW64': ['D64'], 'SW54': ['D54'], 'SW17': ['D17'], 'SW70': ['D70'], 'SW16': ['D16'], 'SW77': ['D77'], 'SW20': ['D20'], 'SW90': ['D90'], 'SW44': ['D44'], 'SW76': ['D76'], 'SW65': ['D65'], 'SW15': ['D15'], 'SW27': ['D27'], 'SW36': ['D36'], 'SW1': ['D1'], 'SW37': ['D37'], 'SW66': ['D66'], 'SW59': ['D59'], 'SW35': ['D35'], 'SW84': ['D84'], 'SW31': ['D31'], 'SW89': ['D89'], 'SW4': ['D4'], 'SW46': ['D46'], 'SW3': ['D3'], 'SW74': ['D74'], 'SW29': ['D29'], 'SW10': ['D10'], 'SW25': ['D25'], 'SW48': ['D48'], 'SW51': ['D51'], 'SW8': ['D8'], 'SW82': ['D82'], 'SW14': ['D14'], 'SW47': ['D47'], 'SW32': ['D32'], 'SW11': ['D11'], 'SW41': ['D41'], 'SW7': ['D7']}
15:25:32: User layout: [{'name': 'TypeMatrix 2020 lookalike with small enters', 'author': 'Tilman Baumann', 'background': {'name': 'PBT Black', 'style': "background-image: url('/bg/plastic/pbt-black.png');"}, 'plate': True, 'pcb': True}, [{'w': 1.5}, 'R0,C0', 'R0,C1', 'R0,C2', 'R0,C3', 'R0,C4', 'R0,C5', {'w': 1.5}, 'R0,C6', {'x': 2, 'w': 1.5}, 'R0,C7', 'R0,C8', 'R0,C9', 'R0,C10', 'R0,C11', 'R0,C12', 'R0,C13', {'w': 1.5}, 'R0,C14'], [{'w': 1.5}, 'R1,C0', 'R1,C1', 'R1,C2', 'R1,C3', 'R1,C4', 'R1,C5', {'w': 1.5}, 'R1,C6', {'x': 2, 'w': 1.5}, 'R1,C7', 'R1,C8', 'R1,C9', 'R1,C10', 'R1,C11', 'R1,C12', 'R1,C13', {'w': 1.5}, 'R1,C14'], [{'w': 1.5}, 'R2,C0', 'R2,C1', 'R2,C2', 'R2,C3', 'R2,C4', 'R2,C5', {'w': 1.5}, 'R2,C6', {'x': 2, 'w': 1.5}, 'R2,C7', 'R2,C8', 'R2,C9', 'R2,C10', 'R2,C11', 'R2,C12', 'R2,C13', {'w': 1.5}, 'R2,C14'], [{'w': 1.5}, 'R3,C0', 'R3,C1', 'R3,C2', 'R3,C3', 'R3,C4', 'R3,C5', {'w': 1.5}, 'R3,C6', {'x': 2, 'w': 1.5}, 'R3,C7', 'R3,C8', 'R3,C9', 'R3,C10', 'R3,C11', 'R3,C12', 'R3,C13', {'w': 1.5}, 'R3,C14'], [{'w': 1.5}, 'R4,C0', 'R4,C1', 'R4,C2', 'R4,C3', 'R4,C4', 'R4,C5', {'w': 1.5}, 'R4,C6', {'x': 2, 'w': 1.5}, 'R4,C7', 'R4,C8', 'R4,C9', 'R4,C10', 'R4,C11', 'R4,C12', 'R4,C13', {'w': 1.5}, 'R4,C14'], [{'w': 1.5}, 'R5,C0', {'w': 1.5}, 'R5,C1', {'w': 1.5}, 'R5,C2', {'w': 3.5}, 'R5,C3', {'x': 2, 'w': 3.5}, 'R5,C9', 'R5,C10', 'R5,C11', 'R5,C12', 'R5,C13', {'w': 1.5}, 'R5,C14'], [{'w': 1.5}, 'R6,C0', {'w': 1.5}, 'R6,C1', {'w': 1.5}, 'R6,C2', {'x': 10}, 'R6,C11', 'R6,C12', 'R6,C13', {'w': 1.5}, 'R6,C14']]
15:25:32: Detected layout convertible to matrix annotated keyboard
15:25:32: Got [] for ('R0', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C3') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C4') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C5') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C6') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C7') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C8') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C9') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C10') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R0', 'C14') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C3') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C4') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C5') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C6') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C7') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C8') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C9') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C10') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R1', 'C14') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C3') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C4') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C5') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C6') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C7') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C8') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C9') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C10') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R2', 'C14') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C3') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C4') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C5') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C6') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C7') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C8') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C9') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C10') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R3', 'C14') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C3') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C4') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C5') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C6') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C7') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C8') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C9') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C10') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R4', 'C14') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C3') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C9') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C10') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R5', 'C14') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C0') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C1') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C2') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C11') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C12') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C13') position
15:25:32: Could not find alternative layout footprint
15:25:32: Got [] for ('R6', 'C14') position
15:25:32: Could not find alternative layout footprint
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/tilli/git/kicad-kbplacer/kbplacer/__main__.py", line 354, in <module>
    app()
  File "/home/tilli/git/kicad-kbplacer/kbplacer/__main__.py", line 345, in app
    board = run(settings)
            ^^^^^^^^^^^^^
  File "/home/tilli/git/kicad-kbplacer/kbplacer/kbplacer_plugin.py", line 46, in run
    placer.run(
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 905, in run
    self.place_switches(keyboard, key_matrix, key_info.position)
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 594, in place_switches
    offset = self._calculate_reference_coordinate(keyboard, key_matrix)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 582, in _calculate_reference_coordinate
    first_key, _ = next(key_iterator)
                   ^^^^^^^^^^^^^^^^^^
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 271, in __next__
    return self.__next__()
           ^^^^^^^^^^^^^^^
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 271, in __next__
    return self.__next__()
           ^^^^^^^^^^^^^^^
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 271, in __next__
    return self.__next__()
           ^^^^^^^^^^^^^^^
  [Previous line repeated 89 more times]
  File "/home/tilli/git/kicad-kbplacer/kbplacer/key_placer.py", line 266, in __next__
    key = next(self._keys)
          ^^^^^^^^^^^^^^^^
StopIteration

Additional context
Annotated KLE file
typematrix-2020-lookalike-with-small-enters(2).json

KiCad Project
typematrix monolyth.tar.gz

I did see that the plugin created a kbplacer.log log file which contains the same error. So that's good to know.

KiCad version info

[nix-shell:~/git/kicad-kbplacer]$ python3
Python 3.11.9 (main, Apr  2 2024, 08:25:04) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pcbnew
>>> pcbnew.GetBuildVersion()
'8.0.2'
>>> pcbnew.GetBaseVersion()
'8.0.2'

My own version of the placer

Just thought I'd mention and bring light to my take on this plugin here.

It removes the need for a kle-serial compatible json. It has it's own serializer/deserializer code. There's also some stuff which lets you customize rotations, do multi-layout, support more complicated layouts with rotation, and also specify diode location.

Disclaimer, I did use a lot of the logic from this project while I was making it (yours wasn't updated to V6 at the time).

(If this interests you, I also have this, which is where the serialization code first came from)

Exception on python action plugin code

Hi,

trying to run the keyboard placer plugin but I'm getting this error.
Screenshot 2023-06-16 at 22 04 35

Here is the keyboard json, converted from KLE using one of the tools mentioned in the guide.
https://pastebin.com/s0VmUtqL

Kicad info

Application: KiCad PCB Editor arm64 on arm64

Version: 7.0.5-0, release build

Libraries:
	wxWidgets 3.2.2
	FreeType 2.12.1
	HarfBuzz 5.3.1
	FontConfig 2.14.0
	libcurl/7.88.1 (SecureTransport) LibreSSL/3.3.6 zlib/1.2.11 nghttp2/1.51.0

Platform: macOS Ventura Version 13.4 (Build 22F66), 64 bit, Little endian, wxMac

Build Info:
	Date: May 26 2023 08:14:40
	wxWidgets: 3.2.2 (wchar_t,wx containers)
	Boost: 1.80.0
	OCC: 7.6.3
	Curl: 7.77.0
	ngspice: 38
	Compiler: Clang 13.0.0 with C++ ABI 1002

Build settings:
	KICAD_SPICE=ON

Routing not working with latest KiCad 7.0.7 release

โš ๏ธ To anyone using release v0.5 with KiCad 7.0.7 - routing is not working due to KiCad's API change. Do not use Route tracks option. It does work with 7.0.6.

        for track in self.board.GetTracks():
>           if connectivity.TestTrackEndpointDangling(track):
E           TypeError: CONNECTIVITY_DATA.TestTrackEndpointDangling() missing 1 required positional argument: 'aIgnoreTracksInPads'

Placement of Hot Swap Sockets on the Back Side

Hi,

Thanks for creating this awesome plugin!

I'd love to place not normal keys, but Hot Swap Sockets, which would go on the backside of the PCB. The LEDs and Diodes need to be on the backside too. I have placed everything on the frontside, but when i flip the entire keyboard, it is mirrored.

What I would love, if there could be a feature to select if the keys go on the front or backside, instead of placing them on the frontside by default.

Cheers
Best
ijon

KeyPlacement not Following Column order

Describe the bug
Tried different layout export from Keyboard Layout Editor and it doesn't follow the column order

Additional context
Heres kbplacer.log
kbplacer.log

Screenshots
Screenshot_13
Screenshot_14
Screenshot_15
image

KiCad version info

Application: KiCad PCB Editor x64 on x64

Version: 7.0.7, release build

Libraries:
	wxWidgets 3.2.2
	FreeType 2.12.1
	HarfBuzz 6.0.0
	FontConfig 2.14.1
	libcurl/7.88.1-DEV Schannel zlib/1.2.13

Platform: Windows 10 (build 19045), 64-bit edition, 64 bit, Little endian, wxMSW

Build Info:
	Date: Aug 14 2023 02:42:39
	wxWidgets: 3.2.2 (wchar_t,wx containers)
	Boost: 1.81.0
	OCC: 7.7.1
	Curl: 7.88.1-DEV
	ngspice: 40
	Compiler: Visual C++ 1936 without C++ ABI

Build settings:
	KICAD_SPICE=ON

Save and reuse switch-diode connection templates

User should be able to save routed template of first switch-diode pair and reuse it.
I'm thinking about new button in main GUI dialog for Save switch-diode template which would create new kicad_pcb file with copy of switch/diode and it's tracks/vias and new option in Postion dropdown, for example From File. When From File selected, then instead of usual offset/orientation and side selectors, there should be file selector.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.