立创EDA转KiCAD的脚本
m24h2023/10/07原创 软件综合 IP:上海

增加了对线型等支持 修改了一些bug 目前还在继续改进 打算之后还是增加原理图也迁移

因为老在修改完善 程序也越来越长 我已经上传ghub 大家还是从XXXXXXXXXXXXXXXXXX/m24h/lcEDA2KiCAD 下载吧

.........................................

最近使用了立创的EDA 发现它的元件符号库太全了 尤其是国内常用产品 KiCAD远远不如 那么 有没有可能转它的符号库给KiCAD用

经研究 发现立创EDA使用SQLite3数据库存储其数据 比如个人建立一个元件库 然后从各处找到感兴趣的元件符号 就可以拷贝到自己的库 也就出现在本地存放的.elib数据库中 在表Components的dataStr字段里  格式大致如下

lceda-elib.png

其实也可以在元件编辑器的菜单"文件"->"查看源码"里面得到

或者在自己工程的备份压缩文件里 各元件符号以.esym后缀的文件独立存放

批量导出数据库字段变成文件并不难 我也不多说 也暂时不需要 只是想把工程中遇到的元件加入KiCad的元件库中 因为我大概是购买了 以后也会用的 所以做了一个脚本 用来转换.esym文件为KiCad的.kicad_sym文件 处理文本 当然是perl最擅长 所以用perl

