146 lines
4 KiB
Python
146 lines
4 KiB
Python
"""
|
|
Circuit Playground Express Compass
|
|
|
|
Adafruit invests time and resources providing this open source code.
|
|
Please support Adafruit and open source hardware by purchasing
|
|
products from Adafruit!
|
|
|
|
Written by Dave Astels for Adafruit Industries
|
|
Copyright (c) 2018 Adafruit Industries
|
|
Licensed under the MIT license.
|
|
|
|
All text above must be included in any redistribution.
|
|
"""
|
|
|
|
import time
|
|
import math
|
|
import board
|
|
import busio
|
|
import adafruit_lsm303
|
|
import neopixel
|
|
import digitalio
|
|
|
|
BLACK = 0x000000
|
|
RED = 0xFF0000
|
|
GREEN = 0x00FF00
|
|
BLUE = 0x0000FF
|
|
|
|
i2c = busio.I2C(board.SCL, board.SDA)
|
|
compass = adafruit_lsm303.LSM303(i2c)
|
|
compass.mag_rate = adafruit_lsm303.MAGRATE_30
|
|
#compass.mag_gain = adafruit_lsm303.MAGGAIN_8_1
|
|
|
|
calibrate_button = digitalio.DigitalInOut(board.BUTTON_A)
|
|
calibrate_button.direction = digitalio.Direction.INPUT
|
|
calibrate_button.pull = digitalio.Pull.UP
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
# Replace these two lines with the results of calibration
|
|
#-------------------------------------------------------------------------------
|
|
raw_mins = [1000.0, 1000.0]
|
|
raw_maxes = [-1000.0, -1000.0]
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
mins = [0.0, 0.0]
|
|
maxes = [0.0, 0.0]
|
|
corrections = [0.0, 0.0]
|
|
|
|
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.2, auto_write=False)
|
|
|
|
led_patterns = [[4, 5], [5], [6], [7], [8], [9], [9, 0], [0], [1], [2], [3], [4]]
|
|
|
|
|
|
def fill(colour):
|
|
pixels.fill(colour)
|
|
pixels.show()
|
|
|
|
|
|
def warm_up():
|
|
fill(BLUE)
|
|
for _ in range(100):
|
|
_, _, _ = compass.magnetic
|
|
time.sleep(0.010)
|
|
|
|
|
|
def calibrate(do_the_readings):
|
|
values = [0.0, 0.0]
|
|
start_time = time.monotonic()
|
|
|
|
fill(GREEN)
|
|
|
|
# Update the high and low extremes
|
|
if do_the_readings:
|
|
while time.monotonic() - start_time < 10.0:
|
|
values[0], values[1], _ = compass.magnetic
|
|
values[1] *= -1 # accel is upside down, so y is reversed
|
|
if values[0] != 0.0 and values[1] != 0.0: # ignore the random 0 values
|
|
for i in range(2):
|
|
if values[i] < raw_mins[i]:
|
|
raw_mins[i] = values[i]
|
|
if values[i] > raw_maxes[i]:
|
|
raw_maxes[i] = values[i]
|
|
# time.sleep(0.005)
|
|
|
|
# Recompute the correction and the correct mins/maxes
|
|
for i in range(2):
|
|
corrections[i] = (raw_maxes[i] + raw_mins[i]) / 2
|
|
mins[i] = raw_mins[i] - corrections[i]
|
|
maxes[i] = raw_maxes[i] - corrections[i]
|
|
|
|
fill(BLACK)
|
|
|
|
|
|
def normalize(value, in_min, in_max):
|
|
mapped = (value - in_min) * 200 / (in_max - in_min) + -100
|
|
return max(min(mapped, 100), -100)
|
|
|
|
|
|
|
|
# Setup
|
|
|
|
warm_up()
|
|
|
|
if not calibrate_button.value or (raw_mins[0] == 1000.0 and raw_mins[1] == 1000.0):
|
|
print("Compass calibration")
|
|
raw_mins[0] = 1000.0
|
|
raw_mins[1] = 1000.0
|
|
raw_maxes[0] = -1000.0
|
|
raw_maxes[1] = -1000.0
|
|
calibrate(True)
|
|
|
|
|
|
print("Calibration results")
|
|
print("Update the corresponding lines near the top of the code\n")
|
|
print("raw_mins = [{0}, {1}]".format(raw_mins[0], raw_mins[1]))
|
|
print("raw_maxes = [{0}, {1}]".format(raw_maxes[0], raw_maxes[1]))
|
|
while True:
|
|
pass
|
|
else:
|
|
calibrate(False)
|
|
|
|
|
|
while True:
|
|
if not calibrate_button.value:
|
|
calibrate(True)
|
|
|
|
x, y, _ = compass.magnetic
|
|
y = y * -1
|
|
|
|
if x != 0.0 and y != 0.0:
|
|
normalized_x = normalize(x - corrections[0], mins[0], maxes[0])
|
|
normalized_y = normalize(y - corrections[1], mins[1], maxes[1])
|
|
|
|
compass_heading = int(math.atan2(normalized_y, normalized_x) * 180.0 / math.pi)
|
|
# compass_heading is between -180 and +180 since atan2 returns -pi to +pi
|
|
# this translates it to be between 0 and 360
|
|
compass_heading += 180
|
|
|
|
direction_index = ((compass_heading + 15) % 360) // 30
|
|
|
|
pixels.fill(BLACK)
|
|
for l in led_patterns[direction_index]:
|
|
pixels[l] = RED
|
|
pixels.show()
|
|
time.sleep(0.050)
|