Pull to refresh

Comments 21

Интересная и полезная статья, спасибо! Работаю с EtherCAT уже как лет 5, для отладки в основном пользуюсь TwinCAT + PLC. Пробовали ли вы измерять jitter пакетов? На обычной Win 11 и Intel Ethernet карточках, поддерживаемых TwinCAT в режиме real-time, получается добиться < 120 мкс. На специально вылизанных Windows < 20 мкс. Особенно круто было бы получить стек с малым jitter под WSL.

Спасибо! Про jitter отвечу честно, но с оговоркой: мы меряем не совсем то, что вы.

Кадры на проводе мы не снимали, ни TAP, ни осциллограф под это не подкладывали. Меряем джиттер пробуждения RT задачи. cyclictest -p80 -i1000 при цикле 1 мс дает max 15 мкс, avg 5. Еще смотрим lcec.read-all.tmax, там 72 мкс, но это сколько функция работает, а не разброс. Так что с вашими 120 и 20 мкс это сравнивать нельзя, величины разные.

Зато вместо метрики у нас есть индикатор, который не соврет. Distributed clocks это самый нежный потребитель на шине. Не уложился в окно, и слейв просто не доходит до OP, виснет в SAFEOP, а в логе Unexpected realtime delay on task 0 with period 1000000. Три привода в OP при sync0 каждый цикл значит с джиттером все нормально. Один раз это стрельнуло уже на боевом прогоне: RT выброс уронил DC sync, привод Z защелкнул SYNC аварию и честно свалил станок в E-STOP. Неприятно, но приятнее чем ось молча мертва.

И вот что интересно. Цифры нам дал не период и не выбор HAL. До тюнинга на том же железе, с той же картой и тем же стеком 1 кГц вообще не держался, машина параллельно тащила homelab, load average под 12. Вылечилось скучным: governor в performance, глубокие C-states запретить (/dev/cpu_dma_latency=0 держим отдельным юнитом, иначе не переживает ребут), isolcpus плюс пиннинг vCPU. После этого LA 3, те самые 15 мкс и ноль realtime delays. Двойку миллисекунд ставить не пришлось. То есть в линуксе джиттер это в первую очередь про C-states и про то, кто еще живет на твоих ядрах, а не про какой то особый real-time драйвер сетевухи.

Теперь про WSL. Тут порадовать нечем, и сразу по двум причинам. Сеть в WSL2 это виртуализованный адаптер под Hyper-V, а IgH нужен сырой доступ к карте (у нас DEVICE_MODULES generic на i226 и igc). Прокинуть физический порт туда нельзя, PCI passthrough в WSL2 нет, usbipd закрывает только USB. А если бы и прокинули, Hyper-V подкинет своих выбросов поверх винды, и никакого детерминизма.

Но EtherCAT из виртуалки сам по себе живет прекрасно, просто гипервизор нужен другой. У нас стенд так и устроен: KVM, физический порт целиком проброшен в гостя через VFIO (igc уходит в vfio-pci, с хоста карта пропадает), внутри Debian с RT ядром, vCPU запинены на изолированные ядра. Из VM поднимается вся шина разом: 3 штуки IS620N, Wecon VD3E, Mitsubishi MR-J4-20TM и каплер Omron. Windows рабочее место при этом никуда не девается, просто ходит на бокс по сети, а не крутит мастер у себя.

Если есть способ померить джиттер прямо на проводе без спецжелеза, расскажите. Прогоню на стенде и выложу цифры, самому интересно.

Как вы и написали, джиттер зависит от системы, которая обеспечивает real-time и от драйвера сетевой карты. Если есть возможность написать/модифицировать драйвер карты, то Intel i210 и тому подобные поддерживают 802.1Qav где есть функция Launch time. То есть вы для пакета задаете время отправки по внутреннему таймеру карты. Тогда джиттер будет измеряться в наносекундах, может в десятках наносекунд. Но кроме модификации драйвера карты нужно ещё иметь возможность обращаться к нему напрямую из real-time системы.

О, спасибо, про launch time не думал в эту сторону. Полез читать, и да, у i210 это есть, шаг таймера 32 нс по даташиту. В линуксе оно даже не требует своего драйвера с нуля: SO_TXTIME на сокете плюс qdisc etf с offload, igb это умеет в ванильном ядре начиная с 4.20. У i225 и i226 (igc) то же самое плюс Qbv, а у нас на стенде как раз i226 стоит, так что железо под рукой.

