Stretchable components

I use KiCAD not only for PCB design, but also when prototyping or breadboarding by hand. It helps prevent and resolve wiring issues, allows me to decide board layout, and results in very nice documentation for when I later forget how a circuit was wired up.
On proto-boards, I use the top layer for jumpers and the bottom layer for solder blobs. (this of course breaks down when jumper need to cross)
On breadboards, I visualize the busses and typically only draw the jumpers.

However, one thing I find myself spending a lot of time on is getting the resistors the right size. Every time I need to change the length of the resistor, I have to use “change footprint” and pick out a new footprint from the library. This is annoying at best.

But through-hole resistors aren’t actually a fixed size. They have very long leads. What I would like is a stretch tool to adjust the size of the resistor fluidly between the min and max lengths, so I can size it to the needs of the layout (which I won’t know during initial footprint selection).
Does anything like this exist?

I can imagine it might be possible to cycle through footprints with a keyboard shortcut tied to a Python script, which would still be an improvement.

There used to be a setting in KiCad to unlock the location of a pad and/or make them “freely moveable” it is even mentioned (and with a screenshot) in the PCB Editor manual, chapter 4.5. But the checkbox has disappeared in KiCad V7. This function may have moved, but I don’t know where it is. Now you know it exists (or at least existed) maybe you can find it.

In V7.0.9

kicad_GS2f0EiQwV

In V7.99 (upcoming V8)

kicad_76DBGzm3Zk

1 Like

Wow. I’m not sure I like that feature.
It certainly provides flexibility, but at the expense of documentation. When I move the pad outside the courtyard, it’s no longer obvious which part it belongs to.

1 Like

You are right, I never thought of this. There should at least be the fine blue line you have when moving a footprint’s refdes. Maybe I’ll post a feature request in the bug tracker…

1 Like

So that is where that checkbox went. I do not understand the reasoning behind it. For most footprints it does not make sense to ever move individual pads. To me it would be much more logical to make it a footprint dependent setting (or maybe just (or also) for individual pads).

I created a THT footprint library for different length 1/4 W resistors and labeled them according to their length (10ths. of inches). eg. RT3.0, RT3.5, RT4.0 etc. so to change the footprint it is:

Hotkey E
Change Footprint
Click Library Box at the end of “New Footprint Library ID”
Select footprint from the library list.

All up 5 sec?

Indeed, but when you have to do that repeatedly for 20 resistors in your project to make them all fit on your breadboard it gets tedious quickly. And that is why he wrote:

On proto-boards it is also tedious to decide where to place jumpers and components then strip the ends of wires and cut copper tracks.
It is also tedious to fit a SMD or TO3 component to a proto-board.

Likewise doing the maths to set-up biasing in an original design, not to mention simulation.

There is a lot of repetitive tedious stuff. This comes with the occupation.
I wonder how a brick-layer feels.

  1. For stripping wires you can get a wire stripper to do it quickly, but I transitioned to using enameled wire some 30+ years ago. You do not need to strip it at all, but can directly solder it with a hot iron
  2. I find cutting copper tracks on those strip boards horrible. (I also never had the proper tool for it) But the main problem is with “reverse thinking” of having to remove connections that are already present. It is an area where KiCad could be of help with planning. If you plan to use that strip board and do an initial layout in KiCad you can make all the cuts (of have a CNC machine do it for you).
  3. SMT parts are often available on breakout boards, others, such as SOT-23 can easily be soldered to single row header pins (use a wire for the third pin).
  4. TO3 is obsolete. And if you still have a few, they are usually put on big heat sinks and connected with some wires to a breadboard (although breadboards are not fit for high currents either).
  5. maths is fun.
  6. Brick laying robots are already in use, but at the moment they are mostly limited to very big jobs, because they still lack flexibility and ease of programming to be cost effective for smaller and more complicated jobs. But i do expect that to change gradually.

Some people do “diamond painting” or are drawing those big round pictures with squiggly details for fun or relaxation, but you don’t hear them complaining about tedious. have a look at" “Manila folder 777-300ER”

But it is when things are perceived as tedious that people start looking for quicker or better methods.

But overall, I do not understand your comment at all. Marshal_Horn wrote he does not like the “change footprint” method, You even quoted him in on that, and in the same post you go on to recommend that exact same method. KiCad’s own libraries also have resistors sized by length and diameter. confused0024

My point was there is a lot of tedium in everything and four clicks, taking 5 seconds, to change a footprint is nothing much compared to other matters when using a proto board.
It is no worse than creating a PCB either.

THT footprints take time to manage and place.

And my point was that it is not just 5 seconds, because you can have a lot of resistors and multiple iterations during footprint placement. having to change the footprints each time is tedious annoying and distracting.

