User Tools

Site Tools


pb

This is an old revision of the document!


Pickle Ball Scoreboard

To do

  • add in change to yellow side after home key. DONE
  • add matrix timeout. Code in activity.py but not currently used
  • add brightness adjustment. DONE
  • use score % 10 to keep score in range 0-9 DONE
  • display symbols S, 1, 2 in the middle instead of red squares. DONE
  • “menu” should to machine.reset DONE
  • check out clear_both with fade. NO. takes too long
  • put classes in separate file
  • panels 1-4 may be ok. all 6 panels good.

IR imports

from ir_rx import IR_RX
from nec import NEC_8
import print_error
#from ir_rx.print_error import print_error
#from ir_rx.nec import NEC_8  # Adjust based on your remote's protocol

Programs

  • hello.py tries to scroll HELLO WORLD in green but just shows blue in rows 0-2 and 12-14.

Wires

  • matrix input connector (DIN) is female at the top
  • Elegoo 830 supports max 21 awg preferably solid
  • I bought 24 AWG Elegoo Dupont connectors
  • Elegoo Fun kit wires are also 24 AWG. Fine for signal, a bit small for power.
  • The 10×14 digit 8 with a green stripe uses 102 pixels - 40% of 256
  • orange multimeter is a Neoteck 8233D Pro
  • grok says 24 AWG wire is generally sufficient for powering 100 out of 256 LEDs on a WS2812B
  • I do not need a reset button in Version 1. They can unplug the Pico from the battery.
  • run red/black from the baseus to the rails.
  • run yellow or orange/blue to the matrices.
  • two green data wire to the matirces.
  • black jumper from pico to a ground rail.

2026 03 24

  • changed blueUp, blueDown, goldUp, and goldDown to change_*_score(integer) where integer is 1 or -1
  • kill green stripes on each end

2026 03 21

  • digit41 fixes su.
  • power does machine reset
  • brightnessDown cannot go below 0.2
  • how to turn off lights reliably?
  • turnOff lets game continue.
  • should any key do a restore or do I need a timeout.
  • grok says pic can take usb-a for thonny work even when powered by 5v from a breadboard rail.

2025 03 20

  • returned amazon remote
  • got onn remote from walmart
  • getSamsung.py can read codes
  • do mapping
  • onn remote uses samsung codes
  • created button.py that can be imported as “from buttons import buttonMapSamsung”
  • getIrSamsung.pr Version 3 reads the codes and looks them up.
  • on to digit41.py
  • power shut off lights but game continues
  • menu/reset does nothing
  • su does not work Fixed

2026 03 19

  • digit(34, 35) are failed attempts to display versions of any key on timeout.
  • digit36 does work but has some timing issues.
  • bottom line is WE DON'T NEED A SCREEN TIMEOUT
  • falling back to digit33 because it has no flashing or timeout code
  • import new PBS positioning DONE
  • fix draw_middle to support 'S' DONE
  • modified button_map to be a list of [string, boolean]
  • if boolean is false, binary will flash red and pass
  • if boolean is true, binary will flash green and process string
  • activity code is present but commented out
  • digit37 is ok
  • activity was moved to activity.py
  • default brightness is now 0.2
  • digit38 is ok
  • tried to get samsung remote found in basement but none of getIrSamsung*.py worked. All lit the ir and GPIO.
  • digit39 shows version number in show_binary at start up
  • copying digit39 to main.py on the pico does run it after a hard boot

2026 03 18

  • spent the afternoon trying to get “Press Any Key” to scroll in digit34 and digit34.
  • Grok gave conflicting advice but nothing worked.
  • Found mutltiple declarations of buf and other, so create an AnyKey class.
  • Copying failed digit35 to digit36 and using the anyKey in numbers
  • fixed show PBS where the gold part of B started in column 2 instead of 0.
  • digit36 will display ANY KEY but response to keyed interrupt is slow commented out
  • ANY KEY is shown in a random color for all letters

2026 03 17

  • digit29 does up/down brightness from 0.1 through 0.5 in su mode only
  • digit30 reduced brightness to 6 pixels
  • digit31 Use random colors for PBS. repeat every 0.1 for 3 seconds
  • digit32 adds timeout
  • digit33 change side to gold after first home key press if done in 15 seconds
  • digit34 calls the anyKey code but nothing happens
  • move on to hardware. this is good enough

