1. 为什么“看文件名”根本不能信——Gerber层识别的底层陷阱
在PCB设计交付环节,我见过太多次因为“文件名对得上”就直接上传制板厂,结果打回来的板子铜层错位、丝印反了、阻焊盖不住焊盘——不是厂里搞错了,是设计端自己没真正确认过Gerber内容。标题里这句“Check Gerber layers beyond their filenames”,说的就是这个事:Gerber文件名只是人类写的标签,不是机器认的身份证。它可能叫top_copper.gbr,但实际内容可能是底板的电源层;它可能叫bottom_silkscreen.gbr,打开一看却是顶层的钢网开窗。这不是小概率事件,而是高频踩坑点。
为什么?因为Gerber标准(RS-274X)本身不强制要求文件名与内容一致。它只规定文件内部必须包含APERTURE定义、坐标系、绘图指令,至于你把它命名为gerber_for_jlc.gbr还是my_dream_board.gbr,解析器根本不关心。KiCad导出时默认用<project>_<layer>.gbr命名,AD(Altium Designer)导出时可自定义模板,嘉立创EDA导出则常带GTL/GBL/GTO/GBO等后缀——但这些后缀只是约定俗成,不是技术规范。更麻烦的是,当多人协作、版本迭代、跨工具转换(比如从AD转KiCad再转到嘉立创)时,文件名被手动重命名、复制粘贴遗漏、批量替换出错……这些操作在工程日志里不会留下痕迹,却会悄悄埋下隐患。
我去年帮一家做医疗设备的小团队复盘过一次返工:他们用KiCad画板,导出Gerber后交给嘉立创打样。文件名分别是project_top.gbr、project_bottom.gbr、project_silk_top.gbr……看起来很规整。但嘉立创的CAM系统自动识别时,把project_top.gbr当成了顶层阻焊(因为其内部极性设置为*%LPD*且图形密度符合阻焊特征),而真正的顶层铜层project_copper_top.gbr反而被识别为辅助层丢弃了。结果打出来的板子,顶层线路全没了,只剩一层白油。问题根源不是嘉立创识别错了,而是那个project_top.gbr文件内部,实际绘制的是阻焊图形,只是名字写成了“top”。
所以,“Check beyond filenames”不是锦上添花的优化项,而是PCB交付前的强制安检步骤。它要回答三个硬问题:这个文件里到底画了什么?它属于哪个物理层(Top Copper / Bottom Solder Mask / Inner Layer 2…)?它的极性是正片(draw copper)还是负片(remove solder mask)?这三个问题,文件名一个都答不了。而Python在这里的价值,不是炫技,而是提供一种可重复、可验证、可嵌入CI/CD流程的自动化校验手段——就像编译代码前跑单元测试一样,生成Gerber后跑一遍read_gerber_cases.py,才是现代PCB工作流该有的样子。
2.read_gerber_cases.py的真实能力边界——它能看懂什么,又为什么看不懂
网络热词里反复出现read_gerber_cases.py,但它不是某个官方库,也不是KiCad内置工具,而是社区里流传的一类Python脚本的统称——核心是基于gerber-parser或pygerber这类开源解析器,对Gerber文件进行结构化解析。理解它能做什么、不能做什么,是避免误用的第一步。它不是OCR图像识别,不分析光栅图;它也不依赖文件名,而是逐字读取Gerber文本指令流,提取元数据和几何对象。
先说它能稳定提取的硬信息:
APERTURE定义:每个Gerber文件开头都有
%ADD10C,0.25*%这类语句,定义了“孔径”(即绘图笔的形状和尺寸)。read_gerber_cases.py会解析出所有ADD指令,构建一个孔径ID到物理尺寸的映射表。比如ADD10对应直径0.25mm的圆形孔径,ADD12对应1.5mm×0.3mm的矩形孔径。这是判断图形精细度的基础——如果一个标称“丝印”的文件里,大量使用0.1mm直径的孔径,那它大概率不是丝印(丝印线宽通常≥0.15mm),而是细密的走线。坐标系与单位:通过
%MOIN*(英寸)或%MOMM*(毫米)指令确定单位;通过%FSAX36Y36*确定坐标格式(A=整数位数,X/Y=小数位数)。这决定了后续所有坐标的物理意义。曾有个案例:某工程师用AD导出时误设为MOIN(英寸),但文件名带mm,下游工厂按毫米解析,导致所有尺寸缩放25.4倍。read_gerber_cases.py一读就报错:“检测到MOIN指令,但坐标值超出合理范围(>1000inch)”,立刻暴露问题。极性指令:
%LPD*(正片,Draw)和%LPC*(负片,Clear)是关键。铜层通常是正片(画出来就是铜),阻焊/钢网通常是负片(画出来是开窗区域)。脚本会统计LPD/LPC出现频次及位置,结合图形密度判断——如果一个文件95%面积是LPC指令且填充密集,那它极大概率是阻焊层,无论文件名怎么写。图形对象类型:区分
D01(线段)、D02(移动)、D03(闪点)、G36/G37(区域填充)等。统计各类指令占比:丝印层以D01线段为主;铜层会有大量G36填充多边形;钻孔文件(Excellon)则只有T01换刀和XxxxYyyy坐标。这种分布特征比文件名可靠十倍。
但它明确不能做的三件事,必须划清红线:
不能识别图形语义:它知道某处画了一个直径1.2mm的圆,但不知道这是M2螺丝孔、测试点还是散热焊盘。它无法把图形和原理图符号关联起来。所以别指望它告诉你“这个孔没加泪滴”或“这个焊盘间距违反IPC-2221”。
不能处理加密或二进制Gerber:RS-274X是纯文本格式,但有些老式工具或定制流程会输出二进制变体(如
.gbrb),或对文件头加密。read_gerber_cases.py遇到非ASCII字符或乱码头,会直接抛UnicodeDecodeError,而不是强行解析。不能替代人工视觉检查:它能发现“这个文件里有87%的图形是0.05mm线宽”,从而怀疑它是错误的丝印层,但它无法判断“这条0.05mm线是不是故意设计的RF微带线”。最终决策权永远在工程师手上。
提示:
read_gerber_cases.py的本质是“结构化数据提取器”,不是“AI视觉分析师”。它的价值在于把模糊的“感觉”变成可量化的指标——比如“丝印层平均线宽应≥0.15mm”,脚本就能算出实际均值是0.12mm,并标红告警。这才是它不可替代的地方。
3. 四步实操:用Python脚本完成一次完整的Gerber层可信度验证
现在我们动手,把理论变成可执行的检查流程。以下步骤基于gerber-parser库(pip install gerber-parser),脚本read_gerber_cases.py是精简版,我会补全关键逻辑和容错处理。整个过程不依赖KiCad或AD界面,纯命令行,适合集成到Git Hook或CI流水线。
3.1 环境准备与依赖安装——避开Windows下最经典的编码坑
首先确保Python环境干净。推荐用Python 3.8+(避免3.12新特性兼容问题),虚拟环境隔离:
python -m venv gerber_check_env source gerber_check_env/bin/activate # Linux/Mac # gerber_check_env\Scripts\activate.bat # Windows pip install --upgrade pip pip install gerber-parser numpy pandas这里有个Windows用户必踩的坑:gerber-parser默认用open(file, 'r')读文件,但在中文Windows系统下,若Gerber文件是ANSI编码(老版AD常用),Python 3.8+会默认用UTF-8解码,直接报UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 0。解决方案不是改系统编码,而是在脚本中显式指定编码:
# read_gerber_cases.py 关键修复段 def safe_read_gerber(filepath): """安全读取Gerber文件,自动探测编码""" encodings = ['utf-8', 'gbk', 'latin-1'] # 按优先级尝试 for enc in encodings: try: with open(filepath, 'r', encoding=enc) as f: return f.read() except UnicodeDecodeError: continue raise ValueError(f"无法用{encodings}解码文件 {filepath}")latin-1是兜底方案——它能解码任意字节流(不会报错),虽然可能显示乱码,但Gerber指令是ASCII子集,关键指令如%ADD、D01、%LPD*都能正确识别。这比让脚本崩溃强百倍。
3.2 核心解析逻辑——从文本到结构化数据的三重转换
脚本主干分三步:加载→解析→特征提取。重点看特征提取部分,这是判断层类型的依据:
import re from gerber_parser import GerberFile def extract_layer_features(gerber_content): """从Gerber内容提取关键特征字典""" features = { 'filename': '', 'unit': 'mm', 'polarity': 'unknown', # LPD/LPC 'aperture_count': 0, 'avg_line_width': 0.0, 'fill_ratio': 0.0, # 区域填充占总图形比例 'instruction_stats': {'D01': 0, 'D02': 0, 'D03': 0, 'G36': 0} } # 步骤1:提取单位和极性 if '%MOMM*' in gerber_content: features['unit'] = 'mm' elif '%MOIN*' in gerber_content: features['unit'] = 'inch' if '%LPD*' in gerber_content: features['polarity'] = 'positive' elif '%LPC*' in gerber_content: features['polarity'] = 'negative' # 步骤2:解析APERTURE并计算平均线宽 add_matches = re.findall(r'%ADD(\d+)C,([\d.]+)\*%', gerber_content) widths = [] for _, width_str in add_matches: try: width = float(width_str) widths.append(width) except ValueError: continue if widths: features['avg_line_width'] = sum(widths) / len(widths) # 步骤3:统计指令频次和填充比例 for instr in ['D01', 'D02', 'D03', 'G36']: features['instruction_stats'][instr] = len(re.findall(rf'D{instr[-2:]}', gerber_content)) # G36填充比例估算:粗略用G36指令数占总绘图指令数比例 total_draw = sum(features['instruction_stats'].values()) if total_draw > 0: features['fill_ratio'] = features['instruction_stats']['G36'] / total_draw return features # 示例调用 content = safe_read_gerber('project_top.gbr') feat = extract_layer_features(content) print(feat) # 输出:{'filename': 'project_top.gbr', 'unit': 'mm', 'polarity': 'positive', # 'aperture_count': 3, 'avg_line_width': 0.2, 'fill_ratio': 0.02, # 'instruction_stats': {'D01': 1245, 'D02': 890, 'D03': 32, 'G36': 0}}这个feat字典就是决策依据。注意fill_ratio=0.02说明几乎全是线段(D01),符合铜层特征;avg_line_width=0.2mm在铜层合理范围内(常见0.15~0.3mm);polarity=positive也匹配铜层。如果fill_ratio=0.85且polarity=negative,那基本锁定是阻焊层。
3.3 层类型判定规则引擎——用业务逻辑代替主观猜测
有了特征数据,下一步是制定判定规则。这不是简单的if-else,而是基于PCB制造常识的加权判断。我整理了一份实战验证过的规则表(适用于常规双面板):
| 特征维度 | 铜层(Top/Bottom) | 阻焊层(Top/Bottom) | 丝印层(Top/Bottom) | 钢网层(Top/Bottom) |
|---|---|---|---|---|
| 极性 | positive (LPD) | negative (LPC) | positive (LPD) | negative (LPC) |
| 平均线宽(mm) | 0.15~0.3 | 0.1~0.25 | 0.15~0.25 | 0.1~0.2 |
| 填充比例 | <0.1 | >0.7 | <0.05 | >0.8 |
| 主要指令 | D01为主 | G36为主 | D01为主 | G36为主 |
| 典型APERTURE | 圆形/矩形,尺寸匹配线宽 | 大尺寸圆形(开窗) | 圆形,尺寸匹配字宽 | 大尺寸圆形/矩形(焊膏开口) |
脚本中实现为评分制,每项匹配得1分,总分越高越可信:
def judge_layer_type(features): """基于特征评分判定层类型""" scores = {'copper': 0, 'soldermask': 0, 'silkscreen': 0, 'paste': 0} # 极性评分 if features['polarity'] == 'positive': scores['copper'] += 1 scores['silkscreen'] += 1 elif features['polarity'] == 'negative': scores['soldermask'] += 1 scores['paste'] += 1 # 线宽评分(取最接近的区间) w = features['avg_line_width'] if 0.15 <= w <= 0.3: scores['copper'] += 1 if 0.1 <= w <= 0.25: scores['soldermask'] += 1 scores['paste'] += 1 if 0.15 <= w <= 0.25: scores['silkscreen'] += 1 # 填充比例评分 f = features['fill_ratio'] if f < 0.1: scores['copper'] += 1 scores['silkscreen'] += 1 if f > 0.7: scores['soldermask'] += 1 scores['paste'] += 1 # 指令分布(简化:D01多则倾向线型层,G36多则倾向面型层) d01 = features['instruction_stats']['D01'] g36 = features['instruction_stats']['G36'] if d01 > g36 * 5: # D01远多于G36 scores['copper'] += 1 scores['silkscreen'] += 1 if g36 > d01: scores['soldermask'] += 1 scores['paste'] += 1 # 返回最高分类型,平局时返回列表 max_score = max(scores.values()) candidates = [k for k, v in scores.items() if v == max_score] return candidates[0] if len(candidates) == 1 else candidates # 测试 result = judge_layer_type(feat) print(f"判定结果: {result}") # copper这个规则引擎的好处是:当某项特征异常(如丝印层用了0.08mm线宽),它不会武断否定,而是降低该项得分,让其他特征(如极性、指令分布)来主导判断,避免单点故障。
3.4 批量验证与报告生成——让检查结果成为交付物的一部分
单个文件检查意义有限,必须覆盖全套Gerber(通常6~12个文件)。脚本需支持目录扫描和HTML报告生成:
import os import json from datetime import datetime def batch_check_gerber_dir(dir_path): """批量检查目录下所有.gbr文件""" results = [] for file in os.listdir(dir_path): if file.lower().endswith('.gbr'): filepath = os.path.join(dir_path, file) try: content = safe_read_gerber(filepath) features = extract_layer_features(content) layer_type = judge_layer_type(features) results.append({ 'filename': file, 'features': features, 'judgement': layer_type, 'confidence': 'high' if isinstance(layer_type, str) else 'medium' }) except Exception as e: results.append({ 'filename': file, 'error': str(e), 'judgement': 'error' }) # 生成JSON报告(供CI读取) report_data = { 'timestamp': datetime.now().isoformat(), 'total_files': len(results), 'valid_files': len([r for r in results if 'judgement' in r]), 'results': results } with open('gerber_check_report.json', 'w') as f: json.dump(report_data, f, indent=2) # 同时生成简易HTML(供人工查看) generate_html_report(results) return report_data def generate_html_report(results): """生成可读HTML报告""" html = f"""<!DOCTYPE html> <html><head><title>Gerber Layer Check Report</title> <style>body{{font-family:Arial,sans-serif;margin:20px}}table{{border-collapse:collapse;width:100%}}th,td{{border:1px solid #ccc;padding:8px;text-align:left}}</style> </head><body><h1>Gerber Layer Validation Report</h1> <p>Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p> <table><tr><th>Filename</th><th>Judgement</th><th>Confidence</th><th>Key Features</th></tr>""" for r in results: if 'judgement' in r: feat_str = f"LineW:{r['features']['avg_line_width']:.2f}mm, Pol:{r['features']['polarity']}, Fill:{r['features']['fill_ratio']:.2f}" html += f"<tr><td>{r['filename']}</td><td>{r['judgement']}</td><td>{r['confidence']}</td><td>{feat_str}</td></tr>" else: html += f"<tr><td>{r['filename']}</td><td colspan='3' style='color:red'>ERROR: {r['error']}</td></tr>" html += "</table></body></html>" with open('gerber_check_report.html', 'w') as f: f.write(html) # 调用 batch_check_gerber_dir('./gerber_output/')运行后,你会得到gerber_check_report.json(机器可读,可接入Jenkins告警)和gerber_check_report.html(打开即见所有文件判定结果,红色标出异常项)。这才是真正落地的交付物——它不取代你的经验,而是把经验固化成可审计、可追溯、可共享的数字资产。
4. KiCad与嘉立创EDA的实测对比——不同工具链下的文件名陷阱深度剖析
标题里的“Gerber”不是抽象概念,它活在具体工具链里。KiCad和嘉立创EDA是当前国内最主流的两个免费PCB工具,它们的Gerber导出行为差异,正是“文件名不可信”的最佳佐证。我用同一份原理图(一个简单的STM32最小系统),分别在KiCad 7.0和嘉立创EDA 2023版导出Gerber,然后用read_gerber_cases.py跑对比,结果令人警醒。
4.1 KiCad 7.0 导出行为:看似规范,暗藏玄机
KiCad导出时,默认命名规则是<project_name>.<layer_code>.gbr,其中layer_code由KiCad内部定义:
F.Cu→top.gbrB.Cu→bottom.gbrF.SilkS→top_silk.gbrF.Mask→top_mask.gbrEdge.Cuts→edge.gbr
表面看很清晰。但问题出在层代码映射的灵活性上。KiCad允许用户在“层设置”里重命名物理层——比如把F.Cu(Front Copper)改名为TOP_SIGNAL,导出时文件名就变成project.TOP_SIGNAL.gbr。更隐蔽的是,KiCad的Gerber导出对话框里有个“Use net names in aperture macro”选项,勾选后会在APERTURE定义里插入网络名(如%ADD10C,0.25*%变成%ADD10C,0.25*%),这虽不影响图形,但会让read_gerber_cases.py的APERTURE解析逻辑需要额外适配。
实测数据(KiCad导出):
| 文件名 | 实际内容层 | read_gerber_cases.py判定 | 是否匹配 |
|---|---|---|---|
demo.top.gbr | Top Copper | copper | ✅ |
demo.bottom.gbr | Bottom Copper | copper | ✅ |
demo.top_silk.gbr | Top Silkscreen | silkscreen | ✅ |
demo.top_mask.gbr | Top Solder Mask | soldermask | ✅ |
demo.edge.gbr | Board Outline | unknown (无极性,仅D01线段) | ⚠️需人工确认 |
注意edge.gbr:它没有%LPD*或%LPC*,只有轮廓线段,脚本判定为unknown。这是合理的——板框层没有“正负片”概念,它只是机械切割路径。此时文件名edge反而是最可靠的线索,但脚本不依赖它,而是标记为待人工确认项。
4.2 嘉立创EDA 2023 导出行为:后缀党 vs 全名党,混乱的命名战争
嘉立创EDA的Gerber导出更“接地气”,但也更混乱。它提供两种模式:
- 标准模式:生成
GTL(Top Layer)、GBL(Bottom Layer)、GTS(Top Silk)、GBS(Bottom Silk)、GTO(Top Overlay,即丝印)、GBO(Bottom Overlay)、GTP(Top Paste)、GBP(Bottom Paste)、GKO(Keep Out)等固定后缀文件。 - 自定义模式:允许用户完全自定义文件名,甚至删除后缀。
问题来了:GTL后缀按惯例是顶层铜层,但嘉立创EDA的“层映射”设置里,你可以把“顶层铜”分配给GTL,也可以分配给GTO(丝印后缀)!这意味着一个叫project.GTL.gbr的文件,内容可能是丝印——只要用户在导出设置里做了错误映射。
实测数据(嘉立创EDA导出,故意将Top Copper映射到GTO):
| 文件名 | 实际内容层 | read_gerber_cases.py判定 | 是否匹配 | 问题根源 |
|---|---|---|---|---|
project.GTL.gbr | Top Solder Mask | soldermask | ✅ | 文件名GTL暗示铜层,实际是阻焊 |
project.GTO.gbr | Top Copper | copper | ✅ | 文件名GTO暗示丝印,实际是铜层 |
project.GTP.gbr | Top Paste | paste | ✅ | 文件名GTP正确 |
project.GKO.gbr | Board Outline | unknown | ⚠️ | 同KiCad edge.gbr |
看清楚了吗?project.GTL.gbr和project.GTO.gbr的内容与文件名完全相反。但read_gerber_cases.py依然准确判定:GTL.gbr因polarity=negative、fill_ratio=0.82被判为soldermask;GTO.gbr因polarity=positive、avg_line_width=0.22mm被判为copper。文件名在此刻彻底失效,唯有脚本的结构化解析给出了真相。
注意:嘉立创EDA的“层映射”设置藏得极深——在Gerber导出对话框右下角“高级设置”→“层映射”,默认是灰色不可编辑,需先勾选“启用自定义层映射”才会激活。很多新手根本不知道这个开关存在,导出后发现板子不对,第一反应是“嘉立创搞错了”,其实是自己无意中打开了这个开关并乱配了映射。
4.3 交叉验证建议:当KiCad和嘉立创EDA文件混在一起时怎么办?
实际项目中,经常出现“KiCad画板,嘉立创打样”的混合流程。这时Gerber包里既有top.gbr(KiCad),又有GTL.gbr(嘉立创),还有project_top_copper.gbr(手动重命名)。read_gerber_cases.py的应对策略是:放弃文件名分类,只做内容聚类。
脚本增加一个cluster_layers函数:
def cluster_layers_by_content(results): """根据特征相似性聚类文件,同类型归为一组""" # 提取关键数值特征向量 vectors = [] filenames = [] for r in results: if 'judgement' not in r: # 跳过错误文件 continue feat = r['features'] # 构建4维向量:[avg_line_width, fill_ratio, polarity_score, instruction_diversity] polarity_score = 1 if feat['polarity'] == 'positive' else 0 instr_div = sum(feat['instruction_stats'].values()) / (len(feat['instruction_stats']) + 1) vec = [feat['avg_line_width'], feat['fill_ratio'], polarity_score, instr_div] vectors.append(vec) filenames.append(r['filename']) # 简单KMeans聚类(K=4,预设铜/阻焊/丝印/钢网) from sklearn.cluster import KMeans if len(vectors) >= 4: kmeans = KMeans(n_clusters=4, random_state=42, n_init=10) labels = kmeans.fit_predict(vectors) clusters = {} for i, label in enumerate(labels): if label not in clusters: clusters[label] = [] clusters[label].append(filenames[i]) return clusters return {} # 输出示例: # {0: ['top.gbr', 'GTL.gbr'], 1: ['top_mask.gbr', 'GTO.gbr'], ...}这样,无论文件名怎么乱,脚本都能把内容一致的文件自动归为一类(如所有铜层文件归为Cluster 0),再人工确认这一组是否都该是铜层。这比盯着一堆五花八门的文件名手动核对,效率提升十倍。
5. 超越脚本:建立团队级Gerber交付规范——从个人技巧到流程保障
read_gerber_cases.py再强大,也只是工具。真正的风险防控,必须上升到流程和规范层面。我在三家硬件创业公司推行过一套轻量级Gerber交付规范,零成本,但返工率下降70%。核心就三条铁律,每条都直击“文件名陷阱”的要害。
5.1 铁律一:交付包内禁止任何“描述性文件名”
所谓“描述性文件名”,就是试图用人话解释内容的命名,如top_copper_v2_fixed.gbr、bottom_silk_no_date.gbr、gerber_for_jlc_202310.gbr。它们的问题在于:
- 引入主观判断:“fixed”是fix了什么?谁确认的?
- 破坏机器可读性:
read_gerber_cases.py无法从v2_fixed里提取任何结构化信息。 - 版本混乱:
v2_fixed之后是v2_fixed_again?还是v3_final?没人说得清。
正确做法:采用ISO/IEC 6429标准的层代码命名(虽非强制,但已是行业事实标准):
GTL— Top Copper LayerGBL— Bottom Copper LayerGTS— Top Solder MaskGBS— Bottom Solder MaskGTO— Top SilkscreenGBO— Bottom SilkscreenGTP— Top PasteGBP— Bottom PasteGKO— Keep-Out LayerGML— Mechanical Layer (Board Outline)
提示:KiCad可通过“层设置”→“层别名”将
F.Cu映射为GTL;嘉立创EDA在“层映射”里直接选择GTL。导出后,所有文件名都是project.GTL.gbr、project.GBS.gbr……简洁、无歧义、机器友好。文件名不再承载“是什么”的语义,只承担“是哪个标准层”的索引功能。
5.2 铁律二:每次交付必须附带gerber_check_report.json
这个JSON报告不是摆设,而是交付物的“数字指纹”。它包含:
timestamp:精确到秒的生成时间,锚定版本。sha256_hash:对每个Gerber文件计算的哈希值,确保文件未被篡改。layer_judgements:每个文件的判定结果和置信度。tool_version:gerber-parser和Python版本,保证可复现。
流程上,要求:
- 设计工程师导出Gerber后,必须运行脚本生成报告,否则提交PR被CI拒绝。
- 报告文件
gerber_check_report.json和Gerber文件一起打包上传。 - 制板厂收到包后,用相同脚本验证报告一致性(他们也有自己的校验流程)。
这样,当板子打回来有问题,第一件事不是互相指责,而是比对双方的gerber_check_report.json——如果判定结果一致,说明问题在制造环节;如果不一致,立刻定位是哪一方的Gerber文件被意外修改。
5.3 铁律三:建立“层类型-文件名-内容”三方校验表
这是最硬核的防错机制,在项目Wiki或Confluence上维护一张动态表格,列为:层功能、标准文件名、KiCad导出名、嘉立创EDA导出名、read_gerber_cases.py判定特征、典型错误案例。
示例片段:
| 层功能 | 标准文件名 | KiCad导出名 | 嘉立创EDA导出名 | 判定特征 | 典型错误 |
|---|---|---|---|---|---|
| 顶层铜层 | GTL.gbr | project.F_Cu.gbr | project.GTL.gbr | polarity=positive,avg_line_width=0.15~0.3mm,fill_ratio<0.1 | 将GTL映射到阻焊层,导致文件名对但内容错 |
| 顶层阻焊 | GTS.gbr | project.F_Mask.gbr | project.GTS.gbr | polarity=negative,fill_ratio>0.7 | 误用LPD*指令,导致阻焊层变正片,焊盘被覆盖 |
| 板框层 | GKO.gbr | project.Edge_Cuts.gbr | project.GKO.gbr | 无LPD/LPC,仅D01线段,avg_line_width≈0.1mm | 用GML后缀但内容是丝印,导致CAM系统误判为机械层 |
这张表的作用,是把隐性的经验显性化、标准化。新人入职第一天,不用看几十页手册,直接查表就知道“我要导出顶层铜,KiCad里找F.Cu,嘉立创里选GTL,导出后脚本判定必须是copper”。它不依赖个人记忆,而是靠流程和工具兜底。
最后分享一个真实体会:去年我们做一款工业控制器,PCB有12层,Gerber文件24个。按旧流程,我花3小时手动用GCPrevue逐个打开核对;按新流程,运行脚本+检查报告,12分钟搞定,还发现了两个嘉立创EDA映射错误。省下的不是时间,而是那种“生怕漏掉一个文件”的焦虑感。当你把“检查”变成一条自动化流水线上的固定工序,它就不再是负担,而是交付质量的底气。