Освой MicroPython играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

M5Stack: Часы с будильником (MicroPython)

MicroPython Clock

Изучая документацию для 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

...
Реклама