Welcome to PCBmodE’s documentation!

Contents:

Introduction

What is PCBmodE?

PCBmodE is a Python script that takes input JSON files and converts them into an Inkscape SVG that represents a printed circuit board. PCBmodE can then convert the SVG it generated into Gerber and Excellon files for manufacturing.

How is PCBmodE different?

PCBmodE was conceived as a circuit design tool that allows the designer to put any arbitrary shape on any layer of the board; it is natively vector-based. PCBmodE uses open and widely used formats (SVG, JSON) together with open source tools (Python, Inkscape) without proprietary elements (Gerber is an exception). It also provides a fresh take on circuit design and opens new uses for the circuit board manufacturing medium.

PCBmodE uses stylesheets with CSS-like syntax. This seperates ‘style’ from ‘content’, similarly to the relationship of HTML and CSS.

PCBmodE is free and open source (MIT license).

What PCBmodE isn’t

PCBmodE is not a complete circuit design tool. It does not (currently) have a notion of schematics, have design rule checks, or support more than two layers.

PCBmodE is ‘alpha’ software and isn’t as user friendly as we’d like it to be, yet.

Workflow

PCBmodE was originally conceived as a tool that enables the designer to precisely define and position design elements in a text file, and not through a GUI. For practical reasons, PCBmodE does not have a GUI of its own, and uses an unmodified Inkscape for visual representation and some editing that cannot practically be done textually.

A typical PCBmodE design workflow is the following:

  1. Edit JSON files with a text editor
  2. “Compile” the board using PCBmodE
  3. View the generated SVG in Inkscape

Then, optionally

  1. Make modifications in Inkscape
  2. Extract changes using PCBmodE

and then

  1. Back to step 1 or step 2

or

  1. Generate production files using PCBmodE

Note

It is possible to design a complete circuit in a text editor without using Inkscape at all! This would only require generating, or hand crafting, SVG paths for the routing.

Tip

Inkscape does not reload the SVG when it is regenerated by PCBmodE. To reload quickly, press ALT+f and the v.

Tip

Until you get used to it, the extraction process may not do what you expect, so experiment first before designing something that will disappear when you reload the SVG. It might also be practical to design in a separate Inkscape window and then copy over the shapes to the design’s SVG.

Setup

PCBmodE is written and tested with Python 2.7 under Linux. It may or may not work on other operating systems or later versions of Python. With time ‘official’ support for Windows/MAC will be added.

It comes in the form of a installable tool called pcbmode which is run from the command line.

What you’ll need

  • Python 2.7
  • Inkscape
  • Text editor

Installation from Source with Virtualenv

Virualenv is a Python tool that makes it easy to keep applications in their own isolated environments. As a bonus, root permissions are not required. This can come useful when running experimental versions of PCBmodE.

These instructions describe how to build PCBmodE for use in a virtualenv. To be able to build python-lxml (one of PCBmodE’s dependencies) you need to install some system-level development packages. On Debian based systems these are installed like this:

sudo apt-get install libxml2-dev libxslt1-dev python-dev

Fetch the PCBModE source. Stable snapshots are available at https://github.com/boldport/pcbmode/releases. The latest development sources are available via git:

git clone https://github.com/boldport/pcbmode.git

After putting PCBmodE in a directory called pcbmode, run these commands to create a virtualenv in the directory pcbmode-env/ next to it, and install PCBmodE in the virtualenv.

virtualenv pcbmode-env
source pcbmode-env/bin/activate
cd pcbmode
python setup.py install

After installation, PCBmodE will be available in your path as pcbmode. But since it was installed in a virtualenv, the pcbmode command will only be available in your path after running pcbmode-env/bin/activate and will no longer be in your path after running deactivate. You will need to activate the virtualenv each time you want to run pcbmode from a new terminal window.

Nothing is installed globally, so to start from scratch you can just follow these steps:

deactivate         # skip if pcbmode-env is not active
rm -r pcbmode-env
cd pcbmode
git clean -dfX     # erases any untracked files (build files etc). save your work!

Running PCBmodE

Tip

To see all the options that PCBmodE supports, use pcbmode --help

By default PCBmodE expects to find the board files under

boards/<board-name>

relative to the place where it is invoked.

Tip

Paths where PCBmodE looks for thing can be changed in the config file pcbmode_config.json

Here’s one way to organise the build environment

cool-pcbs/

PCBmodE/ boards/

hello-solder/

hello-solder.json hello-solder_routing.json components/

...
cordwood/
...

To make the hello-solder board, run PCBmodE within cool-pcbs

pcbmode -b hello-solder -m

Then open the SVG with Inkscape

