from machine import PWM, UART, Pin, Timer from micropython import const import time _PWM_MAX = const(65535) _PWM_FREQ = const(2000) _PIN_EN_MOTOR_VERT = const(0) _PIN_A_MOTOR_VERT = const(0) _PIN_B_MOTOR_VERT = const(0) _PIN_EN_MOTOR_HOR = const(0) _PIN_A_MOTOR_HOR = const(0) _PIN_B_MOTOR_HOR = const(0) _PIN_EN_BACKLIGHT = const(0) _PIN_EN_FRONTLIGHT = const(0) _PIN_LED_RED_BTN = const(0) _PIN_LED_BLU_BTN = const(0) _PIN_RED_BTN = const(0) _PIN_BLU_BTN = const(0) _PIN_SENS_END_VERT = const(0) _PIN_SENS_CNT_VERT = const(0) _PIN_SENS_END_HOR = const(0) _PIN_SENS_CNT_HOR = const(0) CMD_MOT_V = 'V' # run vertical motor CMD_MOT_H = 'H' # run horizontal motor CMD_BL = 'B' # backlight CMD_FL = 'F' # frontlight CMD_UI = 'U' # user interaction CMD_RC = 'C' # recording CMD_RW = 'R' # rewind LED = PWM(Pin(25)) LED.freq(_PWM_FREQ) class Scroll: def __init__(self, cnt_pin:Pin, end_pin:Pin, en_pin:PWM, a_pin:Pin, b_pin:Pin) -> None: self.c = 0 self._dir = 0 self._speed = 0 self.en_pin = en_pin self.a_pin = a_pin self.b_pin = b_pin self.c_pin = cnt_pin self.c_pin.irq(self._count, Pin.IRQ_RISING | Pin.IRQ_FALLING) self.e_pin = end_pin self.e_pin.irq(self._stop, Pin.IRQ_RISING) def _count(self, pin): self.c += self._dir def _stop(self, pin): self.a_pin.value(0) self.b_pin.value(0) @property def dir(self): return self._dir @dir.setter def dir(self, d): self.a_pin.value(1 if d > 0 else 0) self.b_pin.value(1 if d < 0 else 0) self._dir = d @property def speed(self): return self._speed * self._dir @speed.setter def speed(self, speed): self._speed = speed self.en_pin.duty_u16(speed * (_PWM_MAX // 100)) self.dir = (1 if speed > 0 else (-1 if speed < 0 else 0)) pwm_bl = PWM(Pin(_PIN_EN_BACKLIGHT)) pwm_bl.freq(_PWM_FREQ) pwm_fl = PWM(Pin(_PIN_EN_FRONTLIGHT)) pwm_fl.freq(_PWM_FREQ) pwm_mv = PWM(Pin(_PIN_EN_MOTOR_VERT)) pwm_mv.freq(_PWM_FREQ) pwm_mh = PWM(Pin(_PIN_EN_MOTOR_HOR)) pwm_mh.freq(_PWM_FREQ) pin_mv_a = Pin(_PIN_A_MOTOR_VERT, Pin.OUT) pin_mv_b = Pin(_PIN_B_MOTOR_VERT, Pin.OUT) pin_mh_a = Pin(_PIN_A_MOTOR_HOR, Pin.OUT) pin_mh_b = Pin(_PIN_B_MOTOR_HOR) led_blu = Pin(_PIN_LED_BLU_BTN, Pin.OUT) led_red = Pin(_PIN_LED_RED_BTN, Pin.OUT) btn_blu = Pin(_PIN_BLU_BTN, Pin.IN, Pin.PULL_UP) btn_red = Pin(_PIN_RED_BTN, Pin.IN, Pin.PULL_UP) cnt_v = Pin(_PIN_SENS_CNT_VERT, Pin.IN) cnt_h = Pin(_PIN_SENS_CNT_HOR, Pin.IN) end_v = Pin(_PIN_SENS_END_VERT, Pin.IN) end_h = Pin(_PIN_SENS_END_HOR, Pin.IN) uart0 = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1)) scroll_h = Scroll(cnt_h, end_h, pwm_mh, pin_mh_a, pin_mh_b) scroll_v = Scroll(cnt_v, end_v, pwm_mv, pin_mv_a, pin_mv_b) def motor_vert(*opts): _motorctrl(scroll_v, *opts) return 'OK' def motor_hor(*opts): _motorctrl(scroll_h, *opts) return 'OK' def _motorctrl(scroll: Scroll, steps: int, *opts): end = scroll.c + steps while True: err = end - scroll.c if abs(err) > 4: speed = (err / (2 * steps)) + 0.5 scroll.speed = int(100 * speed) else: scroll.speed = 0 break time.sleep_ms(5) def backlight(*opts): _fade_led(pwm_bl, *opts) return 'OK' def frontlight(*opts): _fade_led(pwm_fl, *opts) return 'OK' def _fade_led(led_pin: PWM, intensity: int, fade_ms: int, steps: int): intensity = intensity * (_PWM_MAX // 100) if fade_ms == 0: led_pin.duty_u16(intensity) return cur_intensity = led_pin.duty_u16() step = (intensity - cur_intensity) // steps wait = fade_ms // steps print(f'{cur_intensity} -> {intensity}, step={step}, wait={wait}') if step != 0: for i in range(steps): cur_intensity += step led_pin.duty_u16(cur_intensity) time.sleep_ms(wait) led_pin.duty_u16(intensity) def user_interaction(timeout): def _toggle_leds(timer): led_blu.toggle() led_red.toggle() tmr = Timer() tmr.init(freq=2, mode=Timer.PERIODIC, callback=_toggle_leds) startime = time.ticks_ms() timeout *= 1000 while time.ticks_diff(time.ticks_ms(), startime) < timeout: b, r = btn_blu.value(), btn_red.value() if (b + r) < 2: tmr.deinit() return 'B' if not b else 'R' tmr.deinit() led_blu.value(0) led_red.value(0) return 'T' # Timeout def recording(timeout): pass def rewind(*opts): print(f'rewind({opts})') ############################################################################### choice_map = { CMD_MOT_V: motor_vert, CMD_MOT_H: motor_hor, CMD_BL: backlight, CMD_FL: frontlight, CMD_UI: user_interaction, CMD_RW: rewind } def parseCmd(cmd_str: str): cmd, parm_str = cmd_str.split(':') parms = [] if len(parm_str) != 0: parms = [int(x) for x in parm_str.split('+')] resp = choice_map[cmd](*parms) uart0.write(f'{resp}\n'.encode('utf-8')) if __name__ == '__main__': rxData = '' while True: rxBuf = uart0.read(1) if rxBuf is not None: rxData += rxBuf.decode('utf-8') if rxData.endswith('\n'): parseCmd(rxData.strip()) rxData = ''