change to hoop

This commit is contained in:
Jimmy 2025-09-10 16:41:41 +12:00
parent a829310f45
commit 4b06aa0841
7 changed files with 309 additions and 405 deletions

View File

@ -11,9 +11,9 @@ password = settings.get('wifi', {}).get('password', None)
ip = settings.get('wifi', {}).get('ip', None) ip = settings.get('wifi', {}).get('ip', None)
gateway = settings.get('wifi', {}).get('gateway', None) gateway = settings.get('wifi', {}).get('gateway', None)
for i in range(10): # for i in range(10):
config = wifi.connect(ssid, password, ip, gateway) # config = wifi.connect(ssid, password, ip, gateway)
if config: # if config:
print(config) # print(config)
break # break
time.sleep(0.1) # time.sleep(0.1)

117
src/dma.py Normal file
View File

@ -0,0 +1,117 @@
from machine import Pin
from rp2 import PIO, StateMachine, asm_pio
from time import sleep
import array
import uctypes
from uctypes import BF_POS, BF_LEN, UINT32, BFUINT32, struct
PIO0_BASE = 0x50200000
PIO1_BASE = 0x50300000
DMA_BASE = 0x50000000
DMA_CHAN_WIDTH = 0x40
DMA_CHAN_COUNT = 12
DMA_SIZE_BYTE = 0x0
DMA_SIZE_HALFWORD = 0x1
DMA_SIZE_WORD = 0x2
# DMA: RP2040 datasheet 2.5.7
DMA_CTRL_TRIG_FIELDS = {
"AHB_ERROR": 31<<BF_POS | 1<<BF_LEN | BFUINT32,
"READ_ERROR": 30<<BF_POS | 1<<BF_LEN | BFUINT32,
"WRITE_ERROR": 29<<BF_POS | 1<<BF_LEN | BFUINT32,
"BUSY": 24<<BF_POS | 1<<BF_LEN | BFUINT32,
"SNIFF_EN": 23<<BF_POS | 1<<BF_LEN | BFUINT32,
"BSWAP": 22<<BF_POS | 1<<BF_LEN | BFUINT32,
"IRQ_QUIET": 21<<BF_POS | 1<<BF_LEN | BFUINT32,
"TREQ_SEL": 15<<BF_POS | 6<<BF_LEN | BFUINT32,
"CHAIN_TO": 11<<BF_POS | 4<<BF_LEN | BFUINT32,
"RING_SEL": 10<<BF_POS | 1<<BF_LEN | BFUINT32,
"RING_SIZE": 6<<BF_POS | 4<<BF_LEN | BFUINT32,
"INCR_WRITE": 5<<BF_POS | 1<<BF_LEN | BFUINT32,
"INCR_READ": 4<<BF_POS | 1<<BF_LEN | BFUINT32,
"DATA_SIZE": 2<<BF_POS | 2<<BF_LEN | BFUINT32,
"HIGH_PRIORITY":1<<BF_POS | 1<<BF_LEN | BFUINT32,
"EN": 0<<BF_POS | 1<<BF_LEN | BFUINT32
}
# Channel-specific DMA registers
DMA_CHAN_REGS = {
"READ_ADDR_REG": 0x00|UINT32,
"WRITE_ADDR_REG": 0x04|UINT32,
"TRANS_COUNT_REG": 0x08|UINT32,
"CTRL_TRIG_REG": 0x0c|UINT32,
"CTRL_TRIG": (0x0c,DMA_CTRL_TRIG_FIELDS)
}
# General DMA registers
DMA_REGS = {
"INTR": 0x400|UINT32,
"INTE0": 0x404|UINT32,
"INTF0": 0x408|UINT32,
"INTS0": 0x40c|UINT32,
"INTE1": 0x414|UINT32,
"INTF1": 0x418|UINT32,
"INTS1": 0x41c|UINT32,
"TIMER0": 0x420|UINT32,
"TIMER1": 0x424|UINT32,
"TIMER2": 0x428|UINT32,
"TIMER3": 0x42c|UINT32,
"MULTI_CHAN_TRIGGER": 0x430|UINT32,
"SNIFF_CTRL": 0x434|UINT32,
"SNIFF_DATA": 0x438|UINT32,
"FIFO_LEVELS": 0x440|UINT32,
"CHAN_ABORT": 0x444|UINT32
}
DMA_CHANS = [struct(DMA_BASE + n*DMA_CHAN_WIDTH, DMA_CHAN_REGS) for n in range(0,DMA_CHAN_COUNT)]
DMA_DEVICE = struct(DMA_BASE, DMA_REGS)
DMA_CH0_AL3_TRANS_COUNT = DMA_BASE + 0x38
class PIO_DMA_Transfer():
def __init__(self, dma_channel, sm_num, block_size, transfer_count):
self.dma_chan = DMA_CHANS[dma_channel]
self.channel_number = dma_channel
if (sm_num >= 0 and sm_num < 4):
self.dma_chan.WRITE_ADDR_REG = PIO0_BASE + 0x10 + sm_num *4
self.dma_chan.CTRL_TRIG.TREQ_SEL = sm_num
elif (sm_num < 8):
self.dma_chan.WRITE_ADDR_REG = PIO1_BASE + 0x10 + (sm_num-4) *4
self.dma_chan.CTRL_TRIG.TREQ_SEL = sm_num + 4
if (block_size == 8):
self.dma_chan.CTRL_TRIG.DATA_SIZE = DMA_SIZE_BYTE
if (block_size == 16):
self.dma_chan.CTRL_TRIG.DATA_SIZE = DMA_SIZE_HALFWORD
if (block_size == 32):
self.dma_chan.CTRL_TRIG.DATA_SIZE = DMA_SIZE_WORD
self.dma_chan.TRANS_COUNT_REG = transfer_count
#Do I just always want these?
self.dma_chan.CTRL_TRIG.INCR_WRITE = 0
self.dma_chan.CTRL_TRIG.INCR_READ = 1
def start_transfer(self, buffer):
self.dma_chan.READ_ADDR_REG = uctypes.addressof(buffer)
self.dma_chan.CTRL_TRIG.EN = 1
def transfer_count(self):
return self.dma_chan.TRANS_COUNT_REG
def busy(self):
if self.dma_chan.CTRL_TRIG.DATA_SIZE == 1:
return True
else:
return False

