pizzabox-ctrl/micropizza/main.py

301 lines
7.7 KiB
Python

from machine import PWM, UART, Pin, Timer
from micropython import const
import time
_DEBUG = const(1)
_PWM_MAX = const(65535)
_PWM_FREQ = const(4000)
_PIN_EN_MOTOR_VERT = const(14)
_PIN_A_MOTOR_VERT = const(12)
_PIN_B_MOTOR_VERT = const(13)
_PIN_EN_MOTOR_HOR = const(15)
_PIN_A_MOTOR_HOR = const(11)
_PIN_B_MOTOR_HOR = const(10)
_PIN_EN_BACKLIGHT = const(16) # 17
_PIN_A_BACKLIGHT = const(20) # 18
_PIN_B_BACKLIGHT = const(21) # 19
_PIN_EN_FRONTLIGHT = const(17) # 16
_PIN_A_FRONTLIGHT = const(18) # 20
_PIN_B_FRONTLIGHT = const(19) # 21
_PIN_LED_RED_BTN = const(2)
_PIN_LED_BLU_BTN = const(4)
_PIN_RED_BTN = const(3)
_PIN_BLU_BTN = const(5)
_PIN_SENS_END_VERT = const(9)
_PIN_SENS_CNT_VERT = const(7)
_PIN_SENS_END_HOR = const(8)
_PIN_SENS_CNT_HOR = const(6)
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 = Pin(25, Pin.OUT)
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.stopped = False
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
# if _DEBUG:
# print(f'{self} count={self.c}')
def _stop(self, pin):
if _DEBUG:
print(f'{self} stopped.')
self.speed = 0
self.stopped = True
@property
def dir(self):
return self._dir
@dir.setter
def dir(self, d):
if d == self._dir:
return
if _DEBUG:
print(f'{self} dir={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):
# if _DEBUG:
# print(f'{self} speed={speed}')
self._speed = abs(speed)
self.en_pin.duty_u16(self._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, Pin.OUT)
pin_bl_a = Pin(_PIN_A_BACKLIGHT, Pin.OUT)
pin_bl_b = Pin(_PIN_B_BACKLIGHT, Pin.OUT)
pin_fl_a = Pin(_PIN_A_FRONTLIGHT, Pin.OUT)
pin_fl_b = Pin(_PIN_B_FRONTLIGHT, Pin.OUT)
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, timeout_ms: int = 5000, *opts):
end = scroll.c + steps
if _DEBUG:
print(f'motorctrl, end={end}, scroll.c={scroll.c}')
try:
startime = time.ticks_ms()
while (not scroll.stopped) and (time.ticks_diff(time.ticks_ms(), startime) < timeout_ms):
err = end - scroll.c
if abs(err) > 1:
speed = 100 if err > 0 else -100 # (err / (2 * abs(steps))) * 400 # + 0.5
scroll.speed = int(speed)
else:
scroll.speed = 0
break
time.sleep_us(50)
finally:
if _DEBUG:
print(f'motorctrl, scroll.c={scroll.c}')
scroll.speed = 0
scroll.stopped = False
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()
led_blu.value(0)
led_red.value(0)
return 'B' if not b else 'R'
time.sleep_ms(50)
tmr.deinit()
led_blu.value(0)
led_red.value(0)
return 'T' # Timeout
def recording(timeout):
timeout *= 1000
startime = time.ticks_ms()
endtime = time.ticks_add(startime, timeout)
while time.ticks_diff(time.ticks_ms(), startime) < timeout:
if not btn_blu.value():
led_red.value(0)
return 'I'
restime = time.ticks_diff(endtime, time.ticks_ms())
if restime < 5000:
led_red.value((restime // 500) % 2)
time.sleep_ms(50)
return 'OK'
def rewind(*opts):
#scroll_h.speed = -100
#scroll_v.speed = -100
#while (scroll_h.speed + scroll_v.speed) > 0:
# time.sleep_ms(10)
#scroll_h.c = 0
#scroll_v.c = 0
return 'OK'
###############################################################################
choice_map = {
CMD_MOT_V: motor_vert,
CMD_MOT_H: motor_hor,
CMD_BL: backlight,
CMD_FL: frontlight,
CMD_UI: user_interaction,
CMD_RC: recording,
CMD_RW: rewind
}
def parseCmd(cmd_str: bytes):
cmd, parm_str = cmd_str.decode('utf-8').split(':')
parms = []
if len(parm_str) != 0:
parms = [int(x) for x in parm_str.split('+')]
resp = 'E'
if _DEBUG:
print(cmd, parms, sep=': ')
# resp = 'OK'
# else:
resp = choice_map[cmd](*parms)
if _DEBUG:
print('response', resp, sep=': ')
return resp
def flash_led(times: int = 1, on_ms: int = 200, off_ms: int = 500):
LED.off()
times = 1 if times < 1 else times
for i in range(times):
LED.on()
time.sleep_ms(on_ms)
LED.off()
time.sleep_ms(off_ms)
if __name__ == '__main__':
pin_bl_a.value(0)
pin_bl_b.value(1)
pin_fl_a.value(0)
pin_fl_b.value(1)
rxData = b''
flash_led(2)
while True:
rxBuf = uart0.read(1)
if rxBuf is not None:
rxData += rxBuf # .decode('utf-8')
if rxData.endswith('\n'):
resp = parseCmd(rxData.strip())
uart0.write(f'{resp}\n'.encode('utf-8'))
rxData = b''