2. Датчик расстояния: пороги и зоны
Занятие 2. Датчик расстояния: пороги, зоны, Задание 1
Цель занятия: обучающиеся по показанию датчика выводят 0/1 относительно порога и номер зоны 1–6, используя фильтрацию показаний.
Разминка-вспоминание (5 мин, без подглядывания)
- Сколько попыток даётся на каждую мини-задачу и какая идёт в зачёт?
- Что вернёт датчик расстояния, если перед ним нет объекта?
- Почему датчик стоит заподлицо с передним краем рамы?
Затем квиз по регламенту (контрольная точка, цель 1, 7 вопросов): комплектация устройства; размер стенки; значение белой/чёрной карточки; можно ли перезапускать программу в Задании 1; ширина и цвет стартовой линии; сколько мини-задач в итоговом задании; куда разрешён вывод результата.
Разбор (worked example): полное решение Задания 1 регламента — 25 баллов
Условие (Приложение 1). Стенка ставится перед роботом — её положение задаёт порог; порог вывести в см (5 баллов). Судья дважды переставляет стенку (не ближе ±2 см к порогу); после каждой перестановки по нажатию кнопки вывести 0, если стенка ближе порога, 1 — если дальше (по 10 баллов). Программа работает без перезапуска.
Алгоритм
flowchart TD
S[Старт программы] --> W1[Судья ставит стенку]
W1 --> M[Измерить порог: медиана 7 показаний, перевести в см]
M --> P[Вывести порог на экран/консоль]
P --> B1[Ждать кнопку 1-й раз]
B1 --> D1[Измерить медиану → d1]
D1 --> C1{d1 > порог?}
C1 -- да --> O1[Вывести 1]
C1 -- нет --> Z1[Вывести 0]
O1 --> B2[Ждать кнопку 2-й раз]
Z1 --> B2
B2 --> D2[Измерить медиану → d2]
D2 --> C2{d2 > порог?}
C2 -- да --> O2[Вывести 1]
C2 -- нет --> Z2[Вывести 0]
Два решения регламент делает нетривиальным: (а) одиночное показание ультразвука шумит — берём медиану нескольких измерений; (б) «без перезапуска» — значит одна программа с состояниями, порог хранится в переменной всю дорогу.
Эталонный код (SPIKE 3, Python)
from hub import port, button, light_matrix
import distance_sensor, runloop
DIST = port.C
def median_sm(n=7):
"""Медиана n корректных показаний, в сантиметрах."""
vals = []
while len(vals) < n:
d = distance_sensor.distance(DIST)
if d > 0: # -1 = объект не виден, пропускаем
vals.append(d)
vals.sort()
return round(vals[n // 2] / 10) # мм -> см
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(value):
print(value) # консоль — основной канал для судьи
await light_matrix.write(str(value))
async def main():
# --- Этап 1: фиксация порога (5 баллов) ---
await runloop.sleep_ms(3000) # судье время поставить стенку
porog = median_sm()
await show(porog) # порог в см на экран/консоль
# --- Этапы 2 и 3: два сравнения (по 10 баллов), без перезапуска ---
for _ in range(2):
await wait_press() # судья переставил стенку, мы жмём кнопку
d = median_sm()
await show(1 if d > porog else 0)
runloop.run(main())Построчный разбор ключевых мест: медиана из 7 устойчива к одиночным выбросам и к моменту, когда рука судьи ещё в кадре; wait_press ждёт отпускания — без этого цикл for проглотит оба сравнения за одно длинное нажатие; зазор ±2 см в регламенте гарантирует, что честная медиана не попадёт «на ребро» порога, поэтому строгое > корректно; пауза 3 с в начале — судья должен успеть поставить стенку после запуска (можно заменить ожиданием кнопки, согласовав с судьёй процедуру).
Практика
Воспроизвести Задание 1
Партнёр играет судью: ставит стенку, переставляет, командует. Сдать по протоколу: порог → кнопка → 0/1 → кнопка → 0/1, без перезапуска. Сверить с таблицей: 5 + 10 + 10.
Зоны 1–6 (компетенция 1.3.1)
Поле А4 (длина ≈ 30 см) размечено на N равных зон (регламент: от 2 до 6). Откалибровать границы: поставить стенку на каждую линию разметки, записать медианные показания, пороги взять посередине между соседними. Код зоны для N=6:
GRAN = [5, 10, 15, 20, 25] # см, откалиброванные границы зон 1..6
def zona(d_sm):
z = 1
for g in GRAN:
if d_sm > g:
z += 1
return z # 1..6Вывести номер зоны по нажатию кнопки. Проверка: партнёр ставит стенку в случайную зону 5 раз — 5 верных ответов.
Наличие объекта и высота (1.3.1)
«Наличие»: 1 if 0 < d <= 40 см else 0 — граница по дальнему краю поля. «Высота»: призма стоя (21 см) видна датчику на высоте 10 см, лёжа (9 см) — нет; вывод «высокий/низкий» по наличию эха. Реализовать оба, сдать партнёру.
Типичные ошибки
- Одно показание вместо фильтра — первая попытка проходит, вторая ловит выброс. Признак: «дома работало».
- Сравнение в миллиметрах с порогом в сантиметрах — всегда
1. Приводите единицы в одном месте (median_sm). - Нет ожидания отпускания кнопки — оба сравнения улетают за одно нажатие, теряете 10 баллов.
- Перезапуск между сравнениями — прямое нарушение условия, попытка не засчитывается.
- Калибровка зон «по линейке», а не по датчику — датчик меряет до ближайшей отражающей точки стенки, а не до линии на бумаге; границы берите только из реальных показаний.
Мини-проверка выхода
«Зона за 30 секунд»: наставник ставит стенку — команда называет зону с экрана устройства за ≤30 с, три постановки подряд без ошибок. Плюс вопрос: «зачем в Задании 1 запрет ставить стенку ближе ±2 см к порогу?»