2026 03 16

  • digit23 has show_binary rewrite from grok but still flashes entire screen.
  • also has timeout after 3 minutes to blank the screen with any key restoring it.
  • cannot get rid of entire redraw even with grok's help.
  • going back to digit20.py renamed to digit25.py
  • it does not have timeout that was in digit21.py
  • add back single column green stripes from digit22 into digit25 DONE
  • add back new show_binary from digit24 into digit26 DONE
  • no fade - takes too long DONE
  • digit27 show brightness centered on the bottom line
  • digit28 key 0 toggles su on/off. status is a red/black pixel at gold 14,15

2026 03 15

  • got up at 5:30
  • it is now 9:30 and display ir code as binary works in digit17
  • at 4pm the three symbols ('S', 1, 2) all display in the middle area in digit18.py
  • start replacing the red squares with these in digit19.py
  • done in digit19.py, but stripe display is slow
  • will try grok's suggestion in digit20.py
  • digit20.py has optimization in show() and draw_stripe where I was calling show() 32 times!
  • going to digit21 to add timeout to blank display
  • blank display and any key restore works in digit21
  • going to digit22 to set green stripes to just 1 column DONE
  • going to digit23 to change side on new game (home)

2026 03 14

  • 0zero.py is a digit13 copy.
  • key 9 displays the green right stripe
  • this is the right matrix where 0,0 is top right looking at the face
# xy conversion for the -right- matrix
def xy_to_index(x, y):
    """Top-left origin + reversed serpentine zigzag
    - Even rows (y even): right-to-left (x=15 to x=0)
    - Odd rows (y odd): left-to-right (x=0 to x=15)
    """
    if y % 2 == 0:          # ← Changed: even rows reverse
        x = 15 - x
    return y * 16 + x
  • we are not changing the xy code. the wires will be fine with similar led orientation.
  • digit14.py does all ok. copied to digit15.py
  • digit15 fixes curretn_player. copied to digit16
  • digit16 makes numbers.py 10×13 and displays an 8 pixel red line centered on the bottom row

2026 03 13

  • micropython does not support the match statement
# works - does a soft reboot
        if  button == "menu":
            machine.reset()
  • added to digit16.py
  • original hello.py ran for 20 minutes without Baseus shutting down the power using new breakout board SOLVED
  • hello.py gave repeating patterns.
  • wrote textxy.py and none of grok's suggestions worked.
  • tried pin 8 instead of pin 16 and no joy.
  • panels 5 and 6 both work the same as does (assumed dead) panel 4.
  • the problems with panels 1 - 4 could have been less than great grounding of everything.
  • four.py purports to put squares in each corner but –> nothing despite its 4 different calculations of idx, power injection, new green cable, sufficient voltage (4.97), and different pins
  • textxy.py thinks that 0.0 is the bottom right.
  • mapping is not right nor is color.
  • use textcy.py

2026 03 12

  • got switches and leds today. both too small.
  • other suggested switches require big (3/4“) holes.
  • if i use the Turn Off button to kill all the leds, the ir will be alive drawing minimal power.
  • Power consumption: At 3.3V → ~1.3–3.2 mW; at 5V → ~2–5 mW - battery will last for years.
  • Green light signals that unit is ready to go
  • set the home button to do a soft boot which restarts main.py
  • failing that, they can unplug the pico cable.
  • use a momentary switch only if that fails.

2026 03 10

  • blew up original pico. got two new ones for $23!
  • could not connect o com5. not such port.
  • tried com7 and all is ok.
  • copied ir_rx and ir_tx (remote control files) to the pi.
  • micropython-i2s is part of MP. use from machine import I2S.
  • some keyword arguments do not work in MP → value.to_bytes(2, 'little', signed=True)
  • ptone.py and pwave.py both work but sound is low and wav is unrecognizable
  • looks like matrix 3 and 4 also got toasted along with the pi last friday
  • suspect the stupid switching power supply
  • bought some usb-c to power and ground wires to bypass it
  • also bought some power switches for pico power
  • bought some power indicator leds complete with the needed resistors.
  • latest getir*.py do not work

2026 03 07

  • digit15.py has major refactoring
  • pico is toasted
  • grok says 20 AWG is ok with short runs

2026 03 05

  • digit13.py does changePlayer ok
  • digit14.py works

2026 03 04

  • left matrix shows 5V but will not display.
  • powering both from original side.
  • ok with brightness set to 0.10
  • digit9 shows 0 in different colors on both matrices
  • blue on the left and yellow on the right.
  • to do: fix digit size and offset in digit10 DONE
  • digit 10 resets on home and display 0 to 9 forever on 0
  • todo - add green stripe DONE
  • digit12 does all but changing green strip kills digit

