Skill v1.0.0
currentAutomated scan100/100name: "easyeda-draw-symbol" description: "Create custom schematic symbols for EasyEDA Pro. Invoke when creating custom symbols, building devices from symbols, or when system library lacks required components." metadata: version: "1.0.0"
自定义符号创建
系统库中找不到所需器件符号时(如开发板模块、定制 IC),通过此流程创建自定义符号。
1. 什么时候需要自定义符号
- 系统库搜索不到(如
nice!nano v2、Pro Micro等开发板模块) - 有现成符号但引脚功能与设计不匹配
- 需要自定义引脚排列以优化原理图可读性
2. 创建流程
创建空符号 → 添加引脚/形状/文本 → 创建器件 → 在原理图中使用
Step 1: 创建空符号
const personalLib = await eda.lib_LibrariesList.getPersonalLibraryUuid();const symbolUuid = await eda.lib_Symbol.create(personalLib, "nice!nano v2");// symbolUuid = "57ad2c820a1646eb8a6cfa1ff35c8922"
Step 2: 在符号编辑器中添加引脚和形状
打开符号编辑器,然后使用 SCH_Primitive* API 添加图元:
// 打开符号编辑器await eda.lib_Symbol.openInEditor(symbolUuid, personalLib);// 创建矩形主体// ⚠️ 符号编辑器 Y 轴向上增长(数学坐标系),topLeftY 是矩形最高点// 矩形从 topLeftY 向下延伸 height,所以 topLeftY=130 → 覆盖 y=-130~130await eda.sch_PrimitiveRectangle.create(-80, 130, 160, 260, 0, 0, null, null, null, null, null);// 创建引脚// SCH_PrimitivePin.create(x, y, pinNumber, pinName?, rotation?, pinLength?, pinColor?, pinShape?, pinType?)// ⚠️ 重要:(x, y) 是引脚连接点(圆点)的位置,不是引脚端点// 连接点应该放在矩形边缘上,引脚从连接点向外延伸// ⚠️ 重要:rotation 参数会被 API 反转存储// 传 0 → 存储 180 → 引脚向左延伸(适合左侧引脚)// 传 180 → 存储 0 → 引脚向右延伸(适合右侧引脚)// 左侧引脚: x = 矩形左边缘, rotation=0 (传0→存180→向左延伸)// 右侧引脚: x = 矩形右边缘, rotation=180 (传180→存0→向右延伸)// ⚠️ 重要:符号编辑器 Y 轴向上增长。y=-110 在矩形中间偏上位置(屏幕上方),// 与原理图编辑器的直觉相反(原理图 Y 轴向下增长)。await eda.sch_PrimitivePin.create(-80, -110, "1", "D0", 0, 20, null, "None", "BI");await eda.sch_PrimitivePin.create(80, -110, "13", "D10", 180, 20, null, "None", "BI");// 创建方向标识圆点(指示引脚 1 位置,在矩形左上角内部)// 圆点坐标 (-70, 120):X 比左边缘 (-80) 略靠内,Y 在矩形顶部内侧await eda.sch_PrimitiveCircle.create(-70, 120, 5, null, null, null, null, null);
Step 3: 创建器件(绑定符号)
const deviceUuid = await eda.lib_Device.create(personalLib, "nice!nano v2", undefined, {symbolType: "sch",symbol: { uuid: symbolUuid, libraryUuid: personalLib },});
Step 4: 在原理图中使用
// 搜索自定义器件(需指定个人库 UUID)const results = await eda.lib_Device.search("nice!nano v2", personalLib);// 放置器件await eda.sch_PrimitiveComponent.create({ libraryUuid: personalLib, uuid: results[0].uuid },x, y, "", 0, false, true, true);
3. 引脚创建 API
参数说明
SCH_PrimitivePin.create(x: number, // 引脚连接点 X 坐标(圆点位置,放在矩形边缘)y: number, // 引脚连接点 Y 坐标pinNumber: string, // 引脚编号(如 "1", "2")pinName?: string, // 引脚名称(如 "D0", "VCC")rotation?: number, // 旋转角度: 0, 90, 180, 270(⚠️ 传入值与存储值相反,见下方说明)pinLength?: number, // 引脚长度(从连接点向外延伸)pinColor?: string | null, // 引脚颜色,null=默认pinShape?: ESCH_PrimitivePinShape, // 引脚形状,"None"|"Clock"|"Inverted"|"Inverted Clock"pinType?: ESCH_PrimitivePinType // 引脚类型)
⚠️ pinName 为空时的行为:pinName传undefined或null时,引脚只显示编号不显示名称。传空字符串""效果相同。如果符号中部分引脚不需要名称(如仅用于内部连接的 GND 引脚),可省略pinName参数。
⚠️ 重要:`(x, y)` 是引脚连接点(圆点)的位置,不是引脚端点。引脚从连接点沿rotation方向延伸pinLength单位。连接点应该放在矩形边缘上,这样引脚才能正确对齐。错误示例:x=-100, rotation=0, 矩形边缘=-80→ 连接点和矩形之间有 20 单位间隙 ❌正确示例:x=-80, rotation=0, 矩形边缘=-80→ 连接点正好在矩形边缘 ✅
引脚类型 (pinType)
| 类型 | 说明 | 适用场景 | |
|---|---|---|---|
"BI" | 双向 | GPIO 引脚 | |
"IN" | 输入 | RESET、中断输入 | |
"OUT" | 输出 | TX、PWM 输出 | |
"Power" | 电源 | VCC、VDD、RAW | |
"Ground" | 地 | GND、VSS | |
"Passive" | 无源 | 模拟引脚 | |
"Undefined" | 未定义 | 不使用的引脚 |
引脚方向 (rotation)
⚠️ API 反转行为:`sch_PrimitivePin.create()` 传入的 rotation 值会被反转为存储值。传 0 → 存储 180(向左)→ 引脚向左延伸传 180 → 存储 0(向右)→ 引脚向右延伸传 90 → 存储 270(向下)→ 引脚向下延伸传 270 → 存储 90(向上)→ 引脚向上延伸
| 传入 rotation | 存储 rotation | 引脚方向 | 适用侧 | |
|---|---|---|---|---|
0 | 180 | 向左 | 符号左侧引脚 | |
90 | 270 | 向下 | 符号底部引脚 | |
180 | 0 | 向右 | 符号右侧引脚 | |
270 | 90 | 向上 | 符号顶部引脚 |
4. 矩形创建 API
SCH_PrimitiveRectangle.create(topLeftX: number, // 左上角 XtopLeftY: number, // 左上角 Y(⚠️ Y 轴向上增长,topLeftY 是矩形最高点,向下延伸 height)width: number, // 宽度height: number, // 高度(从 topLeftY 向下延伸)cornerRadius?: number, // 圆角半径rotation?: number, // 旋转角度color?: string | null, // 边框颜色fillColor?: string | null, // 填充颜色lineWidth?: number | null, // 线宽 1-10lineType?: ESCH_PrimitiveLineType | null,fillStyle?: ESCH_PrimitiveFillStyle | null)
⚠️ 符号编辑器 Y 轴方向:与屏幕坐标不同,符号编辑器 Y 轴向上增长(数学坐标系)。topLeftY是矩形的最高点(Y 值最大的边),矩形从此点向下延伸height。例如:要让矩形覆盖 y=-130 到 y=130,应传topLeftY=130, height=260(不是 topLeftY=-130)。
5. CLI 命令
# 创建空符号到个人库./scripts/draw_cli.py create-symbol "器件名称"# 在编辑器中打开符号./scripts/draw_cli.py open-symbol <symbolUuid> <libUuid># 从符号创建器件./scripts/draw_cli.py create-device <名称> <symUuid> <libUuid># 一键构建符号(创建+打开+等待编辑)./scripts/draw_cli.py build-symbol "器件名称"# 搜索器件(默认系统库,指定个人库 UUID)./scripts/draw_cli.py search "nice!nano v2" 5 --lib <libraryUuid>
6. 参考示例
6.1 符号编辑器与原理图编辑器 API 差异
| 操作 | 原理图编辑器 | 符号编辑器 | |
|---|---|---|---|
| 查询引脚 | sch_PrimitivePin.getAll() ✅ | sch_PrimitivePin.getAll() ✅ | |
| 查询矩形 | sch_PrimitiveRectangle.getAll() ✅ | ❌ 返回空数组 | |
| 查询圆 | sch_PrimitiveCircle.getAll() ✅ | ❌ 返回空数组 | |
| 查询引脚 ID | sch_PrimitivePin.getAllPrimitiveId() ✅ | sch_PrimitivePin.getAllPrimitiveId() ✅ | |
| 查询矩形 ID | sch_PrimitiveRectangle.getAllPrimitiveId() ✅ | ❌ 返回空数组 | |
| 查询圆 ID | sch_PrimitiveCircle.getAllPrimitiveId() ✅ | ❌ 返回空数组 | |
| 查询所有图元 | 各类型 getAll() 方法 | sch_SelectControl.getAllSelectedPrimitives() ✅(需先选中) | |
| 获取图元类型 | sch_Primitive.getPrimitiveTypeByPrimitiveId(id) ✅ | ✅ 可用 | |
| 获取图元属性 | sch_Primitive.getPrimitiveByPrimitiveId(id) ✅ | ✅ 可用 |
结论:在符号编辑器中,不要依赖 `sch_PrimitiveRectangle.getAll()` 和 `sch_PrimitiveCircle.getAll()` 等类型专属批量查询方法。 应使用 sch_PrimitivePin.getAllPrimitiveId() 获取所有引脚 ID,再通过 sch_Primitive.getPrimitiveByPrimitiveId(id) 逐个查询。或使用 sch_SelectControl.getAllSelectedPrimitives() 获取已选中图元(圆、矩形等均可用此方式查询)。
6.2 nice!nano v2 符号
符号参数:
- 24 个引脚(左 12 + 右 12)
- 引脚间距 20 单位
- 主体矩形 160×260(topLeftX=-80, topLeftY=130)
- 引脚长度 20
- 方向标识:圆点在矩形左上角内部 (-70, 120),半径 5,指示引脚 1 位置
- 引脚顺序(DIP 标准):
- 左列 Pin 1-12:从上到下,y = 110, 90, 70, 50, 30, 10, -10, -30, -50, -70, -90, -110
- 右列 Pin 13-24:从下到上,y = -110, -90, -70, -50, -30, -10, 10, 30, 50, 70, 90, 110
6.3 引脚布局规范
引脚名称在器件主体内部(推荐):
───┐ D0 GND ├──────┤ D1 VCC ├──────┤ D2 GND ├──────┤ D3 ┌────────┐ RAW ├──────┤ D4 │ 器件主体 │ VCC ├──────┤ D5 │ 160×260 │ GND ├──────┤ D6 └────────┘ RESET ├─────┤ D7 连接点 D21 ├──────┤ D8 x=-80/80 D20 ├──────┤ D9 D19 ├──────┤ D14 D18 ├──────┘ D15 D16 └───引脚连接点 (x,y) 在矩形边缘,引脚线在外侧名称文本在矩形内部,编号在引脚线上方左侧 (rotation=0): 名称在引脚线右侧(矩形内),偏移 +30右侧 (rotation=180): 名称在引脚线左侧(矩形内),偏移 -30
7. 引脚名称位置调整(重要发现)
⚠️ 关键发现:引脚名称是 ATTR 图元(不是独立的 Text 图元),通过 `parentPrimitiveId` 精确关联到 PIN!通过sch_PrimitiveAttribute.getAllPrimitiveId()可以获取所有 ATTR,包括 "Pin Name" 和 "Pin Number"。
7.1 问题现象
sch_PrimitivePin.create() 创建引脚时,EasyEDA 会自动生成 ATTR 图元作为名称和编号,但初始位置通常不正确:
PIN2 (正确): 引脚连接点(-80, 90), 名称ATTR(-50, 90) → 名称在矩形内部 ✅PIN1 (异常): 引脚连接点(-80, 110), 名称ATTR(-103, 110) → 名称在矩形外部 ❌
7.2 原因
- 修改
rotation只会旋转引脚线,不会同步调整已生成的 ATTR 图元位置 - ATTR 的
alignMode(对齐方式)和x,y坐标需要手动修正 - 同名引脚(如多个 GND)不能靠 `value + y` 匹配,必须用 `parentPrimitiveId` 精确匹配
7.3 解决方案
使用 set-pin-labels-position CLI 命令批量修正引脚名称位置:
# 修正左侧引脚名称位置(名称在引脚线右侧,矩形内,左对齐)./scripts/draw_cli.py set-pin-labels-position --side left --offset 30# 修正右侧引脚名称位置(名称在引脚线左侧,矩形内,右对齐)./scripts/draw_cli.py set-pin-labels-position --side right --offset 30
实现原理(已固化到 `fixPinLabels`):
- 通过
sch_PrimitivePin.getAllPrimitiveId()获取所有引脚 - 通过
sch_PrimitiveAttribute.getAllPrimitiveId()获取所有 ATTR 图元 - 用 `parentPrimitiveId` 精确匹配 PIN 和 ATTR(避免同名引脚错乱)
- 设置正确的
alignMode和x,y坐标
或手动用 sch_PrimitiveAttribute API 调整:
// 1. 获取所有 ATTRconst attrIds = await eda.sch_PrimitiveAttribute.getAllPrimitiveId();// 2. 找到 Pin Name ATTR(必须用 parentPrimitiveId 匹配,不能只用 value)const attr = await eda.sch_PrimitiveAttribute.get([attrId]);// 3. 修改位置和对齐方式const at = attr[0].toAsync();at.setState_AlignMode(2); // 左侧=2(左中),右侧=8(右中)at.setState_X(-50);at.setState_Y(-pin.y); // ⚠️ Y 坐标 = -pin.y(符号编辑器坐标系)await at.done();
7.4 名称位置规律(已验证)
| 引脚侧 | rotation | alignMode 设置值 | alignMode 存储值 | 含义 | X 坐标 | Y 坐标 | |
|---|---|---|---|---|---|---|---|
| 左侧 | 0 | 2 (左中) | 3 (左中) | 文字从锚点向右延伸,左对齐 | pin.x + offset | -pin.y | |
| 右侧 | 180 | 8 (右中) | 5 (右中) | 文字从锚点向左延伸,右对齐 | pin.x - offset | -pin.y | |
| 顶部 | 270 | 5 (正中) | 4 (正中) | 文字水平居中,在矩形内部 | pin.x | -pin.y + offset | |
| 底部 | 90 | 5 (正中) | 4 (正中) | 文字水平居中,在矩形内部 | pin.x | -pin.y - offset |
⚠️ 关键规则(实测验证):
- Y 坐标 = `-pin.y`:
setState_Y(-pin.y)后 EasyEDA 内部自动翻转为pin.y存储,显示位置正确 - alignMode 设置值与存储值不同:EasyEDA 内部使用列优先九宫格存储
- 设置值(
setState_AlignMode):1=左上 2=左中 3=左下 4=中上 5=正中 6=中下 7=右上 8=右中 9=右下 - 存储值(
alignMode属性 /getState_AlignMode()):0=左上 1=中上 2=右上 3=左中 4=正中 5=右中 6=左下 7=中下 8=右下
- alignMode 必须用"中"锚点(设置值 2/8/5),不要用"上/下"锚点,否则 Y 位置会偏移
- X 坐标是文字锚点位置,不是文字中心:左中(2)时 X 是文字左边缘,右中(8)时 X 是文字右边缘,正中(5)时 X 是文字中心
- offset 推荐值 5~10:名称与矩形边缘的距离,默认 5
ATTR 属性说明:
key: "Pin Name" 或 "Pin Number"value: 引脚名称或编号x,y: ATTR 锚点位置(设置-pin.y或-pin.y ± offset,存储为pin.y或pin.y ∓ offset)alignMode: 对齐方式存储值(左侧=3 左中,右侧=5 右中,上下=4 正中)parentPrimitiveId: 精确关联的 PIN ID(匹配时必须使用)
7. 常见错误
| 错误 | 原因 | 解决 | |
|---|---|---|---|
| "无法创建引脚图元" | pinShape 传了 null | 改为传 "None" | |
| 搜索不到自定义器件 | 搜索的是系统库 | 传入个人库 UUID | |
| 引脚不显示 | 符号编辑器未激活 | 先 openInEditor 再操作 | |
| 引脚与矩形未对齐 | (x,y) 位置错误,放在矩形边缘 + 长度位置 | (x,y) 应放在矩形边缘上,不是边缘 + 长度 | |
| 矩形查询不到 | sch_PrimitiveRectangle.getAll() 在符号编辑器中无效 | 改用 sch_SelectControl.getAllSelectedPrimitives() |