Wednesday 8 February 2017

Import a RF design (and logos) from svg, png or Gerber files into Kicad

KiCad is a wonderful software for PCB designing, it is open-source and can handle the complete workflow from the schematic to the final layout.

Unfortunately, it is not (yet) intended for RF circuit and antenna design. In these cases, a suitable program should be used, which could be ADS, CST, HFSS, or others. These are expensive but, unfortunately, the open-source tools are still not complete enough. I generally use multiple open-source tools depending of the requirements and quite often compare the results to evaluate the correctness.

Long story short, I was facing with the need to create a PCB by incorporating some custom Inductive Power Transfer coils, which I could export to a Gerber file from CST and some patch antennas and matching circuits, from ADS. The idea was to import the different parts from the Gerbers into different footprints, which are then assigned to schematics blocks and placed on the PCB.

There are no ways (yet) to get it simply by using some pre-baked functions, but some tricks are needed.

This post is a walk-through different options that can be used. I try to compare the options and outline the strengths of each one.

Notice that the same methods can be used to produce custom logos or any custom shape.

Shape conversion

Kicad’s Bitmap to Component Converter

This is method is probably the simplest and requires only simple workarounds, simple enough to be done using a text editor, and provides an very good final PCB. It is suitable for for logos and complex shapes. The disadvantage is that the file can be quite big in size because of its raster nature, anyway I have not yet experienced any issue because of the size (in bytes) of the the footprint. At worst, for example with several footprints in a single board, it might make Kicad sluggish on old pc.

  1. The Gerber (or another format) is converted to a pdf or svg.
  2. The file is opened with Inkscape, the alpha channel (Kicad 5 might work even without that) is changed to 255 (File -> Document Properties -> Background Color) and, by selecting the circuit to be included in the footprint, it is then exported as a png image, possibly with a resolution higher than 600dpi (2400dpi or 4800dpi is better).
  3. From the main Kicad window, open the tool bitmap2component, load the png, if required choose negative and/or an appropriate threshold than makes the Black&White image well defined, then export as kicad_mod. Unfortunately, the tool can only create layers that are not copper, and a workaround is needed to move the layer from SilkScreen to a Cu layer.
  4. Open the .kicad_mod file with a text editor (Kwrite, Notepad++) (or, if you are brave enough, using perl or Python with a regex) and replace the (layer F.SilkS) with (layer F.Cu) for the front copper layer or with (layer B.Cu) for the bottom copper layer. Notice that layer in (module NAME (layer F.Cu) means the default layer for placement of the component. It is normally F.Cu and can be flipped in the editor if required (F hotkey).
  5. From the main Kicad window, open the PCB Footprint Editor, import the kicad_mod file from the file menu, add the pads. Remind that vias, if required, need to be added as pads. My hint is to number the I/O pads with numbers (1, 2, 3, …) and the vias using the ~ as pad number (it is like a no-number).
  6. Save it in a custom library, assign the footprint to a custom symbol from the schematic and then place it in the pcb. You can even use the same png to create a custom symbol and can be done using again bitmap2component without any particular workaround. In this way the schematic will be pretty nice (ADS does something quite similar for the schematic symbol). See the Kicad Doc for more help on this last bullet point.

Kicad’s Gerber to PcbNew converter

This is method is is probably the most complex and error prone of all the methods outlined here. It does not work with all possible Gerbers and it is not easy to know in advance when it will fail. On the other hand, it provides the most accurate translation of the Gerber file and using the same number of shapes as used in the Gerber. The result is a footprint file that has a small size (in bytes).

It is suitable only for footprints that have a Gerber parent, for example exported from ADS. It might require some tweaks which need a bit of experience to be properly done, as they are not known in advance and they sometimes involve a bit of creativity.

  1. The Gerber (this time needs to be a gerber) is opened with GerbView and exported to PcbNew (from the File menu), hence to a .kicad_pcb file.
  2. The issue is to convert the kicad_pcb to a kicad_mod, which is quite dependent on the Gerber file used as input. From the question here we can get some hints for the conversion. Basically, the segment is replaced by fp_line and the (net x) is removed, as the footprint does not have a netlist but only pads for connecting to the outside world. It replaces gr_poly with fp_poly.
  3. The via is replaced by a pad on all copper layers. the arguments are different and hence this should be done carefully. The pad number could be set to ~. For example:
    (pad ~ thru_hole circle (at 72.39 78.73999999999999) (size 1.3 1.3) (drill 0.6) (layers F.Cu B.Cu))
    
  4. A header has to be added above the text:
    (module ModuleName
    (layer F.Cu)
    (at 0.000000 0.000000 0.000000)
    (descr "Module Description")
    
  5. A footer is added below:
    )
    

I tried putting up a regex using python to do the all the above substitutions. It is probably incomplete, comment if you find issues. Adding also a possible fix would be ideal.

#!python3
import re


def process_file(infile, outfile):
    """Process the body of a pcb file."""
    # Define header and footer
    header = '''\
(module ModuleName
 (layer F.Cu)
 (at 0.000000 0.000000 0.000000)
 (descr "Module Description")

  (fp_text reference REF** (at 0 -2.7) (layer F.SilkS)
       (effects (font (size 1 1) (thickness 0.15)))
  )
  (fp_text user %R (at 0 0) (layer F.Fab)
       (effects (font (size 0.6 0.6) (thickness 0.09)))
  )

'''

    footer = '''\
)
'''
    outfile.write(header)

    for line in infile:
        # segments
        m = re.search(r'(\s*)\(segment(.*)\s\(net\s0\)', line)
        if m:
            outfile.write(m.expand(r'\1(fp_line\2)\n'))
            continue
        # vias
        m = re.search(
            r'(\s*)\(via(.*)\(size\s([0-9.]*)\)\s(.*)\s\(net\s0\)', line
                )
        if m:
            outfile.write(
                m.expand(r'\1(pad ~ thru_hole circle\2(size \3 \3) '
                         r'(drill 0.6) \4)\n')
                )
            continue
        # gr
        m = re.search(r'(\s*\()gr(_.*\))', line)
        if m:
            outfile.write(m.expand(r'\1fp\2\n'))
            continue
        m = re.search(r'^(\s*(?:\(xy \d+.\d+ \d+.\d+\)\s?)+)$', line)
        if m:
            outfile.write(m.expand(r'\1'))
            continue
        m = re.search(r'^(\s*(?:\(xy \d+.\d+ \d+.\d+\)\s?)+)(\)\(layer .*\) '
                      r'\(width .*\) \))', line)
        if m:
            outfile.write(m.expand(r'\1\2\n'))
            continue
    outfile.write(footer)


if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("infile")
    parser.add_argument("outfile")
    args = parser.parse_args()

    with open(args.infile, 'r') as infile, open(args.outfile, 'w') as outfile:
        process_file(infile, outfile)
        print(args.outfile + ' has been generated from ' + args.infile)
This can be called as (if the python script is placed in the same folder):
python3 pcb_to_mod.py input.kicad_pcb output.kicad_mod

I think it can be also imported and the function called from kicad’s scripting editor.

  1. Then, by using the footprint editor (GUI), it is possible to change the smd pads to smd from thru_hole and to change their shape, position, layers and so on. To do this double click over each pad. Those pads can be used to place components inside the footprint. For example a lumped capacitor for the matching circuit.

Inkscape’s plugin svg2shenzen

svg2shenzen requires Inkscape and can produce arbitrary footprints quite easily. At the moment of writing, to get the script to work on Linux you need to set it manually to be executable:


chmod +x ~/.config/inkscape/extensions/svg2shenzhen/bitmap2component_linux64

See also Fix file permission on Linux and directly install using git and missing chmod +x on linux. If the maximum resolution is not good enough, it is possible to modify the file ~/.config/inkscape/extensions/svg2shenzhen_export.inx and change the line with the maximum of 2000 (Increase maximum dpi export #54)

<param name="dpi" type="int" min="0" max="2000" _gui-text="Export DPI (default: 600)">600</param>
to 10000, which, from my tests, is the real limit of the exporter:
<param name="dpi" type="int" min="0" max="10000" _gui-text="Export DPI (default: 600)">600</param>

If this is not yet enough, you can export only a magnified version of the copper layers, make them as pads, and then from the custom shape primitives menu it is possible to transform them and scale the pad down to the original size. By copying the pads in the .kicad_mod file, using a text editor, in the other file (not magnified) containing the other layers it is possible to go beyond 10000 dpi. The graphical part cannot be scaled and therefore are only only limited to 10000 dpi. Considering that at 10000 dpi the size of a dot is already around 2.54um, it is quite difficult to find uses for higher resolutions. It is anyway possible! How to create pads is discussed in a following section.

This method has the advantage to start from a vector representation of the shape and that, at least theoretically, can use all the possible primitives in kicad, potentially creating the best shape. It can create all the complex shapes of the bitmap2component but potentially using a minimum number of shapes. It can also create multiple layers. The input file must be svg or pdf or a file-type that can be opened by Inkscape.

The current implementation of svg2shenzen returns a footprint containing fp_poly elements.

Kicad Step Up

See also the Kicad Forum

When the footprint is made into a mechanical CAD, in particular FreeCAD, this can be converted to a very high quality footprint using the great Kicad Step Up plugin. It makes probably the footprint with the minimum number of primitives, but at the moment of writing it still has some limitations. For example the custom shapes cannot contain holes inside, while this is supported by the other methods. A workaround is to divide the shape in two with overlapping edges, which will result into the original connected space with holes, but requires more effort. I am sure those will be resolved in the future, therefore I think this method has a big advantage if the shape needs to be done into a mechanical CAD. It is still possible to export to svg and use the other methods, but this will be more straightforward.

Even if a bit off topic, this plugin is also super useful to make 3D models to be used into Kicad.

See also the Kicad Forum for more information

Which method?

This is a tough question to answer.

The method I usually try first when I have a Gerber is the PcbNew converter using the Python script. When it works, sometimes with a bit of additional manual editing, the result is quick and generally very good. When it fails, the Gerber needs to be plotted to an svg or pdf and then the solution is to try the other methods.

The next method, particularly useful when making logos or complex shapes, is the svg2shenzen. I generally use this if I make the shape on Inkscape.

As said before, the StepUp method is useful if the shape was done in FreeCAD. Sometimes it is very convenient but required a bit of trial and error.

I initially started using the method with bitmap2component with Kicad 4, as it was the only reliable method. I have to admit that I still use it when I need a quick job, as it is still reliable. It is the easiest but probably provides the result that is less optimized. Use it when the other methods are failing. Each layer need to be done separately and the layers merged in the text file.

A combination of all the methods are also possible, merging the shapes manually in the text files.

The last option, which I didn’t include in the list, is to create the shapes manually from zero. This is quite tedious, in particular because there is not any official syntax reference for footprints, but can be useful to make optimized shapes, especially if generated from scripts. The official reference has the S-expression syntax for PcbNew, available here. I found a non official one from Compuphase but it might be outdated. Use the S-expression part to get an idea. Generally, the syntax is very similar to the PcbNew and the changes are usually simple, as gr to fp. See also the previous sections to grasp a bit more of the syntax.

DRC

Most of the methods discussed above, without including the Kicad StepUp, are using graphical shapes (as fp_poly) which were NOT DRC compliant and did not trigger an error if a track crosses those copper graphical lines.

As of Kicad 5.1.6, I noticed that the DRC gives an error if a track tries to cross a graphical line on the same copper layer. This is a new feature that will allow many more possibilities and is very welcome. It is not yet working with fp_poly and therefore I don’t call it fully DRC compliant.

To have a fully DRC compliant footprint, a trick is required and works only with Kicad 5, that introduced custom shaped footprints and I am currently using Kicad 5.1.4.

Add a small SMD pad into the copper areas (one for each closed area), select the pad and the area, right click and use the function “Create pad from the selected shapes”. The copper area is then magically converted to a custom shaped pad! The DRC will be now fully supported! I think this is a really game-changing feature!

An additional note is required. Imagine you want to make a coil, which is a single piece of copper, you convert it to a pad, give it a number, let’s say 1, and then place another pad on the other side, let’s say 2, to place the second connection.

There are two issues in this procedure. The first is that the the DRC will complain, since pad 2 is shorted on pad 1 and therefore the clearance between tracks is not sufficient. In KiCad, the concept of a line making a component is not contemplated (as it is on RF EDAs, as ADS). The second issue is that the connection to the coil can be done everywhere and not only at the extremes, again because the component cannot be made from a single copper track.

What I suggest is the following. Convert the coil in two pads with different numbers but by leaving a gap in the middle of the coil, not next to pads. Then create a small graphic polygon or line to connect the pads together and place the graphical element on the proper copper layer. This will cheat the DRC by getting it to believe that those are not connected. It is not perfect, as theoretically keep out zones should be used to avoid lines in between the gaps, but if the gap is made just a little bit bigger than the minimum clearance then there should be no track that can fit this gap (for example 0.3mm). For what I have seen this is the most effective method.

Inner Layers

In cases when the footprint requires copper tracks on the inner layers, a workaround is required and some limitations will be introduced.

Kicad’s footprint editor does not support pads in the inner layers and it will not even shows any layer that is not F.Cu or B.Cu. A workaround to this is to place the additional layers on some other available layers that are visible on the footprint editor, like Eco, Dwgs etc as graphical shapes.

If those are using fp_lines (graphical lines), then the DRC will be able to show conflicts on the inner layers, otherwise by using fp_poly, the DRC will not be available and extra care should be used to avoid conflicts, with the suggestions to avoid routing on those areas in the inner layers (for example with keepout areas or by not using those inner layers at all for routing). Remember again that pads cannot be placed in internal layers, so the custom pad method explained above cannot be used in inner layers.

The footprint can be then opened with a text editor and the layer changed manually. For example, if the shape uses Eco1.User layer and that layer is not used anywhere else, it is possible to replace all the occurrences of Eco1.User with In1.Cu (or another layer). When the footprint will be opened with the footprint editor, those inner layer will disappear, but when included in the pcb they will be available.

Complete Module Footprint Hints

When making custom footprints of complete modules, a decision has to be made if the SMD discrete components should be placed in the PCB or are considered included in the footprint.

In the first case, the pads in the footprint are ports and the component will be placed overlapping the pads. Those should carefully overlap. The number of the pad should be properly assigned and mapped to a schematic symbol.

In the second case, the component is not placed and the module, or footprint, is considered a black box. The components will not be in the bill of material. The “internal” pad numbers are not needed, but a silkscreen should also be added to the footprint, indicating the discrete components. Name the components accordingly, prefixing them with a different letter indicating that are not related to the main pcb components (as, for example, C_RF_1), avoiding the risk of duplication. Finally, assign the numbers to the external ports (or I/O pins or pads) from the footprint editor.

The procedure is then the same as for standard components: save it in a library, assign the footprint to a symbol from the schematic and then place it in the pcb.

Revision History

  • 2020-10-14 AP: Kicad’s DRC works with graphical lines on copper layers. Added a section on the inner layers.
  • 2020-09-29 AP: Supports gr_poly.
  • 2019-10-27 AP: Fully DRC compliant footprint.
  • 2019-12-27 AP: Updated the structure of the post and changed the regex substitution from perl to Python.

This post is a work-in-progress, I plan to add some images and example files, along with an improved regex, when the time comes.

No comments:

Post a Comment