Komponenter
Det mesta som behövs kan köpas i vår webshop.
- Snap-on-reflex
- ledlist 1 m
- 1 Gemma m0
- 1 batteri
- 1 laddare
- 1 låda
- kablage ~2m
- 30 cm krympslang 60 mm bred
- 20 cm krympslang 25,4 mm bred
- 1 slide switch
- 1 switch
- 1 förlängningskabel för batteri
Val av LED-list
Jag ville ha så många neopixlar som möjligt utan att fullständigt ruinera mig. Därför valde jag en medelväg: mini skinny NeoPixel med 60 LED/m. Jag fick plats med en meter delad i fyra delar på min reflex som är ca 34 cm lång och 3,5 cm bred. Här väljer man naturligtvis själv hur många rader man vill ha och hur tätt dioderna ska sitta. Det finns både billigare och dyrare alternativ.
Programmera Gemman
Gemma M0 programmeras annorlunda än tidigare generationer av Gemma. Det är bara att koppla in den till sin dator via USB så ska den dyka upp som en extern enhet. Öppna filen main.py som redan ska finnas och redigera i valfri texteditor. Programmet uppdateras i realtid varje gång du sparar. Du slipper alltså kompilera och ladda upp.
Programmet har nio olika lägen som man, i det färdiga armbandet, växlar mellan genom att trycka på knappen.
# NeoPixel bracelet import board import neopixel import time from digitalio import DigitalInOut, Direction, Pull import board import time import random class AniMode: all_modes = ['SEPARATE_RAINBOWS', 'ALL_THE_SAME_RAINBOW', 'WHITE_SPARKLE', 'RAINBOW_SPARKLE', 'WHITE_STRIPES', 'WHITE_BANDS', 'ALL_WHITE', 'ALL_ORANGE', 'ALL_BLUE'] m = all_modes.index('WHITE_SPARKLE') def inc(self): self.m = (self.m + 1) % len(self.all_modes) def isMode(self, some_mode): return self.all_modes[self.m] == some_mode class ModeButton: def __init__(self, pin): self.button = DigitalInOut(pin) self.button.direction = Direction.INPUT self.button.pull = Pull.UP def is_pressed(self): return not self.button.value def maybe_step_to_next_mode(self): if self.is_pressed(): time.sleep(0.01) self.wait_until_button_released() animode.inc() return True else: return False def wait_until_button_released(self): while self.is_pressed(): pass def wait_until_button_pressed(self): while not self.is_pressed(): pass led = DigitalInOut(board.D13) led.direction = Direction.OUTPUT button = ModeButton(board.D2) pixpin = board.D1 numpix = 64 numrows = 4 numpix_per_row = numpix // numrows strip = neopixel.NeoPixel(pixpin, numpix, brightness=0.02, auto_write=False) sparkles = [-1 for x in range(10)] animode = AniMode() def make_random_color(): return (random.randrange(0,255), random.randrange(0,255), random.randrange(0,255)) def wheel(pos): if (pos < 0) or (pos > 255): return (0, 0, 0) if (pos < 85): return (int(pos * 3), int(255 - (pos*3)), 0) elif (pos < 170): pos -= 85 return (int(255 - pos*3), 0, int(pos*3)) else: pos -= 170 return (0, int(pos*3), int(255 - pos*3)) def rainbow_cycle(wait): for j in range(255): for i in range(len(strip)): idx = int ((i * 256 / len(strip)) + j) strip[i] = wheel(idx & 255) strip.show() if button.maybe_step_to_next_mode(): return # yes, step to next, abort this function time.sleep(wait) def same_rainbow_cycle(wait): for j in range(255): for i in range(numpix_per_row): idx = int ((i * 256 / numpix_per_row) + j) one_color_column(i, wheel(idx & 255)) strip.show() if button.maybe_step_to_next_mode(): return # yes, step to next, abort this function time.sleep(wait) def one_color_column(i, color): # even rows strip[numpix_per_row * 0 + i] = color strip[numpix_per_row * 2 + i] = color # reverse odd rows strip[numpix_per_row * 2 - i - 1] = color strip[numpix_per_row * 4 - i - 1] = color def sparkle(random_color = False, color = (255, 255, 255), wait = 0.001): for i in range(len(sparkles)): old_led = sparkles[i] new_led = random.randrange(0, len(strip)) # turn of old led, if lit if old_led != -1: strip[old_led] = (0, 0, 0) # turn on new led and store it if random_color: strip[new_led] = make_random_color() else: strip[new_led] = color sparkles[i] = new_led strip.show() time.sleep(wait) def stripes(color): for i in range(numpix_per_row): for j in range(numpix_per_row): if (i+j) % 4 == 0: one_color_column(j, (255, 255, 255)) else: one_color_column(j, (0, 0, 0)) strip.show() if button.is_pressed(): return def bands(color): for x in (a for b in (range(numrows), range(numrows)[::-1]) for a in b): for row in range(numrows): for i in range(numpix_per_row): if row == x: strip[i + row * numpix_per_row] = (255, 255, 255) else: strip[i + row * numpix_per_row] = (0, 0, 0) strip.show() if button.is_pressed(): return def one_color(color): strip.fill(color) strip.show() button.wait_until_button_pressed() while True: if animode.isMode('SEPARATE_RAINBOWS'): rainbow_cycle(0.001) # rainbowcycle with 1ms delay per step elif animode.isMode('ALL_THE_SAME_RAINBOW'): same_rainbow_cycle(0.001) # rainbowcycle with 1ms delay per step elif animode.isMode('WHITE_SPARKLE'): sparkle(color = (255, 255, 255)) elif animode.isMode('RAINBOW_SPARKLE'): sparkle(random_color = True) elif animode.isMode('WHITE_STRIPES'): stripes((255, 255, 255)) elif animode.isMode('WHITE_BANDS'): bands((255, 255, 255)) elif animode.isMode('ALL_WHITE'): one_color((255, 255, 255)) elif animode.isMode('ALL_ORANGE'): one_color((255, 65, 0)) elif animode.isMode('ALL_BLUE'): one_color((0, 0, 255)) button.maybe_step_to_next_mode()
Prototyp-koppling
Testa programmet genom att koppla LED-listen till Gemmans utgångar GND, D1 och Vout samt den lilla knappen mellan GND och Gemmans ingång D2.
Spänningsmata antingen via USB eller batteriet.
Bygg LED-listen
Jag delade min list i fyra delar för att sen löda ihop dem i ändarna. Tänk på att vända bitarna så slingan blir kontinuerlig (se pilarna) och du inte behöver löda i kors.
För att hålla ihop delarna trädde jag transparent krympslang över listerna parvis omväxlande enligt nedan. Om du vill göra likadant, kom ihåg att trä på den innan du löder ändkablarna.
Löd fast övriga komponenter
Löd in slide switchen på den svarta delen i förlängningskabeln. Passa även på att förkorta förlängningskabeln eftersom den är för lång för att få plats i lådan. Isolera runt benen på switchen med krympslang för att undvika kortslutning.
Löd på samma sätt den andra knappen mellan GND och Gemmans ingång D2.
Löd samtidigt fast LED-listen i Gemman eftersom den också ska in på GND.
Lägg till krympslang innan du löder fast LED-listen i Gemman:
Ny prototyp-koppling
Nu är det dags att testa hela den kompletta lösningen. Schematiskt bör det se ut ungefär så här.
Placera i lådan
Lådan modifieras enkelt med lite borrande. Gör hål på ena långsidan för knapparna och gör hål på ena kortsidan för kablarna till slingan.
Fäst knapparna med smältlim från insidan.
Jag klädde in kablarna från slingan till Gemman med en längre bit krympslang och satte dessutom dit ett buntband som dragavlastning.
Det blir trångt i lådan, men det går att få plats. Blir det för trångt rekommenderas att ta bort lite mer av skarvkabeln.
Väderskydd
När du testat att allt fungerar som det ska är det dags att fästa konstruktionen på reflexen och samtidigt väderskydda hela härligheten. Börja genom att täcka alla kablar i ändarna med krympslang. Transparent blir finast.
Kläm ihop den i änden medan den är varm med en flacktång.
Jag avslutade med att klä in både listen och reflexen med en jättestor transparent krympslang.
Observera att du fortfarande behöver kunna komma åt lådan för att ta ur och ladda batteriet. Lådan fäste jag därför med ett gummiband. En alternativ lösning är att fästa både listen och lådan med gummiband eller buntband i reflexen.
Om du använder den jättestora krympslangen är ett tips att låta den svalna med reflexen ihoprullad, annars blir det svårt att rulla ihop den sedan eftersom krympslangen är bastant.
Dags för promenad!
Ut och syns!
Adafruit har gjort ett liknande projekt där led-listen istället kapslas in i en 3D-utskriven låda. Kolla gärna in det också här.
Vi har även gjort ett icke plågsamt djurförsök som föll väl ut: https://www.youtube.com/watch?v=5BDqD5_P-ps
Tack
Klas för programmeringen, Åsa för limningen och Erik för lådmodifieringen.
Kul att du gillar vår blogg!
Skriv upp dig på vår maillista för att få allt det senaste från m.nu - Nya produkter, kampanjer och mycket mer!
Wohoo! Du är nu med på maillistan!