inkscape cool-pcbs/boards/hello-solder/build/hello-solder.svg

If the SVG opens you’re good to go!

Note

PCBmodE processes a lot of shapes on the first time it is run, so it will take a noticeable time. This time will be dramatically reduced on subsequent invocations since PCBmodE caches the shapes in a datafile within the project’s build directory.

Components

Components are the building blocks of the board. In fact, they are used for placing any element on board, except for routes. A via is a ‘component’, and a copper pour is defined within a ‘component’ and then instantiated into the board’s JSON file.

Defining components

Components are defined in their own JSON file. The skeleton of this file is the following

{
  "pins":
  {
  },
  "layout":
  {
    "silkscreen":
    {
    },
    "assembly":
    {
    }
  },
  "pads":
  {
  }
}

pins is where the pins of a components are ‘instantiated’. pads contain what pads or pins are in terms of their shapes and drills. Each ‘pin’ instantiates a ‘pad’ from pads''. ``layout contain silkscreen and assembly shapes.

pins

Here’s what a component with two pins looks like
{
  "pins":
  {
  "1":
    {
      "layout":
      {
        "pad": "pad",
        "location": [-1.27, 0],
        "show-label": false
      }
    },
  "2-TH":
    {
      "layout":
      {
        "pad": "pad",
        "location": [1.27, 0],
        "label": "PWR",
        "show-label": true
      }
    }
  }
}

Each pin has a unique key – 1 and 2-TH above – that does not necessarily need to be a number. pad instantiates the type of landing pad to use, which is defined in the pads'' section. ``location is the position of the pin relative to the centre of the component.

PCBmodE can discreetly place a label at the centre of the pin (this is viewable when zooming in on the pin). The label can be defined using label, or if label is missing, the key will be used instead. To not place the label use "show-label": false.

pads

Pads define the shape of pins. Here’s a definition for a simple throughole capacitor

{
  "pins": {
    "1": {
      "layout": {
        "pad": "th-sq",
        "location": [-2, 0]
      }
    },
    "2": {
      "layout":
      {
        "pad": "th",
        "location": [2, 0]
      }
    }
  },
  "layout": {
    "silkscreen": {
      "shapes": [
        {
          "type": "path",
          "value": "m -10.515586,19.373448 c -0.214789,0.0199 -0.437288,0.01645 -0.664669,-0.0017 m -0.514055,0.01247 c -0.202682,0.02292 -0.412185,0.02382 -0.626017,0.01069 m 1.56129,1.209208 c -0.557685,-0.851271 -0.665205,-1.634778 -0.04126,-2.443953 m -0.82831,2.449655 c -0.07502,-0.789306 -0.06454,-1.60669 1.98e-4,-2.441891",
          "location": [0, 0],
          "style": "stroke"
        }
      ]
    },
    "assembly": {
      "shapes": [
        {
          "type": "rect",
          "width": 2.55,
          "height": 1.4
        }
      ]
    }
  },
  "pads": {
    "th": {
      "shapes": [
        {
          "type": "circle",
          "layers": ["top", "bottom"],
          "outline": 0,
          "diameter": 1.9,
          "offset": [0, 0]
        }
      ],
      "drills": [
        {
          "diameter": 1
        }
      ]
    },
    "th-sq": {
      "shapes": [
        {
          "type": "rect",
          "layers": ["top", "bottom"],
          "width": 1.9,
          "height": 1.9,
          "offset": [0, 0],
          "radii": { "tl": 0.3,"bl": 0.3,"tr": 0.3,"br": 0.3 }
        }
      ],
      "drills": [
        {
          "diameter": 1
        }
      ]
    }
  }
}

This would result in this component

_images/polar-cap.png

Here’s a more complex footprint for a battery holder on an ocean-themed board

