Кратко — основная идея: не пытаться «поймать» мгновенный пик перехода в одном сэмпле, а сделать детектирование устойчивым через калибровку, фильтрацию, гистерезис и подтверждение по времени/пройденному пути (энкодерам) и/или второму датчику. Ниже — конкретные приёмы и примерный алгоритм.
1) Аппаратные рекомендации
- Используйте датчики с собственной подсветкой (IR-эмиттер + приёмник) и, если можно, синхронную детекцию (модуляция), чтобы отбросить влияние внешнего света.
- Узкая апертура / экран вокруг датчика уменьшит «полосу захвата» и смягчит переходные зоны.
- Расстояние между датчиками и ширина зоны их чувствительности должны соизмеряться с размером клеток. Если клетка ~x мм, ставьте датчики так, чтобы при идеальном центре робота оба датчика могли одновременно «видеть» одну клетку и четко реагировать на переход.
2) Калибровка
- На старте (или периодически) измерьте значения на чистой белой и чистой чёрной клетке при текущем освещении: B (black) и W (white).
- Нормируйте показания: r = (raw - B)/(W - B) → значение в ~[0,1]. Это устраняет зависимость от абсолютной яркости и позволяет выбирать пороги.
3) Порог с гистерезисом
- Не один порог, а два: high и low. Пример: mid = 0.5; high = mid + 0.08; low = mid - 0.08 (параметры надо подгонять).
- Состояние меняется на «белое» только если r > high, и на «чёрное» только если r < low. Это исключает дребезг когда r гуляет вокруг середины.
4) Фильтрация и дебаунс
- Применяйте сглаживание (скользящее среднее или экспоненциальное сглаживание) для подавления шума.
- Порог подтверждайте по времени или пройденному пути: состояние должно держаться N сэмплов подряд или N тиков энкодера. Примеры: 5–20 сэмплов при 100–200 Hz или 1–5 мм пройденного пути (в зависимости от размера клетки).
- Вместо «N сэмплов подряд» можно проверять, что среднее/медиана последних M сэмплов принадлежит новому диапазону.
5) Детектирование границы через производную
- При переходе значение r меняется резко. Можно вычислять d = r(t) - r(t-1) и при d > D_thresh или d < -D_thresh помечать потенциальный переход. Но и здесь требуйте подтверждения по нескольким сэмплам/энкодеру, чтобы не реагировать на шум.
6) Использование двух датчиков вместе
- Разница L-R даёт позицию линии: если оба в «одном» состоянии → робот над целой клеткой; если один в белом, другой в чёрном → граница между клетками под роботом.
- Для детектирования смены сегмента полосы (когда полоса меняет цвет каждую клетку) логика: отслеживать момент, когда тот же датчик сменил состояние (чер→бел или бел→чер) с подтверждением по времени/пути. Второй датчик помогает понять направление и момент, когда переход происходит через центр (например, левый переключился раньше правого → известна позиция границы).
7) Дополнительные приёмы
- Используйте «маску по расстоянию»: если датчик видит смесь (частично чёрно, частично бело) — raw будет средним; это нормально, поэтому ждите устойчивого нового уровня.
- Геометрическая проверка: ожидайте переходы через примерно равные интервалы (клетка/номер). Если переходы происходят с частотой, не соответствующей скорости+размеру клетки, сигнал подозрителен.
- Используйте энкодеры/IMU: совмещайте детекции с пройденным расстоянием — если детекция случилась через слишком малый/большой шаг, проигнорировать как ложную.
- Если доступна цветность (RGB) — используйте отношение каналов (R/G/B) вместо абсолютной яркости; это более устойчиво к освещению.
- При сильных проблемах — камера + простая бинаризация/контур/центроид даст гораздо более надёжный результат, но дороже по процессингу.
8) Примерный псевдокод (для одного датчика + энкодера)
- Calibrate: measure B, W; mid=(B+W)/2; low=mid-Δ; high=mid+Δ.
- smoothing S = EMA(raw).
- if S > high then candidateState = WHITE else if S < low then candidateState = BLACK else candidateState = UNKNOWN.
- if candidateState == lastCandidateStateCounterState then counter++ else counter=0.
- if counter >= N_samples OR encoder_ticks_since_last_change >= N_ticks then confirm state change: lastState = candidateState; reset encoder_ticks_since_last_change.
- Use lastState for логики движения.
9) Параметры для старта (пример)
- Частота опроса: 100–200 Hz.
- EMA α = 0.2–0.4 или MA window = 5–15 сэмплов.
- Гистерезис Δ = 0.06–0.12 (в нормированном [0,1]).
- Подтверждение: 5–15 сэмплов или 2–6 мм по энкодеру.
Если хотите, могу:
- Подобрать конкретные значения Δ, N_samples под ваш размер клетки, скорость и тип датчиков;
- Написать пример кода на Arduino/C/C++/Python для ваших датчиков (укажите модель датчика и контроллер);
- Предложить схему для синхронного ИК-излучения и приёма, чтобы избавиться от внешнего света.