Special Strings or Text on PCB

Hi everyone - I’m new to Kicad, but have been raised on Altium. I’m currently transitioning some design workflow over to Kicad and still learning about how to use it fluently. I’m loving Kicad apart from a few quirks (ie like project management for files and copying schematics between designs, but I digress!)

I was wondering whether there is any way to use special strings that autogenerate their content on the PCB. An example of this is the filename with no path would be imported by Altium using the special string “.Pcb_File_Name_No_Path”. There are a whole range of other special strings, but I guess I am looking at an inbuilt function within Kicad to replicate this.

I believe that I could possibly do it using the python scripting, but was wondering if there is an easier way.

All input welcome :slight_smile:

I don’t think there’s anything like that built in to pcbnew (KiCad PCB layout tool).

This isn’t fully tested, and there’s no allowance for repeating the substitution since the original text is destroyed by the substitution, but something like the following might work. It substitutes all strings of the form ‘[string to substitute]’ within the text objects of the board using the python dictionary substrings.

def get_text_objects(self,layer=None):
    """Gets all the text objects, those on the main board and those within
       modules. If specified, the text objects are filtered to return only
       those text objects on the indicated layer."""
        
    Texts = []
    for drawing in pcbnew.GetBoard().GetDrawings():
        if isinstance(drawing,pcbnew.TEXTE_PCB):
            Texts.append(drawing)
    for module in pcbnew.GetBoard().GetModules():
        Texts.append(module.Value())
        Texts.append(module.Reference()) 
        for gi in module.GraphicalItems():
            if isinstance(gi,pcbnew.TEXTE_MODULE):
                Texts.append(gi) 
    if layer is not None:
        Texts = filter(lambda x:x.IsOnLayer(layer),Texts)
    return Texts

def symbol_substitution(symbol_dict):
    substrings = {'talker':'Greg','talkee':'NMNC'}
    for textobj in get_text_objects():
        s = textobj.GetText()
        n=re.sub(r"\[(\w+)\]", lambda x: substrings.get(x.group(1),x.group(1)), s)
        if n != s:
            textobj.SetText(m)
2 Likes

There does appear to be a provision to substitute %R and %V in text within a module with the module’s Reference and Value, respectively. Apparently, %R and %V can be embedded within any placed string within the module.

1 Like

Thanks HiGreg

That looks like one way to do it. I will have to try using your generously supplied code snippet. Further on from that, do you think it is possible to create a part that is selected in the schematic editor and when the pcb is generated, it autofills the part on the pcb? I will give this a try over the next few days.

My use case is I am working out how to auto add information to a PCB based on the name of the project version, so that when designing and building a PCB it is easy to keep track of the version without having to fill it in by hand each time. This would also apply to things like datestamps, variants, etc. One goal might be to try generating barcodes and converting to an image, depending on future font support.

These might be elements that are used by more commercial applications of Kicad, so not sure how much the average user might find it useful though.

Not exactly sure what you mean by “auto fills the part”. But I can offer a few comments.

eeschema (the schematic editor) isn’t as accessible from python, but may not be necessary in this case.

You can add a part to eeschema and associate a footprint and it can automatically populate the PCB.

With the keyword substitution above, you might get the functionality you want. I have some ideas about making the substitution repeatable/updatable.

I don’t think bar codes are supported. I would expect “external fonts”, but those aren’t supported yet either (or at least as of 2015).

I’m sure a bar code python script could be developed.

1 Like

I think there is a sneaky way round it along the lines Greg suggests. If you define a module with a special name, it could be used to identify the type of string. A script like the one above could then update the values accordingly. The module could contain graphics as well as text of course.

A script could certainly read project title, version etc from the schematic file, but I don’t think the script can be run automatically, it would depend on the user invoking it.

Support for other fonts is likely to be a long way off.

1 Like

Here is a quick example. I’ve got symbols in the schematic I use for things like PCB logos (these have no pins).

I can attach these to different footprints to select where the data goes. In this case the footprints are trivial, they have no graphic items, I’m just using the value. I cheated with the “text on copper” footprint, I had to edit that in a text editor, KiCad deprecates putting text on copper.

The PCB initially looks like this after netlist import:

The designators are hidden and don’t appear on PCB, just shown here for reference. Running the script

>>> execfile “test.py”
Setting module M3 Value to 2017-08-08

and the script

import sys
from datetime import datetime
import pcbnew

