kicad:EasyEDA→KiCad 工程(Board1/Board2)、库、脚本与评审文档(IC 引脚、风扇、热、EDL 供电、布局规则)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -0,0 +1,68 @@
|
||||
"""Check registered sense copper against native physical connectivity."""
|
||||
import pcbnew as pcb
|
||||
|
||||
|
||||
def check_measurement_branches(board, branches):
|
||||
if not branches:
|
||||
return {'branches': [], 'errors': []}
|
||||
board.BuildConnectivity()
|
||||
connection = board.GetConnectivity()
|
||||
tracks = {t.m_Uuid.AsString(): t for t in board.GetTracks()}
|
||||
pads = {(f.GetReference(), p.GetNumber()): p for f in board.GetFootprints() for p in f.Pads()}
|
||||
results, errors = [], []
|
||||
for branch in branches:
|
||||
name = branch['connection']
|
||||
ids = set(branch['track_uuids'])
|
||||
source_key, target_key = tuple(branch['from']), tuple(branch['to'])
|
||||
source, target = pads.get(source_key), pads.get(target_key)
|
||||
issues = []
|
||||
if source is None or target is None or not ids <= tracks.keys():
|
||||
errors.append({'kind': 'kelvin_missing_items', 'connection': name})
|
||||
continue
|
||||
if source.GetNetname() != target.GetNetname() or source.GetNetname() != branch['net']:
|
||||
issues.append('net_changed')
|
||||
if source_key[1] not in ('9', '10') or not target_key[0].startswith('Rs'):
|
||||
issues.append('unexpected_measurement_endpoints')
|
||||
seen = set()
|
||||
pending = {t.m_Uuid.AsString() for t in connection.GetConnectedTracks(source)} & ids
|
||||
while pending:
|
||||
uid = pending.pop()
|
||||
if uid in seen:
|
||||
continue
|
||||
seen.add(uid)
|
||||
pending.update({t.m_Uuid.AsString() for t in connection.GetConnectedTracks(tracks[uid])} & ids - seen)
|
||||
if seen != ids:
|
||||
issues.append('disconnected_registered_segments')
|
||||
touched = set()
|
||||
external = set()
|
||||
for uid in ids:
|
||||
track = tracks[uid]
|
||||
if isinstance(track, pcb.PCB_VIA) or track.GetLayer() != pcb.F_Cu:
|
||||
issues.append('measurement_changed_layer')
|
||||
if track.GetWidth() != pcb.FromMM(branch['width_mm']) or track.GetNetname() != branch['net']:
|
||||
issues.append('measurement_geometry_or_net_changed')
|
||||
touched.update((p.GetParentFootprint().GetReference(), p.GetNumber()) for p in connection.GetConnectedPads(track))
|
||||
for other in connection.GetConnectedTracks(track):
|
||||
other_id = other.m_Uuid.AsString()
|
||||
if other_id in ids:
|
||||
continue
|
||||
# Future load copper may join at the shunt land, never on the sense run.
|
||||
shared = [q for q in (track.GetStart(), track.GetEnd())
|
||||
if q == other.GetStart() or q == other.GetEnd()]
|
||||
if not shared or not all(target.HitTest(q) for q in shared):
|
||||
external.add(other_id)
|
||||
if touched != {source_key, target_key}:
|
||||
issues.append('unexpected_or_missing_pad_contact')
|
||||
if external:
|
||||
issues.append('branch_join_outside_shunt_land')
|
||||
length = sum(pcb.ToMM(tracks[uid].GetLength()) for uid in ids)
|
||||
if abs(length - branch['length_mm']) > .001:
|
||||
issues.append('measurement_length_changed_requires_review')
|
||||
result = {'connection': name, 'from': source_key, 'to': target_key,
|
||||
'physically_touched_pads': sorted(touched), 'length_mm': round(length, 5),
|
||||
'external_track_joins': sorted(external), 'passed': not issues}
|
||||
results.append(result)
|
||||
if issues:
|
||||
errors.append({'kind': 'kelvin_branch', 'connection': name, 'issues': sorted(set(issues))})
|
||||
return {'branches': results, 'errors': errors,
|
||||
'limits': 'Zones and final shunt load-current entry geometry require review after power copper is added'}
|
||||
在新工单中引用
屏蔽一个用户