Compare commits

...

5 Commits
main ... code

Author SHA1 Message Date
Jimmy c2b55972d3 Done a heap of stuff 2024-10-06 22:02:39 +13:00
Jimmy c0b0833905 Save settings between powers cycles 2024-10-06 22:01:34 +13:00
Jimmy 9c9fffc3ff Remove unsed files 2024-09-14 20:59:24 +12:00
Jimmy b165811130 Inital commit 2024-09-14 20:57:28 +12:00
Jimmy 64374d4477 Add .gitignore 2024-09-14 20:55:42 +12:00
8 changed files with 777 additions and 102 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
__pycache__/
.venv/
config.py
settings.json

27
boot.py Normal file
View File

@ -0,0 +1,27 @@
import network
from machine import Pin
from config import *
def do_connect():
led = Pin(8, Pin.OUT)
sta_if = network.WLAN(network.STA_IF)
sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect(ssid, password)
led.on()
while not sta_if.isconnected():
pass
print('network config:', sta_if.ifconfig())
do_connect()
ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid="led", password="qwerty1234")
print(ap.ifconfig())

60
index.html Normal file
View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LED Control</title>
<script src="main.js"></script>
<link rel="stylesheet" href="main.css">
</head>
<body>
<h1>Control LEDs</h1>
<button onclick="selectControls()">Controls</button>
<button onclick="selectSettings()">Settings</button>
<!-- Main LED Controls -->
<div id="controls">
<div id="pattern_buttons">
<!-- Pattern buttons will be inserted here -->
</div>
<form id="delay_form" method="post" action="/delay">
<label for="delay">Delay:</label>
<input type="range" id="delay" name="delay" min="1" max="1000" value="{delay}" step="10">
</form>
<form id="brightness_form" method="post" action="/brightness">
<label for="brightness">Brightness:</label>
<input type="range" id="brightness" name="brightness" min="0" max="100" value="{brightness}" step="1">
</form>
<form id="color_form" method="post" action="/color">
<input type="color" id="color" name="color" value="{color}">
</form>
<form id="color2_form" method="post" action="/color2">
<input type="color" id="color2" name="color2" value="{color2}">
</form>
</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="{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="{ssid}">
<br>
<label for="password">Wi-Fi Password:</label>
<input type="password" id="password" name="password">
<br>
<input type="submit" value="Save Wi-Fi Settings">
</form>
</div>
</body>
</html>

74
main.css Normal file
View File

@ -0,0 +1,74 @@
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 0 auto;
padding: 20px;
line-height: 1.6;
}
h1 {
text-align: center;
}
form {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"], input[type="submit"], input[type="range"], input[type="color"] {
width: 100%;
margin-bottom: 10px;
box-sizing: border-box;
}
input[type="range"] {
-webkit-appearance: none;
appearance: none;
height: 25px;
background: #d3d3d3;
outline: none;
opacity: 0.7;
transition: opacity .2s;
}
input[type="range"]:hover {
opacity: 1;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 25px;
height: 25px;
background: #4CAF50;
cursor: pointer;
border-radius: 50%;
}
input[type="range"]::-moz-range-thumb {
width: 25px;
height: 25px;
background: #4CAF50;
cursor: pointer;
border-radius: 50%;
}
#pattern_buttons {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 20px;
}
#pattern_buttons button {
flex: 1 0 calc(33.333% - 10px);
padding: 10px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
#pattern_buttons button:hover {
background-color: #45a049;
}
@media (max-width: 480px) {
#pattern_buttons button {
flex: 1 0 calc(50% - 10px);
}
}

143
main.js Normal file
View File

