--- jupyter: description: 'An Eagle board in planex2d: px.FromKiCad converts an Eagle .brd file with KiCad 10''s kicad-cli, fills its copper pours, and returns its layers as shapes, the copper named by net. The example is SparkFun''s Pro Micro, checked against the 0.1 inch grid of a 24-pin DIP.' --- # Eagle Eagle saves a board as an XML file with the extension `.brd`, from Eagle 6 on. `px.FromKiCad` converts it with `kicad-cli`, the command line tool of KiCad 10 or later, and returns the same dict of layers as for a KiCad board. A binary board from an Eagle version before 6 has to be opened in Eagle and saved again first. See [KiCad, Altium, Eagle and more](index.md) for how the tool is found and how the copper pours of a converted board are filled. ```python import collections import planex as px ``` ```python nbsphinx="hidden" from docs_figures import Row ``` ## The board The example is the Pro Micro from SparkFun Electronics, a microcontroller board with an ATmega32U4, as it is in the folder `Hardware/v20` of SparkFun's repository. The design is licensed under CC BY-SA 4.0 by SparkFun Electronics. Download: [SparkFun_Pro_Micro.brd](SparkFun_Pro_Micro.brd) and SparkFun's [license notes](SparkFun_Pro_Micro_LICENSE.txt). ```python board = px.FromKiCad("SparkFun_Pro_Micro.brd") for name, layer in board.items(): print(f"{name:10} {len(layer.faces):4} faces, {1e6 * layer.mass:9.2f} mm²") ``` The two copper layers have their faces named by net and the drill holes cut out, and the ground pours on both sides come filled. The other layers hold what KiCad prints there, the silkscreen, solder mask and paste openings, the courtyard and the fabrication drawings. The text on the board is not read yet, and `FromKiCad` reports how much it left out. ## Copper per net On both layers, the ground net has the largest share of the copper (Figure 1): ```python fcu, bcu, outline = board["F.Cu"], board["B.Cu"], board["Edge.Cuts"] for name, layer in (("F.Cu", fcu), ("B.Cu", bcu)): area = collections.Counter() for f in layer.faces: area[f.name or "(no net)"] += 1e6 * f.mass print(name, len(area), "nets, the largest:", [(net, round(a, 1)) for net, a in area.most_common(3)]) ``` ```python nbsphinx="hide-input" copper = {"face": "#c87533", "ink": "#6b3410", "dashed": [outline], "lw": 0.4} Row((fcu, "F.Cu, the top layer", copper), (bcu, "B.Cu, the bottom layer", copper), caption="The copper layers of an Eagle board, read through KiCad") ``` The solder mask openings `F.Mask` and the silkscreen `F.SilkS` laid over the outline show the board as it comes from the manufacturer (Figure 2). ```python nbsphinx="hide-input" top = {"face": "#2f6b45", "ink": "#1d4029", "lw": 0.4, "fills": [(board["F.Mask"], "#d9b46c"), (board["F.SilkS"], "#f4f4ee")]} Row((outline, "F.Mask and F.SilkS over the outline", top), caption="The top of the Pro Micro") ``` ## A check against the DIP grid The Pro Micro plugs into a breadboard or a socket like a 24-pin DIP, with two rows of 12 pins on a 0.1 inch grid and the rows 0.6 inch apart. Its pins are the 24 plated holes of 0.85 mm, which are cut out of the outline. Their centers and the size of the board, in inches: ```python inch = 25.4e-3 pins = [] for hole in outline.faces[0].inner: (x0, y0), (x1, y1) = hole.bounding_box if abs(x1 - x0 - 0.85e-3) < 1e-6: pins.append(((x0 + x1) / 2, (y0 + y1) / 2)) x = sorted(p[0] for p in pins) first = pins[0] off = max(abs(d / (0.1 * inch) - round(d / (0.1 * inch))) * 0.1 * inch for p in pins for d in (p[0] - first[0], p[1] - first[1])) (x0, y0), (x1, y1) = outline.bounding_box print(len(pins), "pins, rows", (x[-1] - x[0]) / inch, "inch apart, largest distance from the 0.1 inch grid", off, "m") print("board", (x1 - x0) / inch, "x", (y1 - y0) / inch, "inch") ``` The pins lie on the grid to rounding, and the board measures 0.7 × 1.3 inch. Eagle stores the positions in millimeters, such as 15.24 for a pin six steps up the grid, and the conversion through KiCad keeps them to rounding. ## The board in 3D With a stackup instead of a layer name, `FromKiCad` returns the board as one glued OpenCASCADE shape, as described in [The board in 3D](kicad.md#The-board-in-3D) on the KiCad page. The Eagle file stores no stackup, and the manufacturers' tables in `px.stackups` hold boards of four and six layers, so a two-layer board takes its stackup as a dict, from the number of copper layers to the dielectric thicknesses in millimeters. A common board of 1.6 mm has a core of about 1.5 mm between its two copper layers: ```python from ngsolve_webgpu.jupyter import Draw solid = px.FromKiCad("SparkFun_Pro_Micro.brd", {2: [1.5]}) print("solids", [s.name for s in solid.solids], "|", sum(1 for f in solid.faces if f.name == "pth"), "plated hole walls") Draw(solid, settings={"Objects": {"Edges": False}}) ```