Adafruit_Learning_System_Gu.../CircuitPython_AT_Hand_Raiser/code.py
2021-09-22 17:50:46 -04:00

158 lines
6.5 KiB
Python

# ATMakers HandUp
# Listens to the USB Serial port and responds to incoming strings
# Sets appropriate colors on the DotStar LED
# This program uses the board package to access the Trinket's pin names
# and uses adafruit_dotstar to talk to the LED
# other boards would use the neopixel library instead
from time import sleep
import board
from rainbowio import colorwheel
import adafruit_dotstar
import supervisor
# create an object for the dotstar pixel on the Trinket M0
# It's an array because it's a sequence of one pixel
pixels = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=.95)
# this function takes a standard "hex code" for a color and returns
# a tuple of (red, green, blue)
def hex2rgb(hex_code):
red = int("0x"+hex_code[0:2], 16)
green = int("0x"+hex_code[2:4], 16)
blue = int("0x"+hex_code[4:6], 16)
rgb = (red, green, blue)
# print(rgb)
return rgb
# This array contains digitized data for a heartbeat wave scaled to between 0 and 1.0
# It is used to create the "beat" mode. Ensure each line is <78 characters for Travis-CI
beatArray = [0.090909091,0.097902098,0.104895105,0.118881119,0.132867133,0.146853147,
0.153846154,0.160839161,0.181818182,0.181818182,0.195804196,0.181818182,0.188811189,
0.188811189,0.181818182,0.174825175,0.174825175,0.160839161,0.167832168,0.160839161,
0.167832168,0.167832168,0.167832168,0.160839161,0.146853147,0.146853147,0.153846154,
0.160839161,0.146853147,0.153846154,0.13986014,0.153846154,0.132867133,0.146853147,
0.13986014,0.13986014,0.146853147,0.146853147,0.146853147,0.146853147,0.160839161,
0.146853147,0.160839161,0.167832168,0.181818182,0.202797203,0.216783217,0.20979021,
0.202797203,0.195804196,0.195804196,0.216783217,0.160839161,0.13986014,0.13986014,
0.13986014,0.118881119,0.118881119,0.111888112,0.132867133,0.111888112,0.132867133,
0.104895105,0.083916084,0.020979021,0,0.230769231,0.636363636,1,0.846153846,
0.27972028,0.048951049,0.055944056,0.083916084,0.090909091,0.083916084,0.083916084,
0.076923077,0.076923077,0.076923077,0.090909091,0.06993007,0.083916084,0.076923077,
0.076923077,0.06993007,0.076923077,0.083916084,0.083916084,0.083916084,0.076923077,
0.090909091,0.076923077,0.083916084,0.06993007,0.076923077,0.062937063,0.06993007,
0.062937063,0.055944056,0.055944056,0.048951049,0.041958042,0.034965035,0.041958042,
0.027972028]
# When we start up, make the LED black
black = (0, 0, 0)
# the color that's passed in over the text input
targetColor = black
# pos is used for all modes that cycle or progress
# it loops from 0-255 and starts over
pos = 0
# curColor is the color that will be displayed at the end of the main loop
# it is mapped using pos according to the mode
curColor = black
# the mode can be one of
# solid - just keep the current color
# blink - alternate between black and curColor
# ramp - transition continuously between black and curColor
# beat - pulse to a recorded heartbeat intensity
# wheel - change hue around the colorwheel (curColor is ignored)
mode='wheel'
# We start by turning off pixels
pixels.fill(black)
pixels.show()
# Main Loop
while True:
# Check to see if there's input available (requires CP 4.0 Alpha)
if supervisor.runtime.serial_bytes_available:
# read in text (@mode, #RRGGBB, %brightness, standard color)
# input() will block until a newline is sent
inText = input().strip()
# Sometimes Windows sends an extra (or missing) newline - ignore them
if inText == "":
continue
# Process the input text - start with the presets (no #,@,etc)
# We use startswith to not have to worry about CR vs CR+LF differences
if inText.lower().startswith("red"):
# set the target color to red
targetColor = (255, 0, 0)
# and set the mode to solid if we're in a mode that ignores targetColor
if mode == "wheel":
mode="solid"
# similar for green, yellow, and black
elif inText.lower().startswith("green"):
targetColor = (0, 255, 0)
if mode == "wheel":
mode="solid"
elif inText.lower().startswith("yellow"):
targetColor = (200, 200, 0)
if mode == "wheel":
mode="solid"
elif inText.lower().startswith("black"):
targetColor = (0, 0, 0)
if mode == "wheel":
mode="solid"
# Here we're going to change the mode - which starts w/@
elif inText.lower().startswith("@"):
mode= inText[1:]
# Here we can set the brightness with a "%" symbol
elif inText.startswith("%"):
pctText = inText[1:]
pct = float(pctText)/100.0
pixels.brightness=pct
# If we get a hex code set it and go to solid
elif inText.startswith("#"):
hexcode = inText[1:]
targetColor = hex2rgb(hexcode)
if mode == "wheel":
mode="solid"
# if we get a command we don't understand, set it to gray
# we should probably just ignore it but this helps debug
else:
targetColor =(50, 50, 50)
if mode == "wheel":
mode="solid"
else:
# If no text available, update the color according to the mode
if mode == 'blink':
if curColor == black:
curColor = targetColor
else:
curColor = black
sleep(.4)
# print('.', end='')
pixels.fill(curColor)
pixels.show()
elif mode == 'wheel':
sleep(.05)
pos = (pos + 1) % 255
pixels.fill(colorwheel(pos))
pixels.show()
elif mode == 'solid':
pixels.fill(targetColor)
pixels.show()
elif mode == 'beat':
pos = (pos + 5 ) % 106
scaleAvg = (beatArray[(pos-2)%106] + beatArray[(pos-1)%106] + beatArray[pos] +
beatArray[(pos+1)%106] + beatArray[(pos+2)%106])/5
beatColor = tuple(int(scaleAvg*x) for x in targetColor)
pixels.fill(beatColor)
sleep(.025)
pixels.show()
elif mode == 'ramp':
pos = ((pos + 5 ) % 255)
scaleFactor = (2*abs(pos-127))/255
beatColor = tuple(int(scaleFactor * x) for x in targetColor)
pixels.fill(beatColor)
sleep(.075)
pixels.show()