===== Эксперимент 51. Секундомер =====
В прошлом эксперименте мы получили секундомер, который умеет отсчитывать время, но еще не поддается управлению. В этом эксперименте мы добавим ему кнопку для запуска и остановки.
==== Схема эксперимента ====
{{ :products:esp-iot:exp24.3_mont.png?direct&600 |}}
//Рисунок 1. Монтажная схема эксперимента для дисплея с 8 выводами//
{{ :products:esp-iot:exp24.3_mont_11pin.png?direct&600 |}}
//Рисунок 2. Монтажная схема эксперимента для дисплея с 11 выводами//
==== Программный код эксперимента ====
#include
#include
#include "LittleFS_ImageReader.h"
#define PIN_CS 2
#define PIN_DC 4
#define PIN_RST 5
Adafruit_ST7735 tft = Adafruit_ST7735(PIN_CS, PIN_DC, PIN_RST);
LittleFS_ImageReader reader;
class Stopwatch {
private:
unsigned int hours = 0;
unsigned int mins = 0;
unsigned int secs = 0;
unsigned long start_time = 0;
bool state = 0;
unsigned int backcolor = tft.color565(255, 251, 240);
unsigned int fontcolor = tft.color565(39, 40, 51);
public:
void init() {
tft.fillScreen(backcolor);
reader.drawBMP("/time.bmp", tft, 0, 0);
drawInit();
}
void drawInit() {
drawValue(8, 125, 3, 0);
drawValue(55, 125, 3, 0);
drawValue(98, 132, 2, 0);
tft.setTextColor(fontcolor);
tft.setCursor(41, 125);
tft.setTextSize(3);
tft.print(":");
tft.setCursor(88, 132);
tft.setTextSize(2);
tft.print(":");
}
void drawValue(int x, int y, int size, int value) {
tft.fillRect(x, y, 6 * size * 2, 8 * size -2, backcolor);
tft.setCursor(x, y);
tft.setTextColor(fontcolor);
tft.setTextSize(size);
if (value < 10) tft.print(0);
tft.print(value);
}
void tick() {
if (state) {
unsigned long diff = millis() - start_time;
int hours_cur = diff / (1000 * 60 * 60);
diff = diff % (1000 * 60 * 60);
int mins_cur = diff / (1000 * 60);
diff = diff % (1000 * 60);
int secs_cur = diff / (1000);
if (hours_cur != hours) {
hours = hours_cur;
drawValue(8, 125, 3, hours);
}
if (mins_cur != mins) {
mins = mins_cur;
drawValue(55, 125, 3, mins);
}
if (secs_cur != secs) {
secs = secs_cur;
drawValue(98, 132, 2, secs);
}
}
}
void startStop() {
state = !state;
if (state) start_time = millis();
}
};
class Button {
private:
int pin;
bool pressState;
bool oldState;
public:
Button(int _pin, bool _pressState) {
pin = _pin;
pinMode(pin, INPUT);
pressState = _pressState;
oldState = not _pressState;
}
bool onPress() {
bool state = digitalRead(pin);
if (state != oldState){
oldState = state;
if (state == pressState) return true;
}
return false;
}
};
Stopwatch stopwatch;
Button btn(16, HIGH);
void setup() {
os_update_cpu_frequency(160);
LittleFS.begin();
tft.initR(INITR_BLACKTAB);
tft.setRotation(2);
stopwatch.init();
}
void loop() {
if (btn.onPress()) stopwatch.startStop();
stopwatch.tick();
}
К коду из прошлого эксперимента мы добавили класс кнопки, который уже [[products:laboratory_iot_c:exp45|использовали ранее здесь]]. Создаем объект кнопки на выводе 16 с логической 1 в нажатом состоянии:
Button btn(16, HIGH);
В основном цикле проверяем не нажата ли кнопка. Если нажатие зафиксировано, то изменяем состояние секундомера (запускаем, если не запущен. Останавливаем, если запущен):
if (btn.onPress()) stopwatch.startStop();
Теперь состоянием таймера можно управлять с помощью кнопки.