EasyEDA PCB 快速设计Skills

EasyEDA PCB 快速设计Skills

开源仓库 :github.com/sakurajh/easyeda-pcb-workflow

个人博客 :sakura.work.gd

EasyEDA PCB 快速设计工作流

目标 :从需求到 EDA 画完,全程照着流程走,不需要反复试错。

前提 :已通过 easyeda-api skill 连接 EDA 桥接服务。


一、设计前必读:核心概念

1.1 坐标系统

项目 值 说明
PCB 单位 1 mil = 0.0254 mm mm(v) = v × 39.37
原点 左下角 x 向右,y 向上
常用换算 1mm = 39.37mil 86mm = 3385mil
文字字号 需 ×1.25 补偿 EDA 字形只占字号 0.7 倍

⚠️ 最容易搞错的 :设计稿用 mm,EDA API 用 mil。所有坐标必须 mm(v) = Math.round(v * 39.37 * 100) / 100。

1.2 层 ID 映射(六层板)

视觉层 铜层 ID 阻焊 ID 丝印 ID 用途
L1 顶层 1 (TOP) 5 (TOP_SOLDER_MASK) 3 金色图案 = 铜箔 + 阻焊开窗
L2 内层1 15 (INNER_1) --- --- 装饰/地平面
L3 内层2 16 (INNER_2) --- --- 装饰/星点
L4 内层3 17 (INNER_3) --- --- 装饰/网格
L5 内层4 18 (INNER_4) --- --- 装饰/辐射纹
L6 底层 2 (BOTTOM) 6 (BOTTOM_SOLDER_MASK) 4 金色图案(⚠️需镜像修正)
板框 11 (BOARD_OUTLINE) --- --- 板外形 + 挂孔/挖槽
锡膏 7/8 --- --- 钢网(装饰板不需要)

⚠️ 关键:金色效果 = 铜箔层(1/2)+ 同图案的阻焊开窗层(5/6)。沉金工艺在开窗处露出金色。

1.3 图元 API 速查

图元 API 参数要点
填充矩形 pcb_PrimitiveFill.create(layer, poly('R', x, yTop, w, h, 0, r), '', 0, 6, false) y 是顶边,不是底边!
填充圆 pcb_PrimitiveFill.create(layer, poly('CIRCLE', x, y, r), '', 0, 6, false)
折线 pcb_PrimitivePolyline.create('', layer, poly([x1,y1,'L',...pts]), w, false) 不自动闭合,需手动回到起点
文字 pcb_PrimitiveString.create(layer, x, y, text, 'default', size, lw, 5, rot, false, 0, false, false) size ×1.25 补偿
图像 pcb_PrimitiveImage.create(x, y, cp, layer, w, h, 0, false, false) x,y 是左下角
过孔 pcb_PrimitiveVia.create('', x, y, drill, pad, 0) 参数从简,多了会报错
焊盘 pcb_PrimitivePad.create(...) 用于元件焊盘

二、标准流程(照着走)

Step 1:环境检查