Но с EtherCAT есть засада ровно там, где вы говорите про прямое обращение из RT системы. IgH ходит к карте двумя способами. Либо native драйвер, а это форк старого ядерного драйвера, который лезет в кольца напрямую и весь сетевой стек с его qdisc обходит стороной, значит etf там просто не по пути. Либо generic режим через обычный сокет, и вот тут ETF теоретически применим, но сам IgH никакого SO_TXTIME на пакет не ставит. У нас как раз generic на i226. То есть допиливать все равно придется, только не драйвер карты, а мастер, и это, пожалуй, честнее звучит.

И второй момент, из-за которого мы за наносекундами не гонимся. В EtherCAT с distributed clocks синхронность осей не зависит от того, когда кадр физически приехал. Слейв защелкивает данные по своему sync0, а кадру достаточно просто успеть до него. То есть launch time убирает джиттер отправки, а у нас узкое место было не там: RT выбросы измерялись сотнями микросекунд и миллисекундами, кадр банально опаздывал за окно целиком. Наносекундная точность отправки от такого не спасет, ее лечит только разгрузка ядер и запрет C-states.

Где launch time реально бы выстрелил, так это в схемах без DC и там, где EtherCAT делит провод с другим трафиком, то есть в сторону TSN. Вот там детерминированное окно отправки решает, а не улучшает.

Если руки дойдут собрать generic путь с SO_TXTIME и померить до и после на i226, напишу отдельно. Заодно наконец появится тот самый замер на проводе, которого мне не хватило в ответе выше.

Про отсутствие необходимости наносекунд и узкое место в RT я с вами полостью согласен. У нас RT вообще самописный и из за борьбы с Windows и дошли до всего этого.

А для схем с другим траффиком есть ещё одна полезная вещь в карте: Multiple Transmit Queues. У нас, наример, циклические телеграммы идут через RT в драйвер напрямую в приоритетную очередь, а управляющие телеграмы, mailbox, EoE и т.п в другую, можно даже через обычный сетевой стек.

Про самописный RT из-за Windows - сильно. У нас та же логика, только мы сбежали в другую сторону, в PREEMPT_RT, потому что писать своё не потянули бы.

 Multiple Transmit Queues полез смотреть сразу, у нас i226 и там это есть, mqprio и taprio ложатся штатно. Но с IgH в generic режиме упираешься в то же место, что и с launch time. Мастер шлёт все кадры одним сокетом и сам не различает, что тут domain, а что mailbox. Ручки выставить priority на конкретный кадр я сходу в мастере не нашёл. То есть очереди в карте есть, а раскладывать по ним пока нечего, надо править мастер.

И вторая честность, из-за которой выигрыш у нас будет меньше вашего. У вас в очереди разный трафик, а у нас по проводу всё равно одна линия и кадры идут гуськом. Очередь в карте поменяет только порядок выхода на провод, а не разведёт потоки. Хотя порядок это ровно то, что и надо: mailbox не должен пролезать перед циклическим кадром.

Место, где нам это откликнется, известно. Мы читаем полный паспорт привода, три сотни параметров по SDO, и делаем это на живой шине. Джиттер под этой нагрузкой не мерили ни разу. Спасибо, добавили в список замеров.

С кадрами в очередях к нас всё так же: кадры гуськом, только порядок выхода. Для нас их основная польза в другом: они аппаратно независимы. Поэтому в то время пока одной очередью пользуется стандартная часть драйвера под управлением Windows, другой очередью управляет наш RT, который крутится вообще на изолированном ядре. И не надо думать про синхронизацию. Собственно всё это не от хорошей жизни, а из-за борьбы с Windows.

Понял вас сначала неправильно: думал, про приоритет кадров на проводе, а польза в том, что у карты два независимых хозяина и синхронизация не нужна.

У нас то же самое решено грубее: порт целиком отдан в виртуалку через VFIO, с хоста карта пропадает, внутри Debian с RT ядром и IgH. Второго хозяина нет вовсе. Вам так нельзя, у вас Windows на том же железе.

Грабли, которых нет в README: карты должны лежать в разных группах IOMMU, иначе порт не отдать; dkms сборка IgH 1.6.10 под ядро 6.1.0-51-rt падает на dwmac-intel и stmmac, выкинули их из dkms.conf. И главное, проброс сам по себе латентности не дает: без тюнинга в госте max 136 мкс, 1 кГц там не живет. Цифры дали изоляция ядер и пиннинг.

