4. Энкодер и кнопки: протокол ввода
Занятия 4–5. Энкодер и кнопки: протокол ввода судьи
Занятие 4. Энкодер как устройство ввода
Цель занятия: обучающиеся вводят цифру 1–8 поворотом стрелки на шкале с 8 делениями.
Разминка-вспоминание (5 мин)
- Первое действие с датчиком освещённости на новом месте?
- Как гасятся выбросы датчика? (интервальный возврат: занятие 2)
- Стенка на 12 см, порог 15 см — что выведет Задание 1: 0 или 1?
Разбор (worked example): шкала 8 делений
Конструкция (компетенция 7): неподвижный картонный круг на раме, размечен на 8 секторов по 45° с цифрами 1–8; на оси мотора — стрелка. Регламент разрешает крутить стрелку вручную — мотор работает как энкодер: программа читает угол оси по счётчику энкодера.
Математика перевода угла в цифру: dialDeg() отдаёт угол от нулевой метки в диапазоне 0…359° (счётчик энкодера по модулю одного оборота). Делим на 45:
pos ← угол оси от нулевой метки # 0..359
цифра ← целая часть (pos / 45) + 1 # сектора: 0-44°→1, 45-89°→2, … 315-359°→8#include "stend.h"
int encoderDigit() {
return dialDeg() / 45 + 1; // 0..359 -> 1..8, деление целых
}
void setup() {
Serial.begin(115200);
stendBegin();
}
void loop() {
int d = encoderDigit();
Serial.printf("Ввод: %d\n", d);
screen(String(d));
delay(150);
}Разбор: dialDeg() отсчитывает угол от положения стрелки при включении питания — перед стартом ставьте стрелку на начало сектора «1», иначе введите программную поправку (pos = (pos - SDVIG + 360) % 360 — в C++ остаток от отрицательного числа отрицательный, поэтому + 360); показ текущей цифры в реальном времени — обязательная часть UX: судья и участник видят, что вводится, до подтверждения.
Практика
Изготовить шкалу
Круг из картона, 8 равных секторов (транспортир: 45°), цифры крупно по краю. Закрепить на раме, стрелку — на ось.
Совместить ноль
Добиться, чтобы «1» читалась во всём своём секторе: покрутить стрелку по границам секторов, при рассинхроне добавить программную поправку.
Ввести серию
Партнёр называет цифры — вводите поворотом. «Введи 3, 7, 1» — три из трёх на экране.
Мини-проверка выхода занятия 4
Ввод трёх названных цифр подряд без промаха; вопрос: «почему pos / 45 + 1, и что изменится, если объявить pos как float?»
Занятие 5. Кнопки, автомат ввода, ГСЧ — и сдача Задания 1
Цель занятия: обучающиеся реализуют конечный автомат «команда судьи → ввод → подтверждение кнопкой → вывод» без перезапуска программы.
Разминка-вспоминание (5 мин)
- Стрелка на 200° при шкале из 8 секторов — какая цифра?
- Что будет, если не ждать отпускания кнопки?
- Из чего складываются 25 баллов Задания 1?
Разбор (worked example): автомат ввода
Все мини-задачи регламента устроены одинаково — это конечный автомат:
stateDiagram-v2
[*] --> Ожидание: старт программы
Ожидание --> ВводA: команда судьи
ВводA --> ПоказA: кнопка-подтверждение
ПоказA --> ВводB: команда судьи
ВводB --> ПоказB: кнопка-подтверждение
ПоказB --> Результат: кнопка
Результат --> [*]: либо следующий раунд без перезапуска
Шаблон, в который подставляется любой способ ввода (энкодер, карточка, датчик расстояния) и любая обработка:
#include "stend.h"
int encoderDigit() {
return dialDeg() / 45 + 1;
}
void waitPress(Btn b = BTN_R) { // ждать нажатие И отпускание — иначе одно нажатие сработает дважды
while (!pressed(b)) delay(10);
while (pressed(b)) delay(10);
}
void show(int v) {
Serial.println(v);
screen(String(v));
delay(5000); // «не менее 5 секунд» — требование регламента
}
int vvod(const char* imya) {
Serial.printf("Вводите %s и нажмите правую кнопку\n", imya);
waitPress(BTN_R);
int v = encoderDigit();
show(v); // вывод введённого значения — это баллы!
return v;
}
void setup() {
Serial.begin(115200);
stendBegin();
int a = vvod("A");
int b = vvod("B");
waitPress();
show(a + b); // здесь любая обработка
}
void loop() {}Три системных правила, которые дают баллы: вывод каждого введённого значения — в таблицах Заданий 2–4 за это отдельные строки по 5 баллов; удержание вывода ≥5 с — прямое требование Задания 3; никаких перезапусков внутри задачи, если регламент их не разрешил.
Двухразрядное число (компетенция 2.1): два последовательных ввода — десятки и единицы: chislo = d1 * 10 + d2. Генератор случайных чисел: random(-5, 6) — верхняя граница в Arduino не входит — обязательно сразу вывести на экран/консоль, это оцениваемое событие.
Практика
Собрать автомат «A, B → сумма»
По шаблону: ввод энкодером, подтверждение правой кнопкой, вывод каждого значения на 5 с.
Двухразрядное число
Ввести 47: десятки → кнопка → единицы → кнопка → «47» на экране.
ГСЧ в диапазоне
По кнопке — случайное число от −5 до 5 на экран (заготовка Задания 4). Проверить, что выпадают и отрицательные, и ноль.
Контрольная точка: сдача Задания 1
Наставник — судья, полный протокол занятия 2, без перезапуска. Цель — 25/25.
Типичные ошибки
- Дребезг кнопки — одно нажатие засчитывается дважды, автомат перескакивает состояние. Лечится ожиданием отпускания (
waitPress). - Не вывели введённое значение — обработка верна, но 5-балльные строки «выведено значение A/B» потеряны.
- Вывод мигнул на полсекунды — судья не успел зафиксировать; держите ≥5 с.
- ГСЧ вне диапазона — перепутали
random(-5, 6)сrandom(-5, 5)(5 никогда не выпадет) или сrandom(0, 6). Диапазон — из условия дня, не из привычки.
Мини-проверка выхода
Задание 1 сдано на полный балл; блиц: «какие три события в Заданиях 2–4 оплачиваются по 5 баллов независимо от правильности вычисления?» (вывод A, вывод B, удержание вывода по протоколу)