Say I copy and paste a filled zone in a design where I have a bunch of them that are the same size. The first one was assigned to a net on creation. The pasted pours won’t connect to the pads under them because they belong to a different net.
It would be nice to be able to click on the pad, shift-click on the pour and somehow say “assign” and done.
That’s what I’ve been doing. It’s slow and painful. With hundreds of nets you have to also type something into the filter field to narrow things down.
Something like click > shift-click > Enter would be super fast.
I need to see if something like this can be implemented in Python. Not necessarily worth it for this board at this time, but it would be nice to have the ability for future work.
Another approach (that does not address the pasted fills but would be useful) would be the case of clicking on a pad before starting the filled zone tool. The tool would automatically assign the fill to the net connected to that pad. No need to search through hundreds of nets to find the one you want.
Ah, yes, that is there. It goes through the interim dialog, but that’s not bad at all.
My problem, however, is that I have so many fills (dozens) to place and assign to nets that the best way to do it is to copy and paste them. When you do this the fills (zones) are pasted with the net of the original source. I was looking for way to easily assign the net without going through the dialog and having to search for the desired net.
So…
I took some time to look into this today and wrote a plugin that makes this super easy. See code below. Installation instructions after the code.
This code isn’t fully fine-tuned --got to get back to work!-- but it does not seem to have serious problems.
I enabled a toolbar button for the plugin once loaded. Now I can do the following:
click on a pad > shift-click on a zone > click on the toolbar button > Done!
#assign_zone_action.py
import pcbnew
import wx
class ComplexPluginAction(pcbnew.ActionPlugin):
def defaults(self):
self.name = "Assigned Zone to Net"
self.category = "Assigned Zone to Net"
self.description = "Assigned the net of a selected pad to a filled zone"
#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):
board = pcbnew.GetBoard()
items = board.AllConnectedItems()
selection = []
pad = ""
zone = ""
for item in items:
if item.IsSelected():
selection.append(item)
if len(selection) == 2:
for item in selection:
if isinstance(item, pcbnew.PAD):
pad = item
if isinstance(item, pcbnew.ZONE):
zone = item
if pad != "" and zone != "":
zone.SetNet(pad.GetNet())
# Re-fill all the zones
filler = pcbnew.ZONE_FILLER(board)
filler.Fill(board.Zones())
pcbnew.Refresh()
else:
dialog = wx.MessageDialog(None, "Invalid selection", "Error", wx.OK | wx.ICON_WARNING)
dialog.ShowModal()
dialog.Destroy()
#__init__.py contents:
from .assign_zone_action import ComplexPluginAction
ComplexPluginAction().register()
For anyone not familiar with how to install plugins:
Create a subdirectory within the plugin path, I called mine “assign_zone”
Create two python files within that subdirector with each file having the code above
Tools > External Plugins > Refresh Plugins
You should now be able to go back to Tools > External Plugins and see “Assign Zone to Net”
From here you can just click on a pad, shift-click on a zone and then run the plugin from the menu
If you want to display an button on the toolbar for this plugin:
Preferences > Preferences > Action Plugins > click the checkbox for this plugin.
Here’s a cleaner version of the code with better error checking:
import pcbnew
import wx
class ComplexPluginAction(pcbnew.ActionPlugin):
def defaults(self):
self.name = "Assigned Zone to Net"
self.category = "Assigned Zone to Net"
self.description = "Assigned the net of a selected pad to a filled zone"
#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):
board = pcbnew.GetBoard()
items = board.AllConnectedItems()
selection = []
pad = ""
zone = ""
for item in items:
if item.IsSelected():
selection.append(item)
selection_valid = False
if len(selection) == 2:
for item in selection:
if isinstance(item, pcbnew.PAD):
pad = item
if isinstance(item, pcbnew.ZONE):
zone = item
if pad != "" and zone != "":
selection_valid = True
if selection_valid:
# Assign net to zone
zone.SetNet(pad.GetNet())
# Re-fill all the zones
filler = pcbnew.ZONE_FILLER(board)
filler.Fill(board.Zones())
pcbnew.Refresh()
else:
dialog = wx.MessageDialog(None, "Invalid selection", "Error", wx.OK | wx.ICON_WARNING)
dialog.ShowModal()
dialog.Destroy()