Pull to refresh
8K+
4
Юрий@synctwin

Инженер ПНР: EtherCAT, LinuxCNC, цифровой двойник

21,1
Rating
1
Subscribers
Send message

Да, это и есть главная мысль: шина принадлежит станку, а не приводу. У нас рядом с приводами висит 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 приводы разных вендоров отрабатывают по-разному, про это у нас вторая статья. Неизвестное железо шина переживет, а вот что оно сделает по знакомой команде, стандарт не обещает.

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

У нас то же самое решено грубее: порт целиком отдан в виртуалку через 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 и меток времени нет, так что джиттер на проводе не привезу.

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

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

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

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

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

У нас 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 в приводах мы не трогали ни разу, а он ровно про то, чтобы снять пропорциональное скорости отставание. Так что число это не потолок железа, а замер нашей ненастроенности. Линейных энкодеров на стенде нет, поэтому сколько там на самом деле по столу, а не по мотору, мы не знаем.

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

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

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

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

О, спасибо, про 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, напишу отдельно. Заодно наконец появится тот самый замер на проводе, которого мне не хватило в ответе выше.

Вопрос совсем не глупый, наоборот, его задают чаще всего. Если одной фразой: 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 кГц опять же штатный темп.

Спасибо! Про 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 рабочее место при этом никуда не девается, просто ходит на бокс по сети, а не крутит мастер у себя.

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

Information

Rating
404-th
Location
Москва, Москва и Московская обл., Россия
Registered
Activity

Specialization

Инженер встраиваемых систем, Инженер ПНР
Ведущий
АСУ ТП
Linux
Программирование ЧПУ
Python
Docker
PostgreSQL
Scada
Встраиваемая система