Copy item to new Board using python script (SOLVED)

I’m trying to figure out the pcbnew python/swig api. I want to copy a layout from one Board to another Board. Can anyone give me some pointers. Conceptually I want something like the following::

import pcbnew
brd_in = pcbnew.LoadBoard("my_board.kicad_pcb")
newbrd = pcbnew.BOARD()
for m in brd_in.GetModules():
    item = newbrd.Duplicate(m)
    newbrd.Add(item)
newbrd.Save("my_panel.kicad_pcb)

I understand I’ll need to do the same with tracks, zones etc. but I’m taking baby-steps…
It’s not at all clear how the Duplicate() method works or even if this is the right way to do this.

Any working examples would be most appreciated. I’ve seem the existing scripts in the kicad plugins library. These all seem to act/duplicate items in the same board, so don’t really help me figure out how
to copy things between boards.

I’m using v5.1.7 BTW.

Thanks.

Take a look at Save/Restore action plugin.

Thanks. This is quite complicated. Looks like this replicates the layout by taking a copy of the board, then removing everything it doesn’t need and then saving this to a binary blob. Then it pickles this with a load of metadata to reconstruct stuff. To restore, it is reloading the board from a temp file, then doing a bunch of other things I don’t understand. Looks like all the heavy lifting is left to the pcbnew.SaveBoard() and pcbnew.LoadBoard() methods. I can’t see how to add modules to a board programmatically.

Well the plugin is a complete solution. But you have to use same schematics sheet on both boards.

while I can agree that the solution is not trivial, it works (or at least it should work, it has been a while since I’ve tested it). You can use it to look at the code snippets and you might get an idea how to solve your issue. And while we are on the topic, can you describe a little bit into detail what do you want to achieve? You have two boards that have the same circuitry and you want to share the layout? While just the duplication might work this will leave the destination board out of sync with schematics. Unless you use the same schematics in both boards. But if you do the plugin should help.

Since you figured out most of it pretty quick may I ask is it because you have a lot of experience, or is the code straightforward to figure out and well commented?

Dont use Duplicate, use copy constructor instead.

Just tested this and it works

b1 = pcbnew.LoadBoard("Keithley1950.kicad_pcb")
b2 = pcbnew.BOARD()

for m in b1.GetModules():
    m2 = pcbnew.MODULE(m)
    for p in m2.Pads():
        p.SetNetCode(-1)
    b2.Add(m2)

b2.Save("copy.kicad_pcb")

Note that I have to clear out net information on the pads because otherwise pcbnew crashes. If you want to keep the net info you need to copy nets into the new board before you copy modules.

1 Like

I want to write a script to panelize a PCB. The existing solutions don’t do quite what I want, so being a python programmer of some experience, I thought I’d write my own. I don’t need to maintain any links to the original schematic, just step and repeat a layout, re-annotate the References, write a BOM for the entire panel, then add an outer border, mounting holes and fiducials and I’m done! . Should be easy, right? :wink: While making a panel manually using the Append Board action in the GUI is possible, re-doing this every time I edit the layout would be a chore, but once I have a script, I just re-run the script. If I can get is working nicely, I may make a Kicad_action_script out of it.

I can appreciate the necessity for the complexity of your Save/Restore script, since it strives to maintain the links between schematic and layout but, as a result, it didn’t help my particular problem. For my purposes, I think the main challenge is to understand the pcbnew C++ API. Sadly, the D’oxygen docs don’t contain any descriptive text or explanation for what methods do or how to use them. Here I think a bit more work on the C++ docs would go a long way. Sure, a C++ API isn’t “pythonic” but could still be quite usable if clearly designed and documented. I have seen the kicad_python library but this is too early in its development to help me right now.

Excellent tip. Thanks!

OK, making nice progress on this now. For anyone who wants to do something similar, here’s what I got so far::

mm = 1000000
brd_in = pcbnew.LoadBoard("my_pcb.kicad_pcb")
brd = pcbnew.BOARD()

def append_board(source, target, x_offset=0, y_offset=0):
    for m in source.GetModules():
        m2 = pcbnew.MODULE(m)
        for p in m2.Pads():
            p.SetNetCode(-1)
        ###m2.Move() doesn't work, but GetPosition/SetPosition does.
        pos_in = m2.GetPosition()
        pos_out = pcbnew.wxPoint(pos_in[0]+x_offset, pos_in[1]+y_offset)
        m2.SetPosition(pos_out) 
        target.Add(m2)
        
    shift = pcbnew.wxPoint(x_offset, y_offset)
        
    for t in source.GetTracks():
        t2 = t.Duplicate()
        t2.SetNetCode(-1)
        t2.Move(shift)
        target.Add(t2)
        
    for d in source.GetDrawings():
        d2 = d.Duplicate()
        d2.Move(shift)
        target.Add(d2)
        
    for z in source.Zones():
        z2 = pcbnew.ZONE_CONTAINER(z)
        z2.SetNetCode(-1)
        z2.Move(shift)
        target.Add(z2)

for x,y in itertools.product(range(5), range(5)):
    append_board(brd_in, brd, x_offset=x*15*mm, y_offset=y*10*mm)

pcbnew.SaveBoard("my_pcb_panel.kicad_pcb", brd)

There’s a few more things to do, like copy across board clearance settings (at the moment, re-calculating the fill messes things up) and checking the target board has the same layers as the source.

Instead of creating a new board, you might want to save the existing board under a new name, open in and remove everything. This way you’ll have an empty board with all the nets and netcodes. And you won’t need to remove the track, pad and zone net bindings. Thus the “panelized” board will have more in common with original design.

Yeah, as you will find out, zone rebuild without nets just doesnt work.

Yes, I can see the logic in taking a copy of the source board. Looks like I do need the net-information after all. However, I’m going to try doing it the “hard” way first (creating the board-settings, net and net-class info explicitly), as a learning tool to understand the Board api/data-structures.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.