Skip to content
4. Энкодер и кнопки: протокол ввода

4. Энкодер и кнопки: протокол ввода

Занятия 4–5. Энкодер и кнопки: протокол ввода судьи

Занятие 4. Энкодер как устройство ввода

Цель занятия: обучающиеся вводят цифру 1–8 поворотом стрелки на шкале с 8 делениями.

Разминка-вспоминание (5 мин)

  1. Первое действие с датчиком освещённости на новом месте?
  2. Как гасятся выбросы датчика? (интервальный возврат: занятие 2)
  3. Стенка на 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°→8
from 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: судья и участник видят, что вводится, до подтверждения.

Компетенция 1.3.3 включает и вариант «положительный угол → 1, отрицательный → −1»: это то же чтение 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 мин)

  1. Стрелка на 200° при шкале из 8 секторов — какая цифра?
  2. Что будет, если не ждать отпускания кнопки?
  3. Из чего складываются 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.

Техника безопасности. Стрелку ввода крутить за стрелку, а не за ось мотора; при подтверждении кнопкой придерживать раму — сдвиг устройства ломает измерения расстояния в интегральных задачах.

Типичные ошибки

  1. Дребезг кнопки — одно нажатие засчитывается дважды, автомат перескакивает состояние. Лечится ожиданием отпускания (wait_press).
  2. Не вывели введённое значение — обработка верна, но 5-балльные строки «выведено значение A/B» потеряны.
  3. Вывод мигнул на полсекунды — судья не успел зафиксировать; держите ≥5 с.
  4. ГСЧ вне диапазона — перепутали randint(-5, 5) c randint(0, 5) или random() * 5. Диапазон — из условия дня, не из привычки.

Мини-проверка выхода

Задание 1 сдано на полный балл; блиц: «какие три события в Заданиях 2–4 оплачиваются по 5 баллов независимо от правильности вычисления?» (вывод A, вывод B, удержание вывода по протоколу)

Уровни сложности