mirror of
https://github.com/danbulant/ambientlightdemo
synced 2026-05-19 04:18:32 +00:00
rpi
This commit is contained in:
parent
8e7b04f3ae
commit
634ca63c6c
6 changed files with 38 additions and 24 deletions
4
rpi/autostart.sh
Executable file
4
rpi/autostart.sh
Executable file
|
|
@ -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
|
||||||
|
|
@ -2,8 +2,8 @@ import board
|
||||||
import neopixel
|
import neopixel
|
||||||
|
|
||||||
pixels = neopixel.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.fill((255, 255, 255))
|
||||||
pixels.show()
|
pixels.show()
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ import board
|
||||||
import neopixel
|
import neopixel
|
||||||
|
|
||||||
pixels = neopixel.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.fill((0, 0, 0))
|
||||||
pixels.show()
|
pixels.show()
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,32 @@
|
||||||
import board
|
import board
|
||||||
import neopixel
|
import neopixel
|
||||||
from gdmath import *
|
from gdmath import *
|
||||||
|
from math import cos, pi
|
||||||
|
|
||||||
pixels = neopixel.NeoPixel(
|
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:
|
class Lights:
|
||||||
virtual_rotation = 0
|
virtual_rotation = 0
|
||||||
color = (255, 255, 255)
|
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):
|
def __init__(self, pixels):
|
||||||
self.pixels = pixels
|
self.pixels = pixels
|
||||||
|
|
||||||
def process(self, delta):
|
def process(self, delta):
|
||||||
self.virtual_rotation += self.expected_rotation_delta * (delta * 60)
|
self.virtual_rotation += self.expected_rotation_delta_remote * (delta * 60)
|
||||||
max_darkness = clamp(abs(self.expected_rotation_delta / FULL_DARK_ROTATION_DELTA), 0, 1)
|
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):
|
for i in range(pixels.n):
|
||||||
pattern_offset = wrap((i + (self.virtual_rotation * PATTERN_REPETITION)) / PATTERN_REPETITION, 0, 1)
|
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)
|
new_color = tuple(int(x * energy) for x in self.color)
|
||||||
self.pixels[i] = new_color
|
self.pixels[i] = new_color
|
||||||
self.pixels.show()
|
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)
|
lights = Lights(pixels)
|
||||||
|
|
|
||||||
22
rpi/main.py
22
rpi/main.py
|
|
@ -26,15 +26,15 @@ def receive_json():
|
||||||
except BlockingIOError:
|
except BlockingIOError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
local_rotation = 0
|
local_rotation: float = 0
|
||||||
local_delta = 0
|
local_delta: float = 0
|
||||||
remote_rotation = 0
|
remote_rotation: float = 0
|
||||||
remote_delta = 0
|
remote_delta: float = 0
|
||||||
|
|
||||||
def motor_rotation_fn():
|
def motor_rotation_fn():
|
||||||
global remote_rotation
|
global remote_rotation
|
||||||
while True:
|
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
|
stepper.single_step_towards(target_pos) # blocking / time.sleep
|
||||||
|
|
||||||
def read_thread_fn():
|
def read_thread_fn():
|
||||||
|
|
@ -43,21 +43,23 @@ def read_thread_fn():
|
||||||
old_rotation = local_rotation
|
old_rotation = local_rotation
|
||||||
local_rotation = read_angle_f()
|
local_rotation = read_angle_f()
|
||||||
local_delta = gdmath.shortest_diff(old_rotation, local_rotation)
|
local_delta = gdmath.shortest_diff(old_rotation, local_rotation)
|
||||||
|
lights.expected_rotation_delta_local = local_delta
|
||||||
|
lights.rotation_local = local_rotation
|
||||||
try:
|
try:
|
||||||
send_json({"value": local_rotation, "delta": local_delta})
|
send_json({"value": local_rotation, "delta": local_delta})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error sending data:", e)
|
print("Error sending data:", e)
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
def lights_fn():
|
def lights_fn():
|
||||||
global local_rotation, local_delta, remote_rotation, remote_delta
|
global local_rotation, local_delta, remote_rotation, remote_delta
|
||||||
last_time = time.time()
|
last_time = time.time()
|
||||||
delta = 1/60
|
delta = 1/60
|
||||||
while True:
|
while True:
|
||||||
lights.color = gdmath.sample_color_gradient(local_rotation + remote_rotation)
|
lights.color = gdmath.sample_color_gradient((local_rotation + remote_rotation) / 2)
|
||||||
lights.expected_rotation_delta = local_delta
|
|
||||||
lights.process(delta)
|
lights.process(delta)
|
||||||
current_time = time.time()
|
|
||||||
time.sleep(1/60)
|
time.sleep(1/60)
|
||||||
|
current_time = time.time()
|
||||||
delta = current_time - last_time
|
delta = current_time - last_time
|
||||||
last_time = current_time
|
last_time = current_time
|
||||||
|
|
||||||
|
|
@ -68,8 +70,10 @@ def network_recv_fn():
|
||||||
if data:
|
if data:
|
||||||
if "value" in data:
|
if "value" in data:
|
||||||
remote_rotation = data["value"]
|
remote_rotation = data["value"]
|
||||||
|
lights.rotation_remote = remote_rotation
|
||||||
if "delta" in data:
|
if "delta" in data:
|
||||||
remote_delta = data["delta"]
|
remote_delta = data["delta"]
|
||||||
|
lights.expected_rotation_delta_remote = remote_delta
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
motor_thread = threading.Thread(target=motor_rotation_fn)
|
motor_thread = threading.Thread(target=motor_rotation_fn)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
import time
|
import time
|
||||||
import atexit
|
import atexit
|
||||||
|
from gdmath import wrap
|
||||||
|
|
||||||
class StepperMotor:
|
class StepperMotor:
|
||||||
pins = (17, 27, 22, 23)
|
pins = (17, 27, 22, 23)
|
||||||
step_sleep = 0.002
|
step_sleep = 0.01
|
||||||
step_count = 200
|
step_count = 200
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -28,7 +29,7 @@ class StepperMotor:
|
||||||
|
|
||||||
current_step = 0
|
current_step = 0
|
||||||
def _apply_single_step(self):
|
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:
|
if current_step_abs%4==0:
|
||||||
self._set_pins(GPIO.LOW, GPIO.LOW, GPIO.LOW, GPIO.HIGH)
|
self._set_pins(GPIO.LOW, GPIO.LOW, GPIO.LOW, GPIO.HIGH)
|
||||||
elif current_step_abs%4==1:
|
elif current_step_abs%4==1:
|
||||||
|
|
@ -72,4 +73,4 @@ class StepperMotor:
|
||||||
def fpos_to_pos(self, fpos):
|
def fpos_to_pos(self, fpos):
|
||||||
return int((fpos % 1) * self.step_count)
|
return int((fpos % 1) * self.step_count)
|
||||||
|
|
||||||
stepper = StepperMotor()
|
stepper = StepperMotor()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue