Пришло еще одно письмо - заполните survey и получите код для бесплатной пересылки. Зачем мне два кода?
Занялся плотно почему робот для одного узла при подъезде с одной стороны получает одни координаты, а при подъезде с другой - другие. Причем никакие допуски особо ситуацию не спасают. Собственно, дело в геометрии. Так как центр вращения (точка вокруг которой вращается робот при поворотах) находится за сенсором линии, который и определяет конец сегмента, на расстоянии около 50мм, то добравшись до тупика и развернувшись, этот сенсор окажется уже на расстоянии 100мм от конца тупика. Ну, чуть меньше, снова из-за того же выбега. Пытался эти "коррекции" добавлять/отнимать в зависимости от типа перекрёстка, но лучше не стало. Пришлось делать "геометрически правильно". Обнаружив конец сегмента робот проезжает вперед на расстояние от центра вращения до сенсоров ( чтобы центр вращения оказался именно над концом сегмента) и только тогда выполняет маневр. К размеру следующего сегмента сразу же добавляется это расстояние, так как сенсор уже находится на расстоянии 50мм от "перекрёстка". Теперь, робот движется правильно, как правило.
Проблема всплыла в неожиданном месте - там где нет перекрёстка, а просто поворот. Перекрёсток, тупик и поворот детектируются по такому алгоритму: если все датчики показывают белое - конец сегмента - тупик. Если сработал один или два боковых датчика - конец сегмента - перекрёсток или поворот. причем, в зависимости от срабатывания левого или правого или обоих определяем куда на перекрёстке/повороте есть выход. Дальше едем вперед, до тех пор, пока оба боковых датчика не окажутся над белым полем, тогда если центральные находятся всё еще над линией - значит есть и ход прямо. Так вот, в этом последнем моменте и есть ошибка, так как если робот подходит к повороту немного под углом с внутренней стороны, то боковой сенсор уже освободился, а центральный еще находится над "углом" поворота и алгоритм даёт ложную информацию, что есть ход прямо, хотя на самом деле никакого прямого хода там нет. Пришлось сделать задержку на эту последнюю проверку в 25мс - что при небольших углах входа в перекрёсток оказалось достаточно для надёжного определения типа перекрёстка.
Еще один момент который пришлось стереть и написать по-новой - это выполнение поворота. Когда я взялся за модернизацию разворота на перекрёстках, начал смотреть что я написал до этого... и не мог понять тот бред, что там был написан. Суть выполнения поворота в том, что надо сенсорами линии отследить ту линию, которая "приплывёт" сбоку и остановиться, так, чтобы она была примерно по центру. Самый простой вариант - отлавливать "фронт" и/или "спад" уровня на одном из датчиков сенсора линии. Я для этого использую третий датчик от края. Т.е. отсчитываю переходы уровня от черного к белому и наоборот. Должно произойти ровно два перепада. Первый - появилась линия, второй - линия ушла, предполагая, что она теперь в районе 4 и 5 сенсора от края, т.е. под центральными сенсорами (пятый сенсор - это уже четвёртый с другого края). Судя по исходнику, я пытался отловить только фронт, восстановив еще более раннюю версию, вроде, и фронт, и спад, но как-то странно. Поэтому переписал. Поворот/разворот же я контролирую по таходатчику. Т.е. найдя линию я смотрю на сколько градусов робот повернулся. если до 135 градусов - значит только на 90 и для поворота достаточно, а для разворота надо продолжить искать следующую линию. При этом, думал, как делать разворот - через левое плечо, как в армии, или как-то иначе? Когда, робот в лабиринте выполнял алгоритм "рука ведет по стене", я разворот выбирал так, чтобы соответствующая рука продолжала вести по "виртуальной стене" (или "виртуальная рука" по реальной стене). Т.е. если правая рука то разворачиваемся влево, а если левая, то вправо. Но тут я применил другой алгоритм - представил себя, бегущего по лабиринту, и как бы я забегал бы в тупик и там разворачивался бы. И подумал, что мне было бы сподручнее разворачиваться в ту же сторону, в которую я в этот тупик забежал - т.е. робот разворачивается в ту же сторону в которую перед этим поворачивал.
Так что в итоге оказалось - делать поворот только контролируя линию - не достаточно. Делать поворот только по таходатчикам - тоже не очень хорошо. Нормальный результат получился только учитывая оба источника информации - сенсора линии и таходатчика.
Сейчас оба робота боле-менее нормально проходят лабиринт, при условии, если подходят к перекрёсткам боле-менее ровно. А вот на это уже влияет ПИД регулировка, удерживающая робота на линии, пока он идёт по сегменту между узлами. И тут снова есть проблемы...
Проблема в этих несчастных коэффициентах. Они какие-то нелинейные. Т.е. если при заданной скорости удалось что-то подобрать, то изменив скорость, оказывается, что они уже не работают. Т.е. нет линейной зависимости между отклонением от линии и мощностью подаваемой на двигатели. А если это не так, то похоже, снова приходим к необходимости строить трёхконтурную обратную связь. Но это я еще подумаю...
С другой стороны, заметил, что RSLK-MAX линию держит хуже, чем старый RSLK. Как по мне, причина (одна из) в том, что сенсор находится в два раза ближе к оси - 25мм против почти 50мм. А это значит, что при одинаковом отклонении от линии означает что MAX при этом имеет отклонение почти в два раза больше. И если бы не та фишка, что я использую для центральных сенсоров регистры захвата, чтобы знать не только черное поле или нет, но и насколько черное, чтобы по отношению уровней этих сенсоров немного линеаризировать показания. Но что там линеаризируешь, если всё равно есть позиции, где сенсоры заходят в насыщение и сенсор не может сказать есть отклонение или нет на участке в несколько миллиметров от центра линии. Тем более, что порог срабатывания сенсоров RSLK-MAX стоит на 800 мкс, а "насыщение" наступает на 1024-й мкс. Можно сказать, что используется от силы 20% динамического диапазона сенсора. Поэтому, я решил увеличить в два раза - до 2048 мкс. Ну это легко делается - в парочке мест поправил сдвиги. Попутно решил избавиться от 10мкс задержки внутри прерывания - задействовал второй канал захвата/сравнения таймера.
Кстати, вспомнил, где я видел информацию, что этот сенсор должен быть на высоте 3мм от поверхности. Это было написано в 6-й лабораторной работе.
The optimal sensing distance for this sensor strip is 3 mm (0.125"). The distance
between the line sensor and the floor should be about 3 mm. During this lab,
you could use two 3 mm objects attached to each end of the sensor to set the
distance and make it parallel. A better approach would be to mount the sensor on
the bottom of your robot (if you have purchased the kit and build it in lab 5) again
positioning the sensor parallel to the floor 3 mm above the floor.
Вот только аттачнув сенсор к роботу ну никак 3 мм не получается. Взял гайку М3 (5.5мм) поставил на торец и сверху робота - еще остаётся зазор. И это при том, что я сенсор не втыкаю до конца. Если воткнуть до конца в гнездо то и гайка М6 там пролезает, а это 10 мм! Ну да ладно, почитал лабу - посмотрел всё ли они про этот сенсор правильно написали. Ага, в одном месте пропустили, что подсветка включается отдельно для четных и нечетных сенсоров. И как обычно - включить-выключить... Правда, я тут подумал, что включать подсветку нужно не перед зарядом конденсатора, а после. Хотя делитель 220 ом и освещенный фотодатчик не будет иметь сильное отклонение от неосвещенного фотодатчика, но зачем же зря тратить ток? Но вот о чем не было написано, так это о том, что в датчиках серии QTR
X применен драйвер светодиода. Поэтому, если при смене питания на сенсорах QTR надо было запаивать или удалять перемычку, то у QTRX ничего делать не нужно - ток через светодиоды будет идти одинаковый. Но, у этого драйвера есть еще одна фича - он позволяет установить и меньший ток (32 градации). И это делается через тот же сигнал включения-выключения:
For more advanced use, the CTRL pin can be pulsed low to cycle the associated emitters through 32 dimming levels. To send a pulse, drive the CTRL pin low for at least 0.5 μs (but no more than 300 μs), then high for at least 0.5 μs; (it should remain high after the last pulse). Each pulse causes the driver to advance to the next dimming level, wrapping around to 100% after the lowest-current level. Each dimming level corresponds to a 3.33% reduction in current, except for the last three levels, which represent a 1.67% reduction, as shown in the table below. Note that turning the LEDs off with a >1 ms pulse and then back on resets them to full current.
Так вот... я выключаю светодиод на 350 мкс и всё-равно этот драйвер это воспринимает как импульс для перехода на следующий уровень затемнения. Для надёжного выключения надо бы выключать на 1 мс, но у меня уже нет столько времени: период опроса 2.5мс, время измерения теперь 2.048 мс - остаётся всего 0.452 мс - серая зона.