{
  "pins": {
    "POS-1": {
      "layout":
      {
        "pad": "pad",
        "location": [13.3, 0],
        "rotate": 95
      }
    },
    "NEG": {
      "layout": {
        "pad": "pad",
        "location": [0, 0]
      }
    },
    "POS-2": {
      "layout": {
        "pad": "pad",
        "location": [-13.3, 0],
        "rotate": -95
      }
    }
  },
  "layout": {
    "assembly": {
      "shapes": [
        {
          "type": "rect",
          "layers": ["top"],
          "width": 21.1,
          "height": 19.9,
          "offset": [0, 0]
        }
      ]
    }
  },
  "pads": {
    "pad": {
      "shapes": [
      {
        "type": "path",
        "style": "fill",
        "scale": 1,
        "layers": ["top"],
        "value": "M 30.090397,29.705755 28.37226,29.424698 c 0,0 2.879054,-2.288897 4.991896,-2.270979 2.611383,0.02215 2.971834,2.016939 2.971834,2.016939 l 2.261927,-1.675577 -0.816738,2.741522 0.747218,2.459909 -2.119767,-1.518159 c 0,0 -0.605255,1.760889 -3.359198,1.739078 C 31.737346,32.90704 28.38105,30.56764 28.38105,30.56764 z",
        "soldermask": [
          {
            "type": "path",
            "style": "fill",
            "scale": 1,
            "rotate": 10,
            "layers": ["top"],
            "value": "M 30.090397,29.705755 28.37226,29.424698 c 0,0 2.879054,-2.288897 4.991896,-2.270979 2.611383,0.02215 2.971834,2.016939 2.971834,2.016939 l 2.261927,-1.675577 -0.816738,2.741522 0.747218,2.459909 -2.119767,-1.518159 c 0,0 -0.605255,1.760889 -3.359198,1.739078 C 31.737346,32.90704 28.38105,30.56764 28.38105,30.56764 z"
          },
          {
            "type": "path",
            "style": "fill",
            "scale": 0.5,
            "rotate": 20,
            "location": [0, 4.7],
            "layers": ["top"],
            "value": "M 30.090397,29.705755 28.37226,29.424698 c 0,0 2.879054,-2.288897 4.991896,-2.270979 2.611383,0.02215 2.971834,2.016939 2.971834,2.016939 l 2.261927,-1.675577 -0.816738,2.741522 0.747218,2.459909 -2.119767,-1.518159 c 0,0 -0.605255,1.760889 -3.359198,1.739078 C 31.737346,32.90704 28.38105,30.56764 28.38105,30.56764 z"
          }
        ]
      },
      {
        "type": "circle",
        "layers": ["bottom"],
        "outline": 0,
        "diameter": 2.3,
        "offset": [0, 0]
      }
    ],
    "drills": [
      {
        "diameter": 1.2
      }
    ]
    }
  }
}

This will what it looks like

_images/fish-battery.png

Notice that you can define multiple shapes for the soldermask that are independent of the shape of the shape of the copper.

To control how soldermask shapes are placed, you have the following options:

  • No soldermask definition will assume default placement. The buffers and multipliers are defined in the board’s JSON file
  • "soldermask": [] will not place a soldermask shape
  • "soldermask": [{...},{...},...] as above will place custom shapes

Defining custom solderpaste shapes works in exactly the same way except that you’d use soldepaste instead of soldermask.

layout shapes

Placing components and shapes

Footprints for components and shapes are stored in their own directories within the project path (those can be changed in the configuration file).

This is an example of instantiating a component within the board’s JSON file

{
  "components":
  {
    "J2":
    {
      "footprint": "my-part",
      "layer": "top",
      "location": [
        36.7,
        0
      ],
      "rotate": -90,
      "show": true,
      "silkscreen": {
        "refdef": {
          "location": [
            -7.2,
            2.16
          ],
          "rotate": 0,
          "rotate-with-component": false,
          "show": true
        },
      "shapes": {
        "show": true
        }
      }
    }
  }
}

The key of each component – J2 above – record is the component’s reference designator, or in PCBmodE-speak, ‘refdef’. Note that as opposed to shape types, here layer can only accept one layer.

silkscreen is optional, but allows control over the placement of the reference designator, and whether shapes are placed or not.

Note

The sharp-minded amongst you will notice that ‘refdef’ is not exactly short form of ‘reference designator’. I noticed that fact only in version 3.0 of PCBmodE, way too far to change it. So I embraced this folly and it will forever be.

Shapes

Shapes are the basic building blocks of PCBmodE. Here’s an example of a shape type path:

{
  "type": "path",
  "layers": ["bottom"],
  "location": [3.1, -5.667],
  "stroke-width": 1.2,
  "style": "stroke",
  "value": "m -48.3,0 0,-5.75 c 0,-1.104569 0.895431,-2 2,-2 0,0 11.530272,-0.555504 17.300001,-0.5644445 10.235557,-0.015861 20.4577816,0.925558 30.6933324,0.9062128 C 10.767237,-7.4253814 19.826085,-8.3105055 28.900004,-8.3144445 34.703053,-8.3169636 46.3,-7.75 46.3,-7.75 c 1.103988,0.035813 2,0.895431 2,2 l 0,5.75 0,5.75 c 0,1.104569 -0.895431,2 -2,2 0,0 -11.596947,0.5669636 -17.399996,0.5644445 C 19.826085,8.3105055 10.767237,7.4253814 1.6933334,7.4082317 -8.5422174,7.3888865 -18.764442,8.3303051 -28.999999,8.3144445 -34.769728,8.305504 -46.3,7.75 -46.3,7.75 c -1.103982,-0.036019 -2,-0.895431 -2,-2 l 0,-5.75"
}