Thank you for the animated discussion.
I will see about making a script to cycle through footprints. After all, they’re already in order in the library.

1 Like

Here’s what I have so far:

import pcbnew
import os

class NextFootprint(pcbnew.ActionPlugin):
    def defaults(self):
        self.name = "next_footprint"
        self.category = "placement"
        self.description = "Cycles through footprints. Intended for changing resistor length while prototyping."
        self.show_toolbar_button = False # Optional, defaults to False
        self.icon_file_name = os.path.join(os.path.dirname(__file__), 'simple_plugin.png') # Optional, defaults to ""

    def Run(self):
        # The entry function of the plugin that is executed on user action
        board = pcbnew.GetBoard()
        front = board.GetLayerID("F.Cu")
        back = board.GetLayerID("B.Cu")
        f = board.GetFootprint(board.GetFocusPosition(),front,True)
        fid = f.GetFPID()
        print(f'{str(id.GetLibItemName())} of {id.GetFullLibraryName()}')
        # How to get the list of footprints from the library??
        # Then set the new footprint
        # f.SetFPID(new footprint)

for the libraries sadly no python interface exists so you have to open them as text files and search through them for the footprint names, e.g. with regular expressions.

I’m almost there, but I need help with two things:

  • How to get the actual cursor position (or better, the selected part)
  • How to update footprints from the library
import pcbnew
import os
import wx

def next_fp(direction):
    board = pcbnew.GetBoard()
    # FIXME: Board focus position is always the same.
    print(board.GetFocusPosition())
    f = board.GetFootprint(board.GetFocusPosition(),pcbnew.F_Cu,True)
    fid = f.GetFPIDAsString()
    print(f'Selected {f.GetReference()} {fid}')
    libname,_,fpname = fid.partition(':')
    # Get the list of footprints from the library
    lib = os.path.join(os.environ['KICAD7_FOOTPRINT_DIR']
                       ,libname+'.pretty')
    footprints = os.listdir(lib)
    footprints = [x.partition('.kicad_mod')[0] for x in footprints]
    # TODO: Sort by numbers like the Footprint Library Browser does
    footprints.sort()
    i = footprints.index(fpname)
    i += direction
    if i < 0:
        i = 0
    elif i >= len(footprints):
        i = len(footprints)-1
    # Set the footprint to the next
    newfp = f'{libname}:{footprints[i]}'
    print(f'Changing to {newfp}')
    f.SetFPIDAsString(newfp) 
    # FIXME: Update footprint from library
    pass

def next_fp_callback(context):
    next_fp(1)

def prev_fp_callback(context):
    next_fp(-1)

def findPcbnewWindow():
    """Find the window for the PCBNEW application."""
    windows = wx.GetTopLevelWindows()
    pcbnew = [w for w in windows if "PCB Editor" in w.GetTitle()]
    if len(pcbnew) != 1:
        raise Exception("Cannot find pcbnew window from title matching!")
    return pcbnew[0]

class NextFp(pcbnew.ActionPlugin):
    def defaults(self):
        self.name = "next_footprint"
        self.category = "placement"
        self.description = "Cycles through footprints. Intended for changing resistor length while prototyping."
        self.show_toolbar_button = False # Optional, defaults to False
        self.icon_file_name = os.path.join(os.path.dirname(__file__), 'simple_plugin.png') # Optional, defaults to ""

    def Run(self):
        mainFrame = findPcbnewWindow()
        next_fp_button = wx.NewId()
        prev_fp_button = wx.NewId()
        accel_tbl = wx.AcceleratorTable([(wx.ACCEL_SHIFT,  ord('J'), next_fp_button )
                                         ,(wx.ACCEL_SHIFT,  ord('K'), prev_fp_button )])
        mainFrame.Bind(wx.EVT_TOOL, next_fp_callback, id=next_fp_button)
        mainFrame.Bind(wx.EVT_TOOL, prev_fp_callback, id=prev_fp_button)
        mainFrame.SetAcceleratorTable(accel_tbl)


NextFp().register() # Instantiate and register to Pcbnew

I found a better way to get the selected footprints:

def get_sel(context = None):
    sel = pcbnew.GetCurrentSelection()
    for x in sel:
        print(x)
        if isinstance(x,pcbnew.FOOTPRINT):
            return x
        elif isinstance(x,pcbnew.PAD):
            return x.GetParent()
        else:
            print('not pad or footprint')

I’m still working on changing the footprint, however.
The c++ footprint dialog uses a “LoadFootprint()” function which doesn’t seem to be available in the Python bindings.

Use FootprintLoad()

Why does it return None?
Isn’t this the correct usage?
pcbnew.FootprintLoad('Diode_SMD','D_SMA')

Pass the path to .pretty folder as first argument. If you google the method or even search this forum you will find examples.