Thursday, September 29, 2011

miniEMC2 - что к чему.

Итак, почему именно Linux и EMC2? Начнем с того, что сделать сколько-нибудь приличный интерпретатор G-кода с нуля - задача не из простых и автор вряд-ли бы взялся за это в качестве хобби. Однако все-таки хотелось реализовать все попроще и дешевле. Ему даже удалось втиснуть урезанный EMC2 в простенький ARM7 без всякой ОС ( спасибо зарубежным товарищам, подробнее смотрите здесь ), но все-таки это его не устроило по разным причинам. И в первую очередь из-за того, что производительности и памяти хватало как раз впритык. Впрочем, это было уже более двух лет назад, возможно сейчас можно продолжить изыскания используя, например, последние Cortex-M3 от ST.  Но автору пришла мысль все-таки использовать полноценный EMC2 и более мощный процессор, ну и Linux конечно. Выбор остановился на mini2440 в виду ее широкой распространенности и небольшой цены. Первые эксперименты со сборкой EMC2 под эту платформу показали, что в режиме эмуляции реал-тайм производительности хватает с запасом ( это для EMC2 2.2.0, с версией 2.4.0 он уже не справился). Имеется ввиду, что работал только интерпретатор и интерполятор, HAL отключалась, GUI отсутствовала...работал только через TkEMC на ПК.  Далее встал вопрос - как же реализовать режим реального времени, чтобы  генерировать шаги с необходимой скоростью и точностью ? Решение пришло неожиданно. Просматривая исходный код ядра от gta02 автор обнаружил там интересный трюк, а именно обработчик FIQ от таймера. Fast Interrupt ( FIQ ) сродни обычным прерываниям, однако их скорость реакции несколько выше. И что самое главное, эти самые FIQ не имеют никакой инфраструктуры в Linux. IRQ обернуты в специальные обработчики и демультиплексоры и в любой части кода ядра их можно запретить. FIQ наоборот нигде не используются, не запрещаются и они не прерываются ни одним из обычных IRQ. Таким образом они вполне подходили на роль псевдо-системы жесткого реального времени. Замеренная скорость реакции была около 1-3 микросекунды, что было достаточно для начала экспериментов. Но это только часть проблемы, вторая часть заключалась в том, что надо обеспечить еще и менее жесткий реал тайм для вычисления траектории движения. Тут как раз все оказалось сложнее и долгое время не удавалось найти решение. Пока наконец разработчики Xenomai не добавили поддержку нашего процессора. Тесты показали время отклика процесса, использующего Xenomai, порядка 100 микросекунд при серьезной нагрузке на подсистему ввода/вывода. Это было очень неплохо и в результате была создана следующая структура EMC2 для mini2440:

