Как управлять CNC-роутером, не привлекая внимания…

    Мой CNC-роутер служил верой и правдой два года, но что-то пошло не так слетела прошивка, а был это woodpecker 0.9.

    Сначала я хотел ее просто перезалить, и, с этой целью раздобыл исходные коды Grbl CNC Project. Но любопытство пересилило и я погрузился в изучение этих исходников…

    Построены они очень просто и логично, но какой же русский не любит быстрой езды как же можно пройти мимо возможности что-нибудь подковать улучшить! По мотивам того что получилось, эта короткая воскресная заметка.

    Собственно идея контроллера для CNC-машины довольна проста и интересна. Есть несколько потоков обработки — один читает данные (gcode) и разбирает их, второй превращает команды в блоки исполнения и третий (stepper) собственно исполняет эти блоки. Вот об этом третьем потоке и пойдет речь.

    Степпер имеет дело со списком отдельных команд вида — сделай (X,Y,Z) шагов для всех трёх (как минимум) шаговых двигателей, причем за указанное время и в заданном направлении (ну это так упрощенно). Надо сказать, что шаговый двигатель со своим драйвером довольно простая в управлении штука — задаешь (0 или 1) направление вращения и затем по положительному перепаду входа (0 -> 1) двигатель пытается сделать один шаг (а всего на оборот обычно 200 шагов). Данные уже подготовлены, так что надо просто как-то соотнести 3 целых числа с заданным временем.

    В оригинале у автора использован контроллер atmega328p, но практически без изменений все легко переносится на arm (например, stm32). Но вот сам алгоритм не может не вызывать вопросов.

    С одной стороны, использован весьма совершенный алгоритм Брезенхэма, а точнее его разновидность Adaptive Multi-Axis Step-Smoothing. Но с другой стороны, как-то это все сложно и главное, плавность хода шагового мотора и точность работы роутера прямо зависят от точности выдачи сигналов управления. В данном случае это обуславливается частотой на которой работает таймер и временем обработки прерываний — а это дает не более 40-50 кГц в лучшем случае, а обычно и того менее — ну то есть точность задания управления 20-50 мксек.

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

    Так как я рассматривал переход на cortex-m (ну точнее на stm32h750, который я очень люблю и который очень подешевел), то такая задача может быть решена вовсе без привлечения CPU только лишь с использованием двух каналов DMA и одного 32-битного счетчика.

    Идея очень проста. Пусть один канал по переполнению счетчика записывает новые данные на порт, а второй канал записывает новое максимальное значение счетчика (это разумно делать на первом же такте работы счетчика). Тогда для обработки команды из списка надо подготовить для массива из значений изменения для порта и интервалов ожидания между ними.

    Получится что-то вроде такого.

    Обработка по прерыванию — переключение на новый буфер (двойная буфферизация).

    #define MAX_PGM 32
    typedef struct _pgm_buffer {
            uint32_t data[MAX_PGM];
            uint32_t delta[MAX_PGM];
    } pgm_buffer;
    pgm_buffer buf[2];
    uint32_t current_buf = 1;
    uint32_t flags = 0;
    void program_down(DMA_HandleTypeDef *_hdma) {
            TIM2->CR1 &= ~TIM_CR1_CEN;
            if ((flags & BUF_RUNNING) == 0)
                    return;
            current_buf ^= 1;
            DMA1_Channel5->CCR &= ~1;
            DMA1_Channel2->CCR &= ~1;
            DMA1_Channel5->CNDTR = MAX_PGM;
            DMA1_Channel2->CNDTR = MAX_PGM;
            DMA1_Channel5->CMAR = (uint32_t) (buf[current_buf].delta);
            DMA1_Channel2->CMAR = (uint32_t) (buf[current_buf].data);
            DMA1_Channel5->CCR |= 1;
            DMA1_Channel2->CCR |= 1;
            TIM2->CNT = 0;
            TIM2->ARR = 8;
            TIM2->EGR |= TIM_EGR_UG;
            TIM2->CR1 |= TIM_CR1_CEN;
    }
    

    Инициировать можно так:

           HAL_DMA_RegisterCallback(&hdma_tim2_up, HAL_DMA_XFER_CPLT_CB_ID,
                            program_down);
            HAL_DMA_Start_IT(&hdma_tim2_up, buf, &GPIOA->BSRR, MAX_PGM);
            DMA1_Channel5->CCR &= ~1;
            DMA1_Channel5->CPAR = &TIM2->ARR;
            DMA1_Channel5->CCR |= 1;
            TIM2->CCR1 = 1;
            TIM2->DIER |= TIM_DIER_UDE | TIM_DIER_CC1DE;
            flags |= BUF_RUNNING;
    

    Ну а старт — это:

            program_down(NULL);
    

    Что это дает? Давайте подсчитаем на примере того же stm32h750. Таймер (TIM2) там работает на частоте 200 МГц, минимальное время задержки два такта, но DMA не может переслать данные быстрее 50МГц, то есть между двумя командами на переключение порта можно положить (с учетом возможной занятости шины) 40 нсек (25МГц) — это в 1000 раз лучше исходной реализации!

    С другой стороны, ширина порта — 16 бит, так что можно одновременно управлять 8 шаговыми двигателями вместо 3 еще бы знать зачем

    При этом заполнение собственно данных не вызывает проблем (с таким-то разрешением!) — простая линейная интерполяция по каждому двигателю отдельно с объединением (для оптимизации) событий ближе 40 нсек.

    Собственно выводы.

    В мастерской лежит готовый CNC-станок с размером 1.2 метра на 0.8 метра с двигателями и драйверами, но без контроллера. Похоже, надо завершить работу и попробовать на нем, насколько это будет эпично. Если сделаю — обязательно напишу продолжение. А пока я не понимаю, почему это контроллеры делают на atmega и они пищат на всех 3d-принтерах и cnc-роутерах на этих грубых прерываниях…

    Ну и конечно, наверно имея мощь Cortex-M7, можно реализовать более плавное управление траекторией движения со всеми ограничениями, но это уже совсем другая статья.

    P.S. Видимо, надо дать некоторый гипотетический пример, почему так важно иметь столь малое время.

    Допустим, что станку надо переместится на 100 мм по X и на 11 мм по Y и софт разбил это все на участки ускорения и равномерного движения — много участков по 100 шагов на 11 шагов и они проходятся на максимальной скорости, пусть это соответствует 10 кГц. Ну 10 шагов по Y точно уложатся в 100 шагов по X, а вот с 11-тым может приключится беда — он может быть пропущен, так как вызывает удвоение частоты. В итоге перемещение будет на 100 мм по X и от 10 до 11 мм по Y. И это при линейном перемещении, где собственно даже ограничений на допустимые ускорения и скорости просты. А если это выполняется зигзагом? Ну например идет заметание площади 100 на 110 мм в 10 проходов — тогда мы вообще промахнемся очень сильно…

    Как раз для устранения этой ошибки и служит предлагаемый алгоритм, а вовсе не для суперфрезеров и т.д…
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 40

      +1
      А пока я не понимаю, почему это контроллеры делают на atmega и они пищат на всех 3d-принтерах и cnc-роутерах на этих грубых прерываниях…


      Давно уже контроллеры делают на STM32 и не пищат, так как используют нормальные драйверы от TMC
        0
        но драйвер у меня тоже от TMC, но звук-то есть. Интересно ведь, а как именно делают?
          0
          Может для начала поиграться с током и микрошагом драйвера?
            0
            ниже я ответил, для чего нужно высокое временное разрешения для выдачи импульсов по разным координатам. Конечно, если драйвер дает 256 микрошагов, это здорово, но это не решает (а как бы даже не усугубляет) проблему. И к тому же, наложение ограничений на допустимые скорости и ускорения (привет току) на фоне низкого разрешения приводит к эффекту интерференции сеток по разным координатам, для их решения приходится повышать частоту, что не всегда возможно. А тут, грубо говоря, частота аж 25 МГц (хотя так и нельзя говорить)…
            0
            драйвера 2208 или 2209
          +1
          Вы же имели в виду фрезер?
            0
            да, но вообще-то у меня именно CNC-роутер. Ну так они вот называются…
              +1
              Я просто уточнил.

              Дело в том, что русская калька с этого слова (router) это еще и сетевое устройство, а фрезер — вполне себе распространенное русское слово, и без других побочных смыслов.
                0
                У буржуев есть разделение между router и mill, первый — потомок ручного фрезера, обычно по дереву, второй — «взрослый» фрезер по металлу.
                  0
                  Это вполне естественно. router это же еще и рубанок (грунтубель).

                  Насколько я понимаю, CNC (особенно домашние) ближе к ручному. У фрезера в виде станка все-таки обычно литая чугунная станина. Впрочем, ни на чем не настаиваю.
                    0
                    У фрезера в виде станка все-таки обычно литая чугунная станина. Впрочем, ни на чем не настаиваю.

                    Я так понимаю, деление в первую очередь функциональное. Routing — обработка листовых или погонажных легких материалов линейными стратегиями, зачастую фасонными фрезами. Milling — полноценная обработка детали, обычно стальной. Можно еще привязаться к конструктиву: портал — роутер, консоль — фрезер. Но все это относительно условно, понятно что на роутере можно миллить, а на милле — роутить, понятно что некоторые роутеры за всю жизнь ни разу не видят роутерной фрезы или роутерной обработки, а некоторые фрезеры живут на профилировании погонажа.
                –1
                да, но вообще-то у меня именно CNC-роутер. Ну так они вот называются…
                Первая половина сложного слова — аббревиатура из букв английского алфавита, вторая половина — ошибочная транскрипция русскими буквами английского слова «router». Нет, может где-то там, высоко в горах они так и называются, а на хабре так не годится, по моему мнению.
                  0
                  ну вам виднее, как оно там у вас в горах.
                    0
                    ну вам виднее, как оно там у вас в горах.

                    Не пробовали писать для стендапа? Галкин бы мог озвучить голосом бацьки, у него хорошо получается. Только «горах» надо бы заменить на «болотах» и с сарказмом таким деревенским произносить.

                    Если кому интересно, минус не только в рейтинг, а еще и в карму споймал на предыдущем коментарии. Российская фишка, если вы заметили что-то, что неплохо было бы исправить, то не ждите благодарности, скорее наоборот — минусом и по рейтингу и по карме. Так рушатся империи, к сожалению.
                      0
                      Вот что пишут в этих ваших интернетах:

                      В англоязычной литературе и статьях часто противопоставляются понятия «ЧПУ роутер» (CNC Router) и «фрезерный станок с ЧПУ»(CNC milling machine). В русском языке оба этих словосочетания изначально передавались как «фрезерный станок с ЧПУ», однако вскоре за определенными видами станков закрепилась калька «роутер». Почему это произошло, и какие именно станки называют «роутерами»?

                      На первый вопрос ответить можно достаточно просто — термин появился, т.к. роутеры действительно сильно отличаются от обрабатывающих центров с ЧПУ, как по конструкции, комплектации так и по назначению и возможностям.


                      Поэтому ничего плохого в том, что я использую устоявшийся термин, уточняющий значение, не вижу. Однако вы, видимо, не особенно ознакомившись с темой, высказали свое мнение (это хорошо), но при чем тут упоминание гор, не очень понятно, но видимо, вам близко (я, кстати, живу в равнинной, болотистой местности) — хотя я не вижу, почему в горах должны быть люди хуже или глупее.

                      Как-то так вот, поэтому, я думаю, и минуса поставили вам.

                      Лучше бы что-нибудь толковое по теме статьи написали…
              0
              между двумя командами на переключение порта можно положить (с учетом возможной занятости шины) 40 нсек (25МГц) — это в 1000 раз лучше исходной реализации!

              А есть понимание зачем оно? Большинство драйверов больше 300кГц не держат. Да даже бы и держали, пусть у вашего станка разрешение 10 микрон, 25 000 импульсов в секунду дадут 250 мм/сек или 15 метров в минуту, куда такое?
                +3
                видимо, тут у нас с вами недопонимание. Речь идет не о килогерцах. А именно о разнице в шаге по разным координатах. Допустим, по X нам надо сделать 1000 шагов, а по Y — 1001 шаг и все это за 400 мс. И вот, получается, что если мы может разрешать по времени 40 мксек (25 кГц), то на каждый шаг по X будет 10 прерываний, а вот по Y будет неравномерность, что и приведет к сильному мгновенному ускорению в какой-то момент, что и будет воспринято как сильная неточность движения (всплеск ускорения) (часто это слышно как завывания при движении).

                Это как эффект муара.

                Так что ни разрешение станка ни частота драйвера, ни скорость тут не особо при чём. Хотя они тоже важны, согласен.
                  +1
                  Мне кажется вы переоцениваете свою механику )))
                  1 шаг мотора NEMA 17 на ходовом винте 2мм/оборот — это около 10мкм без микрошага. С учетом микрошага 1/32 — 0.3мкм
                  Пропустите один шаг по Y в любом месте движения по X и ваша механика не заметит этого
                    0

                    Ну, можно оптические линейки для контроля добавить.

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

                        Показания с линеек считать приоритетными и корректировать по ним положение каретки. Каждый шаг это разумеется делать не нужно, а вот каждые n*100 шагов, или меньше, если под нагрузкой — можно.

                          0
                          ну то есть вы предлагаете замкнуть цикл управления по обратной связи? А модель уже есть? А то это может привести к возникновению колебаний и наоборот ухудшить точность процесса…
                          Можно ведь и каждый шаг это делать — этому ничего не мешает, но проблема в устойчивости и сходимости процесса, мне кажется.
                            0
                            Вы все еще уверены что так добавите плавности хода?
                              0
                              Мне кажется, что сама идея ввести петлю обратной связи хорошая, но тут явно нужно много считать — даже в первом приближении, как показывает моя статья имеются существенные проблемы с интерференцией сеток управляющего сигнала, что уж говорить о другом…

                              Вообще-то явно где такая обратная связь хорошо идет — это в местах остановки CNC — для считывание текущих координат. Тут все понятно и вопросов не вызывает — но это лишь пост-фактум информация, ну типа — ну вот, облажались на 10 мм…
                                0

                                Посчитать разницу координат — много ресурсов не надо вроде бы.

                                  0
                                  Так тут проблема не в этом. Попробую попроще объяснить (так то это теория автоматического управления). Вот получили вы на 100 шагах, что ошиблись на 2 шага, ввели поправку, а условия изменились и теперь уже на следующих 100 шагах в другую сторону поправка — так и получится раскачивание, а без поправки бы было лучше! Вот поэтому и надо модель, чтобы все работало стабильно к возмущениям…
                          0
                          Ну вот смотрите — я согласен, что на одном отрезке интерполяции скорее всего шаг будет пропущен и да, механика этого не заметит. Но если этих шагов много — например идет перемещение с таким вот неудобным углом по небольшим отрезкам на большую длину, то это приведет к пропускам на каждом таком отрезке, а их много — вот и накопится ошибка и очень значительная. А вот если перемещения распределены равномерно и возникающие ускорения не приводят к пропуску шагов, то ошибки не будет (ну или она уменьшится). Конечно, это надо дополнить анализом движения на большую глубину самого g-кода…
                            0
                            Все верно — выше частота, больше разрядность — выше точность.
                            Весь вопрос, какая точность вам нужна. Софт при расчете шагов может интерполировать и нужной точностью убирать все погрешности.
                            Есть у меня самодельный станочек на китайских ШВП и рельсах. Раньше им платы фрезеровал.
                            Там точность механики хорошо если 10-20 микрометров при скорости 200.
                            Ну и зачем мне нудна точная электроника, которая будет высчитывать шаги с точностью до 0.1 мкм?
                            Конкретно для этого станка Atmega328 с GControl больше чем достаточно.
                            Другой пример — принтер дельта на работе. Переводит прямоугольные координаты G-кода в управления треугольной кинематикой. Там 8-ми битный AVR дает приличную погрешность, которая растет со скоростью печати. Поэтому 32-битный контроллер там очень целесообразен.
                            У вас же, судя по задаче, какой то прецизионный роутер с очень маленькой погрешностью и высокой скоростью )))
                            Иначе, весь этот труд — из пушки по воробьям. Ну, или святое, потому что интересно поразбираться. Но тогда и цель немного другая. Почему бы тогда не сделать по потоку на каждую ось, с мьютексами синхронизации и прочими интересными вещами? Если запустить такую штуку на многоядерном контроллре, то вообще огонь будет )))
                              0
                              в чем-то вы правы, ведь я писал — интересно же разобраться, как этот степпер реализован, ну и улучшить, конечно! Вот ведь получилось — и точность работы больше, и нагрузка на процессор меньше, и код уменьшился почти в 100 раз, да и что интересно — вот вы пишите
                              Почему бы тогда не сделать по потоку на каждую ось, с мьютексами синхронизации и прочими интересными вещами
                              — как я понимаю, с долей иронии, но именно так и получилось! И сделано это практически аппаратными средствами, годится для любой архитектуры, где есть таймеры и DMA, так почему бы это не погордится не показать другим людям?

                              Мне кажется интересным делать такое, что позволяет достичь горазно большего, чем ожидалось — жаль, если вы так не думаете…
                                0
                                И вот как раз про ваш пример — вообще-то если бы использовалась нормальная математика, то и 8-ми битный AVR давал бы достаточную точность — этому ничего не мешает. Но проблема как раз в том, что механизм управления там точно такой-же, основанный на прерываниях и линейный аппроксимациях, а это особенно дает накапливающуюся погрешность при переводе в треугольную кинематику. А ведь этого можно избежать — но просто мало математики :)
                            0
                            будет воспринято как сильная неточность движения (всплеск ускорения)

                            Как я понимаю, эта «сильная» выражается в тысячных радиана и сотых линейно. Не уверен что завывания оттуда берутся.
                              0
                              так именно что оттуда — ведь что такое эта неточность, как не резкое кратковременное ускорение, то есть фактически удар? И если такие удары идут по 100-1000 раз в секунду, это просто генератор звука…
                                0
                                И если такие удары идут по 100-1000 раз в секунду, это просто генератор звука…

                                Забейте в звукогенератор циферку от 100 до 1000. Первая будет в районе ля большой октавы, вторая — до третьей октавы, и то и другое — не писк вообще.
                                  0

                                  ну так шаговики и не пищат, а вполне себе воют)

                            0
                            дадут 250 мм/сек или 15 метров в минуту, куда такое?

                            для какого-нибудь 3д-принтера или лазерного резака (в лазерах как раз grbl используется) еще и мало будет

                              0
                              для какого-нибудь 3д-принтера или лазерного резака (в лазерах как раз grbl используется) еще и мало будет

                              На принтерах 250 мм/сек? Это полное пересечение поля менее чем за 1 секунду, не дофига ли?
                              На лазерах обычно ремни и, соответственно, миллиметров на оборот больше, раза в 4 как минимум. И это уже 1000 мм/сек, 60 метров в минуту,
                            0
                            Если хотите дорабатывать grbl под ARM, попробуйте посмотреть в сторону grblHAL. Оригинальный grbl сейчас практически мёртв, там очень давно не было никаких значимых изменений, а здесь разработка идёт довольно активно.
                              0
                              Вот это интересно!
                              0
                              cnc роутер. это по-русски чпу фрезер.
                              а в остальном проблема высасана из пальца и решена.
                              профит.

                              для фрезеров есть как готовые системы управления так и самосборные.
                              выбор большой и большей проблемой стоит определиться именно с экосистемой програмного обеспечения для работы на этом чпу. программ много вариантов еще больше.
                              мне нравится вариант автономного контроллера. однако пользуюсь мач3.чрез лпт порт.
                                0

                                Посмотрите на контроллер Kflop, который сделал энтузиаст американец. У него там плис. Управляет и шаговиками и сервами. Обратная связь. И главное программы можно писать не только в Gcode, а прямо на языке С. Хорошо бы и у нас нашелся человек, который бы смог что то подобное сделать

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

                                Самое читаемое