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 4: improved README (V1 overview, images, LED order), Version 2 proposal files
b874429
13d ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
"""Version 2 LED order and WLED maps -> v2/firmware/ (Version 1's firmware/ files are only read, never written).
Version 2's chain is Version 1's chain reversed: the data now enters at the right end, next to the electronics.
V2 LED n sits where V1 LED (108 - n) sits (WLED index: v2 = 106 - v1)
The letter pattern and the visible positions are the same; only the physical numbering (data order) changed.
Writes:
v2/firmware/led-order.csv LED1..LED107 with letter, row, column, V2 position (mm) and the V1 LED at that spot
v2/firmware/ledmap.json 2D map, 41 x 7 grid ("RITHESH V2 41x7")
v2/firmware/ledmap1.json 1D map, left to right, column by column ("RITHESH V2 left-to-right")
The WLED file names must stay ledmap.json / ledmap1.json on the board; the v2/ folder keeps them apart from V1's.
Each map is built twice (from the V2 positions, and by converting V1's map) and both must agree.
Usage: python3 make_v2_ledmaps.py
"""
import csv
import json
import os
V2HW = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
V2 = os.path.dirname(V2HW)
ROOT = os.path.dirname(V2)
OUT = os.path.join(V2, "firmware")
V1_FW = os.path.join(ROOT, "firmware")
COLS, ROWS = 41, 7
X0, Y0, PITCH = 9.1, 5.0, 5.0 # must match make_v2_plan.py
V1_X0, V1_PITCH = 10.0, 7.0
def main():
v1 = list(csv.DictReader(open(os.path.join(V1_FW, "led-order.csv"))))
leds = [] # (v2 index, letter, row, col, v1 index)
for r in v1:
i1 = int(r["WLED index (0-based)"])
col = round((float(r["x mm"]) - V1_X0) / V1_PITCH)
leds.append((106 - i1, r["letter"], int(r["row (0=top)"]), col, i1))
leds.sort()
assert [l[0] for l in leds] == list(range(107))
# 2D map from the V2 positions
grid = [-1] * (COLS * ROWS)
for i2, _, row, col, _ in leds:
grid[row * COLS + col] = i2
# ... and by converting V1's map; both must match
m1 = json.load(open(os.path.join(V1_FW, "ledmap.json")))
conv = [-1 if v < 0 else 106 - v for v in m1["map"]]
assert conv == grid, "2D map mismatch"
# 1D map: columns left to right, top to bottom inside a column
order = [i2 for i2, _, row, col, _ in sorted(leds, key=lambda l: (l[3], l[2]))]
m1d = json.load(open(os.path.join(V1_FW, "ledmap1.json")))
assert [106 - v for v in m1d["map"]] == order, "1D map mismatch"
assert sorted(order) == list(range(107))
os.makedirs(OUT, exist_ok=True)
with open(os.path.join(OUT, "ledmap.json"), "w") as f:
json.dump({"n": "RITHESH V2 41x7", "width": COLS, "height": ROWS, "map": grid}, f, separators=(",", ":"))
with open(os.path.join(OUT, "ledmap1.json"), "w") as f:
json.dump({"n": "RITHESH V2 left-to-right", "map": order}, f, separators=(",", ":"))
with open(os.path.join(OUT, "led-order.csv"), "w", newline="") as f:
w = csv.writer(f)
w.writerow(["WLED index (0-based)", "LED", "letter", "row (0=top)", "column (0=left)", "x mm", "y mm",
"V1 LED at the same spot"])
for i2, letter, row, col, i1 in leds:
w.writerow([i2, f"LED{i2 + 1}", letter, row, col, f"{X0 + col * PITCH:.1f}", f"{Y0 + row * PITCH:.1f}",
f"LED{i1 + 1}"])
print("wrote", OUT, "(ledmap.json, ledmap1.json, led-order.csv); both map methods agree")
first, last = leds[0], leds[-1]
print(f"V2 LED1 = {first[1]} row {first[2]} col {first[3]} (V1 LED{first[4] + 1}); "
f"V2 LED107 = {last[1]} row {last[2]} col {last[3]} (V1 LED{last[4] + 1})")
starts = {}
for i2, letter, row, col, _ in leds:
key = (letter, col // 6)
starts.setdefault(key, [i2 + 1, i2 + 1])[1] = i2 + 1
print("LEDs per letter (V2 numbers):", ", ".join(f"{k[0]}{'' if k[1] != 6 else '(2nd)'} {a}-{b}"
for k, (a, b) in sorted(starts.items(), key=lambda kv: kv[1][0])))
if __name__ == "__main__":
main()