Функциональная схема miniEMC2
Motion controller и IO controller это стандартные части EMC2, после них идет работа непосредственно с оборудованием. IO controller работает в User space, т.к. время реакции для него не очень критично. Motion controller это уже часть HAL ( в терминах EMC2) и должен работать в реальном времени, т.к. он генерирует поток координат для перемещения с периодом сервоцикла. Его обычно выбирают равным 1ms, т.е. точность попадания в этот цикл около +/-10% ( 100uS =10% от 1ms ). Этого все еще недостаточно для наших целей, поэтому пришлось ввести очередь координат. Но сначала давайте рассмотрим новый, нестандартный HAL компонент, который носит название miniemcdrv.so Это компонент специально предназначен для работы на нашей платформе. Он совместно с FIQ-обработчиком выполняет функции, которые на обычных ПК делают модули Stepgen вместе с Parport. Т.е. в задачи  miniemcdrv.so входит прием потока координат от Motion controller, формирование значений для синтезаторов частоты, PI-регулятор позиции.  Кроме того он обеспечивает опрос дискретных входов контроллера  ( GPIO ). Его основной цикл вызывается с периодом сервоцикла, т.е. через 1 ms. На самом деле период сервоцилка выбран чуть меньше, чем 1mS - это связано с "очередью координат".  Выходные данные miniemcdrv.so помещаются в специальную область разделяемой памяти и оттуда они доступны обработчику FIQ.  Последний вызывается с периодом 10uS обеспечивая тем самым максимальную скорость шагов на уровне 50 кГц. Внутри обработчика происходит непосредственно синтез частоты и управление всеми цифровыми выходами. Так-же он предоставляет текущую позицию для каждой координаты(т.е. число уже сделанных шагов), которая учитывается в PI регуляторе позиции miniemcdrv.so.
Теперь об "очереди координат" или точнее об очереди заданий для синтезаторов частоты. Собственно это такой буфер, в котором хранятся вычисленные и готовые к выполнению значения для генератора частоты. Если при возникнут непредвиденные задержки на уровне User space, то FIQ будет иметь какое-то количество работы выбирая данные из этого буфера. Это позволяет нам справиться c относительно большим временем реакции Xenomai. Этот буфер заполняется в miniemcdrv.so  до того, как успевает опустошаться в обработчике FIQ из-за чуть меньшей длительности сервоцикла. Когда буфер заполнен, miniemcdrv.so сигнализирует Motion controller временно приостановить вычисление координат.  
Как несложно догадаться, такая схема создает один недостаток, иногда весьма существенный: текущее положение двигателя всегда отстает от вычисленного на время, равном N*1ms. Где N - размер буфера. По умолчанию этот размер равен 32, т.е. задержка равна 32 mS. Это значение может быть уменьшено до 2. Если вы не планируете запись на SD или USB карту по FTP во время работы станка, то размер буфера можно смело устанавливать в 8 и менее. Если-же вы хотите большей защищенности вашей системы, то лучше его не менять. Когда чреват слишком большой размер буфера? Автор знает только одну сложность: позиционирование по конечным выключателям, т.е. когда станок продолжает движение в течение времени N*1ms, даже если сработал концевик. Если для вас крайне критично, чтобы 0 располагался именно там, где это задумано, то вам не стоит использовать это устройство. Если же допускается некоторый уход от заданной концевиком позиции, то думается что более проблем возникнуть не должно.
     Автор надеется, что немного прояснил особенности архитектуры системы. Теперь несколько слов о том, почему нет дисплея и тачскрина. Автор более всего хотел реализовать полностью автономное устройство, но увы все эксперименты провалились.  Сначала он работал с 3.5" экраном и реализовал небольшой GUI на QT2.3, но эксперименты на реальном оборудовании показали все неуместность столь крошечного дисплея с тачскрином и стилусом на производстве. В результате было решено использовать 7" дисплей. Но результаты оказались еще хуже. Из-за того, что он имел большое разрешение, отнималось порядка 30% пропускной способности у памяти. Плюс к тому контроллер тачскрина у чипа S3C2440 явно не рассчитан на такой большой дисплей. Выражалось это в том, что он ловил ложные срабатывания, порой показывал нажатие  совсем не в том месте, где это требовалось. Автор приобрел дополнительные тачскрины от для проверки - результат был тот-же. Ну и все вместе это давало ужасную картину едва шевелящегося GUI, который при этом еще и работает как попало.  Если учесть, что стоимость такого экрана порядка 90$, то стало понятно что игра не стоит свеч. Было решено просто расширить функциональность прибора, позволив пользователю управлять им через WEB интерфес с любого устройства. Если удастся добиться устойчивой работы WI-FI, то ситуации с подключением значительно упростится. Например, самый дешевый китайский планшетный ПК уже стоит меньше, чем 7"  экран для mini2440.
Ну и напоследок, для нормальной работы mini2440 с контроллерами ШД крайне желательна плата согласования уровней. Автор планирует разработать нечто подобное, если в том будет необходимость у заинтересованных лиц.

