AnasSarkiz/rp2040-usb-c-single-axis-dm542t-motion-controller--01a0e89c

A USB‑C RP2040 controller board with external QSPI flash, crystal clock, regulated 3.3/1.1/5 V power, boost-converted motor-driver supply, protected USB and limit inputs, status LEDs, reset/boot switches, and AO3400A MOSFET outputs for stepper-control signals.

Version
0.1.0-prototype.19
License
unset
Stars
0

scripts/via_spacing.py

"""Exact circular via clearances, including same-net drill separation."""
from itertools import combinations
from math import hypot


def audit_via_spacing(vias, rules):
    pairs = []
    violations = []
    for first, second in combinations(vias, 2):
        # Non-overlapping layer spans cannot collide; this board uses through vias.
        if not set(first['layers']).intersection(second['layers']):
            continue
        center_distance = hypot(first['x'] - second['x'], first['y'] - second['y'])
        drill_gap = center_distance - (first['hole_diameter'] + second['hole_diameter']) / 2
        copper_gap = center_distance - (first['outer_diameter'] + second['outer_diameter']) / 2
        first_net = first.get('subcircuit_connectivity_map_key')
        second_net = second.get('subcircuit_connectivity_map_key')
        same_net = bool(first_net) and first_net == second_net
        pair = {
            'first_via': first['pcb_via_id'], 'second_via': second['pcb_via_id'],
            'first_xy_mm': [first['x'], first['y']], 'second_xy_mm': [second['x'], second['y']],
            'first_net': first_net, 'second_net': second_net, 'same_net': same_net,
            'drill_gap_mm': drill_gap, 'copper_gap_mm': copper_gap,
        }
        pairs.append(pair)
        failed_rules = []
        if drill_gap < rules['drill_gap_mm'] - 1e-6:
            failed_rules.append('drill_to_drill')
        if not same_net and copper_gap < rules['copper_gap_mm'] - 1e-6:
            failed_rules.append('different_net_copper_to_copper')
        if failed_rules:
            violations.append({**pair, 'failed_rules': failed_rules})
    different_net_pairs = [pair for pair in pairs if not pair['same_net']]
    return {
        'rules': rules, 'pair_count': len(pairs),
        'minimum_drill_pair': min(pairs, key=lambda pair: pair['drill_gap_mm']) if pairs else None,
        'minimum_different_net_copper_pair': min(different_net_pairs, key=lambda pair: pair['copper_gap_mm']) if different_net_pairs else None,
        'violations': violations,
    }