devbisme / WireIt

KiCad PCBNEW plugin that lets you add wires between pads on a PCB, delete them, and swap wires between pads.
MIT License
82 stars 10 forks source link

can ‘Disconnect airwires from pads’ also act as a split-net command #6

Open gh-jmg opened 6 years ago

gh-jmg commented 6 years ago

Request: can ‘Disconnect airwires from pads’ also act as a split-net command, where someone selects N segments of a NET, but not the whole net. Usually one split keeps the old net name, and a new net name is assigned to now isolated connection set. PADS and Vias touched would have that new net name applied.

One use case, is in manual duplicate of a cell array, where currently that slavish clones all net names where exact clones may not be desired. Being able to split some routed nets, after clone, would be useful. eg keep GND +3V, but make some local by removing the rats-connection due to same-net-name.

Code example below collects selected TRACK items, and then collects PADS of that Netname, and tests for PADs touching selected segments. End outcome is a selected set (trk/via/PAD), ready for NET split rename.

Other issue - I've raised a BUG report in KiCad PCB as to work best, this will need a fix made to Select Copper Connection. https://bugs.launchpad.net/kicad/+bug/1789807

Currently, KiCad menu Select Copper Connection 'travels over' & selects vias in the sub-group, and can travel-over a PAD but fails if entry/exit traces are on different layers. My thinking here, is Select Copper Connection should work like a multimeter, and via is the same as a pad.

I did find a workaround, which is to manually Shft-Clk select one segment in each PAD fragmented sub-net, and then 'I' will collect all the Select Copper Connections. A little klunky and error prone.

# PcbNew_Select_Track_Pad.py Derived from PcbNew_Export_PcbNew_NET
# eg Usage - in KiCad PcbNew Python Console paste after >>>
# >>> execfile("C:\KiCad_Python\Check_Footprint_Attr\PcbNew_Select_Track_Pad.py")
# 
# Purposes : 
#  Select.CopperConnection picks Vias and Tracks, but does not pick PADS.
#  It also has a BUG in that it fails IF a layerchange occurs at the pad.
#  Workaround: Shift-clk any ONE segment in each pad-fractured subset, and then 'I' will select all copper connects
#
#  This simple script collects sets of selectd traces, and same-net pads, and then cross checks those sets, for selected-trace-end at pad
#

# V1.0  first pass
# V1.01 added pad radius to tolerate slight alignment errors

import pcbnew             # ok on fresh start
pcb = pcbnew.GetBoard()   # Works on Loaded Design file

print '# PcbNew_Select_Track_Pad.py V1.01 start'

SetCount = 0
tPadCount = 0
sPadCount = 0
trks = pcb.GetTracks()   # Via is a case of track 
trkcnt = trks.GetCount()
SelTrackSet = []            # clear set 
PossiblePadSet = []         # clear set 
AddSelectPadSet = []        # clear set 

print '# Found %s Total Track Segments '%(trkcnt)

TagNetName = '?????'  # some default
for ftrk in trks:
    if ftrk.IsSelected():
       TagNetName = ftrk.GetNetname()   # get name
       SelTrackSet.append(ftrk)         # Collect a list of selected tracks - this includes Vias
       SetCount = SetCount + 1

print '# Tag Net name is: %s , Selected Segments & Vias : %s '%(TagNetName, SetCount)

pads = pcb.GetPads()
for pad in pads:
  pad.ClearSelected()                  # debug, clear last pass selects
  if pad.GetNetname() == TagNetName:
    tPadCount = tPadCount + 1
    PossiblePadSet.append(pad)         # Collect a list of SAME NET pads in the design

print '# PossiblePadSet count : %s '%(tPadCount)

for strk in SelTrackSet:                 # Now scan for PAD XY on selected trace end. This does not catch fly-over traces, or not-snapped trace ends  
  if strk.GetClass() != "VIA":           # skip vias 
    sS = strk.GetStart()
    sE = strk.GetEnd()
    for spad in PossiblePadSet:
      if not spad.IsSelected():          # Skip if already have earlier track end causing select
        sP = spad.GetPosition()
        mR = min(spad.GetSize()) / 2     # get min radii (rough) - tolerates allows small errors in trace ends.
        if ((abs(sS.x-sP.x) < mR) and (abs(sS.y-sP.y) < mR)) or ((abs(sE.x-sP.x) < mR) and (abs(sE.y-sP.y) < mR)):   # test trace END inside PAD O
          spad.SetSelected()             # show and tag as done
          sPadCount = sPadCount + 1
          AddSelectPadSet.append(spad)   # collect these added pads
print '# Copper Connect & Selected Pads count : %s '%(sPadCount)

for spad in AddSelectPadSet:           # list those selected
   PinName = spad.GetPadName()
   PadSize = min(spad.GetSize())
   Module  = spad.GetParent()
   RefDes  = Module.GetReference()
   Module.SetSelected()             # TEST PART - for move checks 
   print '# Ref %s Pin %s Size %s' %(RefDes,PinName,pcbnew.ToMM(PadSize))  # show list