Стенд кросс-вендорный и живой, могу прогнать то, что снимается софтом на мастере (cyclictest, счетчики ошибок портов, поведение привода на конкретный SDO). Кадры на проводе не снимаем, TAP и меток времени нет, так что джиттер на проводе не привезу.

возможно глупый вопрос, но если приводы "умные", которым надо только сказать куда ехать и с какой скоростью и энкодер с pid регулятором "внутри", то зачем им именно собственно езеркат (ну разве что для синхронизации часов у нескольких осей, но наверное должен быть и ряд других способов). А если тупые - (а-ля условный linuxCNC / LPT / Mesa) step/dir драйвер шаговика в i/o клемму и чтение обратно энкодера через езеркат, то вроде как 1мс это не сказать что сильно уж быстро, чтобы этот регулятор в ПК вынести, да и просто для step/dir маловато 1кГц?

Вопрос совсем не глупый, наоборот, его задают чаще всего. Если одной фразой: EtherCAT нужен не приводу, а станку.

Одной оси и правда хватит чего угодно. В CiA 402 для этого есть режим PP: послал цель и скорость, привод сам построил разгон и торможение, приехал. Шина тут вырождается в канал команд, справится и Modbus.

А станок режет контур. Дугу, скругленный угол, фаску. Траекторию считает интерполятор наверху, сразу по всем осям, с look ahead по будущим кадрам G кода и с ограничением подачи по вектору. В CSP каждой оси каждый такт приезжает не куда ехать, а очередная точка этой общей кривой. Привод такое не построит в принципе, он не знает что в эту миллисекунду делают соседи. Отсюда и требование к синхронности. На F3000, то есть 50 мм/с, ось за такт проходит 50 мкм. Разъехались оси на такт, и на дуге вылезла видимая ступенька. DC ровно про это, а не приятная мелочь.

Ну и третье, за что EtherCAT в итоге любишь. Обратка достается даром. Кадр все равно проходит слейва насквозь, так что позиция, скорость, момент, statusword и ошибка слежения капают каждую миллисекунду сами собой. Из этого потом бесплатно вырастает touch off по моменту без щупа, following error в виде числа (у нас Kv вышло примерно 37 в минус первой, у всех осей одинаково), осциллограф приводов без осциллографа и работающая фолт цепь. Плюс оси, шпиндель, дискретка и петля E-STOP едут одним шлейфом.

Теперь про 1 мс маловато для step/dir. Тут, по моему, склеились два разных такта.

Импульсы вообще никогда не генерятся на servo-thread, ни в одной схеме. Софтовый stepgen через LPT крутится на base-thread 20 до 50 кГц. У Mesa шаги делает FPGA. У EtherCAT клемм step/dir (EL2521 и родня) импульсы генерит сама клемма, ей по шине едет частота или цель, а не отдельные шажки. Сотни кГц она выдаст независимо от того, что цикл шины 1 кГц.

А 1 кГц это темп обновления команды позиционному контуру, а не частота движения. Ровно на нем LinuxCNC десятилетиями замыкает позицию с Mesa по энкодеру. Это отраслевая норма, а не компромисс. Ваша схема step/dir в клемму плюс энкодер обратно по EtherCAT это та же самая классика, просто на другой физике.

И в CSP сглаживание вообще не наша забота. Между присланными точками привод интерполирует сам до своего внутреннего цикла, а токовый и скоростной контуры у него крутятся на десятках кГц. Разделение получается честное: планирование сверху на 1 кГц, сервоконтуры внизу на своей частоте. Выносить PID в ПК как раз не нужно, и мы не выносим. Это только для CSV схем, где позицию замыкает сам LinuxCNC, и там 1 кГц опять же штатный темп.

Хорошо, пусть step импульсы генерятся пачками снаружи, но если у нас 1мс, и те самые 50мкм на 50мм/c между измерениями положения и соответственно до команды на следующую пачку импульсов, на какую ошибку траектории тогда можно рассчитывать. 50мкм? Да, есть feedforward и с идеальной механикой можно и без обратной связи по линейному энкодеру жить, но если механика говно, то чтобы её регулятором держать по энкодеру где положено разве не надо чтобы "период" регулятора помноженный на максимальную скорость соответствовал ошибке?

Вопрос не мне, но если позволите. "период регулятора помноженный на максимальную скорость" это было бы если бы нужно было на ходу начать регулировать привод несущийся на максимальной скорости. А мы же регулируем движение с самого начала. Поэтому получится "период регулятора помноженный на максимальную ошибку между заданной скоростью и реальной". С поправкой, что в CSP эту заданную скорость привод посчитает сам из разницы между новым положением и старым.

Тут важно разделить два случая, потому что у нас с вами контур замыкается в разных местах.

У нас CSP: позиционный контур живет внутри привода, а по шине едет цель. Наши цифры со стенда, три оси IS620N, F3000 то есть 50 мм/с: joint.N.f-error по p95 = 1.34 мм [замерено]. На F750 = 0.34 мм. В покое ноль. Kv вышел примерно 37 в минус первой, одинаковый у X, Y и Z.

Обратите внимание: это в 27 раз больше вашей оценки в 50 мкм. Работает не e = такт * скорость, а e = v / Kv. Квант такта в этом бюджете просто теряется на фоне отставания петли.

А вот в вашей схеме, где позицию замыкает ПК на 1 кГц, вы правы по сути, но механизм другой. Ограничивает не квант дискретизации, а устойчивость. Полосу замкнутого контура выше примерно десятой доли частоты дискретизации не поднять, то есть при 1 кГц это сотня герц в самом хорошем случае. А Kv упирается в эту полосу. В LinuxCNC на servo-thread 1 кГц реальные Kv это десятки, редко за сотню. Подставьте: при Kv 100 и 50 мм/с получится 0.5 мм. Снова не 50 мкм, и снова по формуле v / Kv, просто Kv низкий именно из-за периода. То есть период регулятора действительно главный ограничитель у вас, но он входит в ошибку через предел устойчивости, а не через путь за один такт.

Теперь про механику, и это самое интересное место в вашем вопросе.

Если механика плохая, потолок ставит не такт шины, а резонанс самой механики. Первый резонанс винта с муфтой это обычно десятки герц, и полосу контура выше него поднимать нельзя, иначе вместо жесткости получите возбуждение. Механика упрется раньше, чем упрется 1 кГц. У нас это не мерили, говорю из общей практики.

И отдельно про люфт: его регулятором не держат в принципе. На реверсе он дает мертвую зону, где датчик не видит движения, и высокий Kv эту зону не убирает, а превращает в автоколебания. Тут только механика или линейный энкодер.

Теперь собственно ответ на ваш вопрос про ошибку траектории. Отставание оси и ошибка формы это разные числа.

На прямой ошибка формы около нуля. Все оси отстают одинаково, значит меняется только фаза, инструмент идет на 1.3 мм позади того места, где должен, а деталь получается той же.

На остром угле вылезает целиком, примерно на величину e. У нас это 1.3 мм на F3000 и 0.34 мм на F750. Отсюда цеховое правило про то, что углы едут медленнее, получает численный вид.

На дуге меньше, чем кажется: при одинаковом Kv у осей радиус просто сжимается, примерно на v^2 / (2 R Kv^2). Для R10 и 50 мм/с это около 0.09 мм. Это уже [не мерили], только формула.

И честность про наши 1.34 мм. Это как из коробки. Velocity feedforward в приводах мы не трогали ни разу, а он ровно про то, чтобы снять пропорциональное скорости отставание. Так что число это не потолок железа, а замер нашей ненастроенности. Линейных энкодеров на стенде нет, поэтому сколько там на самом деле по столу, а не по мотору, мы не знаем.

И дополню про то, что EtherCAT нужен не приводу а станку.

Тут же не только в приводах дело. Сейчас куча оборудования работает по EtherCAT. Входы/выходы, переходники для шин типа CAN, датчики всякие, лазерные головки, штамповка/высечка, шпиндели и т. д. и т. п. Плюс там же можно обычный  Ethernet пустить (многие привода так настраиваются) и не надо второго подключения.

А синхронизировать несколько приводов если они ни чем не объединены я вообще не представляю как. Хотя может и есть способы. Но тут всё сразу есть.

Если это что-то простое, то вы сами решаете как и что делать, а если это CNC для управления разными станками где будет неизвестно что подключаться, то без EherCAT сложно будет. Ну, то есть, наверное есть другие технологии, просто я про них не знаю.

Да, это и есть главная мысль: шина принадлежит станку, а не приводу. У нас рядом с приводами висит IO каплер Omron, добавился как еще один слейв.