use JSON;
my %pintypes=('IN' => 'input', 'OUT' => 'output');
die "Usage: perl $0 <.esym file name> <output filename or - (STDOUT) or empty (use symbol name)>\n" if $#ARGV<0;
die "File '$ARGV[0]' is not found\n" unless open F, "<$ARGV[0]";
$symb=from_json('['.join(',', <F>).']');
close F;
#get all parts 
my @parts;
foreach (@$symb) {
  push @parts, [] if $_->[0] eq 'PART';
  push @{$parts[-1]}, $_ if $#parts>=0;
}
#["FONTSTYLE","st4",null,null,"Times new roman",15,0,0,0,null,1,0]
my %fonts=map {$_->[1] => $_->[5] && '(font (size '.($_->[5]*0.254).' '.($_->[5]*0.254).'))' || ''} grep {$_->[0] eq 'FONTSTYLE'} @$symb;
#["LINESTYLE","st19",null,3,"#330033",null]
my %linestyles=map {$_->[1] => '(stroke (width '. ($_->[5]*0.254 || 0).') (type '.($_->[3] && qw(solid dash dot dash_dot)[$_->[3]] || 'default').')'
                                                  .($_->[2]=~/#([0-9A-F][0-9A-F])([0-9A-F][0-9A-F])([0-9A-F][0-9A-F])/i && " (color ${\hex($1)} ${\hex($2)} ${\hex($3)} 1)" || '').')'
                                                  .($_->[4]=~/#([0-9A-F][0-9A-F])([0-9A-F][0-9A-F])([0-9A-F][0-9A-F])/ && " (fill (type color) (color ${\hex($1)} ${\hex($2)} ${\hex($3)} 1))" || ' (fill (type none))')}
                         grep {$_->[0] eq 'LINESTYLE'} @$symb;
#get symbol name (but there's only part name in file, so the first part name is adopted)
my $name=$parts[0]->[0]->[1]=~s/[\-#\$_\.:,]\d*$//r;
unless ($#ARGV>0 && $ARGV[0] eq '-') {
  $#ARGV>0 &&  (open STDOUT,">$ARGV[1]" or die "Failed to open '$ARGV[1]' for writing\n") or
  open STDOUT, ">$name.kicad_sym" or
  open STDOUT, '>'.($ARGV[0]=~s/\.[^\.]*$//r).'.kicad_sym'
  or die "Failed to open '".($ARGV[0]=~s/\.[^\.]*$//r).".kicad_sym' for writing\n";
}
#start to write header
print  <<"EOF";
(kicad_symbol_lib (version 20220914) (generator esym2kicad_pl)
  (symbol "$name" (in_bom yes) (on_board yes)
    (property "Reference" "${\map {split /\?$/, $_->[4]} grep {$_->[0] eq 'ATTR' && $_->[3] eq 'Designator' } @$symb}" (at -5.08 6.35 0)
      (effects (justify left))
    )
    (property "Value" "${\map {$_->[4]} grep {$_->[0] eq 'ATTR' && $_->[3] eq 'Symbol' } @$symb}" (at -5.08 8.89 0)
      (effects (justify left))
    )
    (property "Footprint" "${\map {$_->[4]} grep {$_->[0] eq 'ATTR' && $_->[3] eq 'Footprint' } @$symb}" (at 0 0 0)
      (effects hide)
    )
    (property "Datasheet" "${\map {$_->[4]} grep {$_->[0] eq 'ATTR' && $_->[3] eq 'link' } @$symb}" (at 0 0 0)
      (effects  hide)
    )
EOF
#do every parts
my $part_suffix=1;
foreach my $part(@parts) {
  print  <<"EOF"; # there seems to be a rule about symbol's name, which is not compatible with LcEDA
    (symbol "${name}_${\$part_suffix++}_1"
EOF
  #["RECT","e3",-60,-55,60,55,0,0,0,"st1",0]
  foreach (grep {$_->[0] eq 'RECT'} @$part) {
    print <<"EOF";
      (rectangle (start ${\($_->[2]*0.254)} ${\($_->[3]*0.254)}) (end ${\($_->[4]*0.254)} ${\($_->[5]*0.254)})
        $linestyles{$_->[9]}
      )
EOF
  }
  #["ARC","e14",4.44,-6.9,1.66049,0.08325,4.53,7.03,"st1",0]
  foreach (grep {$_->[0] eq 'ARC'} @$part) {
    eval {  # will fail if 3 points is in a line
      # can't believe that kiCAD does not support arcs with angles >180 degree, so hard to fix it
      my ($x1,$y1,$x2,$y2,$x3,$y3)=($_->[2]*0.254,$_->[3]*0.254,$_->[4]*0.254,$_->[5]*0.254,$_->[6]*0.254,$_->[7]*0.254);
      my ($x21,$x32,$x13,$y21,$y32,$y13)=($x2-$x1,$x3-$x2,$x1-$x3,$y2-$y1,$y3-$y2,$y1-$y3);
      my ($a,$b)=($x21*$y32-$y21*$x32, $x21*$y13-$y21*$x13);  # 0 means 3 points is in a line
      my ($c,$d)=($x1*$x1+$y1*$y1-$x2*$x2-$y2*$y2, $x1*$x1+$y1*$y1-$x3*$x3-$y3*$y3);
      my ($x0,$y0)=(-($y13*$c+$y21*$d)/$b/2, ($x21*$d+$x13*$c)/$b/2);
      my ($s1,$s3,$pi2)=(atan2($y1-$y0,$x1-$x0), atan2($y3-$y0,$x3-$x0), 4*atan2(1,0));
      my $ang=$a>0?($s3-$s1):($s1-$s3); $ang+=$pi2 if ($ang<0); #CCW running angle
      if ($ang>3.14) { # have to split it
        my $r=sqrt(($x1-$x0)*($x1-$x0)+($y1-$y0)*($y1-$y0));
        my ($x4,$y4)=($x0+$r*cos($s1+$ang/2), $y0+$r*sin($s1+$ang/2));
        my ($x5,$y5)=($x0+$r*cos($s1+$ang/4), $y0+$r*sin($s1+$ang/4));
        my ($x6,$y6)=($x0+$r*cos($s3-$ang/4), $y0+$r*sin($s3-$ang/4));
        print <<"EOF";
      (arc (start $x1 $y1) (mid $x5 $y5) (end $x4 $y4)
        $linestyles{$_->[8]}
      )
      (arc (start $x4 $y4) (mid $x6 $y6) (end $x3 $y3)
        $linestyles{$_->[8]}
      )
EOF
      } else {
        print <<"EOF";
      (arc (start $x1 $y1) (mid $x2 $y2) (end $x3 $y3)
        $linestyles{$_->[8]}
      )
EOF
      }
    };
  } 
  #["POLY","e11",[-2,8,-2,-8],0,"st1",0]
  foreach (grep {$_->[0] eq 'POLY'} @$part) {
    print <<"EOF";
      (polyline
        (pts
EOF
    my $pts=$_->[2];
     for (my $i=0; $i<$#$pts; $i+=2) {
    print <<"EOF";
          (xy ${\($pts->[$i]*0.254)} ${\($pts->[$i+1]*0.254)})
EOF
    }
    print <<"EOF";
        )
        $linestyles{$_->[4]}
      )
EOF
  } 
  #["BEZIER","e211",[-140,-20,-120,0,-90,0,-80,-10],"st1",0], not supported, just take a pose
  foreach (grep {$_->[0] eq 'BEZIER'} @$part) {
    print <<"EOF";
      (polyline
        (pts
EOF
    my $pts=$_->[2];
     for (my $i=0; $i<$#$pts; $i+=2) {
    print <<"EOF";
          (xy ${\($pts->[$i]*0.254)} ${\($pts->[$i+1]*0.254)})
EOF
    }
    print <<"EOF";
        )
        $linestyles{$_->[3]}
      )
EOF
  } 
  #["CIRCLE","e4",-55,50,1.5,"st1",0]
  foreach (grep {$_->[0] eq 'CIRCLE'} @$part) {
    print  <<"EOF";
      (circle (center ${\($_->[2]*0.254)} ${\($_->[3]*0.254)}) (radius ${\($_->[4]*0.254)})
        $linestyles{$_->[5]}
      ) 
EOF
  } 
  #["ELLIPSE","e206",-100,20,10,20,0,"st1",0], not supported, just take a pose
   foreach (grep {$_->[0] eq 'ELLIPSE'} @$part) {
    print  <<"EOF";
      (circle (center ${\($_->[2]*0.254)} ${\($_->[3]*0.254)}) (radius ${\(($_->[4]+$_->[5])*0.127)})
        $linestyles{$_->[7]}
      ) 
EOF
  } 
 
  #["PIN","e5",1,1,-70,45,10,0,null,0,0,1]
  #["ATTR","e6","e5","NAME","VSS",false,true,-56.3,39.08502,0,"st4",0]
  #["ATTR","e7","e5","NUMBER","1",false,true,-60.5,44.08502,0,"st5",0]
  #["ATTR","e8","e5","Pin Type","IN",false,false,-70,45,0,"st2",0]
  foreach (grep {$_->[0] eq 'PIN'} @$part) {
    my $id=$_->[1];
    print  <<"EOF";
      (pin ${\($pintypes{(map {$_->[4]} grep {$_->[0] eq 'ATTR' && $_->[2] eq $id && $_->[3] eq 'Pin Type'} @$part)[0]} ||  'passive')} line (at ${\($_->[4]*0.254)} ${\($_->[5]*0.254)} $_->[7]) (length ${\($_->[6]*0.254)})
        (name "${\map {$_->[4]} grep {$_->[0] eq 'ATTR' && $_->[2] eq $id && $_->[3] eq 'NAME' } @$part}")
        (number "${\map {$_->[4]} grep {$_->[0] eq 'ATTR' && $_->[2] eq $id && $_->[3] eq 'NUMBER' } @$part}"\)
      )
EOF
  } 
  #["TEXT","e313",908,160,0,"yyy","st4",0]
  foreach (grep {$_->[0] eq 'TEXT'} @$part) {
    my $id=$_->[1];
    my $style=$_->[6];
    print  <<"EOF";
      (text "$_->[5]" (at ${\($_->[2]*0.254)} ${\($_->[3]*0.254)} ${\($_->[4]*10)})
        (effects $fonts{$_->[6]})
      )
EOF
  } 
print  <<"EOF";
    )
EOF
}
print  <<"EOF";
  )
)
EOF

close STDOUT;

目前支持引脚 文字 方框 圆 弧 折线 基本够用了 目前测试下来 基本都没有问题

当然 这需要一个个元件加入KiCad 正好顺便检查 批量导入其实大概也有方法的 .kicad_sym文件其实也是库文件 只需要在顶层的kicad_symbol_lib级别下放多个symbol就是了 元件文件就只放一个  至于修改脚本还是后期用copy合并后去掉重复的kicad_symbol_lib头 都不难 但我就不做了

............................... 10.8 .....

更新了脚本  增加了对多单元器件的支持 (比如双运放之类)

顺便 也把从.elib eprj导出所有元件的脚本做了

use DBI;

die "Usage: perl $0 <.elib .eprj file name> \n\tIt will extract all symbols and save them to this directory." if $#ARGV<0;
die "Unable to find '$ARGV[0]'\n" unless -e $ARGV[0];
$dbh=DBI->connect("DBI:SQLite:dbname=$ARGV[0]", '', '', {PrintError=>0}) or  die "Unable to connect file '$ARGV[0]': ".DBI::errstr."\n";
$sth=$dbh->prepare("SELECT title,dataStr from components where docType=2 and title is not null and title!=''") and $sth->execute()>=0 or  die "Failed to extract symbol data from file '$ARGV[0]': ".DBI::errstr."\n";

while(my @row = $sth->fetchrow_array()) {
	$row[0]=~tr/\*\|\"\?\/\\\&;\<\> /_/;
	$row[1]=~s/\r*(?=\n)//gm;;
	next unless $row[0] && $row[1];
	next unless open F, ">$row[0].esym";
	print F $row[1];
	close F; 
}
$sth->finish();
$dbh->disconnect();

还包括把多个.kicad_sym文件合并成一个库的脚本 (这样 导出 for %f in (*.esym) do .... 然后再合并 库迁移就OK了)

die "Usage: perl $0 <.output file name or '-' (STDOUT)>\n\t\All .kicad_sym file (which should be created by esym2kicad.pl) will be packed to a signle lib file\n" if $#ARGV<0;
die "Unable to open '$ARGV[0]'\n" unless $ARGV[0] eq '-' || open STDOUT,">$ARGV[0]";
undef  $/;

print  <<"EOF";
(kicad_symbol_lib (version 20220914) (generator makekicadlib_pl)
EOF
foreach (grep {!-d $_ && -e $_ && !/^\./ } <'*.kicad_sym'>) {
	print STDERR "processing $_\n";
	next unless open T, "<$_";
	$_=<T>;
	close T;
	print "  $1\n" if /(\(\s*symbol\s(.|\n)*?)(\s|\n)*\)[^\)]*$/i;
}
print  <<"EOF";
)
EOF
close STDOUT;


[修改于 1年1个月前 - 2023/10/10 20:18:37]

+1  科创币    大仙    2023/10/29 好人一生平安
+1  科创币    Zhang_TTL    2023/11/09 有用的工具,感谢开发
来自:计算机科学 / 软件综合
4
9
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
20!Dopaminor
1年1个月前 IP:广东
926093

真不错

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
m24h作者
1年1个月前 IP:上海
926180

原理图的转换也做好了 代码太长 就不贴了。。。实际上都有修改 代码也都长了 只能提醒还是从GitHub获取最新版。。。如果每次修正都放在这里 这帖子至少得长两页

基本能考虑的都考虑了 包括文字大小 线型 旋转 电源符号的转换 一般不带子框图的基本都没问题了

当然还是需要手工校正一些的

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
helium
1年1个月前 IP:广东
926630

立创EDA就是经常要提示更新还要登账号这一点很反人类,还是AD没这个问题,没有收录到库里边的的符号和封装我一般是直接画的,库文件找一个路径存在本机里就行,若要备份可以考虑用NAS存一份。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
m24h作者
1年1个月前 IP:上海
926638
引用helium发表于3楼的内容
立创EDA就是经常要提示更新还要登账号这一点很反人类,还是AD没这个问题,没有收录到库里边的的符号和...

毕竟人家是云开发 而且它问题也不少 关键是方便啊 开发到下单速度超快 专业版有完全离线

不过最头疼的是 共享很难做到 而且我看文件数据库 因为考虑团队协作开发 里面有加入参与者的账号信息的可能 虽然我目前个人开发 账号信息是一个公开共用的立创账号 但是也有泄漏什么的可能

而且sch转到kicad也不完美 因为各家都是根据坐标位置重合 来判断连接性的 一种用英式(反而是立创用英式) 一种用国际单位 转换之后因为精度问题 有些时候就对不上

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
m24h
进士 学者 机友
文章
52
回复
896
学术分
1
2020/01/22注册,4时42分前活动

个人开源项目: XXXXXXXXXXXXXX

主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:上海
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}