Creating panelized boards natively in LibrePCB

I’d like to resurrect the topic outlined in Is it possible to create panelized boards in 2.0? . I freely acknowledge the existence of gerber panelizers, and the ability for the manufacturer to panelize them for you. Both are fine for a lot of situations, but sometimes board designers want to explicitly design the panels themselves, for varied reasons.

I’m willing to implement this feature myself and contribute it to the project.

I have been doing some research into the existing code structure as to how it may be integrated. Here’s what I would propose –

  • We’d create a third tab tool – a peer to the Schematic tab and the Board tab – named “Panel”.
  • The code for the Panel tab would start by cloning the existing Board tab. This will keep the two separate (avoiding lots of potentially-confusing conditional code). Where there are common functions between the two, we could extract a library.
  • The Panel tab would effectively replace the component placement aspects of the Board tab with board placements. Placed boards would be referenced rather than duplicating board data. That is, the Panel data would store “board A at X,Y, rotation R”, NOT “traces… vias… components…”.
  • Whereas the Board tab can place traces, vias, etc, the Panel tab would have the ability to place primitives such as tabs, panel-level fiducials, tooling holes, v-grooves, and text.
  • The Panel tab would NOT be able to edit individual board data (i.e., routing, components, etc.). It would, however, provide an “Edit Board” context menu link back to the Boards tab.
  • The first pass of the code would not hook the in-app board ordering just yet, but would facilitate generating gerbers of the panelized boards. The in-app ordering would be connected as a follow-on effort (i.e., a second release).

There are two points of this effort that require explicit approval from @ubruhin :

  • The file format would need to be updated to include the Panel data/information (individual board positions & rotations, as well as primitive data and settings). The current plan would be to model the additions after the boards/ section as presently structured, creating a panels/ section. It is envisioned that ALL data changes would be isolated to this new section. This approach should be backwards-compatible with the existing app code.
  • (Eventually) We would need to update the board ordering system a bit so manufacturers know if the data received is an individual board, or pre-panelized data. Some manufacturers adjust their pricing model based on this detail. It is for this reason that I have explicitly scoped the ordering aspects to a second stage/release.

Thoughts?

Generally that sounds all good and I agree a feature which works that way would be very useful. However, I have one big “problem”:

Building a panel with N identical boards is one use-case, but another use-case is to build panels consisting of different boards, i.e. several projects in one panel. If I remember correctly, this was also requested by users. Some standalone panelizer tools are also able to do this (see for example GitHub - halfmarble/hm-panelizer: a simple PCB panelizer · GitHub which looks really amazing from the screenshots).

So, somehow I think it would be really a pity if LibrePCB is limited to only the use-case of N identical boards. It would be so much more useful being able to build arbitrary panels. However, unfortunately I have no idea how such a feature could be designed from architectural point of view. It seems that panels then would need to be outside of the scope of a LibrePCB project (or in other words, there would be PCB projects and panel projects). But on the other hand, this would be annoying for the use-case of N identical boards, since the panel would not be part of the projects version control system, and maintaining a separate panel project would simply be inefficient and cumbersome. Also I see a problem about how a panel project would reference the contained boards, since those would be in separate project directories – just having relative file path references is not really what I like, since they are fragile.

Any thoughts about this? Of course one possible way would be to say that such a feature is out of scope of LibrePCB, i.e. external tools will be required for that. But I first want to think about a possible solution instead of just giving up early.

Thank you for the honest feedback. I agree with you that having the ability to do multiple designs on a single panel is desirable. I also agree that having to extract board designs from other projects naturally lends itself to an external tool. My intent would be that an internal Panel tool would be able to place any board designs in the current project.

I started this thread with the understanding that a single LibrePCB project may contain multiple board designs within it. After looking into it, I see that there may be different board variants within a project, but that those variants all share the same schematic.

So in the interest of exploratory design (“thinking out loud”), what if we provided a way to say something like “this schematic page gets implemented on board A”? Alternatively, being able to create DRC rules that allow for “these components won’t be placed on board B” may get us to the same target. What we’d end up with is a schematic that captured all boards in a design, and individual boards would implement a portion of the schematic.

That approach has the undesirable affect of enforced unique reference designators, but I wonder if we could get around that, too. Something like “U1” appears in one schematic page, but because that page has been tagged as “board A”, LibrePCB treats it internally as “U1.A” or “A.U1”. That would allow us to also have a “U1” on a page tagged for “board B”. Maybe that would conflict with component gates, though…

A third option would be to allow LibrePCB to have multiple schematics in a single project. We would still need to map them to specific board designs, but maybe that’s easier than mapping individual schematic pages and reference designator aliasing.

One benefit to having all the boards in a single schematic (or multiple schematics in a single project) is that you’d be able to do rule checking against the connectors – If a connector on “board A” was tagged as mating with a connector on “board B”, we could automatically check the signals to make sure the pin-outs were aligned (perhaps?). I’m getting off on a tangent, though…