This will place an SVG path as a stroke with width 1.2 mm at location x=3.1 and y=5.667. The shape will be placed on the bottom layer of the PCB.

Shape types

For each shape a type must be defined. Below are the available shapes.

Rectangle

Below is an example of a filled rectangle with rounded corners except for the top left corner.

{
  "type": "rect",
  "layers": ["top"],
  "width": 1.7,
  "height": 1.7,
  "location": [6, 7.2],
  "radii": {"tl": 0,
            "tr": 0.3,
            "bl": 0.3,
            "br": 0.3},
  "rotate": 15,
  "style": "fill"
}
type
rect: place a rectangle
layers (optional; default ["top"])
list: layers to place the shape on (even if placing on a single layer, the definition needs to be in a form of a list)
width
float: width of the rectangle
height
float: height of the rectangle
location (optional; default [0,0])
list: x and y coordinates for where to place the shape
radii (optional)
dict: radius of round corners tl: top left radius, tr: top right radius, bl: bottom left radius, br: bottom right radius,
rotate (optional; default 0)
float: rotation, clock-wise degrees
style (optional; default depends on sheet)
stroke or fill: style of the shape
stroke-width (optional; default depends on sheet; ignored unless style is stroke)
float: stroke width
buffer-to-pour (optional; defaults to global setting)
float: custom buffer from shape to copper pour; 0 for no buffer

Circle

Below is an example of a circle outline of diameter 1.7 mm and stroke width of 0.23 mm

{
  "type": "circle",
  "layers": ["bottom"],
  "location": [-3.2, -6],
  "diameter": 1.7,
  "style": "stroke"
  "stroke-width": 0.23
}
type
circle: place a circle
layers (optional; default ["top"])
list: layers to place the shape on (even if placing on a single layer, the definition needs to be in a form of a list)
location (optional; default [0,0])
list: x and y coordinates for where to place the shape
diameter
float: diameter of circle
style (optional; default depends on sheet)
stroke or fill: style of the shape
stroke-width (optional; default depends on sheet; ignored unless style is stroke)
float: stroke width
buffer-to-pour (optional; defaults to global setting)
float: custom buffer from shape to copper pour; 0 for no buffer

Path

Other than simple shapes above, and SVG path can be placed.

{
  "type": "path",
  "layers": ["top","bottom"],
  "location": [3.1, 5.667],
  "stroke-width": 1.2,
  "style": "stroke",
  "rotate": 23,
  "scale": 1.2,
  "value": "m -48.3,0 0,-5.75 c 0,-1.104569 0.895431,-2 2,-2 0,0 11.530272,-0.555504 17.300001,-0.5644445 10.235557,-0.015861 20.4577816,0.925558 30.6933324,0.9062128 C 10.767237,-7.4253814 19.826085,-8.3105055 28.900004,-8.3144445 34.703053,-8.3169636 46.3,-7.75 46.3,-7.75 c 1.103988,0.035813 2,0.895431 2,2 l 0,5.75 0,5.75 c 0,1.104569 -0.895431,2 -2,2 0,0 -11.596947,0.5669636 -17.399996,0.5644445 C 19.826085,8.3105055 10.767237,7.4253814 1.6933334,7.4082317 -8.5422174,7.3888865 -18.764442,8.3303051 -28.999999,8.3144445 -34.769728,8.305504 -46.3,7.75 -46.3,7.75 c -1.103982,-0.036019 -2,-0.895431 -2,-2 l 0,-5.75"
}
type
path: place an SVG path
value
path: in SVG this is the d property of a <path>
layers (optional; default ["top"])
list: layers to place the shape on (even if placing on a single layer, the definition needs to be in a form of a list)
location (optional; default [0,0])
list: x and y coordinates for where to place the shape
diameter
float: diameter of circle
style (optional; default depends on sheet)
stroke or fill: style of the shape
stroke-width (optional; default depends on sheet; ignored unless style is stroke)
float: stroke width
rotate (optional; default 0)
float: rotation, clock-wise degrees
scale (optional; default 1)
float: scale factor to apply to the path
buffer-to-pour (optional; defaults to global setting)
float: custom buffer from shape to copper pour; 0 for no buffer

Text

Placing a text shape is covered in Text.

Copper pours

