mirror of
https://github.com/danbulant/ambientlightdemo
synced 2026-05-19 04:18:32 +00:00
rpi update
This commit is contained in:
parent
16ce90afa9
commit
8e7b04f3ae
7 changed files with 48 additions and 14 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
# Godot 4+ specific ignores
|
# Godot 4+ specific ignores
|
||||||
.godot/
|
.godot/
|
||||||
/android/
|
/android/
|
||||||
|
__pycache__
|
||||||
|
|
|
||||||
9
rpi/lights-off.py
Normal file
9
rpi/lights-off.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import board
|
||||||
|
import neopixel
|
||||||
|
|
||||||
|
pixels = neopixel.NeoPixel(
|
||||||
|
board.D12, 10, brightness=1, auto_write=False, pixel_order=neopixel.GRB
|
||||||
|
)
|
||||||
|
|
||||||
|
pixels.fill((0, 0, 0))
|
||||||
|
pixels.show()
|
||||||
|
|
@ -19,7 +19,7 @@ class Lights:
|
||||||
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)
|
||||||
new_color = tuple(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 = lerp(self.expected_rotation_delta, 0, delta * LIGHT_SLOWDOWN_SPEED)
|
||||||
|
|
|
||||||
20
rpi/main.py
20
rpi/main.py
|
|
@ -31,13 +31,22 @@ local_delta = 0
|
||||||
remote_rotation = 0
|
remote_rotation = 0
|
||||||
remote_delta = 0
|
remote_delta = 0
|
||||||
|
|
||||||
|
def motor_rotation_fn():
|
||||||
|
global remote_rotation
|
||||||
|
while True:
|
||||||
|
target_pos = stepper.fpos_to_pos(1 - remote_rotation)
|
||||||
|
stepper.single_step_towards(target_pos) # blocking / time.sleep
|
||||||
|
|
||||||
def read_thread_fn():
|
def read_thread_fn():
|
||||||
global local_rotation, local_delta
|
global local_rotation, local_delta
|
||||||
while True:
|
while True:
|
||||||
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)
|
||||||
send_json({"value": local_rotation, "delta": local_delta})
|
try:
|
||||||
|
send_json({"value": local_rotation, "delta": local_delta})
|
||||||
|
except Exception as e:
|
||||||
|
print("Error sending data:", e)
|
||||||
|
|
||||||
def lights_fn():
|
def lights_fn():
|
||||||
global local_rotation, local_delta, remote_rotation, remote_delta
|
global local_rotation, local_delta, remote_rotation, remote_delta
|
||||||
|
|
@ -57,10 +66,14 @@ def network_recv_fn():
|
||||||
while True:
|
while True:
|
||||||
data = receive_json()
|
data = receive_json()
|
||||||
if data:
|
if data:
|
||||||
remote_rotation = data["value"]
|
if "value" in data:
|
||||||
remote_delta = data["delta"]
|
remote_rotation = data["value"]
|
||||||
|
if "delta" in data:
|
||||||
|
remote_delta = data["delta"]
|
||||||
time.sleep(0.01)
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
motor_thread = threading.Thread(target=motor_rotation_fn)
|
||||||
|
motor_thread.start()
|
||||||
read_thread = threading.Thread(target=read_thread_fn)
|
read_thread = threading.Thread(target=read_thread_fn)
|
||||||
read_thread.start()
|
read_thread.start()
|
||||||
lights_thread = threading.Thread(target=lights_fn)
|
lights_thread = threading.Thread(target=lights_fn)
|
||||||
|
|
@ -68,6 +81,7 @@ lights_thread.start()
|
||||||
network_thread = threading.Thread(target=network_recv_fn)
|
network_thread = threading.Thread(target=network_recv_fn)
|
||||||
network_thread.start()
|
network_thread.start()
|
||||||
|
|
||||||
|
motor_thread.join()
|
||||||
read_thread.join()
|
read_thread.join()
|
||||||
lights_thread.join()
|
lights_thread.join()
|
||||||
network_thread.join()
|
network_thread.join()
|
||||||
4
rpi/stepper-api-test.py
Normal file
4
rpi/stepper-api-test.py
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
from stepper import stepper
|
||||||
|
|
||||||
|
for i in range(stepper.step_count):
|
||||||
|
stepper.single_step()
|
||||||
|
|
@ -36,7 +36,6 @@ def cleanup():
|
||||||
|
|
||||||
# the meat
|
# the meat
|
||||||
try:
|
try:
|
||||||
i = 0
|
|
||||||
for i in range(step_count):
|
for i in range(step_count):
|
||||||
if i%4==0:
|
if i%4==0:
|
||||||
GPIO.output( out4, GPIO.HIGH )
|
GPIO.output( out4, GPIO.HIGH )
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
import time
|
import time
|
||||||
|
import atexit
|
||||||
|
|
||||||
class StepperMotor:
|
class StepperMotor:
|
||||||
pins = (17, 27, 22, 23)
|
pins = (17, 27, 22, 23)
|
||||||
|
|
@ -10,7 +11,9 @@ class StepperMotor:
|
||||||
GPIO.setmode( GPIO.BCM )
|
GPIO.setmode( GPIO.BCM )
|
||||||
for pin in self.pins:
|
for pin in self.pins:
|
||||||
GPIO.setup( pin, GPIO.OUT )
|
GPIO.setup( pin, GPIO.OUT )
|
||||||
|
for pin in self.pins:
|
||||||
GPIO.output( pin, GPIO.LOW )
|
GPIO.output( pin, GPIO.LOW )
|
||||||
|
atexit.register(self.cleanup)
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
for pin in self.pins:
|
for pin in self.pins:
|
||||||
|
|
@ -25,18 +28,19 @@ class StepperMotor:
|
||||||
|
|
||||||
current_step = 0
|
current_step = 0
|
||||||
def _apply_single_step(self):
|
def _apply_single_step(self):
|
||||||
if self.current_step%4==0:
|
current_step_abs = abs(self.current_step)
|
||||||
self._set_pins(GPIO.HIGH, GPIO.LOW, GPIO.LOW, GPIO.LOW)
|
if current_step_abs%4==0:
|
||||||
elif self.current_step%4==1:
|
|
||||||
self._set_pins(GPIO.LOW, GPIO.HIGH, GPIO.LOW, GPIO.LOW)
|
|
||||||
elif self.current_step%4==2:
|
|
||||||
self._set_pins(GPIO.LOW, GPIO.LOW, GPIO.HIGH, GPIO.LOW)
|
|
||||||
elif self.current_step%4==3:
|
|
||||||
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:
|
||||||
|
self._set_pins(GPIO.LOW, GPIO.HIGH, GPIO.LOW, GPIO.LOW)
|
||||||
|
elif current_step_abs%4==2:
|
||||||
|
self._set_pins(GPIO.LOW, GPIO.LOW, GPIO.HIGH, GPIO.LOW)
|
||||||
|
elif current_step_abs%4==3:
|
||||||
|
self._set_pins(GPIO.HIGH, GPIO.LOW, GPIO.LOW, GPIO.LOW)
|
||||||
time.sleep(self.step_sleep)
|
time.sleep(self.step_sleep)
|
||||||
def single_step(self):
|
def single_step(self):
|
||||||
self._apply_single_step()
|
|
||||||
self.current_step += 1
|
self.current_step += 1
|
||||||
|
self._apply_single_step()
|
||||||
def single_step_back(self):
|
def single_step_back(self):
|
||||||
self.current_step -= 1
|
self.current_step -= 1
|
||||||
self._apply_single_step()
|
self._apply_single_step()
|
||||||
|
|
@ -52,10 +56,13 @@ class StepperMotor:
|
||||||
return (self.current_step % self.step_count) / self.step_count
|
return (self.current_step % self.step_count) / self.step_count
|
||||||
|
|
||||||
def single_step_towards(self, target_pos):
|
def single_step_towards(self, target_pos):
|
||||||
|
target_pos = target_pos % self.step_count
|
||||||
current_pos = self.pos()
|
current_pos = self.pos()
|
||||||
|
if target_pos == current_pos:
|
||||||
|
return
|
||||||
# Determine shortest direction
|
# Determine shortest direction
|
||||||
# includes wrap-around (it's a circular motion motor)
|
# includes wrap-around (it's a circular motion motor)
|
||||||
diff = (target_pos - current_pos + self.step_count) % self.step_count
|
diff = (target_pos - current_pos) % self.step_count
|
||||||
if diff > self.step_count / 2:
|
if diff > self.step_count / 2:
|
||||||
self.single_step_back()
|
self.single_step_back()
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue