Jump to content

    

Простенький ЧПУ контроллер

Recommended Posts

MX_Master

У меня нет проблем ни с программным ногодрыгом, ни с любой другой аппаратной реализацией. Уже всё испробовано по несколько раз со всеми возможными извращениями. Ногодрыг используется только там, где соответствующих аппаратных возможностей нет. В F407/H750 достаточно таймеров, чтобы вывод сигналов на разных частотах был приятным занятием как для прогера, так и для процессора.

Share this post


Link to post
Share on other sites

AVI-crak
8 minutes ago, mantech said:

Зачем? Может я чего-то не догоняю и управление ШД вышло на какой-то новый уровень, но всегда для управления ШД использовал только 2 параметра, кол-во шагов и частоту...

Это так, только смотреть нужно с другой стороны - время для каждого шага отдельно, и общее их количество. Дабы уйти от дёрганного уродца, недостаточно повышать дробление шага - нужно плавно разгонять и останавливать вращение. Ну а при совместном движении нескольких моторов по криволинейной траектории - иного способа просто не существует.

Share this post


Link to post
Share on other sites

mantech
1 минуту назад, AVI-crak сказал:

нужно плавно разгонять и останавливать вращение.

Конечно, все прекрасно реализуется изменением частоты по трапеции..

Share this post


Link to post
Share on other sites

jcxz
42 минуты назад, AVI-crak сказал:

Ага, подключить выход таймера на шаг, и получить постоянную скорость вращения движка...

Кто мешает в прерываниях периодически перепрограммировать таймер? Прерываниях с частотой в несколько десятков кГц. Этого достаточно для расчёта следующих нескольких шагов? Или нужно расчёт прям под каждый микрошаг делать?

Цитата

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

Что значит "пропускать шаги"? Заранее рассчитать и подготовить N импульсов заданной длительности и периода, исключив из этой последовательности M-й импульс, а затем подать эту последовательность на двигатель?

Так это элементарно делается на SGPIO. Не зря я о нём сказал.

 

То же самое можно сделать и на связке DMA+таймер (если уж не хочется использовать МК с SGPIO).

 

18 минут назад, AVI-crak сказал:

Это так, только смотреть нужно с другой стороны - время для каждого шага отдельно, и общее их количество. Дабы уйти от дёрганного уродца, недостаточно повышать дробление шага - нужно плавно разгонять и останавливать вращение. Ну а при совместном движении нескольких моторов по криволинейной траектории - иного способа просто не существует.

В прерывании (например 20кГц) рассчитываем последовательность импульсов для следующих 1/20000 сек (хоть идущих с одним периодом, хоть с плавно меняющимся). Кладём это всё в буфер DMA. DMA выплёвывает это всё в таймер.

В след. прерывании вычисляем след.участок.

Ещё лучше использовать SGPIO для этого.

Всё! Никаких ногодрыгов. И выдерживается чёткая времянка импульсов с точностью до такта частоты тактирующей таймер (настолько чёткая, что ногодрыгом её никак не добиться).

Share this post


Link to post
Share on other sites

Eddy_Em
51 minutes ago, AVI-crak said:

Ну а при совместном движении нескольких моторов по криволинейной траектории - иного способа просто не существует.

Да ладно! Моторы даже на 32 микрошагах требуют от силы 100кГц. Так что, даже без всякой синхронизации таймеров все будет отлично  работать: настраиваем таймеры на нужную скорость, да запускаем последовательно.

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

Share this post


Link to post
Share on other sites

AVI-crak
5 minutes ago, mantech said:

Конечно, все прекрасно реализуется изменением частоты по трапеции

Там нет частоты шага двигателя, есть время одного шага. Алгоритмов разгона/торможения несколько десятков. Та самая трапеция подходит только для прямолинейного движения. Для криволинейного движения используются кривые безье, там уже не двигатель важен - а вектор движения исполнительного механизма. Который имеет свою массу, инерцию, и линейную скорость. Поддержка постоянной скорости перемещения исполнительного механизма по криволинейной траектории выполняется обратными расчётами. Рассчитывается точка в которой будет находиться механика через фиксированное время, потом считают насколько нужно довернуть двигатели, коррекция на возможность там появиться, и на их физическое положение. И только после этого появляются дополнительные шаги перемещения. 

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