A copper pour covers the surface area of a board with copper while maintaining a certain buffer from other copper features, such as routes and pads. A ‘bridge’ can connect between a copper feature and a pour.

Defining pours

Pours are defined in their own section in the board’s JSON under shapes

{
  "shapes": {
    "pours":
    [
      {
        "layers": [
          "bottom",
          "top"
        ],
        "type": "layer"
      }
    ]
  }
}

The above will place a pour over the entire top and bottom layer of the board. It’s possible to pour a specific shape, and that’s done just like any other shape definition.

Warning

Since PCBmodE does not have a netlist, those bridges need to be added manually, and careful attention needs to be paid to prevent shorts – there’s no DRC!

Tip

Even if you’re pouring over a single layer, the layers definition only accepts a list, so you’d use ["bottom"], not "bottom".

Defining buffers

The global settings for the buffer size between the pour and a feature is defined in the board’s JSON file, as follows:

"distances": {
  "from-pour-to": {
    "drill": 0.4,
    "outline": 0.25,
    "pad": 0.4,
    "route": 0.25
  }
}

If this block, or any of its definitions, is missing, defaults will be used.

These global settings can be overridden for every shape and route. For routes, it’s done using the pcbmode:buffer-to-pour definition, as described in Routing. For shapes it’s done using the buffer-to-pour definition, as described in Shapes.

Text

One of the unique features of PCBmodE is that any font – as long as it is in SVG form – can be used for any text on the board.

Fonts

SVG fonts have an SVG path for every glyph, and other useful information about how to place the font so the glyphs align. PCBmodE uses that information to place text on the board’s layers.

The folder in which PCBmodE looks for a font is defined in the the configuration file pcbmode_config.json.

{
  "locations":
  {
    "boards": "boards/",
    "components": "components/",
    "fonts": "fonts/",
    "build": "build/",
    "styles": "styles/"
  }
}

When looking for a font file, PCBmodE will first look at the local project folder and then where pcbmode.py is.

Tip

When you find a font that you’d like to use, search for an SVG version of it. Many fonts at http://www.fontsquirrel.com have an SVG version for download.

Defining text

A text definition looks like the following

{
  "type": "text",
  "layers": ["bottom"],
  "font-family": "Overlock-Regular-OTF-webfont",
  "font-size": "1.5mm",
  "letter-spacing": "0mm",
  "line-height": "1.5mm",
  "location": [
    -32.39372,
    -33.739699
  ],
  "rotate": 0,
  "style": "fill",
  "value": "Your text\nhere!"
}
type
text: place a text element
layers (optional; default ["top"])
list: layers to place the shape on (even if placing on a single layer, the definition needs to be in a form of a list)
font-family
text: The name of the font file, without the .svg
font-size
float: font size in mm (the mm must be present)
value
text: the text to display; use \n for newline
letter-spacing (optional; default 0mm)
float: positive/negative value increases/decreases the spacing. 0mm maintains the natural spacing defined by the font
line-height (optional; defaults to font-size)
float: the distance between lines; a negative value is allowed
location (optional; default [0, 0])
list: x and y to place the center of the text object
rotate (optional; default 0)
float: rotation, clock-wise degrees
style (optional; default depends on sheet)
stroke or fill: style of the shape
stroke-width (optional; default depends on sheet; ignored unless style is stroke)
float: stroke width

Routing

Routing, of course, is an essential part of a circuit board. PCBmodE does not have an auto-router, and routing is typically done in Inkscape, although theoretically, routing can be added manually in a text editor. All routing shapes reside in the routing SVG layer of each PCB layer.

Important

Make sure that you place the routes and vias on the routing SVG layer of the desired PCB layer. To choose that layer either click on an element in the layer or open the layer pane by pressing CTRL+SHIFT+L.

Important

In order to place routes, make sure that Inkscape is set to ‘optimise’ paths by going to File->Inkscape Preferences->Transforms and choosing optimised under Store transformation.

Adding routes

Choose the desired routing SVG layer. Using the Bezier tool (SHIFT+F6) to draw a shape.

For a filled shape, make sure that it is a closed path and in the Fill and stroke pane (SHIFT+CTRL+F) click on the flat color button on the Fill tab, and the No paint (marked with an X) on the Stroke point tab.

For a stroke, in the Fill and stroke pane (SHIFT+CTRL+F) click on the No paint button on the Fill tab, and the Flat color on the Stroke point tab. Adjust the stroke thickness on the Stroke style tab.

Note

Shapes can be either stroke or fill, not both. If you’d like a filled and stroked shape, you’ll need to create two shapes.

Finally, you must move the shape with the mouse or with the arrows.

Note

