From 634ca63c6c77f3912976ad7db8679435844c678e Mon Sep 17 00:00:00 2001 From: Daniel Bulant Date: Fri, 5 Dec 2025 10:33:03 +0100 Subject: [PATCH] rpi --- rpi/autostart.sh | 4 ++++ rpi/light-test.py | 6 +++--- rpi/lights-off.py | 4 ++-- rpi/lights.py | 19 ++++++++++++------- rpi/main.py | 22 +++++++++++++--------- rpi/stepper.py | 7 ++++--- 6 files changed, 38 insertions(+), 24 deletions(-) create mode 100755 rpi/autostart.sh diff --git a/rpi/autostart.sh b/rpi/autostart.sh new file mode 100755 index 0000000..705e670 --- /dev/null +++ b/rpi/autostart.sh @@ -0,0 +1,4 @@ +#!/usr/bin/fish +cd /home/dan/ambientlightdemo/rpi +source .venv/bin/activate.fish +/home/dan/.local/bin/uv run main.py diff --git a/rpi/light-test.py b/rpi/light-test.py index 7186111..dd8bafe 100644 --- a/rpi/light-test.py +++ b/rpi/light-test.py @@ -2,8 +2,8 @@ import board import neopixel pixels = neopixel.NeoPixel( - board.D12, 10, brightness=1, auto_write=False, pixel_order=neopixel.GRB + board.D12, 25, brightness=1, auto_write=False, pixel_order=neopixel.GRB ) -pixels.fill((0, 0, 0)) -pixels.show() \ No newline at end of file +pixels.fill((255, 255, 255)) +pixels.show() diff --git a/rpi/lights-off.py b/rpi/lights-off.py index 7186111..4fe295c 100644 --- a/rpi/lights-off.py +++ b/rpi/lights-off.py @@ -2,8 +2,8 @@ import board import neopixel pixels = neopixel.NeoPixel( - board.D12, 10, brightness=1, auto_write=False, pixel_order=neopixel.GRB + board.D12, 25, brightness=1, auto_write=False, pixel_order=neopixel.GRB ) pixels.fill((0, 0, 0)) -pixels.show() \ No newline at end of file +pixels.show() diff --git a/rpi/lights.py b/rpi/lights.py index f632447..8ea7441 100644 --- a/rpi/lights.py +++ b/rpi/lights.py @@ -1,27 +1,32 @@ import board import neopixel from gdmath import * +from math import cos, pi pixels = neopixel.NeoPixel( - board.D12, 10, brightness=.2, auto_write=False, pixel_order=neopixel.GRB + board.D12, 25, brightness=1, auto_write=False, pixel_order=neopixel.GRB ) class Lights: virtual_rotation = 0 color = (255, 255, 255) - expected_rotation_delta = 0 + expected_rotation_delta_remote = 0 + expected_rotation_delta_local = 0 + rotation_remote = 0 + rotation_local = 0 def __init__(self, pixels): self.pixels = pixels def process(self, delta): - self.virtual_rotation += self.expected_rotation_delta * (delta * 60) - max_darkness = clamp(abs(self.expected_rotation_delta / FULL_DARK_ROTATION_DELTA), 0, 1) + self.virtual_rotation += self.expected_rotation_delta_remote * (delta * 60) + max_darkness = clamp(abs(self.expected_rotation_delta_remote / FULL_DARK_ROTATION_DELTA), 0, 1) + light_intensity = 1 - cos(self.rotation_local * 2 * pi - self.rotation_remote * 2 * pi) ** 2 for i in range(pixels.n): pattern_offset = wrap((i + (self.virtual_rotation * PATTERN_REPETITION)) / PATTERN_REPETITION, 0, 1) - energy = (1 - (1 - pattern_offset) * max_darkness) + energy = (1 - (1 - pattern_offset) * max_darkness) * light_intensity new_color = tuple(int(x * energy) for x in self.color) self.pixels[i] = new_color self.pixels.show() - self.expected_rotation_delta = lerp(self.expected_rotation_delta, 0, delta * LIGHT_SLOWDOWN_SPEED) + self.expected_rotation_delta_remote = lerp(self.expected_rotation_delta_remote, 0, delta * LIGHT_SLOWDOWN_SPEED) -lights = Lights(pixels) \ No newline at end of file +lights = Lights(pixels) diff --git a/rpi/main.py b/rpi/main.py index 42020b1..f9eb26e 100644 --- a/rpi/main.py +++ b/rpi/main.py @@ -26,15 +26,15 @@ def receive_json(): except BlockingIOError: return None -local_rotation = 0 -local_delta = 0 -remote_rotation = 0 -remote_delta = 0 - +local_rotation: float = 0 +local_delta: float = 0 +remote_rotation: float = 0 +remote_delta: float = 0 + def motor_rotation_fn(): global remote_rotation while True: - target_pos = stepper.fpos_to_pos(1 - remote_rotation) + target_pos = stepper.fpos_to_pos(remote_rotation) stepper.single_step_towards(target_pos) # blocking / time.sleep def read_thread_fn(): @@ -43,21 +43,23 @@ def read_thread_fn(): old_rotation = local_rotation local_rotation = read_angle_f() local_delta = gdmath.shortest_diff(old_rotation, local_rotation) + lights.expected_rotation_delta_local = local_delta + lights.rotation_local = local_rotation try: send_json({"value": local_rotation, "delta": local_delta}) except Exception as e: print("Error sending data:", e) + time.sleep(0.01) def lights_fn(): global local_rotation, local_delta, remote_rotation, remote_delta last_time = time.time() delta = 1/60 while True: - lights.color = gdmath.sample_color_gradient(local_rotation + remote_rotation) - lights.expected_rotation_delta = local_delta + lights.color = gdmath.sample_color_gradient((local_rotation + remote_rotation) / 2) lights.process(delta) - current_time = time.time() time.sleep(1/60) + current_time = time.time() delta = current_time - last_time last_time = current_time @@ -68,8 +70,10 @@ def network_recv_fn(): if data: if "value" in data: remote_rotation = data["value"] + lights.rotation_remote = remote_rotation if "delta" in data: remote_delta = data["delta"] + lights.expected_rotation_delta_remote = remote_delta time.sleep(0.01) motor_thread = threading.Thread(target=motor_rotation_fn) diff --git a/rpi/stepper.py b/rpi/stepper.py index 1fdb970..6736cb6 100644 --- a/rpi/stepper.py +++ b/rpi/stepper.py @@ -1,10 +1,11 @@ import RPi.GPIO as GPIO import time import atexit +from gdmath import wrap class StepperMotor: pins = (17, 27, 22, 23) - step_sleep = 0.002 + step_sleep = 0.01 step_count = 200 def __init__(self): @@ -28,7 +29,7 @@ class StepperMotor: current_step = 0 def _apply_single_step(self): - current_step_abs = abs(self.current_step) + current_step_abs = wrap(self.current_step, 0, 4) if current_step_abs%4==0: self._set_pins(GPIO.LOW, GPIO.LOW, GPIO.LOW, GPIO.HIGH) elif current_step_abs%4==1: @@ -72,4 +73,4 @@ class StepperMotor: def fpos_to_pos(self, fpos): return int((fpos % 1) * self.step_count) -stepper = StepperMotor() \ No newline at end of file +stepper = StepperMotor()