#   if Module.IsSelected():
#      Module.Move(pcbnew.wxPoint(pcbnew.FromMM(-0.25),pcbnew.FromMM(-0.35)))  #debug, walk selects away from ideal centre

pcbnew.Refresh()                

# Null run gives expected 
# PcbNew_Select_Track_Pad.py start
# Found 1169 Total Track Segments 
# Tag Net name is: ??? , Selected Segments: 0 
# PossiblePadSet count : 0 
# Copper Connect found Pads count : 0 

# PcbNew_Select_Track_Pad.py V1.01 start
# Found 1169 Total Track Segments 
# Tag Net name is: GND , Selected Segments & Vias : 29 
# PossiblePadSet count : 39 
# Copper Connect & Selected Pads count : 9 
# Ref U2 Pin 5 Size 1.6
# Ref J11 Pin 1 Size 2.5
# Ref J12 Pin 1 Size 2.5
# Ref J13 Pin 1 Size 2.5
# Ref MIDI_OUT1 Pin 3 Size 1.7
# Ref J14 Pin 1 Size 2.5
# Ref J15 Pin 1 Size 2.5
# Ref J16 Pin 1 Size 2.5
# Ref J4 Pin 2 Size 1.7

# Workaround test :  Shift-clk ONE segment in each pad-fractured subset, and then 'I' will select all copper connects
# PcbNew_Select_Track_Pad.py V1.01 start
# Found 1176 Total Track Segments 
# Tag Net name is: GND , Selected Segments & Vias : 79 
# PossiblePadSet count : 39 
# Copper Connect & Selected Pads count : 21 
# Ref EXT_FSW_IN1 Pin S Size 2.0
# Ref EXPR_SW_IN1 Pin S Size 2.0
# Ref EXPR_PEDAL_IN1 Pin S Size 2.0
# Ref J9 Pin 1 Size 2.5
# Ref J10 Pin 1 Size 2.5
# Ref U1 Pin 4 Size 1.6
# Ref R10 Pin 2 Size 1.6
# Ref J8 Pin 1 Size 2.5
# Ref J7 Pin 1 Size 2.5
# Ref R6 Pin 1 Size 1.6
# Ref U2 Pin 5 Size 1.6
# Ref J11 Pin 1 Size 2.5
# Ref J12 Pin 1 Size 2.5
# Ref J13 Pin 1 Size 2.5
# Ref MIDI_OUT1 Pin 3 Size 1.7
# Ref J14 Pin 1 Size 2.5
# Ref J15 Pin 1 Size 2.5
# Ref J16 Pin 1 Size 2.5
# Ref J4 Pin 2 Size 1.7
# Ref MIDI_IN1 Pin 3 Size 1.7
# Ref J17 Pin 1 Size 2.5

`

gh-jmg commented 6 years ago

This rough code works around the Select Copper Connection issue, which is awaiting a fix. It can get slow on large datasets, as it sweeps 2 axes, multiple times.

# Select Copper Connection fails to follow-over PADS where LAYER changes, so add a fix to walk along the nets 
for ftrk in trks:
    if TagNetName == ftrk.GetNetname():   
       NetTrackSet.append(ftrk)          # Collect a list of ALL nets tracks - this includes Vias
       NetCount = NetCount + 1
print '# Net name : %s , Possible Seg/Via : %s '%(TagNetName, NetCount)

LastPass = -1
TstCount = 0

while NewCount != LastPass:     # repeat until no more found, ie NewCounts stops increasing
  LastPass = NewCount
  for ntrk in NetTrackSet:      # some selected, some not..
    if ntrk.IsSelected():       # seed tree expansion by Selected flag
      sS = ntrk.GetStart()      # Get this selected Start,End co-ordinates
      sE = ntrk.GetEnd()
      for mtrk in NetTrackSet:    # Scan all other nodes 
       TstCount = TstCount + 1    # this number can eget large very quickly eg Net name : GND , Possible Seg/Via : 144  Track Segs Added 30  tests 48384
       if not mtrk.IsSelected():  # Skip if selected already
         mS = mtrk.GetStart()  
         mE = mtrk.GetEnd()
         if (mS == sS) or (mS == sE) or (mE == sS) or (mE == sE) :
           NewCount = NewCount + 1
           mtrk.SetSelected()     # join new touch
print '#Track Segs Added %s  tests %s '%(NewCount,TstCount)
gh-jmg commented 6 years ago

.. and the good news, is the bug reported https://bugs.launchpad.net/kicad/+bug/1789807 where Select Copper Connection failed to 'follow over' a pad where layer changed, is now fixed.

Fixed in revision 9eec296b0a0d9e9ff6a152aa1ef91d7ae92920dc https://git.launchpad.net/kicad/patch/?id=9eec296b0a0d9e9ff6a152aa1ef91d7ae92920dc Changed in kicad: status: Triaged → Fix Committed assignee: nobody → Seth Hillbrand (sethh)

So that last slower code is not strictly needed, unless you want to allow any single segment select, to be enough to seed the selection ? (or want it to work on older KiCads )

With a properly working Select Copper Connection, that code should exit with nothing to do, after 1 x 2 axis pass.