rgb-lamp/code/main.py

92 lines
2.1 KiB
Python

import machine
from machine import Pin, ADC
from neopixel import NeoPixel
from time import sleep
machine.freq(240000000) # set the CPU frequency to 240 MHz
PIXELPIN = Pin(20, Pin.OUT)
NUM_PIXELS = 40
ADC0 = ADC(Pin(26))
ADC1 = ADC(Pin(27))
ADC2 = ADC(Pin(28))
def read_adc_float(adc: ADC) -> float:
value = adc.read_u16()
return value / 2**16
def read_adc(adc: ADC) -> int:
lower_limit = 1024
upper_limit = 1024
adc_range = 2**16
value = adc.read_u16()
if value < lower_limit:
return 0
if value > adc_range - upper_limit:
return 255
value -= lower_limit
value = min(value, adc_range - lower_limit - upper_limit)
return min(int(value / (adc_range - lower_limit - upper_limit) * 256), 255)
def float_to_u8(value: float) -> int:
return min(255, int(256 * value))
def denoise(value: float, factor: float = 0.05) -> float:
"""
Rescales the range of the float from 0.0 to 1.0 to factor to 1-factor.
Values below factor and above 1-factor are set to 0.0 and 1.0 respecitvely.
"""
if value < factor:
return 0.0
if value > 1 - factor:
return 1.0
return max(0.0, min(1.0, (value - factor) / (1 - 2 * factor)))
def gate(initial: float, new: float, gate: float) -> float:
"""
needs a minimum amount of change (given as gate) between the initial and the new value for the output to change.
"""
if abs(initial - new) > gate:
return new
return initial
np = NeoPixel(PIXELPIN, NUM_PIXELS, bpp=4)
r = 0.0
g = 0.0
b = 0.0
dampening_factor = 0.25
while True:
r = dampening_factor * gate(r, denoise(1-read_adc_float(ADC0)), 4.0/512) + (1-dampening_factor) * r
g = dampening_factor * gate(g, denoise(1-read_adc_float(ADC1)), 4.0/512) + (1-dampening_factor) * g
b = dampening_factor * gate(b, denoise(1-read_adc_float(ADC2)), 4.0/512) + (1-dampening_factor) * b
for i in range(0, NUM_PIXELS):
np[i] = (
float_to_u8(r),
float_to_u8(g),
float_to_u8(b),
float_to_u8(0.0),
)
np.write()
print(float_to_u8(r), float_to_u8(g), float_to_u8(b))
sleep(0.01)