当时JLC还没限定只有LCEDA免费打板,我决定使用KiCad完成后续大部分工程。一个痛点是我找了很久想要一个边框生成的插件也没找到,只有倒角插件,不知道外国人思路怎么这么怪。于是痛定思痛决定自己开发。
python本来就不咋样的我,现在基本忘光光了,而KiCad插件开发的文档基本没有,根据我对其他插件的代码审阅,我觉得他们基本也是猜的,所以这里记下流程备用。
参考内容
这里有一点要注意,虽然插件目录叫做plugins,插件叫做action plugins但是在官方文档中通常称之Scripting(脚本),搜索资料的时候可以考虑更换关键词
官方资源
1、官方文档: PcbNew 插件 | 开发者文档 | KiCad 2、pcbnew python api手册 KiCad Pcbnew Python Scripting: Namespace List KiCad Pcbnew Python Scripting: pcbnew Namespace Reference
然而这些手册没啥鸟用,都是注释生成的,注释写的也很简约,有的api根本看不出来作用是什么,后面会说怎么办。
3、官方例程 安装目录下,例如我的安装目录:
C:\Program Files\KiCad\7.0\share\kicad\scripting
这里面是官方用python实现的功能
(5条消息) 如何使用wxPython GUI平台插件,快速实现开发python简单Application桌面应用程序_唤醒手腕的博客-CSDN博客_wxpython 镜像
安装wxFormBuilder,用来辅助GUI设计,不然手搓太累了 。他支持导出python和c++等语言。可视化wxPython GUI构建工具wxFormBuilder介绍 - 简书 (jianshu.com)
(还有一个辅助工具wxglade,没试过,上次更新两年前了。(5条消息) wxPython GUI 编辑器 - wxglade_迦蓝叶的博客-CSDN博客_wxglade
wxGlade: a GUI builder for wxWidgets/wxPython (sourceforge.net))
还有一个“wxpython可视化编辑器“ 看起来挺好用,国内做的.
先点form添加一个窗体
然后layout添加一个sizer
F8调试
layout-wxstaticBoxsizer可以添加一个带线条的框(类似lceda的那个框分块)
开发环境
vscode. python 在vscode的解释器选择中添加kicad中的python,这样可以解析对应的包,或者可以从kicad 6.0 command prompt打开命令行,这样就配置了kicad内置python的环境。
Kicad下Python脚本的调试
首先我不知道kicad是怎么启动脚本的,blender调试脚本的方法挺多的,一般都是安装一个调试插件,这里我也不会写这个插件。。但是还是有别的方法可以来完成调试。
ps.有时候横竖调不出来就是kicad的bug,等他更新wx组件也许就好了。
1、直接外部调试
由于插件的功能是提供了一个Dialog供kicad打开,也可以直接写一个tester.py,其中包含:
import wx |
然后把Kicad的python的bin文件加入环境变量,或者打开kicad 6.0 command prompt打开命令行,然后就可以打开Vsode,选择使用的python环境为kicad 的python,就可以调试了。不过涉及到板子的操作,因为原来的pcbnew.GetBoard()是直接从c++导入的_pcbnew.GetBoard()这个函数。
所以需要使用pcbnew.LoadBoard这个函数来打开一个pcb文件,这样才能获取到一个对象在编写的启动器中加入下面代码:
boardobj = pcbnew.GetBoard()被替换为 |
这样可以在vscode里面调试界面和函数,不用打开Kicad,不用刷新插件来打开新的插件或者使用kicad那个并不好用的命令行。
可以加入调试信息print().
具体见tester.py的内容和主函数的todo debug处
能不能直接传参打开?GetCopperLayerCountGetCopperLayerCount
2、使用Kicad内置的Python控制台使用pdb运行脚本
但是涉及到板子操作时候的bug,还是用kicad内置的环境加入断点或者调试信息来看。
2.1在脚本文件中加入断点。例如:
import pcbnew |
2.2 在插件图标左边那个 运行Python脚本控制台
,点击之后会运行内置的Kicad python。
C:\\Users\\Always\\Documents\\KiCad\\6.0\\3rdparty\\plugins\\KicadShapeEditor |
或者:在KiCad中,打开“工具”菜单,选择“Python控制台”,在弹出的Python控制台窗口中输入以下命令:
import sys |
这几行也可以写成一个脚本保存下来,比如叫做tester.py,不过最好是不要启动dialog为showmodal(),否则会阻塞后面的程序,而是使用上面那样,这样报错信息可以正常输出而不是阻塞后面的语句
在kipython命令行中输入:
cd C:\\Users\\Always\\Documents\\KiCad\\6.0\\3rdparty\\plugins\\KicadShapeEditor |
然后,在Python控制台窗口中,你可以看到运行脚本时,执行到断点时会暂停执行。此时,你可以在Python控制台窗口中输入指令,来查看脚本的执行过程。
例如,你可以输入n
命令,执行下一条语句;你也可以输入s
命令,进入函数内部进行操作,这里就是pdb的调试方法。见[[PDB的使用]]。
断点相关命令:
设置断点: (Pdb) b 8 #断点设置该文件的第8行(b即break的首字母)
显示所有断点:(Pdb) b #b命令,没有参数,显示所有断点
删除断点:(Pdb) cl 2 #删除第2个断点 (clear的首字母)Step Over:(Pdb) n #单步执行,next的首字母
Step Into:(Pdb) s #step的首字母
Setp Return:(Pdb) r #return的首字母
Resume:(Pdb) c #continue的首字母
Run to Line:(Pdb) j 10 #运行到地10行,jump的首字母(Pdb) p param #查看当前param变量值
(Pdb) l #查看运行到某处代码
(Pdb) a #查看全部栈内变量(Pdb) h #帮助,help的首字母
(Pdb) q #退出,quit的首字母
当然,之类也可以像第一步那样写一个启动器然后在kipython下启动调试:
exec(open('tester2.py').read()) |
不过,在kicad里面调试很容易出bug卡死。。另外更改代码之后要刷新import 自己的插件(使用剪切板的时候win10,稳定卡死)
2.3
除此之外如果不想写pdb也可以直接在kipython内用上述方法打开自己的函数,输出错误信息或者print的结果。
如果一定要用kicad的直接打开来测试,最好给外部插件刷新分配一个快捷键。
参考信息:
Linux下使用命令行调试Python程序 - 逐梦客! - 博客园
还有问ChatGPT:kicad如何调试插件脚本。。。他的回答比我想到的还完善,直接搜网上不容易找到答案。
更改pyshell配置
实际上Kicad内置的PyShell是可以修改的,因为它本身就是一个python插件的实现,当然KiCad也提供了接口。
在C:\Users\Always\AppData\Roaming\kicad\6.0
中,有一个PyShell_pcbnew_startup.py
,用于配置打开pcbnew的时候首先执行哪些脚本,例如import
pcbnew,省的自己再输入一次。
3、使用Kicad 6.0 Command prompt
可选:配置这个加入到Windows Terminal,就可以方便的在Windows Terminal打开
打开之后,自动进入到kicad 6.0 的python环境,在这个环境下,可以进行如下操作来测试命令或者执行python脚本
|
这样就可以加载一个板子用来测试功能,也可以在这个命令行里面运行python脚本来直接进行测试。不过这里就没有python的方法的自动补全了。
4、调试总结
最好的办法是使用vscode对插件脚本进行调试,把kicad的python加入环境变量或者在kicad prompt里面启动code,就可以方便的使用kicad的python环境调试。
通过编写一个启动器,可以是另外一个文件也可以是直接放在原来的插件入口脚本内,使用是否处于调试模式(见上面)来区分要不要运行单独的app入口,然后在调试模式里面使用pcbnew.LoadBoard(filename)来替代pcbnew.GetBoard()函数来获取一个板子的对象方便后面调试(如果这里不需要调试操作pcb的逻辑就可以先不改这一部分代码)。这样可以做到不用打开KiCad刷新就能调试,当然了,看效果还是得打开PCB.
而如果Kicad本身崩溃。。。需要构建debug版的kicad,可能是命令加–debug?
dd
python -m <package_name> 作为模块调试是文档说的,不知道怎么用。
新问题:有些需要交互的操作获取当前板子的信息有效吗
关于wx.Dialog
(5条消息) 【Python】wx.Dialog详解_猫兮ぃCatci的博客-CSDN博客_wx.dialog
ui设计部分强烈推荐直接使用wxformbuilder生成,不容易掉进坑里(还是有坑,比如下面这个)。
#–combobox如果加载panel之上的容器里面就会阻塞panel加载。
关于如何让KiCad插件运行后还能点击后面
使用模式对话框和无模式对话框来区分:
模式对话框会阻止其他窗口上的程序流和用户输入,直到被关闭为止,而无模式对话框的行为更像是程序流中的框架,并且仍然可以在其他窗口中输入
ShowModal 方法,显示模式对话框
dialog.ShowModal()#使用模式显示会导致kicad回显已经删除的边框的bug |
无模式地显示对话框,您只需使用 Show,就像使用框架一样。
dialog.Show() #不要紧跟着写destroy,不然无模式显示会被关掉的 |
同时,使用无模式对话框修复了Kicad在使用插件添加后的边框删除后会重新显示的bug。
combobox
(5条消息) wxpython comboBox 自动完成提示功能_saii的博客-CSDN博客_wxpython 自动提示
wx. EVT_TEXT↳
当组合框的文本发生变化
关于bug
之前那个showmodal()之后回显不正常的bug,在kipython的shell里面调用却不会有bug。
注释不会自动显示。
关于kicad python api 插件
官方文档:KiCad Pcbnew Python Scripting: pcbnew Namespace Reference
官方文档是用doxgen生成的,啥都没有,就是一坨shit,还不如问chatgpt让他解释作用和参数。
pcbnew相关
TRACK只能在铜皮层 排序从0-最后分别是F in0—in30 B 然后是其他层,这里层可以直接用pcbnew.F_Cu这样的元素表示。 KiCad6的API和KiCAD5的API不一样,走线以外的元素称之为Shape,有对应的操作函数。 不同层分别对应的数字是:
0-59,分别是
F.Cu In1-30.Cu B.Cu B.Adhesive F.Adhesive B.Paste F.Paste B.Silkscreen F.Silkscreen B.Mask F.Mask User.Drawings User.Comments User.Eco1 User.Eco2 Edge.Cuts Margin B.Courtyard F.Courtyard B.Fab F.Fab User.1-9 Rescue
使用pcbnew.LayerName(idnum)来通过数字索引出来层名称或BOARD_GetStandardLayerName
使用pcbnew.ToLAYER_ID可以得到id???但是这个函数输入就是一个int
共有60层,0-59,可以通过 pcbnew.PCB_LAYER_ID_COUNT 输出层数
print(pcbnew.PCB_LAYER_ID_COUNT)
ToLAYER_ID(idnum)切换层
对不知道的数据的内建函数,可以使用vscode的自动补全,也可以在python环境下dir(对象),或者直接去问chatgpt。。。kipython里面也有代码提示。
比如:
board = pcbnew.GetBoard() |
使用GetLayer可以获取当前layer,使用GetEnabledLayers获取使能的layer集合,类型是LSET,具有如下特性,他不能直接使用迭代特性,所以不能直接使用使用for循环
|
然后使用
enabled_layers = layers1.SeqStackupBottom2Top()可以获取一个数组,数组内是整数,通过for迭代pcbnew.LayerName(i)可以得到当前pcb的各层名称。但是要按顺序的话,应该使用Seq(),比如:
|
而GetLayerSet()
是一个在KiCad中定义的函数,它可以用来获取当前画板上使用的层集。在KiCad中,层集表示一组层的集合,可以用来指定在哪些层上放置元件。
例如,您可以使用GetLayerSet()
函数来获取当前画板上使用的层集,然后使用它来指定要在哪些层上放置某个元件:
Copy code
# Import the necessary libraries import pcbnew # Get the PCB board = pcbnew.GetBoard() # Get the current layer set layer_set = board.GetLayerSet() # Add some layers to the layer set layer_set.AddLayer(pcbnew.F_Cu) layer_set.AddLayer(pcbnew.B_Cu)
只是获取了一个板子上的层集合,是可以自己自定义的。
GetCopperLayerCount可以用来获取板子的铜皮层。
而wxpoint的坐标和实际mm坐标的转换可以通过pcbnew.ToMM()来转换,当然也可以直接计算10^-6来计算
boardobj = pcbnew.GetBoard()
board_X,board_Y = boardobj.GetCenter()
xmm = pcbnew.ToMM(board_X)
ymm = pcbnew.ToMM()
而获取板子上元素的信息不算难。
修改属性的时候,可以在pcb中绘制一个要生成的东西,按e查看一下有哪些属性就知道缺什么l
pcb标注为dimension
(dimension (type aligned) (layer “Cmts.User”) (tstamp 40db000a-2685-415b-b6e4-eba530284df3) (pts (xy 111.125 52.07) (xy 111.125 78.74)) (height -25.4) (gr_text “26.6700 mm” (at 136.525 65.405 90) (layer “Cmts.User”) (tstamp 2c592233-bd69-4594-a2ec-6e3e42bd308e) (effects (font (size 1 1) (thickness 0.15))) ) (format (units 3) (units_format 1) (precision 4)) (style (thickness 0.15) (arrow_length 1.27) (text_position_mode 1) (extension_height 0.58642) (extension_offset 0.5) keep_text_aligned) )
text_position_mode 1为内联模式,0是外部,2是手动
SetOverrideTextEnabled()方法用于启用或禁用尺寸线的文本重写,例如:
dimensionObj.SetOverrideTextEnabled(True)
在添加尺寸线时,可以使用SetUnits()方法设置尺寸线的单位,例如:
dimensionObj.SetUnits(pcbnew.EDA_UNITS_MILLIMETRES)
这样就可以在尺寸线中显示毫米单位了。
SetBrightened
是一个用来设置尺寸符号颜色是否变亮的方法。通常来说,当尺寸符号的颜色被设置为变亮时,它们会显得更加突出,便于观察。
此方法不接受任何参数,它的作用是将尺寸符号的颜色设置为变亮。例如:、
如果不知道setxxx的参数怎么写,就调用getxxx打印出来看一下。但是基本上可以直接对应pcb文件中的数字来做。
标注具有的属性:
dir(dimensionObj) [‘Cast’, ‘ClassOf’, ‘ClearBrightened’, ‘ClearEditFlags’, ‘ClearFlags’, ‘ClearSelected’, ‘ClearTempFlags’, ‘Clone’, ‘DeleteStructure’, ‘Duplicate’, ‘Flip’, ‘GetAngle’, ‘GetArrowLength’, ‘GetBoard’, ‘GetBoundingBox’, ‘GetCenter’, ‘GetClass’, ‘GetCrossbarEnd’, ‘GetCrossbarStart’, ‘GetEditFlags’, ‘GetEffectiveShape’, ‘GetEnd’, ‘GetExtensionHeight’, ‘GetExtensionOffset’, ‘GetFlags’, ‘GetFocusPosition’, ‘GetHeight’, ‘GetKeepTextAligned’, ‘GetLayer’, ‘GetLayerName’, ‘GetLayerSet’, ‘GetLineThickness’, ‘GetMeasuredValue’, ‘GetMenuImage’, ‘GetMsgPanelInfo’, ‘GetOverrideText’, ‘GetOverrideTextEnabled’, ‘GetParent’, ‘GetParentFootprint’, ‘GetParentGroup’, ‘GetPosition’, ‘GetPrecision’, ‘GetPrefix’, ‘GetSelectMenuText’, ‘GetShapes’, ‘GetStart’, ‘GetState’, ‘GetStatus’, ‘GetSuffix’, ‘GetSuppressZeroes’, ‘GetText’, ‘GetTextPositionMode’, ‘GetUnits’, ‘GetUnitsFormat’, ‘GetUnitsMode’, ‘GetValueText’, ‘GetX’, ‘GetY’, ‘HasFlag’, ‘HitTest’, ‘IsBrightened’, ‘IsConnected’, ‘IsDragging’, ‘IsEntered’, ‘IsForceVisible’, ‘IsLocked’, ‘IsModified’, ‘IsMoving’, ‘IsNew’, ‘IsOnCopperLayer’, ‘IsOnLayer’, ‘IsReplaceable’, ‘IsResized’, ‘IsSelected’, ‘IsTrack’, ‘IsType’, ‘IsWireImage’, ‘Matches’, ‘Mirror’, ‘Move’, ‘Replace’, ‘Rotate’, ‘SetArrowLength’, ‘SetAutoUnits’, ‘SetBrightened’, ‘SetEnd’, ‘SetExtensionHeight’, ‘SetExtensionOffset’, ‘SetFlags’, ‘SetForceVisible’, ‘SetHeight’, ‘SetKeepTextAligned’, ‘SetLayer’, ‘SetLayerSet’, ‘SetLineThickness’, ‘SetLocked’, ‘SetMeasuredValue’, ‘SetModified’, ‘SetOverrideText’, ‘SetOverrideTextEnabled’, ‘SetParent’, ‘SetParentGroup’, ‘SetPos’, ‘SetPosition’, ‘SetPrecision’, ‘SetPrefix’, ‘SetSelected’, ‘SetStart’, ‘SetStartEnd’, ‘SetState’, ‘SetStatus’, ‘SetSuffix’, ‘SetSuppressZeroes’, ‘SetText’, ‘SetTextPositionMode’, ‘SetTextSize’, ‘SetUnits’, ‘SetUnitsFormat’, ‘SetUnitsMode’, ‘SetWireImage’, ‘SetX’, ‘SetY’, ‘Sort’, ‘SwapData’, ‘Text’, ‘TransformShapeWithClearanceToPolygon’, ‘Type’, ‘Update’, ‘UpdateHeight’, ‘ViewBBox’, ‘ViewGetLayers’, ‘Visit’, ‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘gt’, ‘hash’, ‘init’, ‘init_subclass’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘swig_destroy’, ‘weakref’, ‘m_Uuid’, ‘this’, ‘thisown’]
对其中的部分进行解释:
下面是这些函数的具体作用和输入参数:
- SetArrowLength(self, aLength: int): 该函数的作用是设置dimension对象的箭头长度。输入参数aLength是一个整数,表示箭头的长度。
- SetAutoUnits(self, aAutoUnits: bool): 该函数的作用是设置dimension对象的自动单位。输入参数aAutoUnits是一个布尔值,表示是否使用自动单位。
- SetBrightened(self, aBrightened: bool): 该函数的作用是设置dimension对象的亮度。输入参数aBrightened是一个布尔值,表示是否使用高亮显示。
- SetEnd(self, aEnd: wx.Point): 该函数的作用是设置dimension对象的终点坐标。输入参数aEnd是一个wx.Point对象,表示终
TransformShapeWithClearanceToPolygon有什么用
SetSelect有什么用
dd–
关于翻译:
在 Python 中,可以使用 gettext 模块来实现不同语言的支持。首先,你需要创建一个 .pot 文件,这是一个用来存储语言翻译的模板文件。然后,你可以使用 xgettext 工具将这个文件生成不同语言的 .po 文件,这些文件里面包含了各种语言的翻译。
接下来,你可以在程序中使用 gettext.install() 方法来加载语言翻译文件,并使用 _() 函数来获取相应语言的翻译。例如:
# Import the gettext module |
gettext是python默认自带的
关于chatgpt提问:
kicad 中 使用python pcbnew获取所有pcb的层
这样问基本可以得到看起来靠谱但是不一定对的答案,然后指出不对的地方,比如
GetLayers()在kicad6.0中已经失效
关于版本兼容
拖了半年,kicad7来了,这次改动点不算很大,但是还是有些不兼容,原来的坐标使用wxpoint,现在改成了vector,部分功能可以通过修改调用函数来兼容,部分只能单独写判断。(我不明白开发组原来怎么就不写个重载来兼容一下。。)
参考内容
Kicad 插件 - 这个帮助不大 ,还不如直接看源码
KiCad Python 操作插件 - 知乎 (zhihu.com) 这里是TaotieRen收集的别人写的插件,可以当作参考用