2026 03 03

  • red pixel and checkerboard test run if I bypass the resistor
  • resistors are not directional
  • use short wire and no resistor
  • five.py (red pixel) works
  • check.py works
  • stripe4.py works. displays green on bottom two rows. can change color and row.
  • led orientation is pixel 0 top right when facing leds.
  • pin 17 works better than pin 16
  • wvBlue looks pink. use blue 0x0000FF. wvGold is ok.
  • digit0 works.
  • digit1 has reversed digits.
  • digit2 works with fuller digits
  • putting resistor serial in line with data pin works, so resistor is ok if wired correctly.
  • leftGreen.py works putting a one pixel column on the left. Note the GRB notation.
  • digit4.py puts a green stripe on the left and then increments blue score with a lot of flashing.
  • digit5.py is latest good version, but match does not work
  • digit6 has futile attempt to use blankPattern

xy_to_index(x, y)

def xy_to_index(x, y):
    """Top-left origin + reversed serpentine zigzag
    - Even rows (y even): right-to-left (x=15 to x=0)
    - Odd rows (y odd): left-to-right (x=0 to x=15)
    """
    if y % 2 == 0:          # ← Changed: even rows reverse
        x = 15 - x
    return y * 16 + x

wire gauge

Yes, 0.75 mm is a real and very common wire size — it refers to the cross-sectional area 
of the conductor in square millimeters (mm²), which is the standard way wire is specified 
in most of the world (especially Europe, Asia, and metric countries).Quick conversion & 
context0.75 mm² ≈ AWG 18 (very close)  Exact AWG 18 = 0.823 mm²  
0.75 mm² is slightly thinner but commonly grouped with AWG 18 in practice

Typical current rating (for low-voltage DC like your 5 V LED project):~6–10 A (depending 
on insulation, temperature, length, and safety margin)
Safe for most hobby LED matrix projects (your two 16×16 WS2812B panels likely draw 5–12 A 
max at full brightness)

Common uses of 0.75 mm² wirePower distribution in low-voltage DC projects (5 V, 12 V, 24 V)
LED strip power injection (common in WS2812B setups)
Automotive and marine wiring (12 V accessories)
Household low-power lighting (e.g. LED downlights, 230 V but low amps)
Speaker wire (short runs, 8–16 ohm)

Comparison to other common sizes
**Wire size    Cross-section    Closest AWG     Typical max current (5 V DC)    Usage**
0.3 mm²          0.3 mm²         AWG 22          ~3–5 A                    Signal/data lines only
0.75 mm²         0.75 mm²        AWG 18          ~6–10 A                   Good for power to matrices
1.0–1.5 mm²      1.0–1.5 mm²     AWG 16–14       ~10–15 A+                 High current / long runs
2.5 mm²          2.5 mm²         AWG 12          20 A+                     Heavy power injection

Recommendation for your LED matrices projectUse 0.75 mm² wire for:5 V power wires 
from Baseus bank to power distribution point
Power injection wires to matrices (middle and end of strips)

Use thicker (1.0–1.5 mm² / AWG 16–14) if:Runs > 1–2 meters
Full brightness on all LEDs at once (>10 A draw)

Use thinner (0.3–0.5 mm² / AWG 22–20) for:Data lines (GP16/GP17 to matrix DIN)
IR receiver wiring

Color coding tip (very common convention):Red = +5 V
Black = GND
Green/Yellow = data (WS2812B DIN)
Other colors = signals, control lines

So yes — 0.75 mm (meaning 0.75 mm²) is a standard and very useful wire gauge/size 
for your project. It's widely available and called "0.75 mm² hookup wire" or "0.75 mm² 
flexible cable" when shopping.Let me know if you're asking about a specific wire you 
have (photo/link?) or what part of the project you're wiring — I can recommend exact 
lengths/colors/gauge! 

clear() and show()

From Grok: Yes, that's correct — in the code structure we've been using, the clear() and show() functions work together in exactly the way you described.Here's a precise breakdown of what each does:clear()python

def clear():
    for i in range(NUM_LEDS):
        leds[i] = 0

What it does:
It resets the software buffer (leds array) by setting every LED's 
color value to 0 (black/off).
→ This is just changing values in memory (the Python array leds).
→ Nothing is sent to the LEDs yet — the physical matrix stays unchanged 
until you call show().
Purpose: Prepares a "blank" state before drawing new content (prevents 
old pixels from remaining lit).

show()python