def testfunc():
  my_board = pcbnew.GetBoard()
  for module in my_board.GetModules():
    fpid = module.GetFPID()
    if fpid.GetFootprintName() == "text_auto_date":
      new_text = "{:%Y-%m-%d}".format(datetime.now())
      print ("Setting module %s Value to %s " % ( module.GetReference(), new_text ) )
      module.Value().SetText(new_text)
      
testfunc()

I can’t see how to get to the sch file from the board object, is there another way?
board.GetFileName() should do it…

5 Likes

There already is a bar code generation script in the footprint wizads.

Footprint Editor -> Icon: New Footprint using Wizard -> Icon: Select Wizard script -> BARCODE USS-39

3 Likes

That’s handy… I used that code to generate a barcode from the module value, so you can set the value in eeschema. Well, that is the theory… as soon as I move the module or save file, all my graphics added to the module are replaced with zero length lines…spent a few hours struggling with that and got nowhere!

Also discovered that my scanner will not read Code39 barcodes which have only a single character without changing the setup. :frowning:

1 Like

If you can use nightly there is an option

2 Likes

I miss this, too. I’d like to be able to enter information at the project level (KiCAD’s *.pro file) and have it accessible from at least EESchema and PCBNew, and possibly any of the other tools. I think there’s a case for having defined fields for the bare PCB’s part number, revision designator, and revision date; as well as part number, revision designator, and revision date for the completed PC board assembly. Beyond that, there could be user-defined fields - either a pre-set number of fields, with pre-defined generic names (like “Field1” through “Field8”, or “%F1”, etc) or a totally user-defined name-and-value pair.

With a feature like this I could create a title block in EESchema using a syntax such as “%AsyPN”, “%AsyRev”, etc; then write a drawing note similar to “1. This Assy built on PWB p/n %PCBPN, revision level %PCBRev.”. Then in PCBNew I can etch the PCB part number into copper with just a reference to “%PCBPN”, or write the assembly information to the silkscreen with “Assy # %AsyPN, Rev %AsyRev”.

Dale

2 Likes

Oh wow - that’s great news to see, Maui. That didn’t turn up in my initial searches, so I’m glad to see this. I think I am going to have to learn more about python scripts in KiCad. I’m glad there is a sensible scripting system for automation of some tasks!

Exactly my thoughts, Dale. Being able to auto complete this information on board revisions is a boon for those of us who do commercial design.

And you enter it only once - at the project level - and it automagically finds its way to the appropriate places in each of the tools. As you said, a great way to save time and avoid worry if you clone an existing project to create the next revision.

Dale

2 Likes

I sorted out my barcode problems, there are some strange interactions between Python and KiCad, including some which crash KiCad :frowning: I also extended the script to read title block data from the schematic.


The %T etc names are taken from KiCad worksheet editor, I didn’t bother with sheet specific data. I think that should handle most use cases, are there any others?

The script could do with some more refinement, e.g. preserving properties of text fields set by the user, passing parameters to barcode generator, implementing action script thing etc.

autofill.py (9.1 KB)

3 Likes

Because I’m on a roll, and Python makes it easy, I implemented some user defined fields. There are other ways to do it, perhaps put the fields into a schematic component would be neater.

autofill.py (9.4 KB)

4 Likes

You can look at the KiPadCheck nightly source for hints on how to implement action script. It’s not perfect yet. I’m unclear how it deals with re-entrance. And I’m not sure if I implemented import vs. reload properly.

When I work out these things, I’ll try to remember to ping you about it. Either way, I’ll put an indicator in the update notes in the main KiPadCheck nightly thread. There are just a few methods you have to implement. I’ve implemented them in a class definition, but you might also be able to put the definitions in the top-level module script.

2 Likes

I’ve written a new script that implements Action Plugin integration for a python script into KiCad. It also happens to be a good example for integration a gui developed in wxFormBuilder. Just a few hundred lines, it contains both gui integration and Action Plugin integration in one simple example.

Thanks @HiGreg, I hope to follow that example when I have time. For now I have pushed what I have got to

I added Code128 barcodes, a more traditional user title block, and the ability to place text in any layer with a %layer prefix. If the user has changed text properties, the script tries to preserve those, so you can move the text or put it on a different layer.

With this script method, it would also be possible to create other dynamic content like read values from a file, import graphics, render system fonts. Maybe even use it to import subcircuits.

I have been having trouble with the layer manager checkboxes and newly drawn objects added to board.Drawings showing up in the view.

When in windows OpenGL canvas, it requires a switch view to default and back for the objects to appear. Haven’t figured out a way around this, but have started several conversations here and on the developers list.