Занятие 4. Энкодеры: точный проезд S см (задачи 4.3–4.4)
Занятие 4. Точное перемещение на S см (мини-задачи 4.3–4.4)
Цель занятия: обучающиеся проезжают вперёд/назад заданное судьёй расстояние S по энкодерам с допуском ±2 см на метр.
Разминка-вспоминание (5 мин)
- Почему путь за фиксированное время «плавает»? (2 причины из вчерашнего эксперимента.)
stopBrakevsstopCoast— что для точной остановки?- Из карты конфигурации: ваши D и N_т?
- Почему тики считаем в прерываниях, а не опросом?
Теория: единственная формула пути
За один оборот колесо проходит длину окружности πD и энкодер даёт N_т тиков. Значит:
- мм на тик:
m = πD / N_т(пример: π·65/20 ≈ 10,2 мм/тик); - тиков на путь S:
T = S / m = S · N_т / (πD).
Разрешение системы = m: точнее, чем ±m/2, по энкодерам остановиться нельзя в принципе. Если m > 10 мм и нужен «олимпиадный» допуск ±1 см — увеличиваем N (диск с большим числом прорезей, ловим оба фронта) или уменьшаем D. Это инженерное решение, а не программное.
Разбор (worked example): проезд S мм с ровным курсом
Наивное решение (ехать, пока тики < T) страдает дважды: робота уводит вбок (моторы не одинаковы) и он проскакивает цель (тормозной путь). Эталон лечит оба:
// Проезд S мм вперёд (S<0 — назад). Использует только HAL.
void driveMM(float S_mm) {
const float m = 10.2; // мм/тик из карты калибровки
long T = fabs(S_mm) / m; // целевые тики
int dir = (S_mm >= 0) ? 1 : -1;
const int PWM_MAX = 170, PWM_MIN = 70; // ниже PWM_MIN мотор не страгивается — измерить свой!
const float KP_SYNC = 3.0; // сила выравнивания курса
resetTicks();
while ((ticksL() + ticksR()) / 2 < T) {
long tl = ticksL(), tr = ticksR();
// --- 1. Трапеция скорости: последние 25% пути — замедление до PWM_MIN
long done = (tl + tr) / 2;
int pwm = PWM_MAX;
if (T - done < T / 4)
pwm = PWM_MIN + (PWM_MAX - PWM_MIN) * (T - done) / (T / 4);
// --- 2. Синхронизация: кто уехал вперёд — того притормозить
int corr = KP_SYNC * (tl - tr); // >0: левый обогнал
drive(dir * (pwm - corr), dir * (pwm + corr));
}
stopBrake();
}Построчный разбор с группой обязателен (это worked example ДО самостоятельной попытки):
- среднее тиков двух колёс — путь центра робота: даже если колёса шли неровно, центр проехал сколько нужно;
- трапеция: на PWM_MIN тормозной путь почти нулевой → остановка точная; без замедления робот на PWM_MAX проскакивает на 2–5 см;
- corr: П-регулятор прямолинейности. Разница тиков
tl−tr— это уже «энкодерный компас»: если она растёт, робот дугой уходит вправо/влево.
Практика
Калибровка m (уточнение расчётного значения)
Проехать driveMM(1000) три раза, измерить фактический путь рулеткой от одной и той же точки корпуса. Новое m = m_старое × (факт / 1000), среднее по трём заездам. Внести в карту калибровки с датой.
Подобрать PWM_MIN своего робота
Плавно поднимать мощность с 40 до страгивания с места — это и есть минимальная рабочая мощность; +10 запаса.
Сдать 4.3 и 4.4 по протоколу
Судья задаёт S (например, 47 см и 83 см — не круглые!). Три попытки, отклонение рулеткой в журнал.
Проверка прямолинейности
driveMM(2000) вдоль клейкой ленты на полу: боковой снос на 2 м ≤ 3 см. Если больше — крутить KP_SYNC (снос) или искать механику (датчик/колесо люфтит).
Типичные ошибки:
- калибровка m на столе, заезд на поле — покрытие меняет проскальзывание; калибруемся на том, на чём ездим;
- измерение пути «от разных точек корпуса» до и после — фантомная ошибка ±2 см; метка на бампере, мерим от метки;
- KP_SYNC слишком большой — робот «виляет рыбой»: уменьшить вдвое;
- щелевой датчик ловит дребезг на границе прорези (тики сыплются на стоящем роботе) — в HAL добавить минимальный интервал между прерываниями (например, игнор повторного фронта в течение 1–2 мс) или подтяжку/триггер Шмитта.
Мини-проверка выхода
Заезд на S от судьи в допуске ±2 см/м + вопрос: «регламент завтра поменяет S с 50 на 68 см — что меняется в вашем коде?» (правильно: ничего, S — аргумент функции; константы берутся из калибровки).