View File

@ -1,54 +1,34 @@
import asyncio
from settings import Settings from time import sleep
from web import web from neopixel import NeoPixel
from machine import UART, Pin, PWM, ADC
import _thread
import network
import espnow
from patterns import Patterns from patterns import Patterns
import gc
import utime
import machine
import ntptime
import time
import wifi
adc = ADC(2, atten=ADC.ATTN_11DB)
sta = network.WLAN(network.WLAN.IF_STA) # Or network.WLAN.IF_AP
sta.active(True)
async def main(): e = espnow.ESPNow()
e.active(True)
#e.add_peer(broadcast)
p = Patterns()
settings = Settings() _thread.start_new_thread(p.scan_single_led, ((255,0,0),0))
patterns = Patterns(4, settings["num_leds"], selected=settings["selected_pattern"])
patterns.set_color1(tuple(int(settings["color1"][i:i+2], 16) for i in (1, 5, 3)))
patterns.set_color2(tuple(int(settings["color2"][i:i+2], 16) for i in (1, 5, 3)))
patterns.set_brightness(int(settings["brightness"]))
patterns.set_delay(int(settings["delay"]))
w = web(settings, patterns)
print(settings)
# start the server in a bacakground task
print("Starting")
server = asyncio.create_task(w.start_server(host="0.0.0.0", port=80))
wdt = machine.WDT(timeout=10000)
async def tick():
while True:
patterns.tick()
await asyncio.sleep_ms(1)
asyncio.create_task(tick())
first = True
while True: while True:
#print(time.localtime()) value = adc.read_uv()*2
if value < 3_500_000:
# gc.collect() p.run = False
for i in range(60): p.off()
wdt.feed() print(f"Voltage {value}")
await asyncio.sleep_ms(500) sleep(1)
# cleanup before ending the application
await server
asyncio.run(main())
i = 0

View File