@ -0,0 +1,143 @@
let delayTimeout;
let brightnessTimeout;
let colorTimeout;
let color2Timeout;
async function post(path, value) {
console.log(path, value);
try {
const response = await fetch(path, {
method: "POST",
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: value
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
} catch (error) {
console.error('Error during POST request:', error);
}
}
async function get(path) {
try {
const response = await fetch(path);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return await response.json(); // Assuming you are expecting JSON response
} catch (error) {
console.error('Error during GET request:', error);
}
}
async function updateColor(event) {
event.preventDefault();
clearTimeout(colorTimeout);
colorTimeout = setTimeout(async function() {
const color = document.getElementById('color').value;
await post("/color", color);
}, 500);
}
async function updateColor2(event) {
event.preventDefault();
clearTimeout(color2Timeout);
color2Timeout = setTimeout(async function() {
const color = document.getElementById('color2').value;
await post("/color2", color);
}, 500);
}
async function updatePattern(pattern) {
event.preventDefault();
await post("/pattern", pattern);
}
async function updateBrightness(event) {
event.preventDefault();
clearTimeout(brightnessTimeout);
brightnessTimeout = setTimeout(async function() {
const brightness = document.getElementById('brightness').value;
await post('/brightness', brightness);
}, 500);
}
async function updateDelay(event) {
event.preventDefault();
clearTimeout(delayTimeout);
delayTimeout = setTimeout(async function() {
const delay = document.getElementById('delay').value;
await post('/delay', delay);
}, 500);
}
async function updateNumLeds(event) {
event.preventDefault();
const numLeds = document.getElementById('num_leds').value;
await post('/num_leds', numLeds);
}
async function updateWifi(event) {
event.preventDefault();
const ssid = document.getElementById('ssid').value;
const password = document.getElementById('password').value;
console.log(ssid, password);
//await post('/num_leds', numLeds);
}
function createPatternButtons(patterns) {
const container = document.getElementById('pattern_buttons');
container.innerHTML = ''; // Clear previous buttons
patterns.forEach(pattern => {
const button = document.createElement('button');
button.type = 'button'; // Use 'button' instead of 'submit'
button.textContent = pattern;
button.value = pattern;
button.addEventListener('click', async function(event) {
event.preventDefault();
await updatePattern(pattern);
});
container.appendChild(button);
});
}
document.addEventListener('DOMContentLoaded', async function() {
document.getElementById('color').addEventListener('input', updateColor);
document.getElementById('color2').addEventListener('input', updateColor2);
document.getElementById('delay').addEventListener('input', updateDelay);
document.getElementById('brightness').addEventListener('input', updateBrightness);
document.getElementById('num_leds_form').addEventListener('submit', updateNumLeds);
document.getElementById('wifi_form').addEventListener('submit', updateWifi);
document.getElementById('delay').addEventListener('touchend', updateDelay);
document.getElementById('brightness').addEventListener('touchend', updateBrightness);
try {
const patterns = await get("/patterns");
console.log('Patterns fetched:', patterns);
createPatternButtons(patterns);
} catch (error) {
console.error('Error fetching patterns:', error);
}
});
// Function to toggle the display of the settings menu
function selectSettings() {
const settingsMenu = document.getElementById('settings_menu');
controls = document.getElementById('controls');
settingsMenu.style.display = 'block';
controls.style.display = 'none';
}
function selectControls() {
const settingsMenu = document.getElementById('settings_menu');
controls = document.getElementById('controls');
settingsMenu.style.display = 'none';
controls.style.display = 'block';
}

183
main.py Normal file
View File

@ -0,0 +1,183 @@
from machine import Pin
from patterns import Patterns
from settings import Settings
import socket
import select
import json
import utime
import sys
class LEDServer:
SETTINGS_FILE = "/settings.json" # Path should be adjusted for MicroPython's filesystem
def __init__(self, num_leds=50, pin=4, led_pin=8, brigtness=255):
# Initialize NeoPixel Patterns
self.settings = Settings()
print(self.settings)
self.patterns = Patterns(pin, num_leds)
self.patterns.select(self.settings["selected_pattern"])
self.patterns.set_color1(tuple(int(self.settings["color1"][i:i+2], 16) for i in (1, 5, 3)))
self.patterns.set_color2(tuple(int(self.settings["color2"][i:i+2], 16) for i in (1, 5, 3)))
# Initialize single LED
self.led = Pin(led_pin, Pin.OUT)
# Initialize server
self.server_socket = socket.socket()
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind(('0.0.0.0', 80))
self.server_socket.listen(1)
self.server_socket.settimeout(1) # Adjust timeout as needed
self.poll = select.poll()
self.poll.register(self.server_socket, select.POLLIN)
self.html = self.read_file("/index.html")
self.js = self.read_file("/main.js").encode('utf-8')
self.css = self.read_file("/main.css").encode('utf-8')
self.patterns_json = json.dumps(list(self.patterns.patterns.keys()))
def read_file(self, file_path):
try:
with open(file_path, 'r') as file:
return file.read()
except OSError as e:
print(f"Error reading file {file_path}: {e}")
return ""
def handle_post(self, path, post_data, client_socket):
paths = {
"/num_leds" : self.num_leds,
"/pattern": self.pattern,
"/delay": self.delay,
"/brightness": self.brightness,
"/color": self.color,
"/color2": self.color2
}
if path in paths:
paths[path](client_socket, post_data)
else:
client_socket.send(b'HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\n')
def num_leds(self, client_socket, post_data):
try:
num_leds = int(post_data)
self.patterns.update_num_leds(4,num_leds)
self.settings["num_leds"] = num_leds
self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
except ValueError:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def pattern(self, client_socket, post_data):
if self.patterns.select(post_data):
self.settings["selected_pattern"] = post_data
self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
else:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def delay(self, client_socket, post_data):
try:
delay = int(post_data)
self.patterns.set_delay(delay)
self.settings["delay"] = delay
self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
except ValueError:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def brightness(self, client_socket, post_data):
try:
brightness = int(post_data)
self.patterns.set_brightness(brightness)
self.settings["brightness"] = brightness
self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
except ValueError:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def color(self, client_socket, post_data):
try:
self.patterns.set_color1(tuple(int(post_data[i:i+2], 16) for i in (1, 5, 3))) # Convert hex to RGB
self.settings["color1"] = post_data
self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
except:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def color2(self, client_socket, post_data):
try:
self.patterns.set_color2(tuple(int(post_data[i:i+2], 16) for i in (1, 5, 3))) # Convert hex to RGB
self.settings["color2"] = post_data
self.settings.save()
client_socket.send(b'HTTP/1.0 200 OK\r\n\r\n')
except:
client_socket.send(b'HTTP/1.0 400 Bad request\r\n\r\n')
def handle_get(self, path, client_socket):
if path == "/":
client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
client_socket.send(self.html.format(
num_leds=self.settings["num_leds"],
delay=self.settings["delay"],
brightness=self.settings["brightness"],
color=self.settings["color1"],
color2=self.settings["color2"],
ssid=self.settings["wifi"]["ssid"]).encode())
elif path == "/main.js":
client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: application/javascript\r\n\r\n')
client_socket.send(self.js)
elif path == "/main.css":
client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: text/css\r\n\r\n')
client_socket.send(self.css)
elif path == "/patterns":
client_socket.send(b'HTTP/1.0 200 OK\r\nContent-type: application/json\r\n\r\n')
client_socket.send(self.patterns_json.encode())
else:
client_socket.send(b'HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\n')
def start(self):
count = 0
average_time = 0
previous_time = utime.ticks_us()
try:
while True:
count += 1
events = self.poll.poll(1)
for file in events:
if file[0] == self.server_socket:
client_socket, addr = self.server_socket.accept()
request = client_socket.recv(1024).decode()
method, path, _ = request.split('\r\n')[0].split()
print(f"Method: {method}, Path: {path}")
if method == "POST":
post_data = request.split('\r\n\r\n')[1] if '\r\n\r\n' in request else ''
self.handle_post(path, post_data, client_socket)
elif method == "GET":
self.handle_get(path, client_socket)
client_socket.close()
if count > 50:
self.led.off()
#print(utime.ticks_us() - previous_time)
if count > 100:
self.led.on()
count = 0
# previous_time = utime.ticks_us()
self.patterns.tick()
except Exception as e:
print("Error:", e)
sys.print_exception(e)
finally:
self.server_socket.close()
# Example of creating and starting the server
if __name__ == "__main__":
server = LEDServer()
server.start()

View File

@ -1,114 +1,243 @@
from machine import Pin
from neopixel import NeoPixel
import _thread
import time, math
import sys
import utime
import random
class LedPatterns:
def __init__(self, pin, num_leds):
class Patterns:
def __init__(self, pin, num_leds, color1=(0,0,0), color2=(0,0,0), brightness=127, selected="rainbow_cycle", delay=100):
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds)
self.num_leds = num_leds
self.np = NeoPixel(Pin(pin), num_leds)
self.run = True
self.pattern_step = 0
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 # Added color transition pattern
}
self.selected = selected
self.color1 = color1
self.color2 = color2
self.transition_duration = 50 # Duration of color transition in milliseconds
self.transition_step = 0
def color_chase(self, color, wait):
self.run = True
def tick(self):
self.patterns[self.selected]()
def update_num_leds(self, pin, num_leds):
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds)
self.num_leds = num_leds
self.pattern_step = 0
def set_delay(self, delay):
self.delay = delay
def set_brightness(self, brightness):
self.brightness = brightness
def set_color1(self, color):
print(color)
self.color1 = self.apply_brightness(color)
def set_color2(self, color):
self.color2 = self.apply_brightness(color)
def apply_brightness(self, color):
return tuple(int(c * self.brightness / 255) for c in color)
def select(self, pattern):
if pattern in self.patterns:
self.selected = pattern
return True
return False
def fill(self):
for i in range(self.num_leds):
self.np[i] = color
self.np.write()
if not run:
break
time.sleep(wait)
self.n[i] = self.color1
self.n.write()
def wheel(self, pos):
if pos < 0 or pos > 255:
return (0, 0, 0)
def off(self):
color = self.color1
self.color1 = (0,0,0)
self.fill()
self.color1 = color
def on(self):
color = self.color1
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:
def wheel(pos):
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
return (0, pos * 3, 255 - pos * 3)
def rainbow_cycle(self, wait):
run = True
for j in range(255):
for i in range(self.num_leds):
self.np[i] = self.wheel((i * 256 // self.num_leds) + j)
self.np.write()
if not run:
break
time.sleep(wait)
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 breathing(self, color, duration):
steps = 256
for _ in range(steps):
brightness = int(255 * abs(steps / 2 - _) / (steps / 2))
self.np.fill((brightness * color[0] // 255, brightness * color[1] // 255, brightness * color[2] // 255))
self.np.write()
time.sleep(duration / steps)
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 color_transition(self, start_color, end_color, duration):
steps = 256
for step in range(steps):
color = (
int(start_color[0] + (end_color[0] - start_color[0]) * step / steps),
int(start_color[1] + (end_color[1] - start_color[1]) * step / steps),
int(start_color[2] + (end_color[2] - start_color[2]) * step / steps),
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)
)
self.np.fill(color)
self.np.write()
if not self.running():
return
time.sleep(duration / steps)
def scanner(self, color, speed):
position = 0
direction = 1
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:
self.np.fill((0, 0, 0))
self.np[position] = color
self.np.write()
time.sleep(speed)
position += direction
if position == self.num_leds - 1 or position == 0:
direction *= -1
def bidirectional_scanner(self, color_left, color_right=None, speed=0.1):
color_right = color_right or color_left
position_left = 0
position_right = self.num_leds - 1
direction_left = 1
direction_right = -1
while True:
self.np.fill((0, 0, 0))
self.np[position_left] = color_left
self.np[position_right] = color_right
self.np.write()
time.sleep(speed)
position_left += direction_left
position_right += direction_right
if position_left == self.num_leds - 1 or position_left == 0:
direction_left *= -1
if position_right == self.num_leds - 1 or position_right == 0:
direction_right *= -1
def sine_wave_propagation(self, color, speed):
frequency = 10
phase = 0
while True:
self.np.fill((0, 0, 0))
for i in range(self.num_leds):
brightness = int(127.5 * (math.sin(frequency * i + phase) + 1))
self.np[i] = (brightness * color[0] // 255, brightness * color[1] // 255, brightness * color[2] // 255)
self.np.write()
time.sleep(speed)
phase += 0.1
def fill(self,color):
for i in range(self.num_leds):
self.np[i] = color
self.np.write()
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))

55
settings.py Normal file
View File

@ -0,0 +1,55 @@
import json
import os
import uasyncio as asyncio
class Settings(dict):
SETTINGS_FILE = "/settings.json"
def __init__(self):
super().__init__()
self.load() # Load settings from file during initialization
def set_defaults(self):
self["num_leds"] = 50
self["selected_pattern"] = "blink"
self["color1"] = "#000f00"
self["color2"] = "#0f0000"
self["delay"] = 100
self["brightness"] = 100
self["wifi"] = {"ssid": "", "password": ""}
def save(self):
try:
j = json.dumps(self)
with open(self.SETTINGS_FILE, 'w') as file:
file.write(j)
print("Settings saved successfully.")
except Exception as e:
print(f"Error saving settings: {e}")
def load(self):
try:
with open(self.SETTINGS_FILE, 'r') as file:
loaded_settings = json.load(file)
self.update(loaded_settings)
print("Settings loaded successfully.")
except Exception as e:
print(f"Error loading settings: {e}")
self.set_defaults()
# Example usage
def main():
settings = Settings()
print(f"Number of LEDs: {settings['num_leds']}")
settings['num_leds'] = 100
print(f"Updated number of LEDs: {settings['num_leds']}")
settings.save()
# Create a new Settings object to test loading
new_settings = Settings()
print(f"Loaded number of LEDs: {new_settings['num_leds']}")
print(settings)
# Run the example
if __name__ == "__main__":
main()