When creating a new shape Inkscape adds a matrix transform, which is removed when the shape is moved because of the optimise settings as described above. This minor inconvenience is a compromise that greatly simplifies the extraction process.

If the route is placed where there is a copper pour, it will automatically have a buffer around it that’s defined in the board’s configuration. Sometimes, it is desirable to reduce or increase this buffer, or eliminate it completely in order to create a bridge (for example when connecting a via to a pour). This is how it is done:

  1. Choose the route
  2. Open Inkscape’s XML editor (SHIFT+CTRL+X)
  3. On the bottom right, next to set remove what’s there and type in pcbmode:buffer-to-pour
  4. In the box below type in the buffer in millimeters (don’t add ‘mm’) that you’d like, or 0 for none
  5. Press set or CTRL+ENTER to save that property

Tip

Once you’ve created one route, you can simply cut-and-paste it and edit it using the node tool without an additional settings. You can even cut-and-paste routes from a different design.

Adding vias

Vias are components just like any other. There are placed just like other components, but in the routing file ``<design_name>_routing.json”, not the main board’s JSON.

You can assign a unique key to the via, but that will be over-written by a hash when extracted.

Note

Since vias are components, anything could be a via, so if it makes sense to place a 2x2 0.1” header as a “via”, that’s possible.

Important

Don’t forget to extract the changes!

Extraction

One of the common steps of the PCBmodE workflow is extracting information from the SVG and storing it in primary JSON files.

The following will be extracted from the SVG:

  • Routing shapes and location
  • Vias’ location
  • Components’ location and rotation
  • Documentation elements’ location
  • Drill index location

That’s it.

Note

It’s quite likely that more information will be extracted in the future to make the design process require fewer steps. Architecturally, however, the use of a GUI is meant only to assist the textual design process, not replace it.

Other information needs to be entered manually with a text editor. A great tool in this process is Inkscape’s built-in XML editor (open with SHIFT+CTRL+X) which allows you to see the path definition of shape (the d property) and copy it over to the JSON file.

Tip

Since some shapes (pours, silkscreen, etc.) are not extracted, it’s sometimes a bit of a guesswork to get the location just right. To do that in a single iteration, use the XML editor to change the transform of the shape (press CTRL+ENTER to apply) until the position is right. Then copy over the coordinates for that shape to the JSON file. Note that Inkscape inverts the y-axis coordinate, so when entering it into the JSON invert it back.

Layer control

When opening a PCBmodE SVG in Inkscape, the board’s layers can be manipulated by opening the layer pane (CTRL+SHIFT+L). Each layer can then be set to be hidden/visible or editable/locked. The default for each layer is defined in utils/svg.py

layer_control = {
  "copper": {
    "hidden": False, "locked": False,
    "pours": { "hidden": False, "locked": True },
    "pads": { "hidden": False, "locked": False },
    "routing": { "hidden": False, "locked": False }
  },
  "soldermask": { "hidden": False, "locked": False },
  "solderpaste": { "hidden": True, "locked": True },
  "silkscreen": { "hidden": False, "locked": False },
  "assembly": { "hidden": False, "locked": False },
  "documentation": { "hidden": False, "locked": False },
  "dimensions": { "hidden": False, "locked": True },
  "origin": { "hidden": False, "locked": True },
  "drills": { "hidden": False, "locked": False },
  "outline": { "hidden": False, "locked": True }
}

but can be overridden in the board’s configuration file. So, for example, if we wish to have the solderpaste layers visible when the SVG is generated, we’d add

{
  "layer-control":
  {
    "solderpaste": { "hidden": false, "locked": true }
  }
}

Or if we’d like the outline to be editable (instead of the default ‘locked’) we’d add

{
  "layer-control":
  {
    "solderpaste": { "hidden": false, "locked": true },
    "outline": { "hidden": false, "locked": false }
  }
}

Tip

The reason that some layers are locked by default – ‘outline’ is a good example – is because they are not edited regularly, but span the entire board so very often take focus when selecting objects. Locking them puts them out of the way until an edit is required.

Tutorial: hello-solder

The ‘hello-solder’ is a fun design for learn how PCBmodE by example.

_images/board.png

Setup

Get the boards repository from here and follow the instructions Setup to ‘compile’ the board. This command should do it

pcbmode -b hello-solder -m

Then open the SVG you produced with Inkscape

inkscape path/to/project/boards/hello-solder/build/hello-solder.svg

Once opened, open the layers pane by pressing CTRL+SHIFT+L and get familiar with the layers of the board by making some hidden and visible.

Outline

Using the layer pane hide all layers except for outline. This shape is defined by an SVG path. In SVG (actually XML) is looks like this

