Освой MicroPython играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Изучая документацию для M5Stack, наткнулся на пример часов с будильником, написанный в режиме Blockly. Я честно прошёл этот квест до конца и решил посмотреть, как выглядит код на MicroPython. Код оказался очень "грязным". Всевозможные проверки, лишние выражения, не слишком оптимальные варианты и т.д. Даже чисто визуально программа на экране смотрелась некрасиво - числа от 0 до 9 выводились без ведущего нуля.
Собственно, Blockly и не служит для написания хорошей программы, его можно использовать для быстрого прототипирования на начальных этапах. Оптимизируя код, я заодно изучал возможности языка Python. Возможно, даже мой финальный код ещё можно улучшить.
Для сравнения сначала приведу "плохой" код, который сгенерировал Blockly.
from m5stack import *
from m5ui import *
from uiflow import *
setScreenColor(0x222222)
label0 = M5TextBox(20, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
label1 = M5TextBox(130, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
label2 = M5TextBox(240, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
label3 = M5TextBox(100, 100, ":", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
label4 = M5TextBox(210, 100, ":", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
from numbers import Number
m = None
h = None
s = None
def buttonA_wasPressed():
global m, h, s
h = (h if isinstance(h, Number) else 0) + 1
pass
btnA.wasPressed(buttonA_wasPressed)
def buttonB_wasPressed():
global m, h, s
m = (m if isinstance(m, Number) else 0) + 1
pass
btnB.wasPressed(buttonB_wasPressed)
def buttonC_wasPressed():
global m, h, s
s = (s if isinstance(s, Number) else 0) + 1
pass
btnC.wasPressed(buttonC_wasPressed)
s = 0
m = 0
h = 0
while True:
label0.setText(str(h))
label1.setText(str(m))
label2.setText(str(s))
wait(1)
s = (s if isinstance(s, Number) else 0) + 1
if s >= 60:
s = 0
m = (m if isinstance(m, Number) else 0) + 1
if m >= 60:
m = 0
h = (h if isinstance(h, Number) else 0) + 1
if h >= 24:
h = 0
if h == 19 and m == 55 and s == 5:
for count in range(10):
speaker.tone(1600, 1000)
label0.setText(str(h))
label1.setText(str(m))
label2.setText(str(s))
s = (s if isinstance(s, Number) else 0) + 1
wait_ms(2)
Причесал код. Вкратце, что делает программа. Сначала выводится время 00:00:00. С помощью трёх кнопок вы можете выставить текущее время, каждое нажатие кнопки увеличивает на единицу час, минуту или секунду соответственно. Также в коде жёстко прописано время срабатывания будильника. Я выбрал время, как в фильме "День сурка" - 6 часов утра. Стандартное время, когда коты залезают на кровать с вопросом: "Наташ, ты спишь?".
from m5stack import *
from m5ui import *
from uiflow import *
setScreenColor(0x222222)
hourLabel = M5TextBox(20, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
minuteLabel = M5TextBox(130, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
secondLabel = M5TextBox(240, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
colonHMLabel = M5TextBox(100, 100, ":", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
colonMSLabel = M5TextBox(210, 100, ":", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
s = 0
m = 0
h = 0
def buttonA_wasPressed():
global m, h, s
h = h + 1
pass
btnA.wasPressed(buttonA_wasPressed)
def buttonB_wasPressed():
global m, h, s
m = m + 1
pass
btnB.wasPressed(buttonB_wasPressed)
def buttonC_wasPressed():
global m, h, s
s = s + 1
pass
btnC.wasPressed(buttonC_wasPressed)
while True:
hourLabel.setText('{:02d}'.format(h))
minuteLabel.setText('{:02d}'.format(m))
secondLabel.setText('{:02d}'.format(s))
wait(1)
s = s + 1
if s >= 60:
s = 0
m = m + 1
if m >= 60:
m = 0
h = h + 1
if h >= 24:
h = 0
if h == 6 and m == 0 and s == 0:
for count in range(9):
speaker.tone(1600, 1000)
hourLabel.setText(str(h))
minuteLabel.setText(str(m))
secondLabel.setText(str(s))
s = s + 1
wait_ms(2)
Получились симпатичные часы-будильник. По идее, этот код применим и к обычному устройству M5Stack Basic (чёрная модель).
Потом решил дописать программу и сделать будильник для Наташи.
Пришлось добавить несколько новых строчек кода.
from m5stack import *
from m5ui import *
from uiflow import *
setScreenColor(0x222222)
image0 = M5Img(0, 0, "res/natasha.jpg", True)
rectangle0 = M5Rect(43, 98, 246, 50, 0x0f0f0f, 0x191919)
hourLabel = M5TextBox(45, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
minuteLabel = M5TextBox(130, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
secondLabel = M5TextBox(215, 100, "00", lcd.FONT_DejaVu56,0x39e2c6, rotate=0)
colonHMLabel = M5TextBox(115, 100, ":", lcd.FONT_DejaVu40,0x39e2c6, rotate=0)
colonMSLabel = M5TextBox(200, 100, ":", lcd.FONT_DejaVu40,0x39e2c6, rotate=0)
natashaLabel = M5TextBox(5, 3, "Наташ, ты спишь?", lcd.FONT_UNICODE, 0xffffff, rotate=0)
s = 0
m = 0
h = 0
...