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
Rithesh03
Update 3: PCB design completed - routed board, manufacturing package (prototype, do not order yet), WLED guide, final checklist, Hydrogen feedback
1ed072d
13d ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
"""Draw the LED pad comparison diagram (hardware/layout-review/led-pad-comparison.svg).
All numbers come from the two LED datasheets (see check_footprints.py)."""
import os
HW = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
S = 70 # px per mm
OX, OY = 330, 300
def X(v):
return OX + v * S
def Y(v):
return OY + v * S
def rect(x0, x1, y0, y1, style):
out = []
for sx in (-1, 1):
for sy in (-1, 1):
a, b = sorted((sx * x0, sx * x1))
c, d = sorted((sy * y0, sy * y1))
out.append(f'<rect x="{X(a):.1f}" y="{Y(c):.1f}" width="{(b - a) * S:.1f}" '
f'height="{(d - c) * S:.1f}" {style}/>')
return "\n".join(out)
svg = [f'<svg xmlns="http://www.w3.org/2000/svg" width="1260" height="620" font-family="DejaVu Sans" font-size="16">',
'<rect width="1260" height="620" fill="white"/>',
'<text x="20" y="32" font-size="22" font-weight="bold">LED footprint: XL pads with both LED options on top (top view, mm)</text>',
rect(1.55, 2.85, 0.9, 2.2, 'fill="#c9a0a0" stroke="none"'), # XL pads
rect(1.7, 3.2, 1.2, 2.1, 'fill="none" stroke="#2a9d2a" stroke-width="3" stroke-dasharray="10,6"'), # WS rec pad
rect(1.7, 2.7, 1.1, 2.1, 'fill="none" stroke="#1f5fd1" stroke-width="3"'), # XL terminal
rect(1.8, 2.7, 1.2, 2.1, 'fill="none" stroke="#e07b00" stroke-width="3" stroke-dasharray="4,4"'), # WS terminal
f'<rect x="{X(-2.5)}" y="{Y(-2.5)}" width="{5 * S}" height="{5 * S}" fill="none" stroke="#888" stroke-width="1.5"/>',
f'<rect x="{X(-2.5)}" y="{Y(-2.7)}" width="{5 * S}" height="{5.4 * S}" fill="none" stroke="#e07b00" stroke-width="1" stroke-dasharray="3,5"/>',
f'<line x1="{X(-3.4)}" y1="{Y(0)}" x2="{X(3.4)}" y2="{Y(0)}" stroke="#ccc"/>',
f'<line x1="{X(0)}" y1="{Y(-3)}" x2="{X(0)}" y2="{Y(3)}" stroke="#ccc"/>',
f'<text x="{X(-3.3)}" y="{Y(-1.55) + 6}">1</text><text x="{X(-3.3)}" y="{Y(1.55) + 6}">2</text>',
f'<text x="{X(3.05)}" y="{Y(1.55) + 6}">3</text><text x="{X(3.05)}" y="{Y(-1.55) + 6}">4</text>']
lx, ly = 650, 80
legend = [("#c9a0a0", "fill", "Our pads (XL datasheet): 1.3 x 1.3 mm"),
("#1f5fd1", "solid", "XL-5050RGBC-2812B metal terminals (1.0 x 1.0)"),
("#e07b00", "dots", "WS2812B-B/T metal terminals (0.9 x 0.9)"),
("#2a9d2a", "dash", "WS2812B's own recommended pads (1.5 x 0.9)")]
for i, (col, kind, text) in enumerate(legend):
y = ly + i * 34
if kind == "fill":
svg.append(f'<rect x="{lx}" y="{y - 14}" width="30" height="18" fill="{col}"/>')
else:
dash = {"solid": "", "dots": 'stroke-dasharray="4,4"', "dash": 'stroke-dasharray="10,6"'}[kind]
svg.append(f'<rect x="{lx}" y="{y - 14}" width="30" height="18" fill="none" stroke="{col}" stroke-width="3" {dash}/>')
svg.append(f'<text x="{lx + 42}" y="{y}">{text}</text>')
notes = ["Both parts' terminals land fully on our pads.",
"Pad reaches past the terminal's outer end (toe):",
"\u00a0\u00a0\u00a0XL: +0.15 mm (as XL recommends)",
"\u00a0\u00a0\u00a0WS2812B: +0.15 mm, but WS2812B recommends +0.50 mm",
"WS2812B on these pads = smaller solder fillet than its",
"maker intends, and JLCPCB treats a part/footprint",
"mismatch as 'not populated'.",
"Result: footprint is for the XL LED only.",
"Switching to WS2812B needs its own footprint (board change)."]
for i, t in enumerate(notes):
svg.append(f'<text x="{lx}" y="{ly + 170 + i * 26}" font-size="15"'
f'{" font-weight=\"bold\"" if i >= 7 else ""}>{t}</text>')
svg.append(f'<text x="{X(-2.5)}" y="{Y(3.25)}" font-size="13" fill="#666">grey = XL body 5.0 x 5.0; orange dotted = WS2812B body 5.0 x 5.4</text>')
svg.append("</svg>")
out = os.path.join(HW, "layout-review", "led-pad-comparison.svg")
open(out, "w").write("\n".join(svg))
print("wrote", out)