Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
products:laboratory_iot:exp50 [2020/06/01 18:47] – [Класс Stopwatch] labuser29products:laboratory_iot:exp50 [2021/07/21 16:47] (текущий) – [Программный код эксперимента] labuser29
Строка 14: Строка 14:
  
 {{ :products:esp-iot:exp24.1_mont.png?direct&600 |}} {{ :products:esp-iot:exp24.1_mont.png?direct&600 |}}
-//Рисунок 1. Монтажная схема эксперимента//+//Рисунок 1. Монтажная схема эксперимента для дисплея с 8 выводами//
  
 +{{ :products:esp-iot:exp24.1_mont_11pin.png?direct&600 |}}
 +//Рисунок 2. Монтажная схема эксперимента для дисплея с 11 выводами//
 ==== Класс Stopwatch==== ==== Класс Stopwatch====
  
-<code python Exp49.py[enable_line_numbers="2", start_line_numbers_at="1"]>+<code python [enable_line_numbers="2", start_line_numbers_at="1"]> 
 +class Stopwatch: 
 +    def __init__(self): 
 +        self.hours = 0 # Значение часов 
 +        self.mins = 0 # Значение минут 
 +        self.secs = 0 # Значение секунд 
 +        self.start_time = 0 # Время запуска 
 +        self.state = 0 # Состояние. 0 - секундомер не запущен, 1 - запущен 
 +        self.backcolor = tft.rgbcolor(255,251,240) # Цвет фона 
 +        self.fontcolor = tft.rgbcolor(39,40,51) # Цвет шрифта 
 +        self.draw_init() # Вызов функции отображения начального значения- нулей 
 + 
 +    # Функция вывода начального значения секундомера- нулей 
 +    def draw_init(self): 
 +        self.draw_value(98, 132, 2, 0) # Выводим на дисплей 0 секунд 
 +        self.draw_value(55, 125, 3, 0) # Выводим на дисплей 0 минут 
 +        self.draw_value(5, 125, 3, 0) # Выводим на дисплей 0 часов 
 + 
 +        # Выводим разделитель часов и минут 
 +        tft.text(41, 125, ":", font.terminalfont, self.fontcolor, 3)  
 +        # Выводим разделитель минут и секунд 
 +        tft.text(90, 130, ":", font.terminalfont, self.fontcolor, 2) 
 + 
 + 
 +    # Основная функция секундомера, отсчет времени 
 +    def tick(self): 
 +        if self.state: # отсчет производим только, если секундомер запущен 
 +            # Находим разницу в миллисекундах между текущим временем и временем запуска 
 +            diff = time.ticks_diff(time.ticks_ms(), self.start_time) 
 +            hours = diff // (1000 * 60 * 60) # Деление без остатка. Находим сколько целых часов прошло 
 +            diff = diff % (1000 * 60 * 60) # Находим остаток после деления на часы и сохраняем в diff 
 +            mins = diff // (1000 * 60) # Деление без остатка. Находим сколько целых минут прошло 
 +            diff = diff % (1000 * 60) # Находим остаток после деления на минуты и сохраняем в diff 
 +            secs = diff // (1000) # Деление без остатка. Находим сколько целых секунд прошло 
 + 
 +            # Если сохраненное ранее значение секунд отличается от вычисленных- обновляем и выводим на дисплей 
 +            if secs != self.secs: 
 +                self.secs = secs 
 +                self.draw_value(98, 132, 2, secs) 
 +            
 +            # Если сохраненное ранее значение минут отличается от вычисленных- обновляем и выводим на дисплей 
 +            if mins != self.mins: 
 +                self.mins = mins 
 +                self.draw_value(55, 125, 3, mins) 
 + 
 +            # Если сохраненное ранее значение часов отличается от вычисленных- обновляем и выводим на дисплей 
 +            if hours != self.hours: 
 +                self.hours = hours 
 +                self.draw_value(5, 125, 3, hours) 
 +         
 + 
 +    # Функция запуска и остановки секундомера 
 +    def start_stop(self): 
 +        if self.state: # Если секундомер запущен- останавливаем 
 +            self.state = 0 
 +        else: # Иначе- запускаем 
 +            self.state = 1 
 +            self.start_time = time.ticks_ms() # Сохраняем время запуска секундомера 
 + 
 + 
 +    # Функция отображения на дисплее значений 
 +    def draw_value(self, x, y, size, value): 
 +        # Перед выводом на дисплей новых данных закрашиваем старые прямоугольником с цветом фона 
 +        tft.rect(x+2, y, 6 * size * 2, 8 * size -2, self.backcolor) 
 + 
 +        # Если значение для вывода менее 10, то добавляем ведущий ноль, чтобы всегда было 2 знака 
 +        # конвертируем значение из числа в строку 
 +        if value < 10: 
 +            value = '0' + str(value) 
 +        else: 
 +            value = str(value) 
 + 
 +        # Выводим значение в виде строки на дисплей в нужном месте нужным цветом и размером 
 +        tft.text(x, y, value, font.terminalfont, self.fontcolor, size) 
 +</code> 
 + 
 +Класс содержит конструктор ''__init__'' и методы: 
 +  * ''draw_init'' — отображает начальное значение таймера, нули, как в прошлом эксперименте. 
 +  * ''start_stop'' — запускает и останавливает секундомер.  
 +  * ''draw_value'' — выводит значение часов минут или секунд. В качестве параметров принимает координаты, размер шрифта и значение. 
 +  * ''tick'' — системная функция секундомера. Она определяет сколько часов, минут и секунд прошло с момента его запуска. Эту функцию необходимо вызывать постоянно. 
 + 
 +Код класса снабжен комментариями, подробно описывающими почти каждую строку. Кроме этого дадим несколько пояснений. Когда мы говорим "Сохраняем время запуска секундомера", то имеется в виду, что мы сохраняем значение количества миллисекунд с момента запуска микроконтроллера. И все упоминания времени следует читать в этом ключе. 
 + 
 +Функция ''diff = time.ticks_diff(time.ticks_ms(), self.start_time)'' нужна для нахождения разницы между  количеством миллисекунд, прошедших со старта микроконтроллера при запуске секундомера и сейчас. Несмотря на то, что это есть обычное число, которое можно было бы вычесть обычным знаком минус, лучше это делать с помощью данной функции. Дело в том, что это значение может переполниться и обнулиться и начать считать "по второму кругу". Тогда простое вычитание даст ошибку. Только функция ''ticks_diff'' гарантирует правильное значение. 
 + 
 +Заострим внимание на вычислении количества часов: 
 +<code python> 
 +hours = diff // (1000 * 60 * 60) 
 +diff = diff % (1000 * 60 * 60) 
 +</code> 
 + 
 +Оператор ''%%//%%'' — это оператор деления без остатка. Например 5 %%//%% 2 = 2. А остаток 0.5 был отброшен. 
 +А оператор ''%'' — напротив возвращает только остаток от деления. 5 % 2 = 0.5 
 + 
 +Сначала мы вычисляем целое количество часов, а потом мы вычисляем по сути сколько осталось после выделения целого количества часов. После этого там останется значение меньше одного часа. Его мы уже будем делить на минуты. А после вычитания минут будем определять сколько осталось секунд. 
 + 
 +Теперь сделаем программу с использованием данного класса 
 + 
 +==== Программный код эксперимента ==== 
 + 
 +<file python Exp50.py[enable_line_numbers="2", start_line_numbers_at="1"]> 
 +from machine import Pin, SPI 
 +from tft import TFT_GREEN 
 +import font 
 +import time 
 +_init() 
 +machine.freq(160000000) 
 + 
 + 
 +dc  = Pin(4, Pin.OUT)  
 +cs  = Pin(2, Pin.OUT) 
 +rst = Pin(5, Pin.OUT) 
 + 
 +spi = SPI(1, baudrate=40000000, polarity=0, phase=0) 
 +tft = TFT_GREEN(128, 160, spi, dc, cs, rst, rotate=0) 
 + 
 +tft.initr(tft.BGR) # tft.initr(tft.RGB) #Если вместо синего цвета отображается красный, а вместо красного синий 
 +tft.clear(tft.rgbcolor(255,251,240))  
 +tft.draw_bmp(0,0,'time.bmp'
 + 
 class Stopwatch: class Stopwatch:
     def __init__(self):     def __init__(self):
Строка 79: Строка 202:
  
         tft.text(x, y, value, font.terminalfont, self.fontcolor, size)         tft.text(x, y, value, font.terminalfont, self.fontcolor, size)
 +
 +
 +class Button:
 +    def __init__(self, p, pressSate):
 +        self.pin = Pin(p, Pin.IN)
 +        self.pressSate = pressSate
 +        self.oldState = not pressSate
 + 
 +    def onPress(self):
 +        state = self.pin.value()
 +        if state != self.oldState:
 +            self.oldState = state
 +            if state == self.pressSate:
 +                return True
 +        return False
 +
 +
 +stopwatch = Stopwatch()
 +stopwatch.start_stop()
 +
 +while True:
 +    stopwatch.tick()
 +</file>
 +
 +Код эксперимента должен быть понятен. Сначала как обычно подключаем библиотеки, настраиваем SPI и дисплей. Потом код класса секундомера и в конце мы создаем объект секундомера
 +<code python[enable_line_numbers="2", start_line_numbers_at="98"]>
 +stopwatch = Stopwatch()
 </code> </code>
  
-Класс содержит конструктор ''__init__'' и методы: +Запускаем его 
-  * ''draw_init'' — отображает начальное значение таймера, нули, как в прошлом эксперименте. +<code python[enable_line_numbers="2", start_line_numbers_at="99"]> 
-  * ''start_stop'' — запускает и останавливает секундомер.  +stopwatch.start_stop() 
-  * ''draw_value'' — выводит значение часов минут или секунд. В качестве параметров принимает координаты, размер шрифта и значение. +</code> 
-  * ''tick'' — системная функция секундомера. Она определяет сколько часов, минут и секунд прошло с момента его запуска. Эту функцию необходимо вызывать постоянно.+ 
 +И в бесконечном цикле вызываем его метод ''tick()''. В нем он занимается отслеживаем времени и отображением изменений на дисплее 
 +<code python[enable_line_numbers="2", start_line_numbers_at="101"]> 
 +while True: 
 +    stopwatch.tick() 
 +</code> 
 + 
 +Теперь наш секундомер умеет считать времяНо еще не слушается управления. В следующем эксперименте мы добавим управление с помощью кнопки и получим полноценный секундомер.