Аппаратный таймер не способен реализовать весь необходимый диапазон времени для одного шага. Даже простой программный таймер на это не способен. Однако программный таймер на дробных числах - легко с этим справляется. Потому как реализует функцию интерполяции. Там по условию вполне может потребоваться пропустить 1 шаг из тысячи, и общее движение останется плавным.

22 minutes ago, jcxz said:

Что значит "пропускать шаги"?

Программный счётчик на дробных числах uint32_t: старший бит целое число, всё остальное - дробная часть. Общая частота обслуживания всех счётчиков допустим 10КГц (выше нет смысла).

Для того чтобы получить время 200us (5КГц) - достаточно каждый раз прибавлять по  2147483648, это 1 целое и 0 дробное.

Чтобы получить время 199,99999990686us (5000,000002328КГц) - необходимо добавлять  0 целое и 2147483647 дробное.

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

Share this post


Link to post
Share on other sites

jcxz
1 час назад, AVI-crak сказал:

Для того чтобы получить время 200us (5КГц) - достаточно каждый раз прибавлять по  2147483648, это 1 целое и 0 дробное.

Чтобы получить время 199,99999990686us (5000,000002328КГц) - необходимо добавлять  0 целое и 2147483647 дробное.

Ничего не понял - о чём это?  :wacko2:

Если речь о том, чтобы сформировать последовательность импульсов с периодом 199.99999990686мкс, то просто:

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

Допустим частота тактирования таймера = 144МГц. Тогда: 199.99999990686e-6*144e6 = 28799.99998658784;

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

 

В каждом прерывании ISR формируем участок этой последовательности (N импульсов), записываем в DMA-буфер и выходим из прерывания.

Т.е. - одно прерывание, обслуживающее сразу K счётчиков (для каждого свой DMA-поток с величинами длительностей импульсов).

Никакого ногодрыга, пропусков шагов и джиттера фронтов/спадов импульсов (из-за ногодрыга).

 

1 час назад, AVI-crak сказал:

Аппаратный таймер не способен реализовать весь необходимый диапазон времени для одного шага.

Да ладно! С чего бы это? Что именно нельзя сформировать аппаратным таймером, но можно ногодрыгом?

Share this post


Link to post
Share on other sites

mantech
8 минут назад, jcxz сказал:
1 час назад, AVI-crak сказал:

Аппаратный таймер не способен реализовать весь необходимый диапазон времени для одного шага.

Да ладно! С чего бы это? Что именно нельзя сформировать аппаратным таймером, но можно ногодрыгом

И правда, тоже интересно. Дискрет таймера, как правило меньше, чем вход в прерывание, выход из него и какое-то действие, если ногодрыг без прерывания, в цикле осн. программы - это ужас тихий. Единственное в чем соглашусь, использовать ногодрыг когда по-другому нельзя (нет таймеров), низкая частота, ну и работать с ним посложнее, конечно...

Share this post


Link to post
Share on other sites

AVI-crak
9 minutes ago, jcxz said:

Ничего не понял - о чём это?

О том что G код для кривых выдаёт позиции реперных точек, а всё промежуточное контролёр должен рассчитать сам. Там нет таких команд типа "подать частоту шага на двигатель". Ну вот совсем нет, и никогда не было. 

15 minutes ago, jcxz said:

нужно выдать последовательность импульсов длительностью 28799 и 28800 тактов

В этом случае будет 199,993055us и 200us. Допустим двигается только одна ось с переменной частотой. В этом случае у меня будет всего одна ступенька в произвольном месте, когда позиция уже не будет совпадать с возможностями механики. А у тебя явная граница перехода, железобетонная. С дополнительным накоплением ошибки от второй оси.

И ещё, допустим нужна скорость перемещения близкая к нулю - сколько будет делитель у таймера? А если просто остановиться?

Для дробного счётчика таких проблем не существует вообще. А для режима стоп вообще всё красиво, значение перемещения ноль - и мы сохраняем позицию без накопления ошибки.

Share this post


Link to post
Share on other sites

jcxz
13 минут назад, AVI-crak сказал:

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