Синхронизировать ничем не объединенные приводы и правда нечем, в EtherCAT это закрывает Distributed Clocks: часы всем задает первый DC-слейв, мастер только подстраивается. Наши оси в CSP на такте 1 кГц ходят именно так.

У нас эта задача почти домашняя: порты i226 розданы виртуалкам через VFIO, в каждой свой мастер и своя шина. Сейчас таких две, целевая коробка на 4 порта, три шины по станку плюс управление. Виртуалки живут на одном хосте, часы у всех от одного TSC, так что PTP по проводу между ними даже не нужен: каждый мастер подтягивает опорные часы своей шины к своим системным, IgH это позволяет. Сразу скажу, сами не мерили, пока обе шины живут каждая по своим часам.

Два физически разных стенда склеиваются так же, только уже через PTP по обычному Ethernet. С аппаратными метками времени (i210 и i226 их умеют) на прямом кабеле между хостами выходит субмикросекунда, через обычный свитч хуже, итог по шинам порядка единиц микросекунд, это по литературе, не наш замер. Внутри одной шины DC держит лучше 100 нс, так что интерполировать оси все равно правильно на одной шине, а межстендовая синхронизация нужна разве что для передачи детали, там хватает и миллисекунд.

А вот обычный Ethernet поверх шины недавно проверили, и вышло не то, чего я сам ждал. EoE не заявляет ни один наш слейв: у всех только CoE, у MR-J4 еще FoE. Настраиваются по CoE, тот же mailbox, только без IP. Интересно, какие железки EoE реально поднимают.

Другие технологии есть, PROFINET IRT, Sercos III, POWERLINK. Но мастер EtherCAT это просто софт на обычной сетевухе, вся жесткая механика времени в чипе слейва. Поэтому в открытом мире выбор по факту один.

Единственное, где чуть поспорю с “тут все сразу есть”: шина дает общий провод и общее время, но не общее поведение. Один и тот же SDO приводы разных вендоров отрабатывают по-разному, про это у нас вторая статья. Неизвестное железо шина переживет, а вот что оно сделает по знакомой команде, стандарт не обещает.

Вы с Inovance работаете, у них есть привода с EoE. IS810N, IS650N и ещё какие-то. Но я не уврен это модификации или все такие привода поддерживают. И сам не пользовался.

плюс эзерката только в том что тебе не надо блудняк из проводов устраивать и у тебя сразу система с замкнутым контуром, 1кгц еще в 80х выявили что достаточно для motion.

1кгц еще в 80х выявили что достаточно для motion.

не всегда, от точности зависит. Есть линейные подвижки от ньюпорта с их же родным контроллером, десяток мм/с и микронные точности позиционирования в "статике", но в "динамике" видно что не справляются, что там внутри хз, но какие-то несколько кГц цикла заявлены.

ну и "EtherCAT ≠ Beckhoff" в статье конечно пример хороший приведён, но в целом с аналогами twinCATа как-то довольно печально имхо.

Стабильность Distributed Clock (DC) нельзя использовать для оценки джиттера пакетов, т.к. коррекция периода DC выполняется одним фиксированным значением (20 нс, по-моему) в зависимости только от знака разницы периода пришедшего от мастера фрейма.

Если мы захотим разогнать ECAT до 10-40 КГц, то величина джиттера станет главным лимитирущим фактором. Кроме того, в большинстве real-time приложений задержка (latency) должна быть стабильной от мастера к слейв и обратно. Если джиттер большой, то это трудно выполнить.

Согласен, поправка по делу. Разница DC это выход петли подстройки часов, джиттер прихода она сглаживает, а не показывает. Мы его мерили на мастере, cyclictest headless: max 15 мкс на разгруженной машине.

Про 10-40 кГц тоже согласен. На 1 кГц окно до sync0 в 1000 мкс против 15 мкс джиттера, запас такой, что шина не ограничивает ничего. На 25 мкс окна нет вовсе. Мы туда не идём по другой причине: замеренное отставание оси 1.34 мм на F3000 в 27 раз больше кванта такта, и замкнуты мы по энкодеру мотора, так что люфт и кручение винта регулятор не видит. Пока это так, разгон шины съест механика.

Выложил конфиги со стенда: github.com/SyncTwin/linuxcnc-ethercat-configs

Описание шины и HAL для трёх осей IS620N с каплером Omron, минимальный пример на одну ось, README с граблями рядом с каждым набором. Отдельно методика замеров: cyclictest, f-error через halsampler, счётчики ошибок портов.

Sign up to leave a comment.

Articles