<path
d="m -16.699260,-6.454745 c -2.780854,0.8264621 -4.806955,3.3959901 -4.806955,6.44592474 0.0,3.04953526 2.025571,5.63383146 4.805863,6.46294446 0.373502,0.1206099 0.541906,0.3377362 0.36641,0.7166985 -0.537601,0.9664023 -0.841925,2.0765939 -0.841925,3.2625791 0.0,3.718159 3.019899,6.738056 6.738055,6.738056 1.1862717,0.0 2.2968105,-0.30644 3.2633909,-0.844923 0.2779016,-0.144746 0.6338321,-0.09921 0.7184502,0.343724 0.8185077,2.79334 3.3927864,4.831546 6.45156129,4.831546 3.06962611,0.0 5.66024241,-2.052348 6.47040841,-4.860911 0.097465,-0.315553 0.453736,-0.434303 0.7700817,-0.273567 0.9522855,0.514048 2.0438307,0.804131 3.2017325,0.804131 3.718159,0.0 6.729236,-3.019897 6.729236,-6.738056 0.0,-1.1177297 -0.269937,-2.1676049 -0.750914,-3.0935477 -0.277868,-0.520065 0.07101,-0.817639 0.379848,-0.9166584 2.730845,-0.859225 4.710233,-3.4176958 4.710233,-6.43201596 0.0,-2.98855014 -1.945688,-5.51459174 -4.640357,-6.39242304 -0.362382,-0.1152866 -0.660925,-0.5371332 -0.411209,-1.0139163 0.45685,-0.9074068 0.712399,-1.9307068 0.712399,-3.0182436 0.0,-3.718158 -3.011077,-6.746875 -6.729236,-6.746875 -0.165351,0.02476 -0.410376,-0.219946 -0.219238,-0.595553 0.129165,-0.314741 0.201599,-0.658879 0.201599,-1.018404 0.0,-1.496699 -1.2196914,-2.707569 -2.7163892,-2.707569 -1.0789126,0.0 -2.0094311,0.629927 -2.4450348,1.542338 -0.119881,0.280927 -0.5068697,0.412753 -0.8079468,0.144495 -1.1862758,-1.048846 -2.7462918,-1.686833 -4.45521281,-1.686833 -3.12285319,0.0 -5.73997179,2.120433 -6.49986279,5.003566 -0.079222,0.219391 -0.1844607,0.406694 -0.6008463,0.210249 -0.9826557,-0.564791 -2.1176191,-0.892287 -3.3326933,-0.892287 -3.718156,0.0 -6.738055,3.028717 -6.738055,6.746875 0.0,1.0923431 0.258164,2.1203908 0.718982,3.0310127 0.257646,0.4766398 0.146527,0.778116 -0.242375,0.9476435 z"
style="stroke-width:0.05;"
pcbmode:style="stroke"
transform="translate(0, 0)"
/>

You can view this by clicking on the outline and pressing SHIFT+CTRL+X to invoke Inkscape’s built-in XML editor. This shows you the group the outline belongs to, so collapse the list on the left and choose the single element in the group. This should show you something like the above.

Tip

Can’t select the outline? That’s because the layer is locked. On the layer pane click the lock next to the outline layer.

Now open hello-solder.json in the project directory with a text editor. The shape above was created using the following definition

