Python Scripting: Creating Tracks and Vias

Introduction:

I’m planning to build a Studio Clock with 59 SMD-LED ordered in a
Circle. A ideal job for a Script, but quit hard for a newbie who just
started to use KiCad (used Eagle before) and Python Scripting (but quite
familiar with programming).
I managed to get all LED-Modules and rearrange them in a circle, that
was the easy part. Creating the Tracks wasn’t easy too, cause I
haven’t found any examples and had use pcbnew.py to help me out. I
managed to create Tracks and place them were I wanted them.

My Problem:
when I’m starting to Add Vias (with the same techniques I used for
the Tracks), the Python script runs through and the Vias are added, but
when I zoom in, KiCad crashes.

I know (or rather already experienced) KiCad will crash when your not careful where to add new Elements.
My Question

  1. Am I doing it the right way or am I just lucky that I had not more Problems
  2. Were do I have to add the Vias and who am I doing it?

Edit:
3. The Tracks are not connected to the Pads, how is it done

I haven’t got the time to look through the GUI-Source code to find the function used when I’m doing it graphical and I hope somebody can help me out so I don’t have to do it ;-).
(end Edit)

#Cad Studio Clock (2016-01-30)
# 
# This script places leds in Clock Formation

import codecs
import pcbnew
import math 
import sys

pcb = pcbnew.GetBoard()
Radius = 20

Mat = [None]*(12+1) #Index 0 stays empty to align Diod number with index

NetsInner = [1,3,4]
NetsOuter = [2,5,6,7]

mods = pcb.GetModules()
print type(mods)

#Get All Diods
print '---------------------------------------------------------------'
print '---Gathering-Diods-and-Info------------------------------------'
print '---------------------------------------------------------------'
for modu in pcb.GetModules():
	ref = modu.GetReference().encode('utf-8')
	if(ref.startswith('D')):
		pos = int(ref.split('D')[-1])
		rot = 2*math.pi/(len(Mat)-1)*(pos-1)
		padA = None
		padB = None
		netA = None
		netB = None
		for pad in modu.Pads():
			if int(pad.GetPadName()) == 1:
				padA = pad
				netA = pad.GetNetCode()
			else:
				padB = pad
				netB = pad.GetNetCode()
		Mat[pos] = [modu,rot,padA,netA,padB,netB,ref]
		print 'Read: %s,  Rotation %f, NetA %d, NetB %d' % (ref,rot,netA,netB)

#Calculate and Set  Positions
print '---------------------------------------------------------------'
print '---Calculating-and-Setting-Module-Positions--------------------'
print '---------------------------------------------------------------'
for mat in Mat[1:]:
	deg = math.degrees(mat[1])
	mat[0].SetOrientation((deg+90)*10)
	posX = math.sin(mat[1])*Radius
	posY = math.cos(mat[1])*Radius
	mat[0].SetPosition(pcbnew.wxPointMM(posX, posY))
	print 'Placed: Diod %s at %f, %f with rot %f' % (mat[6], posX, posY, deg)

print '---------------------------------------------------------------'
print '---Delete-Nets-------------------------------------------------'
print '---------------------------------------------------------------'
tracks = pcb.GetTracks()
for t in tracks:
	pcb.Delete(t)

#Built Net
print '---------------------------------------------------------------'
print '---Build-Net---------------------------------------------------'
print '---------------------------------------------------------------'
Mat.append([None,Mat[1][1],None,None,None,None,None])
for i in range(0, len(NetsInner)):
	for j in range(1, len(Mat)-1):
		t = pcbnew.TRACK(pcb)
		pcb.Add(t)
		r = 15 - i
		xStart = math.sin(Mat[j][1])*r
		yStart = math.cos(Mat[j][1])*r
		xEnd = math.sin(Mat[j+1][1])*r
		yEnd = math.cos(Mat[j+1][1])*r
		t.SetStart(pcbnew.wxPointMM(xStart, yStart))
		t.SetEnd(pcbnew.wxPointMM(xEnd, yEnd))
		t.SetNetCode(NetsInner[i])
		t.SetLayer(31)
		if Mat[j][5] == NetsInner[i]:
			print 'Added: Connection to %s with Net %d' % (Mat[j][6], Mat[j][5])
			c = pcbnew.TRACK(pcb)
			pcb.Add(c)
			c.SetNetCode(NetsInner[i])
			c.SetStart(pcbnew.wxPointMM(xStart, yStart))
			c.SetEnd(Mat[j][4].GetPosition())
			c.SetLayer(0)
                    v = pcbnew.VIA(pcb)
                    pcb.Add(v)
                    v.SetPosition(pcbnew.wxPointMM(xStart, yStart))
                    v.SetLayerPair(0,31)

I did some more testing. It turned out, that when I’m moving a connected Item or changing the Canvas View, KiCad won’t crash any more. It must be some function that is called at these actions that fixes the problem. I have tried to find it in the source code, but could find an equivalent in the pcbnew.py.

I also found the reference when I was searching in the Manual. Google couldn’t find it. Here is the Link:
http://ci.kicad.org/job/kicad-doxygen/ws/build/pcbnew/doxygen-python/html/index.html

I extended the script further and can already place and route all the LEDs. The plan is to let the script do most / all of the routing for me, so I can resize the Layout in seconds. I will post it under Projects when I’m finished.

2 Likes

SOLVED

I found the error. It was so obvious that I haven’t seen it. It was the Net Not being set. Thanks to mmccoo’s Tutorial I had a working example to compare. The function called when moving stuff must be auto-setting an undefined Net.

1 Like

AttributeError: ‘BOARD’ object has no attribute ‘GetModules’

kicad 6.0.9 python 3.914