import time from math import e, exp, pi, sin import pulseio from micropython import const led_config = { 'brightness_step': 5, 'brightness_limit': 100, 'breathe_center': 1.5, 'animation_mode': 'static', 'animation_speed': 1, } class led: brightness = 0 time = int(time.monotonic() * 1000) pos = 0 effect_init = False led = None brightness_step = 5 brightness_limit = 100 breathe_center = 1.5 animation_mode = 'static' animation_speed = 1 enabled = True user_animation = None def __init__(self, led_pin, config): self.led = pulseio.PWMOut(led_pin) self.brightness_step = const(config['brightness_step']) self.brightness_limit = const(config['brightness_limit']) self.animation_mode = const(config['animation_mode']) self.animation_speed = const(config['animation_speed']) self.breathe_center = const(config['breathe_center']) if config.get('user_animation'): self.user_animation = config['user_animation'] def __repr__(self): return 'LED({})'.format(self._to_dict()) def _to_dict(self): return { 'led': self.led, 'brightness_step': self.brightness_step, 'brightness_limit': self.brightness_limit, 'animation_mode': self.animation_mode, 'animation_speed': self.animation_speed, 'breathe_center': self.breathe_center, } def _init_effect(self): self.pos = 0 self.effect_init = False return self def time_ms(self): return int(time.monotonic() * 1000) def set_brightness(self, percent): self.led.duty_cycle = int(percent / 100 * 65535) def increase_brightness(self, step=None): if not step: self.brightness += self.brightness_step else: self.brightness += step if self.brightness > 100: self.brightness = 100 self.set_brightness(self.brightness) def decrease_brightness(self, step=None): if not step: self.brightness -= self.brightness_step else: self.brightness -= step if self.brightness < 0: self.brightness = 0 self.set_brightness(self.brightness) def off(self): self.set_brightness(0) def increase_ani(self): ''' Increases animation speed by 1 amount stopping at 10 :param step: ''' if (self.animation_speed + 1) >= 10: self.animation_speed = 10 else: self.val += 1 def decrease_ani(self): ''' Decreases animation speed by 1 amount stopping at 0 :param step: ''' if (self.val - 1) <= 0: self.val = 0 else: self.val -= 1 def effect_breathing(self): # http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ # https://github.com/qmk/qmk_firmware/blob/9f1d781fcb7129a07e671a46461e501e3f1ae59d/quantum/rgblight.c#L806 sined = sin((self.pos / 255.0) * pi) multip_1 = exp(sined) - self.breathe_center / e multip_2 = self.brightness_limit / (e - 1 / e) self.brightness = int(multip_1 * multip_2) self.pos = (self.pos + self.animation_speed) % 256 self.set_brightness(self.brightness) return self def effect_static(self): self.set_brightness(self.brightness) # Set animation mode to none to prevent cycles from being wasted self.animation_mode = None return self def animate(self): ''' Activates a "step" in the animation based on the active mode :return: Returns the new state in animation ''' if self.effect_init: self._init_effect() if self.enabled: if self.animation_mode == 'breathing': return self.effect_breathing() elif self.animation_mode == 'static': return self.effect_static() elif self.animation_mode == 'user': return self.user_animation(self) else: self.off() return self