Это старая версия документа!


Эксперимент 50. Класс секундомера, логика работы

В прошлом эксперименте мы нарисовали интерфейс секундомера. Вывели симпатичную картинку и нули вместо часов, минут и секунд. Теперь нужно «оживить» этот прототип, заставить его считать время.

Первый вопрос, который возникает — как отсчитывать время? Как вариант, знакомая нам функция time.sleep(1), которая дает задержку на 1 секунду. Алгоритм работы получается простой. Завели переменную с секундами, которая в начале равна нулю. Отображаем ее значение на дисплее и делаем паузу на секунду. Потом увеличиваем значение переменной на 1 и отображаем новое значение. И так дальше.

Приведенный выше алгоритм простой, но не правильный. Дело в том, что на отображение данных на дисплее уходит время помимо паузы на 1 секунду и такой секундомер не будет считать правильно. Для данной задачи есть более верное решение.

Системная библиотека time предлагает функцию ticks_ms(), которая возвращает количество миллисекунд с начала запуска микроконтроллера. Это значение обновляется аппаратно по прерыванию от таймера, который настроен точно и не зависит от действий программы. Поэтому лучше ориентироваться именно на это значение.

При запуске таймера мы будем запоминать текущее значение ticks_ms() и следить за его изменением.

Схема эксперимента

Рисунок 1. Монтажная схема эксперимента

Класс Stopwatch

Exp49.py
  1. class Stopwatch:
  2. def __init__(self):
  3. self.hours = 0
  4. self.mins = 0
  5. self.secs = 0
  6. self.start_time = 0
  7. self.state = 0
  8. self.backcolor = tft.rgbcolor(255,251,240)
  9. self.fontcolor = tft.rgbcolor(39,40,51)
  10. self.draw_init()
  11.  
  12.  
  13. def draw_init(self):
  14. self.draw_value(98, 132, 2, 0)
  15. self.draw_value(55, 125, 3, 0)
  16. self.draw_value(5, 125, 3, 0)
  17.  
  18. tft.text(41, 125, ":", font.terminalfont, self.fontcolor, 3)
  19. tft.text(90, 130, ":", font.terminalfont, self.fontcolor, 2)
  20.  
  21.  
  22. def tick(self):
  23. if self.state:
  24. diff = time.ticks_diff(time.ticks_ms(), self.start_time)
  25. hours = diff // (1000 * 60 * 60)
  26. diff = diff % (1000 * 60 * 60)
  27. mins = diff // (1000 * 60)
  28. diff = diff % (1000 * 60)
  29. secs = diff // (1000)
  30.  
  31. if secs != self.secs:
  32. self.secs = secs
  33. self.draw_value(98, 132, 2, secs)
  34.  
  35. if mins != self.mins:
  36. self.mins = mins
  37. self.draw_value(55, 125, 3, mins)
  38.  
  39. if hours != self.hours:
  40. self.hours = hours
  41. self.draw_value(5, 125, 3, hours)
  42.  
  43.  
  44. def start_stop(self):
  45. if self.state:
  46. self.state = 0
  47. else:
  48. self.state = 1
  49. self.start_time = time.ticks_ms()
  50.  
  51.  
  52. def draw_value(self, x, y, size, value):
  53. tft.rect(x+2, y, 6 * size * 2, 8 * size -2, self.backcolor)
  54.  
  55. if value < 10:
  56. value = '0' + str(value)
  57. else:
  58. value = str(value)
  59.  
  60. tft.text(x, y, value, font.terminalfont, self.fontcolor, size)

Класс содержит конструктор init и методы:

  • draw_init — отображает начальное значение таймера, нули, как в прошлом эксперименте.
  • start_stop — запускает и останавливает секундомер.
  • draw_value — выводит значение часов минут или секунд. В качестве параметров принимает координаты, размер шрифта и значение.
  • tick — системная функция секундомера. Она определяет сколько часов, минут и секунд прошло с момента его запуска. Эту функцию необходимо вызывать постоянно.