Captures everything needed to redeploy the two-display clock (hour on I2C 0x61, minute on I2C 0x63) on a fresh Pi: - Both systemd units (matrix0x61.service, matrix0x63.service) - Deployed Pimoroni script tree, including the local %I (12-hour) clock customization - Vendored upstream sources (ltp305-python, breakout-garden) so restore is fully offline-capable - Boot config snippet enabling I2C - install.sh that wires it all back up idempotently - Inventory doc cross-referencing every live-system path Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
101 lines
2.8 KiB
Python
Executable File
101 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import time
|
|
import math
|
|
import colorsys
|
|
from lsm303d import LSM303D
|
|
from rgbmatrix5x5 import RGBMatrix5x5
|
|
|
|
print("""This Pimoroni Breakout Garden example requires an LSM303D
|
|
Motion Sensor Breakout and a 5x5 RGB Matrix Breakout.
|
|
|
|
The Rainbow Compass calculates and displays compass heading as an
|
|
RGB colour around the hue wheel, with North being red, South cyan,
|
|
East green, and West purple, appromximately.
|
|
|
|
Press Cyrl-+C to exit.
|
|
""")
|
|
|
|
|
|
def raw_heading(minimums, maximums, zero=0):
|
|
"""Return a raw compass heading calculated from the magnetometer data."""
|
|
|
|
X = 0
|
|
Y = 2 # Change to 1 if you have the breakout flat
|
|
|
|
# The range over which values will be calculated, i.e. -1 to +1
|
|
mag_range = 2
|
|
|
|
# Get the magnetometer's values
|
|
mag = list(lsm.magnetometer())
|
|
|
|
# Scale and shift values
|
|
for i in range(len(mag)):
|
|
mag[i] = ((mag_range / (maximums[i] - minimums[i])) * mag[i]) - \
|
|
(mag_range / 2.0)
|
|
|
|
# Calculate the heading from the vector
|
|
heading = math.atan2(mag[Y], mag[X])
|
|
|
|
if heading < 0:
|
|
heading += (2 * math.pi)
|
|
|
|
# Convert radian value to degrees
|
|
heading_degrees = (round(math.degrees(heading), 2) - zero) % 360
|
|
|
|
return heading_degrees
|
|
|
|
|
|
lsm = LSM303D(0x1d) # Change to 0x1e if you have soldered the address jumper
|
|
|
|
# Set up the 5x5 RGB matrix
|
|
rgbmatrix5x5 = RGBMatrix5x5()
|
|
rgbmatrix5x5.set_clear_on_exit()
|
|
rgbmatrix5x5.set_brightness(0.8)
|
|
|
|
# Python 2/3 compatibility
|
|
try:
|
|
input = raw_input
|
|
except NameError:
|
|
pass
|
|
|
|
input("Lay your LSM303D in Breakout Garden flat (LSM303D vertical), \n\
|
|
press a key to start, then rotate it 360 degrees, keeping it flat...\n")
|
|
|
|
# Variables to govern calibration time
|
|
t_start = time.time()
|
|
t_elapsed = 0
|
|
calibration_time = 30
|
|
|
|
# Initial values for mins and maxs
|
|
minimums = list(lsm.magnetometer())
|
|
maximums = list(lsm.magnetometer())
|
|
|
|
# Run calibration until time limit is reached
|
|
while t_elapsed < calibration_time:
|
|
mag = lsm.magnetometer()
|
|
for i in range(len(mag)):
|
|
if mag[i] < minimums[i]: # Set new min
|
|
minimums[i] = mag[i]
|
|
if mag[i] > maximums[i]: # Set new max
|
|
maximums[i] = mag[i]
|
|
t_elapsed = time.time() - t_start
|
|
|
|
input("Calibration complete!\n\nIf you want to set a zero (North) point, \n\
|
|
then turn your breakout to that point and press a key...\n")
|
|
|
|
# Zero point for the compass
|
|
zero = raw_heading(minimums, maximums)
|
|
|
|
input("Press a key to begin readings!\n")
|
|
|
|
# Begin compass readings and display on RGB matrix
|
|
while True:
|
|
rh = raw_heading(minimums, maximums, zero=zero)
|
|
hue = rh / 360.0 # Hue is based on compass heading
|
|
r, g, b = [int(c * 255) for c in colorsys.hsv_to_rgb(hue, 1.0, 1.0)]
|
|
rgbmatrix5x5.set_all(r, g, b) # Set whole matrix to calculated RGB
|
|
rgbmatrix5x5.show()
|
|
print("compass heading: {:0.0f} degrees".format(rh))
|
|
time.sleep(0.1)
|