def show():
    dimmed = array.array("I", [0] * NUM_LEDS)
    for i, color in enumerate(leds):
        r = int(((color >>  8) & 0xFF) * BRIGHTNESS)
        g = int(((color >> 16) & 0xFF) * BRIGHTNESS)
        b = int( (color       & 0xFF) * BRIGHTNESS)
        dimmed[i] = (g << 16) + (r << 8) + b
    sm.put(dimmed, 8)
    time.sleep_ms(10)

What it does:  Takes the current values from the software buffer (leds).  
Applies brightness scaling (creates a temporary dimmed array).  
Sends the final color data to the PIO state machine via sm.put(...).  
The PIO hardware then sends the WS2812B protocol bitstream to the 
matrix → the physical LEDs update.

Key point:
show() is the only function that actually transfers data from the 
buffer to the LEDs.
Any change to leds (clearing, setting pixels, drawing digits, etc.) 
is invisible until show() is called.

Summary – Correct SequenceModify the buffer (leds array):  clear() → sets all to 0  
set_pixel(), draw_digit(), set_bottom_stripe(), etc. → sets desired colors

Call show() → sends the buffer to the state machine → LEDs update on the matrix

So yes:
clear() prepares the state in memory → show() displays it on the hardware.
If you ever change the LEDs but forget to call show(), nothing visible 
happens — that's a very common debugging gotcha.Let me know if you want 
to add auto-refresh (e.g., call show() inside every drawing function) or any other tweaks! 

PIO State Machine

PIO (Programmable I/O) state machines are one of the most powerful and unique 
features of the Raspberry Pi Pico (RP2040 chip). They allow you to create 
custom, high-performance peripherals in hardware, running independently of 
the CPU.Here’s a clear, practical explanation of what PIO state machines are, 
how they work, and why they’re used (especially for WS2812B/NeoPixel LEDs in 
your project).What is a PIO State Machine?A PIO state machine is a small, 
programmable processor inside the RP2040 chip. Each state machine can:Run its 
own tiny program (up to 32 instructions)
Execute instructions in parallel with the CPU
Interact directly with GPIO pins
Transfer data to/from memory via DMA (Direct Memory Access)
Run at system clock speed (up to 133 MHz)

The RP2040 has 8 PIO state machines (divided into two PIO blocks of 4 each), 
so you can run up to 8 independent custom peripherals at once.Why PIO is 
Perfect for WS2812B LEDsWS2812B LEDs require a very precise, high-speed serial 
protocol:Each bit is sent as a pulse: ~0.4 µs high for 0, ~0.8 µs high for 1
24 bits per LED (GRB order)
Strict timing (no CPU interrupts allowed to break the stream)

If you try to bit-bang this in normal Python/MicroPython code, timing glitches 
occur (CPU is too busy).
PIO solves this by running the bit protocol in hardware, with perfect timing, 
while the CPU just prepares data.How a PIO State Machine Works (Simplified)
You write a tiny assembly program (in PIO assembly language) that describes 
the waveform you want.
Example: the WS2812 code you’ve been using:pio

.side_set 1
out x, 1            .side 0   [T3-1]
jmp !x do_zero      .side 1   [T1-1]
jmp bitloop         .side 1   [T2-1]
do_zero:
nop                 .side 0   [T2-1]

This is the “send one bit” loop — high for longer on 1, shorter on 0.
You load the program into one of the 8 state machines:python

sm = rp2.StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(16))
sm.active(1)

0 = state machine number (0–7)
ws2812 = your PIO program
freq=8000000 = clock speed tuned for WS2812 timing
sideset_base=Pin(16) = GPIO pin where the data signal goes

You feed it data:python

sm.put(buffer, 8)   # send 32-bit words, shifted by 8 bits

The state machine automatically turns your color buffer into 
the exact WS2812 pulse train — no CPU involvement.

Main Advantages of PIO for LEDsPerfect timing — no jitter, even if CPU is busy
Very low CPU usage — CPU just prepares data and calls put()
High speed — can drive long chains or multiple strips
Flexible — same PIO hardware can do WS2812, I2S audio, VGA, DVI, SPI, I2C, UART, etc.

Summary – What PIO State Machines AreTiny hardware processors inside the RP2040
Run custom programs you write in PIO assembly
Control GPIO pins with precise timing
Used for WS2812B LEDs because they need exact pulse widths the CPU can’t reliably produce
Your code uses one state machine (sm = StateMachine(0, ...)) to drive the matrix

If you want:Code to drive two matrices with two state machines (one per panel)
Explanation of any line in the PIO assembly
How to add IR control or other effects using PIO

2026 03 01

  • Unordered List Itemused male connector (DOUT) at the bottom and toasted first tow leds
pb.1774380444.txt.gz · Last modified: 2026/03/24 19:27 by donald