@ -4,289 +4,92 @@ import utime
import random import random
class Patterns: class Patterns:
def __init__(self, pin, num_leds, color1=(0,0,0), color2=(0,0,0), brightness=127, selected="rainbow_cycle", delay=100): def __init__(self):
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds) self.pin_data = (21, 277) # Example: Pin 21, 277 LEDs
self.num_leds = num_leds self.strip = NeoPixel(Pin(self.pin_data[0]), self.pin_data[1])
self.pattern_step = 0 self.run = False
self.last_update = utime.ticks_ms()
self.delay = delay
self.brightness = brightness
self.patterns = {
"off": self.off,
"on" : self.on,
"color_wipe": self.color_wipe_step,
"rainbow_cycle": self.rainbow_cycle_step,
"theater_chase": self.theater_chase_step,
"blink": self.blink_step,
"random_color_wipe": self.random_color_wipe_step,
"random_rainbow_cycle": self.random_rainbow_cycle_step,
"random_theater_chase": self.random_theater_chase_step,
"random_blink": self.random_blink_step,
"color_transition": self.color_transition_step,
"2 step forward 1 step back": self.two_steps_forward_one_step_back_step,
"external": None
}
self.selected = selected
self.color1 = color1
self.color2 = color2
self.transition_duration = 50 # Duration of color transition in milliseconds
self.transition_step = 0
def sync(self): self.strip.fill((0,0,0))
self.pattern_step=0 self.strip.write()
self.last_update = utime.ticks_ms() print(f"Initialized single strip on Pin {self.pin_data[0]} with {self.pin_data[1]} LEDs.")
def tick(self):
if self.patterns[self.selected]:
self.patterns[self.selected]()
def update_num_leds(self, pin, num_leds): def scan_single_led(self, color=(255, 255, 255), delay_ms=0):
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds) """
self.num_leds = num_leds Scans a single LED along the length of the strip, turning it on and then off
self.pattern_step = 0 as it moves. Optimized for speed by batching writes.
def set_delay(self, delay): Args:
self.delay = delay color (tuple): The (R, G, B) color of the scanning LED.
delay_ms (int): Optional extra delay in milliseconds between each LED position.
Set to 0 for fastest possible without *extra* delay.
"""
self.run = True
num_pixels = len(self.strip)
last_pixel_index = num_pixels - 1
def set_brightness(self, brightness): # Turn off all pixels initially for a clean start if not already off
self.brightness = brightness self.strip.fill((0, 0, 0))
# No write here yet, as the first pixel will be set immediately
def set_color1(self, color): while self.run:
print(color) # --- Scan Forward ---
self.color1 = self.apply_brightness(color) for i in range(num_pixels):
if not self.run:
break
def set_color2(self, color): # Turn on the current pixel
self.color2 = self.apply_brightness(color) self.strip[i] = color
def apply_brightness(self, color): # Turn off the previous pixel if not the first one
return tuple(int(c * self.brightness / 255) for c in color) if i > 0:
self.strip[i - 1] = (0, 0, 0)
# If it's the first pixel, ensure the last one from previous cycle is off (if applicable)
elif i == 0 and num_pixels > 1: # Only relevant if scanning backwards too
self.strip[last_pixel_index] = (0,0,0)
def select(self, pattern):
if pattern in self.patterns:
self.selected = pattern
return True
return False
def set(self, i, color): self.strip.write() # Write changes to the strip
self.n[i] = color if delay_ms > 0:
utime.sleep_ms(delay_ms)
def write(self): # Ensure the last pixel of the forward scan is turned off
self.n.write() if self.run and num_pixels > 0:
self.strip[last_pixel_index] = (0, 0, 0)
self.strip.write() # Write this final change
# --- Scan Backward (optional, remove this loop if you only want forward) ---
for i in range(num_pixels - 1, -1, -1): # From last_pixel_index down to 0
if not self.run:
break
# Turn on the current pixel
self.strip[i] = color
# Turn off the next pixel (which was the previous one in reverse scan)
if i < last_pixel_index:
self.strip[i + 1] = (0, 0, 0)
# If it's the last pixel of the reverse scan, ensure the first one from previous cycle is off (if applicable)
elif i == last_pixel_index and num_pixels > 1: # Only relevant if scanning forward too
self.strip[0] = (0,0,0)
self.strip.write() # Write changes to the strip
if delay_ms > 0:
utime.sleep_ms(delay_ms)
# Ensure the first pixel of the backward scan is turned off
if self.run and num_pixels > 0:
self.strip[0] = (0, 0, 0)
self.strip.write() # Write this final change
def fill(self):
for i in range(self.num_leds):
self.n[i] = self.color1
self.n.write()
def off(self): def off(self):
color = self.color1 print("Turning off LEDs.")
self.color1 = (0,0,0) self.run = False
self.fill() self.strip.fill((0,0,0))
self.color1 = color self.strip.write()
utime.sleep_ms(50)
def on(self): # Example Usage (for MicroPython on actual hardware):
color = self.color1 # (Same as before, just removed from the main block for brevity)
self.color1 = self.apply_brightness(self.color1)
self.fill()
self.color1 = color
def color_wipe_step(self):
color = self.apply_brightness(self.color1)
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
if self.pattern_step < self.num_leds:
for i in range(self.num_leds):
self.n[i] = (0, 0, 0)
self.n[self.pattern_step] = self.apply_brightness(color)
self.n.write()
self.pattern_step += 1
else:
self.pattern_step = 0
self.last_update = current_time
def rainbow_cycle_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay/5:
def wheel(pos):
if pos < 85:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (0, pos * 3, 255 - pos * 3)
for i in range(self.num_leds):
rc_index = (i * 256 // self.num_leds) + self.pattern_step
self.n[i] = self.apply_brightness(wheel(rc_index & 255))
self.n.write()
self.pattern_step = (self.pattern_step + 1) % 256
self.last_update = current_time
def theater_chase_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
for i in range(self.num_leds):
if (i + self.pattern_step) % 3 == 0:
self.n[i] = self.apply_brightness(self.color1)
else:
self.n[i] = (0, 0, 0)
self.n.write()
self.pattern_step = (self.pattern_step + 1) % 3
self.last_update = current_time
def blink_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
if self.pattern_step % 2 == 0:
for i in range(self.num_leds):
self.n[i] = self.apply_brightness(self.color1)
else:
for i in range(self.num_leds):
self.n[i] = (0, 0, 0)
self.n.write()
self.pattern_step = (self.pattern_step + 1) % 2
self.last_update = current_time
def random_color_wipe_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
if self.pattern_step < self.num_leds:
for i in range(self.num_leds):
self.n[i] = (0, 0, 0)
self.n[self.pattern_step] = self.apply_brightness(color)
self.n.write()
self.pattern_step += 1
else:
self.pattern_step = 0
self.last_update = current_time
def random_rainbow_cycle_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
def wheel(pos):
if pos < 85:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (0, pos * 3, 255 - pos * 3)
random_offset = random.randint(0, 255)
for i in range(self.num_leds):
rc_index = (i * 256 // self.num_leds) + self.pattern_step + random_offset
self.n[i] = self.apply_brightness(wheel(rc_index & 255))
self.n.write()
self.pattern_step = (self.pattern_step + 1) % 256
self.last_update = current_time
def random_theater_chase_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
for i in range(self.num_leds):
if (i + self.pattern_step) % 3 == 0:
self.n[i] = self.apply_brightness(color)
else:
self.n[i] = (0, 0, 0)
self.n.write()
self.pattern_step = (self.pattern_step + 1) % 3
self.last_update = current_time
def random_blink_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
if self.pattern_step % 2 == 0:
for i in range(self.num_leds):
self.n[i] = self.apply_brightness(color)
else:
for i in range(self.num_leds):
self.n[i] = (0, 0, 0)
self.n.write()
self.pattern_step = (self.pattern_step + 1) % 2
self.last_update = current_time
def color_transition_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
# Calculate transition factor based on elapsed time
transition_factor = (self.pattern_step * 100) / self.transition_duration
if transition_factor > 100:
transition_factor = 100
color = self.interpolate_color(self.color1, self.color2, transition_factor / 100)
# Apply the interpolated color to all LEDs
for i in range(self.num_leds):
self.n[i] = self.apply_brightness(color)
self.n.write()
self.pattern_step += self.delay
if self.pattern_step > self.transition_duration:
self.pattern_step = 0
self.last_update = current_time
def interpolate_color(self, color1, color2, factor):
return (
int(color1[0] + (color2[0] - color1[0]) * factor),
int(color1[1] + (color2[1] - color1[1]) * factor),
int(color1[2] + (color2[2] - color1[2]) * factor)
)
def two_steps_forward_one_step_back_step(self):
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, self.last_update) >= self.delay:
# Move forward 2 steps and backward 1 step
if self.direction == 1: # Moving forward
if self.scanner_position < self.num_leds - 2:
self.scanner_position += 2 # Move forward 2 steps
else:
self.direction = -1 # Change direction to backward
else: # Moving backward
if self.scanner_position > 0:
self.scanner_position -= 1 # Move backward 1 step
else:
self.direction = 1 # Change direction to forward
# Set all LEDs to off
for i in range(self.num_leds):
self.n[i] = (0, 0, 0)
# Set the current position to the color
self.n[self.scanner_position] = self.apply_brightness(self.color1)
# Apply the color transition
transition_factor = (self.pattern_step * 100) / self.transition_duration
if transition_factor > 100:
transition_factor = 100
color = self.interpolate_color(self.color1, self.color2, transition_factor / 100)
self.n[self.scanner_position] = self.apply_brightness(color)
self.n.write()
self.pattern_step += self.delay
if self.pattern_step > self.transition_duration:
self.pattern_step = 0
self.last_update = current_time
if __name__ == "__main__":
p = Patterns(4, 180)
p.set_color1((255,0,0))
p.set_color2((0,255,0))
#p.set_delay(10)
try:
while True:
for key in p.patterns:
print(key)
p.select(key)
for _ in range(2000):
p.tick()
utime.sleep_ms(1)
except KeyboardInterrupt:
p.fill((0, 0, 0))

View File

@ -37,35 +37,5 @@
<input type="color" id="color2" name="color2" value="{{settings['color2']}}"> <input type="color" id="color2" name="color2" value="{{settings['color2']}}">
</form> </form>
</div> </div>
<!-- Settings Menu for num_leds, Wi-Fi SSID, and Password -->
<div id="settings_menu" style="display: none;">
<h2>Settings</h2>
<!-- Separate form for submitting num_leds -->
<form id="num_leds_form" method="post" action="/num_leds">
<label for="num_leds">Number of LEDs:</label>
<input type="text" id="num_leds" name="num_leds" value="{{settings['num_leds']}}">
<input type="submit" value="Update Number of LEDs">
</form>
<!-- Form for Wi-Fi SSID and password -->
<form id="wifi_form" method="post" action="/wifi_settings">
<label for="ssid">Wi-Fi SSID:</label>
<input type="text" id="ssid" name="ssid" value="{{settings['wifi']['ssid']}}">
<br>
<label for="password">Wi-Fi Password:</label>
<input type="password" id="password" name="password">
<br>
<label for="ip">Wi-Fi IP:</label>
<input type="ip" id="ip" name="ip" value="{{settings.get('wifi', {}).get('ip', '')}}">
<br>
<label for="gateway">Wi-Fi Gateway:</label>
<input type="gateway" id="gateway" name="gateway" value="{{settings.get('wifi', {}).get('gateway', '')}}">
<br>
<input type="submit" value="Save Wi-Fi Settings">
</form>
</div>
</body> </body>
</html> </html>

View File

@ -5,7 +5,7 @@ from microdot.websocket import with_websocket
import json import json
import wifi import wifi
def web(settings, patterns): def web(settings, patterns, patterns2):
app = Microdot() app = Microdot()
Response.default_content_type = 'text/html' Response.default_content_type = 'text/html'
@ -20,24 +20,13 @@ def web(settings, patterns):
return 'Not found', 404 return 'Not found', 404
return send_file('static/' + path) return send_file('static/' + path)
@app.post("/num_leds")
def num_leds(request):
try:
data = json.loads(request.body.decode('utf-8'))
num_leds = int(data["num_leds"])
patterns.update_num_leds(4, num_leds)
settings["num_leds"] = num_leds
settings.save()
return "OK", 200
except (ValueError, KeyError, json.JSONDecodeError):
return "Bad request", 400
@app.post("/pattern") @app.post("/pattern")
def pattern(request): def pattern(request):
try: try:
data = json.loads(request.body.decode('utf-8')) data = json.loads(request.body.decode('utf-8'))
pattern = data["pattern"] pattern = data["pattern"]
if patterns.select(pattern): if patterns.select(pattern):
patterns2.select(pattern)
settings["selected_pattern"] = pattern settings["selected_pattern"] = pattern
settings.save() settings.save()
return "OK", 200 return "OK", 200
@ -52,6 +41,7 @@ def web(settings, patterns):
data = json.loads(request.body.decode('utf-8')) data = json.loads(request.body.decode('utf-8'))
delay = int(data["delay"]) delay = int(data["delay"])
patterns.set_delay(delay) patterns.set_delay(delay)
patterns2.set_delay(delay)
settings["delay"] = delay settings["delay"] = delay
settings.save() settings.save()
return "OK", 200 return "OK", 200
@ -64,6 +54,7 @@ def web(settings, patterns):
data = json.loads(request.body.decode('utf-8')) data = json.loads(request.body.decode('utf-8'))
brightness = int(data["brightness"]) brightness = int(data["brightness"])
patterns.set_brightness(brightness) patterns.set_brightness(brightness)
patterns2.set_brightness(brightness)
settings["brightness"] = brightness settings["brightness"] = brightness
settings.save() settings.save()
return "OK", 200 return "OK", 200
@ -76,6 +67,7 @@ def web(settings, patterns):
data = json.loads(request.body.decode('utf-8')) data = json.loads(request.body.decode('utf-8'))
color = data["color"] color = data["color"]
patterns.set_color1(tuple(int(color[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB patterns.set_color1(tuple(int(color[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
patterns2.set_color1(tuple(int(color[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
settings["color1"] = color settings["color1"] = color
settings.save() settings.save()
return "OK", 200 return "OK", 200
@ -88,39 +80,13 @@ def web(settings, patterns):
data = json.loads(request.body.decode('utf-8')) data = json.loads(request.body.decode('utf-8'))
color = data["color2"] color = data["color2"]
patterns.set_color2(tuple(int(color[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB patterns.set_color2(tuple(int(color[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
patterns2.set_color2(tuple(int(color[i:i+2], 16) for i in (1, 3, 5))) # Convert hex to RGB
settings["color2"] = color settings["color2"] = color
settings.save() settings.save()
return "OK", 200 return "OK", 200
except (KeyError, json.JSONDecodeError, ValueError): except (KeyError, json.JSONDecodeError, ValueError):
return "Bad request", 400 return "Bad request", 400
@app.post("/wifi_settings")
def wifi_settings(request):
try:
data = json.loads(request.body.decode('utf-8'))
print(data)
ssid = settings['wifi']['ssid'] = data['ssid']
password = settings['wifi']['password'] = data.get('password', settings['wifi']['password'])
ip = settings['wifi']['ip'] = data.get('ip', None)
gateway = settings['wifi']['gateway'] = data.get('gateway', None)
print(settings)
if config := wifi.connect(ssid, password, ip, gateway):
print(config)
settings.save()
return "OK", 200
except Exception as e:
print(f"Wifi {e}")
return "Bad request", 400
@app.post("/sync")
def sync(request):
patterns.sync()
return "OK", 200
@app.route("/external") @app.route("/external")
@with_websocket @with_websocket
async def ws(request, ws): async def ws(request, ws):

68
src/ws2812.py Normal file
View File

@ -0,0 +1,68 @@
import array, time
from machine import Pin
import rp2
from time import sleep
import dma
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=8)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
class WS2812B:
def __init__(self, num_leds, pin, state_machine, brightness=0.1, invert=False):
self.sm = rp2.StateMachine(state_machine, ws2812, freq=8_000_000, sideset_base=Pin(pin))
self.sm.active(1)
self.ar = bytearray(num_leds*3)
self.num_leds = num_leds
self.brightness = brightness
self.invert = invert
self.pio_dma = dma.PIO_DMA_Transfer(state_machine+4, state_machine, 8, num_leds*3)
def show(self):
self.pio_dma.start_transfer(self.ar)
def set(self, i, color):
self.ar[i*3] = int(color[1]*self.brightness)
self.ar[i*3+1] = int(color[0]*self.brightness)
self.ar[i*3+2] = int(color[2]*self.brightness)
def fill(self, color):
for i in range(self.num_leds):
self.set(i, color)
def busy(self):
return self.pio_dma.busy()
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)
if __name__ == "__main__":
num_leds, pin, sm, brightness = 10, 0, 0, 1
ws0 = WS2812B(num_leds, pin, sm, brightness)
while True:
for color in ws0.COLORS:
ws0.fill(color)
ws0.show()
time.sleep(1)