Component Auto-Placement

Intro & Reasoning

For my modular synthesizer project, I need to make a lot of different circuits come to life in Autodesk Eagle’s PCB designer. The first two boards I worked on took me over 10 hours of work each. I know - that’s really slow. One of the tricks for faster PCB creation is using Eagle’s built-in “auto-router”. This feature automatically connects placed components together correctly following the schematic.

However, if you place the components willy-nilly, the algorithm will add new holes in the design after failing to solve the puzzle without them. These holes are not too much of an issue, but more holes equals more soldering. And more soldering means more time that needs to be spent, contributing to more opportunity for error.

Soldering on small traces or pads can be tricky. Too much applied heat can delaminate the copper from the substrate, essentially “breaking” the PCB trace. There are solutions for when this happens; but, bottom line: unnecessary holes should be avoided.

TLDR: I need to place components in an organized way to help Eagle’s auto-router algorithm achieve better results. However, I don’t want to place the components myself. I wrote a Python script to do that for me.

Data

Every circuit can be written as a “netlist”, which is essentially a list of components grouped by the nodes, or “nets”, they are connected to. Here is an example of a netlist from my mixer board exported by EAGLE.

In this example, the components IC1B and R24 will be connected together by some trace on the PCB called IC1_5. Practically, the pins of certain components needs to be taken into account too, such as for op-amps. However, for this version of the script, we only care to put components that share a net/node in the same ballpark, since the auto-router will do the dirty routing work for us.

Data the script will need to work with:

  • A list of grouped components, with each group being a list of strings. Denoted as G.

  • A unique list of components, which are strings. Denoted as C.

Getting the .txt data in this form is just a matter of file I/O using tokens in Python. As a special case, I do not allow the ground (GND) and supply voltage nets in my data. This is because I am using a ground pour in my PCB design, and supply rails can be routed easily on the opposite side of the board from the other nets.

My Algorithm

I acknowledge there are multiple ways to algorithmically place components in the Cartesian plane in an organized fashion. Here is my iterative approach:

  1. Begin an adjacency matrix M by initializing an NxN matrix of zeroes, where N is the length of C.

  2. For each entry E in C, find the lists which contain E in G. For every entry F in those found lists, add 1 to M[x, y], where y and x is the index of E and F in C respectively.

  3. Clear the diagonal of M to zeroes. This finalizes M as our adjacency matrix.

  4. Sum the rows of M vertically to obtain a vector V. This vector V gives us the number of connections each component in C has with other components.

  5. Take the argmax I of V. This will return the index of the first maximum, incase there are multiple maximums in V. This argmax I shows us which component in C has the most connections. Let’s call it the “hub”.

  6. Give the hub Cartesian coordinates such that it will not interfere with other hubs. On first iteration, the coordinates can be (0, 0).

  7. Each non-zero entry in the column I of M becomes a “child” of the hub. Give each of these children Cartesian coordinates relative to its hub using the roots of unity. The x coordinate is the real part, and the y coordinate is the imaginary part.

  8. Print to terminal the commands that will be used to move the hub and its children. The EAGLE command for moving a component is: “MOVE [NAME] (X, Y);” where [NAME], X, and Y are inputs.

  9. Remove the strings associated with the hub and its children from G and C.

  10. Repeat this algorithm until there are no more components in C, or until physical space runs out. Since I am using the free version of EAGLE, my PCB size is limited.

Results

The terminal output will be a long string of commands, which can then be copy-pasted in EAGLE’s command prompt to perform the auto-placement. Unfortunately, inputting so many commands all at once crashes the software; so, it may be better to use pyautogui to automatically input a few commands at a time.

Here’s a video on the current version’s performance:

There is some randomness involved - running the script twice will give different results. I have achieved 0-via results before; but, as shown in the video, the script will not always be optimal. Since the algorithm does not handle the physical properties of the components, it will sometimes overlap components or place them slightly out of bounds. Also, not all the components will be automatically placed, since the script can think that it has run out of manageable space.

I call this script “auto-placement”; but, in its current state, it’s more-so “semi-auto-placement”. While it significantly cuts down the time of component placement, the algorithm needs more work to remove all human intervention. The bugs mentioned above need to be fixed. I also acknowledge that my algorithm is not the best solution for component auto-placement, and I can see a machine learning algorithm performing better. However, I will still count this attempt as a success, considering it takes me under 10 minutes to get it working - much better than 10 hours.

You can download the script here, although it is not user friendly. For use, scroll to the bottom and read the comments on lines 185 and 186.

Previous
Previous

Dolphin “Click Train” Synthesis

Next
Next

The Modular Synthesizer Project