自定义符号创建
系统库中找不到所需器件符号时(如开发板模块、定制 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~130
await 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, // 左上角 X
topLeftY: number, // 左上角 Y(⚠️ Y 轴向上增长,topLeftY 是矩形最高点,向下延伸 height)
width: number, // 宽度
height: number, // 高度(从 topLeftY 向下延伸)
cornerRadius?: number, // 圆角半径
rotation?: number, // 旋转角度
color?: string | null, // 边框颜色
fillColor?: string | null, // 填充颜色
lineWidth?: number | null, // 线宽 1-10
lineType?: 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. 获取所有 ATTR
const 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() |