/ CircuitPython_AT_Hand_Raiser / code.py
code.py
1 # SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 # ATMakers HandUp 6 # Listens to the USB Serial port and responds to incoming strings 7 # Sets appropriate colors on the DotStar LED 8 9 # This program uses the board package to access the Trinket's pin names 10 # and uses adafruit_dotstar to talk to the LED 11 # other boards would use the neopixel library instead 12 13 from time import sleep 14 import board 15 from rainbowio import colorwheel 16 import adafruit_dotstar 17 import supervisor 18 19 # create an object for the dotstar pixel on the Trinket M0 20 # It's an array because it's a sequence of one pixel 21 pixels = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=.95) 22 23 # this function takes a standard "hex code" for a color and returns 24 # a tuple of (red, green, blue) 25 def hex2rgb(hex_code): 26 red = int("0x"+hex_code[0:2], 16) 27 green = int("0x"+hex_code[2:4], 16) 28 blue = int("0x"+hex_code[4:6], 16) 29 rgb = (red, green, blue) 30 # print(rgb) 31 return rgb 32 33 # This array contains digitized data for a heartbeat wave scaled to between 0 and 1.0 34 # It is used to create the "beat" mode. Ensure each line is <78 characters for Travis-CI 35 beatArray = [0.090909091,0.097902098,0.104895105,0.118881119,0.132867133,0.146853147, 36 0.153846154,0.160839161,0.181818182,0.181818182,0.195804196,0.181818182,0.188811189, 37 0.188811189,0.181818182,0.174825175,0.174825175,0.160839161,0.167832168,0.160839161, 38 0.167832168,0.167832168,0.167832168,0.160839161,0.146853147,0.146853147,0.153846154, 39 0.160839161,0.146853147,0.153846154,0.13986014,0.153846154,0.132867133,0.146853147, 40 0.13986014,0.13986014,0.146853147,0.146853147,0.146853147,0.146853147,0.160839161, 41 0.146853147,0.160839161,0.167832168,0.181818182,0.202797203,0.216783217,0.20979021, 42 0.202797203,0.195804196,0.195804196,0.216783217,0.160839161,0.13986014,0.13986014, 43 0.13986014,0.118881119,0.118881119,0.111888112,0.132867133,0.111888112,0.132867133, 44 0.104895105,0.083916084,0.020979021,0,0.230769231,0.636363636,1,0.846153846, 45 0.27972028,0.048951049,0.055944056,0.083916084,0.090909091,0.083916084,0.083916084, 46 0.076923077,0.076923077,0.076923077,0.090909091,0.06993007,0.083916084,0.076923077, 47 0.076923077,0.06993007,0.076923077,0.083916084,0.083916084,0.083916084,0.076923077, 48 0.090909091,0.076923077,0.083916084,0.06993007,0.076923077,0.062937063,0.06993007, 49 0.062937063,0.055944056,0.055944056,0.048951049,0.041958042,0.034965035,0.041958042, 50 0.027972028] 51 52 # When we start up, make the LED black 53 black = (0, 0, 0) 54 # the color that's passed in over the text input 55 targetColor = black 56 57 # pos is used for all modes that cycle or progress 58 # it loops from 0-255 and starts over 59 pos = 0 60 61 # curColor is the color that will be displayed at the end of the main loop 62 # it is mapped using pos according to the mode 63 curColor = black 64 65 # the mode can be one of 66 # solid - just keep the current color 67 # blink - alternate between black and curColor 68 # ramp - transition continuously between black and curColor 69 # beat - pulse to a recorded heartbeat intensity 70 # wheel - change hue around the colorwheel (curColor is ignored) 71 72 mode='wheel' 73 74 # We start by turning off pixels 75 pixels.fill(black) 76 pixels.show() 77 78 # Main Loop 79 while True: 80 # Check to see if there's input available (requires CP 4.0 Alpha) 81 if supervisor.runtime.serial_bytes_available: 82 # read in text (@mode, #RRGGBB, %brightness, standard color) 83 # input() will block until a newline is sent 84 inText = input().strip() 85 # Sometimes Windows sends an extra (or missing) newline - ignore them 86 if inText == "": 87 continue 88 # Process the input text - start with the presets (no #,@,etc) 89 # We use startswith to not have to worry about CR vs CR+LF differences 90 if inText.lower().startswith("red"): 91 # set the target color to red 92 targetColor = (255, 0, 0) 93 # and set the mode to solid if we're in a mode that ignores targetColor 94 if mode == "wheel": 95 mode="solid" 96 # similar for green, yellow, and black 97 elif inText.lower().startswith("green"): 98 targetColor = (0, 255, 0) 99 if mode == "wheel": 100 mode="solid" 101 elif inText.lower().startswith("yellow"): 102 targetColor = (200, 200, 0) 103 if mode == "wheel": 104 mode="solid" 105 elif inText.lower().startswith("black"): 106 targetColor = (0, 0, 0) 107 if mode == "wheel": 108 mode="solid" 109 # Here we're going to change the mode - which starts w/@ 110 elif inText.lower().startswith("@"): 111 mode= inText[1:] 112 # Here we can set the brightness with a "%" symbol 113 elif inText.startswith("%"): 114 pctText = inText[1:] 115 pct = float(pctText)/100.0 116 pixels.brightness=pct 117 # If we get a hex code set it and go to solid 118 elif inText.startswith("#"): 119 hexcode = inText[1:] 120 targetColor = hex2rgb(hexcode) 121 if mode == "wheel": 122 mode="solid" 123 # if we get a command we don't understand, set it to gray 124 # we should probably just ignore it but this helps debug 125 else: 126 targetColor =(50, 50, 50) 127 if mode == "wheel": 128 mode="solid" 129 else: 130 # If no text available, update the color according to the mode 131 if mode == 'blink': 132 if curColor == black: 133 curColor = targetColor 134 else: 135 curColor = black 136 sleep(.4) 137 # print('.', end='') 138 pixels.fill(curColor) 139 pixels.show() 140 elif mode == 'wheel': 141 sleep(.05) 142 pos = (pos + 1) % 255 143 pixels.fill(colorwheel(pos)) 144 pixels.show() 145 elif mode == 'solid': 146 pixels.fill(targetColor) 147 pixels.show() 148 elif mode == 'beat': 149 pos = (pos + 5 ) % 106 150 scaleAvg = (beatArray[(pos-2)%106] + beatArray[(pos-1)%106] + beatArray[pos] + 151 beatArray[(pos+1)%106] + beatArray[(pos+2)%106])/5 152 beatColor = tuple(int(scaleAvg*x) for x in targetColor) 153 pixels.fill(beatColor) 154 sleep(.025) 155 pixels.show() 156 elif mode == 'ramp': 157 pos = ((pos + 5 ) % 255) 158 scaleFactor = (2*abs(pos-127))/255 159 beatColor = tuple(int(scaleFactor * x) for x in targetColor) 160 pixels.fill(beatColor) 161 sleep(.075) 162 pixels.show()