Last updated: 2026-05-23
The installation is live, deployed, and running on the Pi. A system-health baseline monitor is now logging continuously to catch a suspected long-term slowdown/leak (weeks-to-months timescale). No code changes were made to the shader or Python host.
/home/pi/rainshine/baseline_monitor.py— logs system + process metrics every 60s to/home/pi/rainshine/monitor_data/metrics.csv- Rolling baseline stats (min/mean/p95/max) recomputed hourly to
baseline.json - Tracks: RSS, VSZ, FD count, thread count, V3D BO count, load, temp, GPU throttle, memory, disk, journal size
baseline_monitor.service— systemd unit, enabled, auto-starts on boot/home/pi/rainshine/monitor_report.sh— one-shot report: current state vs baseline
- Shader and Python code were not modified (user request)
- Suspected issue: after weeks-to-months of uptime, animation slows down; reboot fixes it
- Current hypothesis: long-term memory/FD/V3D leak, or shader
uTimeprecision loss inmediump float - Next step: wait for slowdown, then SSH in and compare live metrics against baseline
- Drops always spawn in an off-screen buffer
trailLenrows above the visible panel. Once spawned, they travel their full lifecycle off the bottom, never interrupted. - Sensor ON → spawn gate opens → drops form off-screen and enter fully-formed from top.
- Sensor OFF → spawn gate closes → existing drops drain naturally → screen goes dark on its own.
- Still presence → dim (
motion_brightness_base, currently0.01) - Active movement → bright (climbs toward
1.0asmotion_valuerises) - EMA-smoothed (α=0.15) — no flicker, no snapping
brightnessconfig key is the ceiling (keep at1.0);motion_scaleoperates within it
- Trail direction corrected (trail is now above the head, behind the falling drop)
- Hue randomised per-cycle pass (
hash2(seed, cycleIdx)) — each drop has a new color every time - Trail fade:
smoothstep(1.0, 0.0, t)— smooth cubic ease to black at tail
[shader]
speed = 25.0
trail = 25
density = 0.5
[output]
fps = 60.0
universe = 1
color_order = grb
brightness = 1.0
sacn_dest = 10.0.0.123
[osc]
port = 7700
[sensor]
enabled = true
trigger_hold = 5.0
presence_threshold = 2.0
motion_threshold = 5.0
trigger_hits = 1
motion_brightness_base = 0.01
motion_brightness_full = 150.0- Repo:
jpkelly/PiDMX, branchmain - Latest commit:
d21a99c—Remove entry spawn buffer — drops appear instantly at top edge - Mac workspace:
/Users/jp/Documents/GitHub/PiDMX - Pi repo:
~/rainshine/ - Pi process uptime: ~2 days, 6 hours
- Current health: 60.0 fps, RSS 106 MB, 12 FDs, 10 threads, temp 38–40°C, no throttling
uTime, uSpeed, uTrailLen, uDensity, uActive, uSpawnGateStart, uSpawnGateStop
speed, trail, density, fps, brightness, active, spawn_gate_start_abs, spawn_gate_stop_abs, motion_scaleeffective_brightness = params.brightness * params.motion_scalemotion_valueis signed —abs()is required for threshold comparisons- EMA never snaps to zero — always let it decay naturally
trigger_hits = 1for fastest response; raise to 2-3 if false triggers occur
| Key | Location | Effect |
|---|---|---|
speed |
[shader] |
Drop fall speed |
trail |
[shader] |
Trail length in pixels |
density |
[shader] |
Drops per column (≥1) or probability (<1) |
fps |
[output] |
Render rate |
brightness |
[output] |
Keep at 1.0 — ceiling for motion_scale |
trigger_hold |
[sensor] |
Seconds of inactivity before gate closes |
presence_threshold |
[sensor] |
Raw presence_value floor to count as hit |
motion_threshold |
[sensor] |
Raw abs(motion_value) floor to count as hit |
motion_brightness_base |
[sensor] |
Dim floor brightness when still (0.0–1.0) |
motion_brightness_full |
[sensor] |
motion_value that maps to full brightness |
# From Mac command line:
python3 -c "
from pythonosc.udp_client import SimpleUDPClient
c = SimpleUDPClient('pidmx.local', 7700)
c.send_message('/rainshine/brightness', 0.8)
"
# Addresses: /rainshine/speed, /rainshine/trail, /rainshine/density, /rainshine/fps, /rainshine/brightness- Density driven by motion — more drops when moving, fewer when still
- Speed driven by motion — drops fall faster with more energetic movement
- Multiple shaders — config key to switch which
.fragis loaded at startup - Move COLS/ROWS to config — currently hardcoded as constants in both Python and shader
- Multi-destination sACN — comma-separated IPs in
sacn_destfor multiple OCTO units
# Live logs
journalctl -u rainshine -f
# Recent errors only
journalctl -u rainshine --since "1 hour ago" --no-pager | grep -E "ERROR|WARNING|Status:"
# Restart count
systemctl show rainshine --property=NRestarts
# Memory check
free -h# Quick report (current state vs rolling baseline)
/home/pi/rainshine/monitor_report.sh
# Raw metrics
head -1 /home/pi/rainshine/monitor_data/metrics.csv
tail -20 /home/pi/rainshine/monitor_data/metrics.csv
# Baseline stats
python3 -c "import json; print(json.dumps(json.load(open('/home/pi/rainshine/monitor_data/baseline.json')), indent=2))"
# Monitor service status
systemctl status baseline_monitor --no-pager
journalctl -u baseline_monitor -f- Run
/home/pi/rainshine/monitor_report.shon the Pi - Check which metrics have drifted from baseline (RSS, FDs, V3D BOs, load, temp)
- Do NOT reboot until diagnostics are captured