Ну и рассчитывайте. Кто-ж мешает? Я же пишу: рассчитали вперёд на некоторое время моменты включения/выключения ключа питания двигателя, положили результаты расчёта в буфер DMA, отправляющему их в таймер, и вышли из ISR до следующего расчёта.

Цитата

В этом случае будет 199,993055us и 200us. Допустим двигается только одна ось с переменной частотой.

Т.е. вы думаете, что с помощью GPIO и ногодрыга сможете сформировать длительности импульсов между 199,993055us и 200us при тактовой CPU=144МГц???

И как же это?? Просветите нас, неразумных.  :biggrin:

 

13 минут назад, AVI-crak сказал:

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

В этом случае у вас будет ступенька (из-за кривого алгоритма расчёта, требующего пропуска шага), а у меня - её не будет.

Разницу в 1/28800 длительности шага, любая механика с самой малой инерцией сгладит до 0. Т.е. - её будет незаметно от слова "совсем". В отличие от ваших пропусков.

Share this post


Link to post
Share on other sites

AVI-crak
3 minutes ago, jcxz said:

И как же это??

Это не при 144МГц, а при 10КГц общего счётчика, используя дробные значения для каждого программного счётчика. Каким образом -это я уже в трёх вариантах написал, но могу ещё проще.

Возьми тетрадный лист в клетку, нарисуй кривую, а потом зарисовывай клеточки на которые она попадает. Это и есть реализация программного счётчика с дробным делителем. Клетки - это возможность перемещения, перескочить на новую клетку счётчик может только при переполнении, при этом дробная часть не сбрасывается, и продолжает участвовать в вычислениях дальше. К слову, графика рисуется точно таким-же способом.

Share this post


Link to post
Share on other sites

jcxz
3 минуты назад, AVI-crak сказал:

Это не при 144МГц, а при 10КГц общего счётчика, используя дробные значения

Ещё раз, по слогам:

Как с помощью GPIO и ногодрыга сформировать длительности импульсов между 28799/144e+6 сек и 28800/144e+6 сек при тактовой CPU=144МГц???

[28799/144e+6 > X > 28800/144e+6]  

ЗЫ: Тетради с клетками оставьте себе.

Share this post


Link to post
Share on other sites

AVI-crak
7 minutes ago, jcxz said:

Ещё раз, по слогам:

Повторяю ещё раз - дробный счётчик. На этот раз будем считать на пальцах, как начальных классах. :biggrin:

Счётчик без целой части, только дробная - количество значений 5 (подсказка - это одна рука). Нам нужно за 10 сложений подняться на 3 ступеньки, то-есть должно быть 3 явных переполнения одной руки. 5*3/10=1.5~2 целых пальца.

2+2+2+2+2+2+2+2+2+2

2=4=1=3=5=2=4=1=3=5   5 - остаток дробной части, который дальше участвует в вычислениях.

0=0=1=0=0=1=0=1=0=0  3 ступеньки/переполнения.

Share this post


Link to post
Share on other sites

MDD

А как обычно реализуют обратную связь от энкодера/линейки? Типа так - непрерывный контроль местоположения, и как увидели несоответствие ожидаемому, тут же добавляем или убавляем шаг? Или как-то сложнее?

Share this post


Link to post
Share on other sites

MX_Master
28 минут назад, MDD сказал:

А как обычно реализуют обратную связь от энкодера/линейки? Типа так - непрерывный контроль местоположения, и как увидели несоответствие ожидаемому, тут же добавляем или убавляем шаг? Или как-то сложнее?

Обычно, чем-то типа программного PID. Но в простом виде можно, просто, чуть больше/меньше шагов добавить к следующему заданию.

2 часа назад, AVI-crak сказал:

Возьми тетрадный лист в клетку, нарисуй кривую, а потом зарисовывай клеточки на которые она попадает.

Метод Брезенхема?

Господа, не зацикливайтесь сильно на методе вывода шагов/сигналов. Это не самое сложное. И небольшая дискретность - не самое страшное. Всё это вместе можно воплотить в коде, дав юзеру выбор в настройках. Куда сложнее на лету рассчитывать траекторию на основе контрольных точек из G кода и затем, учитывая все ускорения, делить полученное на одинаковые мелкие кусочки по времени.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.