Вот про типы корпусов для PSoC6 я и не посмотрел. Ну это просто для интереса. Пока с ним ничего не планирую (как было и с MSP432). Хочу только подстраховаться. А то попытался экстраполировать обработку 8 фото сенсоров на 128 сенсоров ПЗС линейки и, возникло странное предчувствие. Ожидаю большую проблему в различии освещенности "кадра". Надо будет, вероятно, через первые производные картинку анализировать. Но это позже.
30 000 rpm - это именно мотор робота. Что в RSLK, что в LineFollower. Ну, может, в RSLK чуть по медленнее. Когда делал 17 лаб.работу и двигатель бесконтрольно разгонялся, у меня показывало более 220 rpm (колеса), что с учетом редуктора 1:120 даёт 26000 rpm мотора. В LineFollower использую моторы
Pololu micro metal gear и, если посмотреть на параметры, то мощные моторы (HP - High Power) имеют от 31000 до 33000 rpm. Но в данном случае проблему вызывает нижняя граница. По книжке Валвано получается (и у меня получились похожие результаты), что постоянная времени двигателя (с редуктором и колесом) около 100мс. Следовательно, частота вызова ПИ контроллера должна быть раз в 10 больше - выбираем около 10мс. Далее время измерения периода следования импульсов таходатчика. Желательно, обеспечить ПИ контроллер свежими данными, поэтому 12МГц и 16 бит обеспечивают 5.461мс - вполне приемлемый вариант. Уменьшать разрядность нельзя, так как rpm к периоду - обратная функция и при малых значениях шаги будут очень грубыми. Вот и сейчас получается диапазон от 8000 до 65535. В предыдущем сообщении я не верно выбрал частоту. 3 Кгц там не будет. Оказалось, что несмотря на то что магнитный диск 6-полюсный, датчики дают только 3 импульса на оборот. Наверное, срабатывают только на одно направление магнитных линий, а на противоположное - не срабатывают. Ну так вот, что происходит со значением - 65535. Это 5.461 мс - период следования импульсов. Так как на оборот двигателя приходится 3 импульса, значит один оборот выполняется за 16.384 мс. Ну и делим 60 секунд на 16.384 = 3662 оборота в минуту. Это минимальные обороты. У робота для Line Follower двигатель имеет редуктор 1:10 - значит минимальные обороты 366 rpm, что при длине окружности колеса в 66 мм соответствует скорости около 40 см/с. Многовато. (у RSLK эти же обороты двигателя при редукторе 1:120 и окружности колеса 220 мм дают, соответственно, 31 rpm и 10 см/с (грубо)). Для опускания нижней границы, надо или увеличивать время измерения, что приведет к увеличению времени реакции двигателя, или увеличить число событий на один оборот. Второй вариант для RSLK тоже не особо приемлем, так как каждое событие должно обрабатывать прерывание - а это время! И вот если сейчас у меня прерывания могут вызываться с максимальной частотой 1.5 кГц, то при увеличении - эта частота соответственно увеличится. В PSoC, так как всё это происходит аппаратно, проблем никаких не должно вызвать. Проблему вызывает то, что для увеличения числа импульсов, можно последовательно выполнить следующие мероприятия: детектировать не только фронт, но и спад; использовать второй канал тоже. Но тут я прикинул, что если эти оба сигнала с энкодера объединить через исключающее ИЛИ, я могу использовать полученные фронты для измерения интервала между фронтом и спадом одного канала или если контролировать еще и спады, то получить всю максимальную разрешающую способность энкодера - 12 cpr (импульсов на оборот). Правда, с отлавливанием спадов есть проблема. Если EdgeDetect без проблем этот режим включается, то у таймера в режиме Fixed Function такой возможности нет. Она есть только у таймера в режиме UDB. Ну что ж, попробую на пробной платке проверить как этот режим пойдёт.
А тем временем, снова поймал пару раз робота на том, что он заблудился в лабиринте. Так как я уже был сделавши журналирование показаний сенсоров линии, т.е. эти данные собираются и даже записываются во флеш-память. Но вот удобного инструмента для просмотра так и нет. Вот и решил немного порешать этот вопрос. Во-первых изменил условие сохранения лог-файла. Теперь он сохраняется только в том случае, если робот завершает работу с ошибкой. А во вторых, к функции, которая через UART сливает карту, добавил и передачу лог-файла в "интерпретированном" виде:
Спойлер
- Код:
17.2125,...**..., ,Segment
17.2150,...**..., ,Segment
17.2175,...**..., ,Segment
17.2200,...**..., ,Segment
17.2225,...**..., ,Segment
17.2250,...**.**, ,Segment
17.2275,...*****, ,Segment
17.2300,...*****, R,Solve
17.2325,...*****, R,Solve
17.2350,...*****, R,Solve
17.2375,...*****, R,Solve
17.2400,...*****, R,Solve
17.2425,...*****, R,Solve
17.2450,...*****, R,Solve
17.2475,...*****, R,Solve
17.2500,...*****, R,Solve
17.2525,...*****, R,Solve
17.2550,...*****, R,Solve
17.2575,...*****, R,Solve
17.2600,....****, R,Solve
17.2625,.....*.*, R,Solve
17.2650,........, R,Solve
17.2675,........, R,Solve
17.2700,........, R,Solve
17.2725,........, R,Solve
17.2750,........, R,Solve
17.2775,........, R,Solve
17.2800,........, R,Solve
17.2825,........, R,Solve
17.2850,........, R,Solve
17.2875,........, R,Solve
17.2900,........, R,Solve
Current index = 15 , Coord X = 0 , Coord Y = 0
17.2925,........, R,Solve
17.2950,........, R,Solve
17.2975,........, R,Solve
17.3000,........, R,Solve
17.3025,........, R,Solve
17.3050,........, R,Solve
17.3075,........, R,Solve
17.3100,........, R,Solve
17.3125,........, R,Solve
17.3150,........, R,Solve
17.3175,........, R,Solve
17.3200,........, R,Solve
17.3225,........, R,Solve
17.3250,........, R,Solve
17.3275,........, R,Solve
17.3300,........, R,Solve
17.3325,........, R,Solve
17.3350,........, R,Solve
17.3375,........, R,Solve
17.3400,........, R,Solve
17.3425,........, R,Solve
17.3450,........, ,Turn
Первое поле - время в секундах, второе поле - показания сенсора линии: "*" - черное, "." - белое, затем флаги найденных поворотов: левый, прямо, правый и в конце имя функции где программа находится: в главной Solve_Maze или в функциях Run_Segment или Turn. На показанном примере видно, что робот идёт по сегменту довольно ровно - линия под центральными датчиками, потом появляется что-то черное с правого края и когда это зафиксировано два отсчета подряд функция завершается и управление возвращается в главную функцию Solve_Maze на 17.23 секунде. Она начинает определять конфигурацию узла. на 17,2650 пропал сигнал с бокового датчика, но робот продолжает двигаться еще 10 отсчетов, чтобы выяснить, есть ход прямо или нет (хм, тут видно, что я могу быстрее отказаться от поиска, если это поворот, а не T-образный перекрёсток). И тогда, программа назначает номер этому узлу - 15. Правда, координаты тут указаны нулевые, потому как я это добавил позже и этой информации в лог-файле нет. Далее, робот движется еще некоторое время вперед, чтобы центр робота оказался над центром перекрёстка(поворота или тупика) и на 17,345 секунде управление отдаётся функции поворота, которая будет выполнять поворот.Этот лог-файл показал, что всё работает верно, а "заблудовка" случилась потому, что робот не опознал возврат на узел 3, а присвоил новый номер - 10 (на трассе сейчас всего 9 узлов). Поэтому, еще сделал чтобы в лог-файл писались и координаты узлов и , думаю, надо сделать запись длин пройденных сегментов. Если с геометрией сейчас должно быть боле-менее нормально, то теперь причина в "непопадании" координат может быть проскальзывание колёс при старте. Всё же этот ПИ контроллер старается выполнить "заявку сверху" максимально быстро и точно. Поэтому если ему задано крутиться 110 rpm, он с места и пытается на все 110 рвануть. Так что теперь надо озаботиться более плавным разгоном. Хотя, у меня уже есть параметр acceleration. Сейчас, он позволяет увеличивать скорость на 1.28 rpm за 2.5 миллисекунды. Но толку от этого мало, так как ПИ контроллер реально что-то сможет делать только тогда, когда значение превысит 30.5 rpm - до этого момента поведение будет совершенно неадекватным. Надо еще думать.
Лог пишется до, примерно, 20 секунды. я выделил на это дело 16К памяти. правда, в конце идёт какая-то белиберда и не могу понять откуда этот мусор взялся. Может, опять стек наезжает куда не надо? Собственно, причина в том, что оба робота у меня валились в GPF в том, что размер стека был больше, чем Кейл под него выделял. А выделяет он всего 512 байт. И самое обидное, что стек размещается не в конце ОЗУ (как обычно принято), а сразу за последней глобальной/статической переменной отсчитал 512 байт и поставил вершину стека. И плевать, что у меня в какой-то функции есть автоматический массив на килобайт, а то и на 4. Сделал, как рекомендовали, добавление в листинг информацию об использовании стека. Сейчас утоптал память и получил:
- Код:
Maximum Stack Usage for __rt_entry_main 0x188 bytes.
Call chain for maximum stack usage:
__rt_entry_main => main => solveMaze => show_number => update_display => lcddatawrite
Т.е. теперь даже в дефолтные 0x200, возможно, укладываюсь, так как в этом репорте не показано, сколько стека отъедают вызовы прерываний. Да и компилятор не может этого сделать, так как во многих прерываниях используется CallBack. Так что никто не знает, куда оно по прерыванию дальше пойдёт.
Попутно узнал, что деление на 0 без специальных телодвижений GPF не вызывает. Но тем не менее, сделал маленький обработчик GPF, чтобы я знал, что робот туда ввалился - включает белый цвет на трёхцветном светодиоде и, главное, выключает двигатели.
p.s. Еще поанализировал логи, робот сбился потому, что один из сегментовпо которому ехал "на восток" , измерил на 28мм длиннее, чем параллельный, по которому ехал "на запад". А границу допуска я поставил 26мм. Вот и таким образом образовался "новый" узел. Правда, я измерил линейкой - тот второй, на 10мм длиннее сам по себе. Но закономерность заметил, что если робот входит на участок после поворота, результат измерения сегмента оказывается на 20-24 мм больше, чем если он попадает на этот же сегмент продолжая прямолинейное движение.