4. Энкодер и кнопки: протокол ввода
Занятия 4–5. Энкодер и кнопки: протокол ввода судьи
Занятие 4. Энкодер как устройство ввода
Цель занятия: обучающиеся вводят цифру 1–8 поворотом стрелки на шкале с 8 делениями.
Разминка-вспоминание (5 мин)
- Первое действие с датчиком освещённости на новом месте?
- Как гасятся выбросы датчика? (интервальный возврат: занятие 2)
- Стенка на 12 см, порог 15 см — что выведет Задание 1: 0 или 1?
Разбор (worked example): шкала 8 делений
Конструкция (компетенция 7): неподвижный картонный круг на раме, размечен на 8 секторов по 45° с цифрами 1–8; на оси мотора — стрелка. Регламент разрешает крутить стрелку вручную — мотор работает как энкодер: программа читает абсолютный угол оси.
Математика перевода угла в цифру: SPIKE отдаёт абсолютную позицию в диапазоне −180…179°. Приводим к 0…359 и делим на 45:
pos ← абсолютный угол оси # -180..179
если pos < 0: pos ← pos + 360 # теперь 0..359
цифра ← pos // 45 + 1 # сектора: 0-44°→1, 45-89°→2, … 315-359°→8from hub import port, button, light_matrix
import motor, runloop
ENC = port.A # мотор-ввод; шкалу клеим так, чтобы «1» начиналась от нулевой метки оси
def encoder_digit():
pos = motor.absolute_position(ENC) # -180..179
if pos < 0:
pos += 360
return pos // 45 + 1 # 1..8
async def main():
while True:
d = encoder_digit()
print("Ввод:", d)
await light_matrix.write(str(d))
await runloop.sleep_ms(150)
runloop.run(main())Разбор: absolute_position привязана к физической метке на моторе — при сборке совместите стрелку с началом сектора «1» на нулевой метке, иначе введите программную поправку (pos = (pos - SDVIG) % 360); показ текущей цифры в реальном времени — обязательная часть UX: судья и участник видят, что вводится, до подтверждения.
absolute_position с одним условием. Диапазоны из регламента (0–90 → 1, 91–180 → 2, …) — тот же приём с делителем 90 вместо 45.Практика
Изготовить шкалу
Круг из картона, 8 равных секторов (транспортир: 45°), цифры крупно по краю. Закрепить на раме, стрелку — на ось.
Совместить ноль
Добиться, чтобы «1» читалась во всём своём секторе: покрутить стрелку по границам секторов, при рассинхроне добавить программную поправку.
Ввести серию
Партнёр называет цифры — вводите поворотом. «Введи 3, 7, 1» — три из трёх на экране.
Мини-проверка выхода занятия 4
Ввод трёх названных цифр подряд без промаха; вопрос: «почему pos // 45 + 1, а не pos / 45?»
Занятие 5. Кнопки, автомат ввода, ГСЧ — и сдача Задания 1
Цель занятия: обучающиеся реализуют конечный автомат «команда судьи → ввод → подтверждение кнопкой → вывод» без перезапуска программы.
Разминка-вспоминание (5 мин)
- Стрелка на 200° при шкале из 8 секторов — какая цифра?
- Что будет, если не ждать отпускания кнопки?
- Из чего складываются 25 баллов Задания 1?
Разбор (worked example): автомат ввода
Все мини-задачи регламента устроены одинаково — это конечный автомат:
stateDiagram-v2
[*] --> Ожидание: старт программы
Ожидание --> ВводA: команда судьи
ВводA --> ПоказA: кнопка-подтверждение
ПоказA --> ВводB: команда судьи
ВводB --> ПоказB: кнопка-подтверждение
ПоказB --> Результат: кнопка
Результат --> [*]: либо следующий раунд без перезапуска
Шаблон, в который подставляется любой способ ввода (энкодер, карточка, датчик расстояния) и любая обработка:
from hub import port, button, light_matrix
import motor, runloop, random
ENC = port.A
def encoder_digit():
pos = motor.absolute_position(ENC)
if pos < 0:
pos += 360
return pos // 45 + 1
async def wait_press(b=button.RIGHT):
while not button.pressed(b):
await runloop.sleep_ms(10)
while button.pressed(b):
await runloop.sleep_ms(10)
async def show(v):
print(v)
await light_matrix.write(str(v))
await runloop.sleep_ms(5000) # «не менее 5 секунд» — требование регламента
async def vvod(imya):
print("Вводите", imya, "и нажмите правую кнопку")
await wait_press(button.RIGHT)
v = encoder_digit()
await show(v) # вывод введённого значения — это баллы!
return v
async def main():
a = await vvod("A")
b = await vvod("B")
await wait_press()
await show(a + b) # здесь любая обработка
runloop.run(main())Три системных правила, которые дают баллы: вывод каждого введённого значения — в таблицах Заданий 2–4 за это отдельные строки по 5 баллов; удержание вывода ≥5 с — прямое требование Задания 3; никаких перезапусков внутри задачи, если регламент их не разрешил.
Двухразрядное число (компетенция 2.1): два последовательных ввода — десятки и единицы: chislo = d1 * 10 + d2. Генератор случайных чисел: random.randint(-5, 5) — обязательно сразу вывести на экран/консоль, это оцениваемое событие.
Практика
Собрать автомат «A, B → сумма»
По шаблону: ввод энкодером, подтверждение правой кнопкой, вывод каждого значения на 5 с.
Двухразрядное число
Ввести 47: десятки → кнопка → единицы → кнопка → «47» на экране.
ГСЧ в диапазоне
По кнопке — случайное число от −5 до 5 на экран (заготовка Задания 4). Проверить, что выпадают и отрицательные, и ноль.
Контрольная точка: сдача Задания 1
Наставник — судья, полный протокол занятия 2, без перезапуска. Цель — 25/25.
Типичные ошибки
- Дребезг кнопки — одно нажатие засчитывается дважды, автомат перескакивает состояние. Лечится ожиданием отпускания (
wait_press). - Не вывели введённое значение — обработка верна, но 5-балльные строки «выведено значение A/B» потеряны.
- Вывод мигнул на полсекунды — судья не успел зафиксировать; держите ≥5 с.
- ГСЧ вне диапазона — перепутали
randint(-5, 5)crandint(0, 5)илиrandom() * 5. Диапазон — из условия дня, не из привычки.
Мини-проверка выхода
Задание 1 сдано на полный балл; блиц: «какие три события в Заданиях 2–4 оплачиваются по 5 баллов независимо от правильности вычисления?» (вывод A, вывод B, удержание вывода по протоколу)