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)