Now that I’ve been typing this out, my mind is drawn to another possibility. If we implemented a hierarchical schematic system, we could map top-level hierarchy blocks to individual boards and/or schematics. Interconnections between blocks are where we could scrutinize connector interfaces. Hmm…

Like I said – I’m just “thinking out loud” here, so no right or wrong answers. :grin:

The more I’ve been pondering this, the more I like the idea of a top-level, single-layer hierarchy “page”. Per common practice, that page would describe, using blocks and connectors, how individual “designs” in the project are tied together. Each block (an individual “design”) would map to a unique schematic and a set of board variants. In a lot of ways, we’re taking the existing project structure and adding a layer above it.

I think the existing file structure would largely support this. We’d need to extend the Schematic section to facilitate multiple schematics, but that would just follow the model that the Boards use. We’d add a single “Hierarchy” (name TBD) section that defined schematic/board set pairings (“designs”), as well as how the various pairings are interconnected.

With that in place, an integrated panel tool would then be able to pull any of the boards from any of the designs in the overarching set. Support for multiple panels in a single project would facilitate things like a panel for FR4 mainboards and a panel of flex boards.

Note that the designs wouldn’t necessarily need to interconnect or have anything in common. A top-level hierarchy of blocks without any interconnection would act as a collection of designs that you want to combine onto a panel.

Just more “thinking out loud”. :smiley:

I’ve been doing a bit more digging, and I think I have a strategy that could work.

My previous post led to some investigation about what would need to be done to implement a structure level above the existing Project level. Here’s what I found -

Extending the existing Project structure to support multiple Schematics would be a big change. Scores of files and hundreds of calling locations would need to be updated to support it. I can’t, in good conscience, recommend that path. But I have an alternative that would be simpler, and still match the previous post conceptually.

Here’s what I’m thinking. We gain isolated, multi-schematic/multi-circuit support if we capture multiple Projects under a single container.

A Project today consists of a single set of schematics (multiple pages, but a single circuit), and multiple board variants for that single circuit. A Project’s isolated scope already realizes the vast majority of the changes that would be needed to include multiple schematics (i.e., multiple circuits) in a single Project. So what if we allow a Project (or Projects) to be nested inside a higher-level Project? This wouldn’t be a reference to an external Project (at least not yet), but rather a real, full Project tree as it stands today.

Here’s where things start acting serendipitous. ProjectLoader::open(), as it stands today, would need little modification to become recursive. It would use the directory structure to determine if it was dealing with a container of Projects or a single Project. If it finds a “projects/” (note plural) directory, it’d walk down and invoke itself again to load each of the individual projects contained under the projects// folder. On the other hand, if it finds “schematics/” and “boards/”, it continues loading the design without going down any further.

A file fidelity check could enforce that the “boards”/“schematics” directories are mutually exclusive with the “projects” directory. We may also want to limit the number of child projects that the container project could hold, as well as the nesting level (at least for now).

The “hierarchy” page I described in my previous post now becomes nearly fully defined: A block is simply a reference to a child Project, with its schematic and board(s) already known. No additional mapping necessary. A future effort could tackle figuring out how to describe connections between child Projects and DRC for verifying connector pin-outs, etc.

Note that with the recursion, the containing Project is completely optional without incurring additional code checks. It only needs to exist if you want to include multiple schematics/circuits (i.e., child Projects) in a single Project.

Additional future features could include “Import Project” and “Export Project”, used to pull an existing Project design into a Project container, or to save a child Project as an independent design.

How this connects to Panelization: We would allow a panels/ directory at either the container level, or the individual design level. A Panel would have the ability to reference any Board files contained within its tree, referenced by UUID. So if you want to put multiple unique designs on a single panel, you just declare a panel at the top level, and include multiple child projects. If you declare the panel at the individual design level, it can include only the layout in that individual design (as an array, presumably).

I’m getting long-winded. I tend to do that when I’m excited. Sorry about that. :folded_hands:

@ubruhin: I came across a more targeted question that I wanted to get your opinion on. As the code stands today, if I were to use LibrePCB to design a panel, it is unclear what mechanism I would use to specify any v-cuts/v-grooves. In KiCad, we can generate a gerber file from a comment or assembly layer, and pass that gerber file along to the manufacturer as part of the package.

It seems that (as things stand today) LibrePCB is only set up to generate gerbers from actual board fab layers, so using a comment/assembly gerber layer is not an option. Perhaps I have missed something.

Regardless, how would you like to see fabrication details such as v-cuts/v-grooves captured in LibrePCB, and subsequently passed to a manufacturer?

v-cuts and v-grooves are actually a good point, currently LibrePCB does not support it at all. This would be a good feature request for LibrePCB 3.x as it seems something quite important. I opened an issue to keep this in mind (feel free to add your comments there):

This is by intention. In contrast to other EDA tools, we do not just provide arbitrary layers which the user then has to assign to corresponding Gerber files etc, because this way the tool does not have any knowledge about what the layers actually do. In LibrePCB I want only layers with a specific, well-defined purpose. Only this way we can make sure that for example the DRC and the 3D viewer can handle those objects accordingly.

