board
RITHESH LED Display
Public Unreviewedby Rithesh03
A 300 x 70 mm PCB that spells RITHESH with 107 WS2812B RGB LEDs, controlled over Wi-Fi.
main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
"""Check the KiCad-exported netlist against the intended design.
Usage: python3 check_netlist.py <netlist.xml>
Exit code 0 = every expected connection found and no unexpected merges.
"""
import sys
import xml.etree.ElementTree as ET
tree = ET.parse(sys.argv[1])
nets = {}
for net in tree.getroot().iter("net"):
name = net.get("name").split("/")[-1]
nodes = {(n.get("ref"), n.get("pin")) for n in net.iter("node")}
nets[name] = nets.get(name, set()) | nodes
pin_net = {}
for name, nodes in nets.items():
for node in nodes:
pin_net[node] = name
EXPECT = {
"VBUS": ["J1.A4", "J1.A9", "J1.B4", "J1.B9", "D1.1", "U1.5", "C1.1", "U2.3", "U2.4", "R4.1", "TP1.1"],
"GND": ["J1.A1", "J1.S1", "R1.2", "R2.2", "D1.2", "U1.2", "C1.2", "U2.8", "U2.9", "R5.2", "C2.2",
"R3.2", "U3.3", "U3.5", "U3.7", "C7.2", "C8.2", "TP4.1", "TP5.1", "U4.1", "U4.49", "C9.2",
"C10.2", "C11.2", "C13.2", "C14.2", "SW1.2", "SW2.2", "SW3.2", "U5.1", "U5.3", "R12.2", "C12.2",
"LED1.3", "LED107.3", "C101.2", "C207.2", "C301.2", "C304.2"],
"+5V": ["U2.5", "U3.6", "U3.4", "C7.1", "TP2.1", "U5.5", "C12.1", "LED1.1", "LED54.1",
"LED107.1", "C101.1", "C207.1", "C301.1", "C302.1", "C303.1", "C304.1"],
"+3V3": ["U3.1", "U3.2", "C8.1", "TP3.1", "R6.1", "U4.3", "C9.1", "C10.1", "R7.1", "R8.1",
"R9.1", "R10.1", "R11.1"],
"CC1": ["J1.A5", "R1.1", "U4.12"],
"CC2": ["J1.B5", "R2.1", "U4.13"],
"USB_DP": ["J1.A6", "J1.B6", "U1.1", "U1.6", "R14.1"],
"USB_DN": ["J1.A7", "J1.B7", "U1.3", "U1.4", "R15.1"],
"USB_DP_MCU": ["R14.2", "U4.27", "C13.1"],
"USB_DN_MCU": ["R15.2", "U4.26", "C14.1"],
"U0RXD": ["U4.30", "TP9.1"],
"U0TXD": ["U4.31", "R16.1"],
"U0TXD_TP": ["R16.2", "TP10.1"],
"EN_UVLO": ["U2.2", "R4.2", "R5.1"],
"DVDT": ["U2.1", "C2.1"],
"ILM": ["U2.7", "R3.1", "TP8.1"],
"~{FLT}": ["U2.6", "R6.2", "TP7.1"],
"EN": ["U4.8", "R7.2", "C11.1", "SW1.1"],
"BOOT": ["U4.23", "R8.2", "SW2.1"],
"BTN_ONOFF": ["U4.19", "R11.2", "SW3.1"],
"IO8_STRAP": ["U4.22", "R9.2"],
"IO2_STRAP": ["U4.5", "R10.2"],
"LED_DATA_3V3": ["U4.16", "U5.2", "R12.1"],
"LED_DATA_5V": ["U5.4", "R13.1"],
"LED_DIN": ["R13.2", "TP6.1", "LED1.4"],
}
errors = []
for name, pins in EXPECT.items():
found = {pin_net.get(tuple(p.split("."))) for p in pins}
if len(found) != 1 or None in found:
errors.append(f"{name}: pins spread over nets {sorted(map(str, found))}")
# LED data chain: LEDn.DOUT(2) must share a net with LED(n+1).DIN(4) and nothing else.
for n in range(1, 107):
a, b = pin_net.get((f"LED{n}", "2")), pin_net.get((f"LED{n + 1}", "4"))
if a is None or a != b or len(nets[a]) != 2:
errors.append(f"chain break LED{n}->LED{n + 1}: {a} / {b}")
if pin_net.get(("LED107", "2")) and len(nets[pin_net[("LED107", "2")]]) > 1:
errors.append("LED107 DOUT should be unconnected")
# every LED and per-LED capacitor on +5V/GND
for n in range(1, 108):
if pin_net.get((f"LED{n}", "1")) != "+5V" or pin_net.get((f"LED{n}", "3")) != "GND":
errors.append(f"LED{n} power pins wrong")
for n in range(101, 208):
if pin_net.get((f"C{n}", "1")) != "+5V" or pin_net.get((f"C{n}", "2")) != "GND":
errors.append(f"C{n} not across +5V/GND")
# single-pin nets (dangling) other than intentional no-connects
for name, nodes in nets.items():
if len(nodes) < 2 and not name.startswith("unconnected-"):
errors.append(f"single-pin net {name}: {sorted(nodes)}")
refs = {r for r, _ in pin_net}
print(f"{len(nets)} nets, {len(refs)} parts")
for key in ["VBUS", "+5V", "+3V3", "GND"]:
print(f" {key}: {len(nets[key])} pins")
if errors:
print("PROBLEMS:")
for e in errors:
print(" " + e)
sys.exit(1)
print("All expected connections present; LED chain LED1..LED107 continuous.")