6 comments:

  1. Вы правда наблюдали у Xenomai "непредвиденные задержки"? На mini2440 латентность в юзерспейсе даже под большой нагрузкой не превышает 200 мкс, то есть можно спокойно обойтись без FIFO и сделать обычную двойную буферизацию. Наноядро Xenomai устроено так, что под нагрузкой лесом идет ядро линукса, а процессы Xeno-домена продолжают работать нормально.

    Если у вас motion время от времени тормозит, скорее всего у вас щелкают режимы Xenomai - где-то остался ядерный вызов. Я бы вообще выкинул все треды и подгрузку модулей. В своей тестовой версии я просто добавил функцию main в motion.c и сделал все там по-своему, ИМХО так безопаснее. rtapi и обертку вокруг него я выкинул полностью, из hal убрал все, кроме работы с пинами, а все нужные модули гружу статически в motion (у меня он называется motiontask). Могу dlopen сделать.

    ReplyDelete
  2. Я не совсем понял почему 200 мкс это не критично. Если у нас 5 подряд задержек на 200 мкс, то мы пропускаем один сервоцикл. Думаю ситуация вполне реальная. И я, кстати, пробовал с FIFO размером 2. С моим FIQ-генератором работает отвратительно: фаза дрожит и шаговики останавливаются

    ReplyDelete
  3. Они не могут быть ПОДРЯД, если сервоцикл действительно работает в Xenomai. Это задержки только на старт очередной итерации. Если у нас 5 подряд задержек по 200 мкс, то всего лишь надо, чтобы каждый цикл motion занимал не более 800 мкс, тогда он успеет кончиться вовремя. Если он занимает больще, тогда лучше период чуть-чуть увеличить, чтобы он даже с латентностью вписывался.

    Надо разбираться, почему у Вас дрожит. Я не смотрел код внимательно, но по симптомам - это несанкционированное переключение mode 1 и mode 2. Тред почему-то выскакивает из-под рилтайма на обычный планировщик. Вы не пробовали pthread_set_mode_np(0, PTHREAD_WARNSW); поставить?

    Я собираюсь вообще HAL выкинуть и дергать функции motion из своего цикла. Тогда задержки от прохода через "пины" хала можно будет исключить (сейчас из-за этого возможно опоздание сигнала на 1 цикл при неудачной последовательности выполнения тредов). Как обычно, ни на что нет времени :(

    Я тестировал латентность под стрессовой нагрузкой (рендеринг OpenGL на весь экран + интенсивная работа с сетью одновременно), латентность выше 240 мкс не поднимается.

    ReplyDelete
  4. Обратите внимание на это проект: http://www.raspberrypi.org/

    Мне кажется намного интересней и дешевле любой другой платы :)

    ReplyDelete
  5. Да борда интересная, надо только дождаться ее в продаже по заявленным ценам. И еще пока непонятно насколько она будет Open Source в плане возможности собрать свое ядро, а не использовать готовое. Да и по поводу поддержки RTAI/Xenomai еще не понятно. Будем ждать.

    ReplyDelete
  6. Ну, поддержку можно доточить, хоть под Xenomai, хоть под rt-preempt. (Не под RTAI точно, у RTAI почти нет инфраструктуры под ARM). Мой опыт работы с Xenomai на mini2440 показал, что с состояния "намертво вешается при загрузке" до состояния "работает замечательно" ядро доводится силами двух человек (Gilles Chanteperdrix и вашего покорного слуги) за три выходных дня. (Я сидел с gdb и JTAG-отладчиком, а Gilles показывал, чего где поправить). То же самое с другим кодом - загрузчик barebox под mini2440 тоже я патчил и тоже за пару дней. Это все из серии "глаза боятся, а руки делают".

    Гораздо хуже с периферией. Если на плате некуда подключать шаговики (напрямую или через CPLD/FPGA) - значит, их там некуда подключать, и точка. Если бы не это, можно было бы вообще не париться с платами, а купить китайский iPad-подобный планшеткик и припаяться к нему. На том же s3c2440 сейчас только ленивый не делает железки. У меня вообще осциллограф на нем же (и с линуксом).

    ReplyDelete