bash 复制代码
# 扫描桥接端口
for port in $(seq 49620 49629); do
  resp=$(curl -s --max-time 1 http://127.0.0.1:$port/health 2>/dev/null)
  if echo "$resp" | grep -q '"easyeda-bridge"'; then echo "PORT=$port"; break; fi
done
# 确认 EDA 已连接
curl -s http://127.0.0.1:49620/health
# 确认文档类型(必须是 3 = PCB)
curl -s -X POST http://127.0.0.1:49620/execute \
  -H "Content-Type: application/json" \
  -d '{"code":"const d = await eda.dmt_SelectControl.getCurrentDocumentInfo(); return JSON.stringify(d);"}'

Step 2:建工程 + PCB

javascript 复制代码
// 创建工程
const projUuid = await eda.dmt_Project.createProject('名称', '代号', undefined, undefined, '描述');
await eda.dmt_Project.openProject(projUuid);
// 创建 PCB
const pcbUuid = await eda.dmt_Pcb.createPcb();
await eda.dmt_EditorControl.openDocument(pcbUuid);

⚠️ 坑 :createProject + openProject + createPcb 合计耗时 >30s,单次 /execute 会超时。用 90s timeout。

Step 3:画板框(必须严格闭合)

javascript 复制代码
// 圆角矩形:100点,首尾必须重合(误差 <0.001mm)
const pts = []; // 四角圆弧采样
pts.push([pts[0][0], pts[0][1]]); // ← 这行不能少!
const mk = (f) => eda.pcb_MathPolygon.createPolygon([f[0], f[1], 'L', ...f.slice(2)]);
await eda.pcb_PrimitivePolyline.create('', 11, mk(flat(pts)), mm(0.15), false);
// 挂孔/挖槽:同样闭合
await eda.pcb_PrimitivePolyline.create('', 11, mk(flat(hole)), mm(0.15), false);

⚠️ 最大的坑:板框不闭合 → 3D 里板子变成挂孔那个小圆饼!EDA 把闭合的孔当成板外形。

Step 4:逐层绘制

javascript 复制代码
// 分批写入,每批 ≤40 个
async function pushItems(items, layer) {
  for (let i = 0; i < items.length; i += 40) {
    const batch = items.slice(i, i + 40);
    // ... 用 pcb_PrimitiveFill/Polyline/String/Image 逐个创建
  }
}
// 顺序:内层(15-18) → 顶层铜箔(1) → 底层铜箔(2) → 阻焊(5/6)

Step 5:图像描摹(校徽/签名/Logo)

javascript 复制代码
// 1. 图片预处理(Python PIL)
//    - 灰度 → 二值化(阈值150) → 裁白边 → 缩放480px
//    - 笔迹=黑(0),背景=白(255) ← 极性别搞反!
// 2. 传入 EDA 描摹
const blob = await (await fetch('data:image/png;base64,' + b64)).blob();
const cp = await eda.pcb_MathPolygon.convertImageToComplexPolygon(
  blob, 480, 480, 0.55, 0.35, 0.5, 1.5, true, false
);
// 3. 放置(x,y = 左下角)
await eda.pcb_PrimitiveImage.create(x, y, cp, layer, w, h, 0, false, false);
// 铜箔(1) + 阻焊开窗(5) 各放一次 = 金色效果

⚠️ 描摹参数 (0.6, 0.3, 0.45, 2.0) 会内部报错 ,用 (0.55, 0.35, 0.5, 1.5)。

⚠️ 图片极性:黑(0)=笔迹,白(255)=背景。反了会描出白底方块。

Step 6:过孔

javascript 复制代码
await eda.pcb_PrimitiveVia.create('', x, y, mm(0.4), mm(0.9), 0); // drill, pad
// 别加多余参数(null),会报"参数不正确"

Step 7:保存 + 验证

javascript 复制代码
await eda.pcb_Document.save();
// 统计各层图元
const all = await eda.pcb_PrimitiveFill.getAll(); // 不带 layer 参数
// ... 按 getState_Layer() 自行分类统计

三、避坑速查表(按出现频率排序)

🔴 致命错误

# 问题 症状 解决
1 板框不闭合 3D 里板子变成小圆饼 首尾点重合,误差 <0.001mm
2 文档类型不对 所有 API 返回 null / "参数不正确" 先 openDocument(pcbUuid) 确认 type=3
3 底层不镜像 背面校徽跑到板外 L6/L6mask 的 x 用 3150 - x
4 图片极性反 描出白底方块而非笔迹 笔迹=黑(0),背景=白(255)
5 getAll 带 layer 参数 返回 null 用 getAll() 不带参数,自行 filter

🟡 常见错误

# 问题 症状 解决
6 文字太小 比设计稿小 30% size × 1.25
7 填充矩形 y 错位 矩形偏上/偏下 'R' 的 y 是顶边
8 折线不闭合 少一条边 手动加回到起点的线段
9 过孔创建失败 返回 null 参数只传 6 个:(net, x, y, drill, pad, type)
10 描摹参数错 "Cannot read properties of null" 用 (0.55, 0.35, 0.5, 1.5)
11 'L' 模式填充失败 Fill.create 返回 null 'L' 只能用于 Polyline,不能用于 Fill
12 任务超时 30s 未返回 复杂操作分批,每批 ≤40 个图元
13 重复图元 多次运行脚本叠加 每次先清旧再放新
14 丝印残留 旧文字不消失 清除 layer 3/4 的 String

🟢 已知特性(非 bug)

现象 原因 处理
2D 里底层内容偏左 底层镜像显示 正常,3D 里正确
内层图案透过顶层可见 2D 视图多层叠加 正常,3D 里被阻焊盖住
DRC 报孤岛铜/无网络 纯装饰板无电气网络 正常,可跳过 DRC
阻焊开窗碰到板边 装饰板故意铺满 正常,不影响打样

四、加速技巧

4.1 批量写入模式

javascript 复制代码
// 把一批图元序列化后一次 /execute 发过去
const data = JSON.stringify(items); // ≤40个
const code = `const items = ${data}; /* 逐个创建 */ return ok;`;
await exec(code, 60000);

4.2 几何生成模板

javascript 复制代码
// 基础图元(设计层用)
const stroke = (pts, w) => ({ t: 'stroke', pts, w });
const fillRect = (x, y, w, h, r=0) => ({ t: 'fillRect', x, y, w, h, round: r });
const fillCircle = (cx, cy, r) => ({ t: 'fillCircle', cx, cy, r });
const text = (x, y, s, size, rot=0, center=true) => ({ t: 'text', x, y, s, size, rot, center });

// 圆弧采样
function arcPts(cx, cy, r, a0, a1, steps=48) {
  const pts = [];
  for (let i = 0; i <= steps; i++) {
    const a = (a0 + (a1-a0)*(i/steps)) * Math.PI/180;
    pts.push([cx + r*Math.cos(a), cy + r*Math.sin(a)]);
  }
  return pts;
}
const ring = (cx, cy, r, w) => stroke(arcPts(cx, cy, r, 0, 360, 64), w);

4.3 贴片元件封装(建筑/装饰用)

javascript 复制代码
function smd(cx, cy, w, h) {
  const pad = Math.min(w*0.35, 1.2), gap = w*0.12;
  return [
    fillRect(cx-w/2, cy-h/2, pad, h, 0.05),         // 左焊盘
    fillRect(cx+w/2-pad, cy-h/2, pad, h, 0.05),     // 右焊盘
    fillRect(cx-w/2+pad+gap, cy-h/2+1, w-2*pad-2*gap, h-2, 0.05), // 本体
  ];
}

4.4 验证抓图

javascript 复制代码
// 抓 EDA 画布
const blob = await eda.dmt_EditorControl.getCurrentRenderedAreaImage();
// → base64 → PNG 文件 → ViewImage 查看

4.5 自动化脚本结构

复制代码
project.mjs   → 建工程+PCB(单次,90s timeout)
outline.mjs   → 板框+挂孔
layers.mjs    → 逐层绘制(分批)
images.mjs    → 校徽/签名描摹放置
vias.mjs      → 过孔
save.mjs      → 保存+统计
grab.mjs      → 抓画布验证

每个脚本开头都先 openDocument(pcbUuid) 确认文档类型!


五、工艺效果速查

想要的效果 做法
金色图案(绿油底) 铜箔层画图案 + 阻焊层开窗同样图案 + 沉金 ENIG
黑金卡 黑色阻焊 + 沉金
红金卡 红色阻焊 + 沉金
暗纹底色 铜层画网格/纹理但不开窗,被阻焊压住
白色文字 丝印层(3/4)放文字
立体浮雕 多层铜箔叠不同图案 + 大量装饰过孔
NFC 天线 底层画 4 圈螺旋线圈,天线区域不铺铜

六、打样参数模板

项目 装饰卡 功能板 六层免费券
尺寸 86×54mm 自定义 ≤100×100mm
层数 2 2 6
板厚 1.6mm / 1.2mm 1.6mm 1.6mm
阻焊 红/黑 绿 绿
表面处理 沉金 ENIG HASL/沉金 沉金
数量 5 5 5
DRC 可跳过 需通过 可跳过

七、调试工具箱

检查文档状态

javascript 复制代码
const p = await eda.dmt_Project.getCurrentProjectInfo();
const d = await eda.dmt_SelectControl.getCurrentDocumentInfo();
// d.documentType 必须是 3(PCB)

检查图元分布

javascript 复制代码
const imgs = await eda.pcb_PrimitiveImage.getAll();  // 不带参数!
const lc = {};
for (const p of imgs) { const L = p.getState_Layer(); lc[L] = (lc[L]||0)+1; }

检查板框闭合

javascript 复制代码
const src = prim.getState_Polygon().getSource();
const nums = src.filter(v => typeof v === 'number');
const closed = Math.abs(nums[0]-nums[nums.length-2]) < 0.01
            && Math.abs(nums[1]-nums[nums.length-1]) < 0.01;

清空重建

javascript 复制代码
for (const cls of ['pcb_PrimitiveFill','pcb_PrimitivePolyline','pcb_PrimitiveString','pcb_PrimitiveImage']) {
  const all = await eda[cls].getAll(); // 不带参数
  if (all?.length) await eda[cls].delete(all.map(p => p.getState_PrimitiveId()));
}

开源地址

本工作流已开源,欢迎 Star!

相关推荐
程序喵大人2 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
quantdash_cc2 小时前
如何验证历史行情的交易日期是否完整覆盖研究区间?
python·数据分析·pandas·量化交易·股票数据·quantdash
I Am a robert girl2 小时前
当智能体学会“串通”:从长程交互中读懂涌现式合谋
python·多智能体系统·多智能体协作·llm agent·涌现式合谋·对齐问题·激励机制设计
云和数据.ChenGuang3 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
专注仿真3 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
jimy14 小时前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
wflynn4 小时前
GitHub 今日推荐|Edge0:让大号 MoE 模型在一台 Mac 上流式跑起来
python·开源·github
2601_967980115 小时前
python之用scapy分层解析pcap报文(Ethernet帧、IP数据包、TCP数据包、UDP数据包、Raw数据包)
python·scapy·pcap·协议分析·网络数据包
心疼你的一切5 小时前
Python自动发邮件实战定时发报表
大数据·开发语言·python