{
  "outline": {
    "shape": {
      "type": "path",
      "value": "m -16.698952,-6.4545028 c -2.780854,0.8264621 -4.806955,3.3959901 -4.806955,6.44592474 0,3.04953526 2.025571,5.63383146 4.805863,6.46294446 0.373502,0.1206099 0.541906,0.3377362 0.36641,0.7166985 -0.537601,0.9664023 -0.841925,2.0765939 -0.841925,3.2625791 0,3.718159 3.019899,6.738056 6.738055,6.738056 1.1862717,0 2.2968105,-0.30644 3.2633909,-0.844923 0.2779016,-0.144746 0.6338321,-0.09921 0.7184502,0.343724 0.8185077,2.79334 3.3927864,4.831546 6.45156129,4.831546 3.06962611,0 5.66024241,-2.052348 6.47040841,-4.860911 0.097465,-0.315553 0.453736,-0.434303 0.7700817,-0.273567 0.9522855,0.514048 2.0438307,0.804131 3.2017325,0.804131 3.718159,0 6.729236,-3.019897 6.729236,-6.738056 0,-1.1177297 -0.269937,-2.1676049 -0.750914,-3.0935477 -0.277868,-0.520065 0.07101,-0.817639 0.379848,-0.9166584 2.730845,-0.859225 4.710233,-3.4176958 4.710233,-6.43201596 0,-2.98855014 -1.945688,-5.51459174 -4.640357,-6.39242304 -0.362382,-0.1152866 -0.660925,-0.5371332 -0.411209,-1.0139163 0.45685,-0.9074068 0.712399,-1.9307068 0.712399,-3.0182436 0,-3.718158 -3.011077,-6.746875 -6.729236,-6.746875 -0.165351,0.02476 -0.410376,-0.219946 -0.219238,-0.595553 0.129165,-0.314741 0.201599,-0.658879 0.201599,-1.018404 0,-1.496699 -1.2196914,-2.707569 -2.7163892,-2.707569 -1.0789126,0 -2.0094311,0.629927 -2.4450348,1.542338 -0.119881,0.280927 -0.5068697,0.412753 -0.8079468,0.144495 -1.1862758,-1.048846 -2.7462918,-1.686833 -4.45521281,-1.686833 -3.12285319,0 -5.73997179,2.120433 -6.49986279,5.003566 -0.079222,0.219391 -0.1844607,0.406694 -0.6008463,0.210249 -0.9826557,-0.564791 -2.1176191,-0.892287 -3.3326933,-0.892287 -3.718156,0 -6.738055,3.028717 -6.738055,6.746875 0,1.0923431 0.258164,2.1203908 0.718982,3.0310127 0.257646,0.4766398 0.146527,0.778116 -0.242375,0.9476435 z"
    }
  }
}

Since this is the board’s outline PCBmodE assumes that its placement is at the center (that is location: [0,0]) and that the style is an outline.

Let’s try something. In Inkscape, modify the path using the node tool (press F2). Using the XML editor cut-and-paste the path into the board’s JSON file, replacing the existing outline path. Now recompile the board using the same command as above.

When it’s done, back in Inkscape, press ALT+F and then V to reload. Click yes and see your shape used as an outline. Notice that the shape is centered – it’s always like that with PCBmodE, all coordinates are relative to the center of the board. Also, the dimensions for the new outline are calculated and added automatically.

Components

Placing components is done by “instantiating” a component that is defined in another JSON file in the components directory within the project. Here’s an example from hello-solder.json for reference designator R2

{
  "R2": {
    "footprint": "0805",
    "layer": "top",
    "location": [
      5.3,
      5.3
    ],
    "rotate": 45,
    "show": true
  }
}

R2 is the unique name for this instantiation of footprint 0805. It can be any unique (for the design) name, but convention is to keep it short, one or two letters followed by a number.

Tip

There are no hard rules about reference designator format and prefixes, so they vary depending on the context. Wikipedia has a list that you can follow in the absence of other guidelines.

The footprint for 0805 is defined in the file

components/0805.json

Open it with a text editor.

{
"pins":
  {
  "1":
    {
      "layout":
      {
        "pad": "pad",
        "location": [-1.143, 0]
      }
    },
  "2":
    {
      "layout":
      {
        "pad": "pad",
        "location": [1.143, 0],
        "rotate": 180
      }
    }
  }
}

We define two pins (we’ll also call surface mount pads “pins”) called 1 and 2. For each of these we instantiate pad as the shape and place it at the coordinate defined in location (remember, placement is always relative to the center). We rotate pin 2 by 180 degrees.

Tip

Pin names can be any text, and a label can be added too. See Components for more detail.

The pad is defined in the same file, like so

{
  "pads":
  {
    "pad":
    {
      "shapes":
      [
        {
          "type": "rect",
          "layers": ["top"],
          "width": 1.542,
          "height": 1.143,
          "radii": {"tl": 0.25, "tr": 0, "bl": 0.25, "br": 0}
        }
      ]
    }
  }
}

Of course it’s possible to define more than one pad, and it’s even possible to have multiple shapes as part of a single pad in order to create complex shapes. See Shapes for more on defining shapes.

We would like to now add a silkscreen shape and assembly drawing. Here’s how we do that

{
  "layout":
  {
    "silkscreen":
    {
      "shapes":
      [
        {
          "type": "rect",
          "width": 0.3,
          "height": 1,
          "location": [0, 0],
          "style": "fill"
        }
      ]
    },
    "assembly":
    {
      "shapes":
      [
        {
          "type": "rect",
          "width": 2.55,
          "height": 1.4
        }
      ]
    }
  }
}

Here’s an exercise: instead a small silkscreen square, draw an outline rectangle with rounded corners around the component’s pads. For a bonus, add a tiny silkscreen dot next to one of the pads.

Shapes

Routing

Documentation and indexes

Extraction

Production

Indices and tables