Regarding “hierarchic projects” / multiple circuits per project: Here I strongly insist on not overengineering the thing. Those things sound extremely complex and will lead to tons of new problems. I don’t want LibrePCB to be the next Altium (full of features, but unusable due to instability and complexity). For me, the rule is simple: One project represents one PCB. It doesn’t matter if your machine consists of 17 separate PCBs (whether interconnected or not). Every PCB is a separate product, with separate development cycles, separate release cycle, separate versioning, separate circuit, separate Gerber files, - you get the point.

Even for panelizing IMHO it doesn’t make sense to bundle multiple PCBs of your “machine project”. If you need to make a bugfix in one of those 17 PCBs, why should you have to order the other 16 (good) PCBs too if you already ordered them before? I see mainly two different use-cases for panels:

  • Either N times the same board
  • Or completely random boards, not related to a particular “machine project” or so - the user just wants to fill a big panel with lots of PCBs to reduce the price, no matter whether those PCBs are related to each other or not
  • (I agree there is also the use-case to put e.g. 2 interconnected boards into one panel, when you always want to order the same amount of both boards - however, somehow I expect that is done much less often than the two use-cases above)

I understand the point that an ERC could be helpful to work across PCB interconnections. But I really really wonder if that is worth any additional complexity. Maybe a tiny little bit complexity could be acceptable if we find a simple solution for this use-case (e.g., let a project to export its netlist, which can be imported by another projects to specify the connectors behavior). But honestly I still have some doubts if that would be really helpful. For example, even the best ERC cannot detect if you got your connector pinout completely wrong because the flat ribbon cable mirrored the pinout mechanically. So if such a cross-project ERC cannot even detect the simplest, most common errors, what is it worth then at all?

Don’t get me wrong - I am not completely against some kind of “project container”. I do see some use-cases for such a feature, but I just think those use-cases are rather “nice to have” than essential. So they are not worth a lot of complexity. If we can support them in a simple way, good - if not, better let it be completely.

I can understand your perspective and stance, and I am happy to support it. :+1: Thank you for helping me understand your perspective with more clarity.

With your thoughts in mind, I wonder about this – What if panels became a peer to data and projects at the workspace level instead?

  • We may need to add some additional information to the .librepcb-workspace file to help panels find and identify the boards they need to operate, but it shouldn’t be very heavy.
  • Alternatively, a minimum-impact path could be to have the panel editor parse the workspace directory tree itself, but that somehow seems to be a bit of a waste to me.
  • Another approach would be having a globally-scoped (app-level), public table that dereferenced Board UUIDs to a relative file path. That could be built when the workspace was opened, without modifying .librepcb-workspace. :thinking: {That probably already exists, but may not be accessible from the project scope.}

Regardless, the objective would be to leave the project structure alone completely.

Under this plan, a Panel would ALWAYS be a feature of the workspace, never an individual project. If you want to build a panel with N copies of the same board, you only reference one project in the workspace. The “completely random boards” case would impose a requirement that those boards live in the same workspace, but maybe that’s not too bad of an imposition? :person_shrugging:

Full disclosure: I do have a fully working prototype for a Panel tool tab in one of my branches. It can place any Boards in a single project, and has options for tabs, routing, v-cuts, etc. It can even generate gerber files. :smiley:

Disclosure stated, rest assured that I’m happy to massage Panel’s construction and implementation any way you’d like to bring it into compliance with your vision. Please just continue to be patient with me while I work things out. :folded_hands:

Honestly I think for the very common use-case of N copies of the same board, it is simply too cumbersome to do this in some separate “panel project”. As a (professional) user, I’d expect such a panel can be created right in the project of that board, so it is also part of the version control etc.

After discussing and thinking a lot about this thing, I still have the impression that we should ignore the use-case of different boards in a panel for now. Instead, let’s focus on panelizing a board within a project. If we ever want to support creating panels of different boards, we will have to build something like that “project container” – which would just be a feature on top of the existing projects.

Anyway, that is currently nothing I can work on. It simply has too low priority compared to the tons of other open feature requests.

That is nice, but honestly I think it will be a looong way to bring this all into LibrePCB officially. The way from a working prototype (“works for me”) to a solid, clean, well-thought solution, including file format upgrade mechanism, and the confidence and commitment that we really want to maintain such features for the next 20 years, that is a long way. Everything which lands in master will have to be maintained by myself because usually contributors of features just disappear after their initial patch was accepted (“merged, now not my problem anymore”). And my time is limited, so I have to focus on the really important things.

Understood. I’m not trying to force anything. Forgive me, please, if I gave that impression. I do have use cases of my own that I’m trying to support, but I recognize those are my own. I’ll continue to fill out capability in accordance to the established approaches and methods I see in the existing code base. If something needs to be changed in the future, that will be fine.

Also understood. If this is something that doesn’t fit in the roadmap until version 5.0 (just to make up a number), so be it. I appreciate the time you’ve taken to discuss your vision and how this might fit in. Meanwhile, I will continue to study the existing code base and how it works so that I can be more effective at helping.

Thank you.

1 Like