Skip to content
Занятие 4. Энкодеры: точный проезд S см (задачи 4.3–4.4)

Занятие 4. Энкодеры: точный проезд S см (задачи 4.3–4.4)

Занятие 4. Точное перемещение на S см (мини-задачи 4.3–4.4)

Цель занятия: обучающиеся проезжают вперёд/назад заданное судьёй расстояние S по энкодерам с допуском ±2 см на метр.

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

  1. Почему путь за фиксированное время «плавает»? (2 причины из вчерашнего эксперимента.)
  2. stopBrake vs stopCoast — что для точной остановки?
  3. Из карты конфигурации: ваши D и N_т?
  4. Почему тики считаем в прерываниях, а не опросом?

Теория: единственная формула пути

За один оборот колесо проходит длину окружности π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 — аргумент функции; константы берутся из калибровки).