да я про веремя и не заикался больше, сообщил что Вы неправильно что то посчитали и забыл, то что не совсем совпало, понятно что правильно надо было поделить в нужном месте.
Про натурные испытания это я про график зависимости от количества импульсов. Например здесь рисунок 2-6, показаны шаги с разной продолжительностью по времени, по расчетам в каждом шаге одинаковое количесвто импульсов, когда мы перенесем эти импульсы на равноудаленные расстояния(чтоб создать график зависимость от количества импульсов), график изменится на кривую которая представлена на картинке у дельты
Bad programmers worry about the code. Good programmers worry about data structures and their relationships
среди успешных людей я не встречала нытиков
Барбара Коркоран
Ещё раз прошу. Удалите, пожалуйста свои сообщения #447, #450, #455, #470
Я удалю свои ответы на них. Да, с 2606мс был мой косяк, но я с самого начала и сказал, что "конкретная цифра не важна".
Я почти неделю ждал, пока администраторы меня переименовали.
Не надо осложнять им жизнь.
Я много раз говорил, что "натурные испытания" это добавление лишних сущностей в проблему.
Есть алгоритм -- должен быть график его работы.
Попытка приплести "натурные испытания" для того, чтобы объяснить почему график не соответствует теоретическому описанию это полный бред.
У дельты описана вполне конкретная формула. С чего вы думаете, что "график изменится на кривую которая представлена на картинке у дельты"?
Вот, реально, с чего бы ему измениться?
Каким боком алгоритм "от AVR" относится к дельте? Правильно, никаким.
Хотя бы свой java код посмотрите, и увидите, что зависимость "y" от "i" у вас линейная.
И, да, если построить график "частота от количества импульсов" в равноускоренном разгоне, то он будет выглядеть как "график корня".
steps = a * t2/2
speed = a * t
Т.е. speed = a * SQRT(2*steps/a) == SQRT(2 * a * steps)
Кривая корня выглядит вовсе не так, как кривая на графике дельты.
Последний раз редактировалось Владимир Ситников; 28.09.2016 в 15:41.
В ПЛК110 М02 есть 4 быстрых выхода, с помощью которых можно управлять шаговыми двигателями и серво-системами.
Сам инструментарий для создания "быстрых" программ на текущий момент широкой публике не доступен и обсуждается в теме Программирование ПЛК110 М02 для задач реального времени
Я записался на beta тестирование и мне удалось сделать PRU программу, которая выдаёт указанное количество импульсов на быстрый 3-ий выход.
Должно получиться управление четыремя ШД (одновременно только 2). Один ШД на выходы 1 или 2, второй -- на выходы 3 или 4.
Сама тема "использования PRU" программ пока под вопросом -- ОВЕН пока никак не обозначили свою позицию.
Тем не менее, можно надеяться, что PRU0.prg будет работать и в будущих версиях прошивки ПЛК110.
Внимание, для работы нужно подключать библиотеку pruAccessLib.lib, которую берут тут http://www.owen.ru/forum/showthread....l=1#post180471
2016-12-19: Доступно обновление Hardella IDE 1.6.0: https://hardella.com/blog.
* Блок управления ШД встроен в стандартную библиотеку, пример входит в базовую поставку
2016-10-02: 12-ая версия pru_stepper_v12.zip
* Поправлен цикл задержки. Частота на выходе должна лучше соответствовать уставке.
* "decel_ramp>0 AND enable=false" баг исправлен
2016-10-02: 10-ая версия pru_stepper_v10.zip
* Уж теперь-то 2 ШД должны заработать. Помним, что одновременно могут работать следующие комбинации выходов: 1 и 3, 1 и 4, 2 и 3, 2 и 4.
* За частоту PRU взята 200MHz (совпадает с тестами dima64)
* Убран выходной параметр "READY". Вместо него стоит проверять STATE=STOP_STEPPER.
* Добавлен выходной параметр "CURRENT_SPEED : REAL"
* Изменён тип параметра "STATE" на enum PRU_STEPPER_STATE
* Баг: при ненулевом decel_ramp enable=false не останавливает генерацию
Демонстрация "разгона ПЛК110 М02 до 2МГц": http://recordit.co/XLaOe3LOYE (то же самое в виде анимированного gif: http://g.recordit.co/XLaOe3LOYE.gif )
2016-09-30: 8-ая версия pru_pulse_v8.zip
* Добавлен выходной параметр "количество сгенерированных импульсов"
* За частоту PRU теперь берётся 228МГц, а не 150МГц
2016-09-30: 7-ая версия pru_pulse_v7.zip
* Добавлен параметр "минимальная скорость"
* Параметр OUT_NUM теперь должен работать по-настоящему. Т.е. выбирать номер выхода. Тем не менее, для разных выходов лучше использовать разные экземпляры ФБ PRU_STEPPER.
2016-09-30: 6-ая версия pru_pulse_v6.zip
* не работает
2016-09-29: 5-ая версия pru_pulse_v5.zip
* Исправлено поведение при quantity=0, 1 (т.е. выдаётся 0 и 1 импульс)
* PRU1.prg подхватится, но работать не будет
2016-09-26: 4-ая версия pru_pulse_v4.zip
* Реализован разгон-торможение
* Реализован режим "выдачи нужного количества импульсов без разгона/торможения"
* Реализован "внезапный останов" (включается торможение с текущей позиции)
ШД управляется следующим блоком (pru_stepper.lib):
max_speed/quantity/accel_ramp/decel_ramp можно менять только в состоянии INIT. Т.е. менять на ходу параметры нельзя.Код:FUNCTION_BLOCK PRU_STEPPER VAR_INPUT ENABLE: BOOL; MIN_SPEED: REAL; (* Гц *) MAX_SPEED: REAL; (* Гц *) QUANTITY: DWORD; (* количество импульсов *) ACCEL_RAMP: REAL; (* Гц/сек, положительное. Например, 10000Гц/20сек == 500Гц/сек *) DECEL_RAMP: REAL; (* Гц/сек, положительное. Например, 10000Гц/10сек == 1000Гц/сек *) OUT_NUM: BYTE; (* 1, 2, 3 или 4 *) END_VAR VAR_OUTPUT STATE : PRU_STEPPER_STATE; (* INIT -> ACCEL -> RUN -> DECEL -> STOP *) CURRENT_SPEED: REAL; PULSES_GENERATED: DWORD; END_VAR VAR TMP: DWORD; pru_num : BYTE; bit_num : BYTE; END_VAR TYPE PRU_STEPPER_STATE : ( INIT_STEPPER, (* STEPPER is waiting for new configuration and activation ENABLE=TRUE signal *) ACCEL_STEPPER, (* STEPPER is accelerating *) RUN_STEPPER, (* STEPPER is moving at MAX_SPEED *) DECEL_STEPPER, (* STEPPER is decelerating *) STOP_STEPPER (* STEPPER is stopped and it is waiting for ENABLE=FALSE to switch to INIT state *) ); END_TYPE
ENABLE можно выключать в любое время (будет плавный останов, если исходно был плавный запуск).
Для экстренного останова сначала перевести decel_ramp в 0, а потом уже передавать ENABLE=FALSE -- будет просто останов, без плавного торможения.
Если ACCEL_RAMP равно нулю, то ускорения/замедления не происходит, а просто генерируются QUANTITY импульсов с частотой MAX_SPEED
Если QUANTITY равно -1 (16#ffffffff), то генерируется бесконечное количество импульсов. Генератор работает до перевода ENABLE в false.
До 100кГц должно работать с запасом.
Для использования, нужно залить файлы PRU0.prg/PRU1.prg в контроллер и перезагузить его.
При использовании PRU0.prg/PRU1.prg напрямую работать с fast output 3, 4 не получится. При использовании PRU1.prg выходы 1 и 2 будут доступны только через программу ШД.
Вот несколько графиков, на которых отображена работа библиотеки:
move_100_50_60.png
10pulses_1000_500_60.png
Лицензия: Apache License 2.0
Тестирование выполнялось как на эмуляторе сопроцессора (графики выше получены с эмулятора), так и на реальном сервоприводе.
Последний раз редактировалось Владимир Ситников; 21.12.2016 в 12:09. Причина: 12-ая версия: более точное выдерживание частоты
Понимаю и уважаю это мнение, но, пожалуйста, тема далеко не про вас, не про меня, не про дельту, а про ПЛК110 М02 и его PRU.
Все, кому надо (кто читал тему) уже увидели. Кому не надо -- тому и не надо.
Напишите в дельту -- и спросите у них.
По-моему, мы слишком много времени тратим на дельту в теме про ПЛК110.
Ничего нового оно нам не даёт и не даст.
BETEP правильно сказал. Если и смотреть, то в сторону дальнейшего развития: корректировка по ходу работы, больше чем 1 ШД и т.п.
Товарищи, а не кажется ли Вам, что подход к управлению движением в виде 1 ФБ "сделай всё" в корне не верен?
ИМХО, правильнее было бы разделить задачу на:
1. Вычисление кривой движения (делает основной цикл ПЛК)
2. Деление кривой на N отрезков (опять же основной цикл)
3. Выдача импульсов по отрезкам силами PRU
Проводить сложные вычисления с плавающей точкой (или её эмуляциями) внутри PRU - это много лишнего кода и времени.
Код генератор N импульсов с M периодом и подгрузкой нового отрезка по мере выполнения - гораздо проще и гибче.
Тролль-наседка, добрый, нежный и ласковый
теоретически конечно так, а на практике нужно будет организовывать кэш в памяти ПРУ ( довольно маленькой!), ибо такт основного цикла в 1 мс не сильно подходит для бесшовной передачи новых блоков... а способ "забирать" подготовленные данные средствами ПРУ, по необходимости, из основной памяти пока не понятен
Я бы решал задачи по мере поступления. Конечно, можно год-два потратить на проектирование идеального ФБ (или двух), но по-моему, лучше сделать 1-ую версию хоть какую (но рабочую), а потом уже дорабатывать (или переделывать нафиг) по мере необходимости.
Скажу честно, что я не представляю какие "строительные PRU кирпичики" нужны для того же самого ШД. Я сторонник того, чтобы слушать что просят и фильтровать.
Конечно, есть ещё вариант выпить чаю с кем-то типа Вольда/Прибориста/Newcomer'а/ВЕТЕРа и собрать требований/пожеланий на "ШД мечты", но без понимания требований я никак не могу сказать верен или нет в корне подход "сделай всё".
Конечных же пользователей детали реализации волновать вообще не должны.
Текущая программа работает? Работает.
Параметры удобные? Удобные.
Лишние параметры есть? Вроде, нет.
Какие претензии? Я вовсе не обижаюсь, а просто выступаю адвокатом дьявола.
Ну, реально, если ФБ решает нужную задачу, то зачем его делать "более концептуальным"?
И, да, конечным пользователям "мелкие PRU блоки" всё равно не нужны -- у них нет возможности составлять свои PRU программы. Даже если сделать "концептуально" в виде "PRU кирпичиков", то конечные пользователи всё равно не поймут разницы, т.к. они что так, что сяк, не могут составлять PRU программы.
Будет более сложная задача -- будем решать, и, вполне возможно, делить задачи между HOST и PRU.
Непосредственно сейчас у меня 2 задачи:
1) Либо завести PRU1. Сейчас PRU1.prg не подхватывается:
2) Либо сделать управление двумя ШД в рамках PRU0. На текущий момент я упираюсь в количество регистров PRU (все R1...R29 используются, не хватает 4 DWORD регистров). Тут я либо найду какую-нибудь лишнюю переменную, либо сделаю register spilling (временную выгрузку ненужных регистров в оперативную память).Код:................................................ Retain init Slave Retain loaded EEPROM init PRU0 user programm loaded Dublicate PRU programm PRU1 user prg not loaded!
Некая проблема, что все переменные у меня DWORD (step_count, max_speed, quantity, accel_ramp, decel_ramp, accel_count, decel_count, step_delay) и ещё несколько BYTE переменных. Т.е. один блок занимает ~12 регистров. Два занимают 24 и уже на временные вычисления не особо хватает. Не то, чтобы прямо беда, но ограничение даёт о себе знать.
Более того, можно даже опрос провести: сколько разработчиков (из тех, которые употребляют ШД в проектах) смогут правильно составить и протестировать код разгона ШД?
Я вовсе не к тому, что "я тут самый умный".
Я к тому, что задача действительно непростая, и конечному пользователю блок типа "Выдача импульсов по отрезкам" будет практически бесполезным. Конечному пользователю нужен именно высокоуровневый API типа "пододвинуть ШД на столько-то импульсов", "ой, всё, двигай назад" и т.п.
1) В текущей моей программе на каждом шаге выполняется одно деление и несколько сложений.
Есть смысл выносить одно это деление в HOST?
На мой взгляд, это лишь повысит сложность и хрупкость системы.
2) На мой взгляд, управление требует знания текущей скорости/положения. Одно дело, когда ШД стоит на месте, и HOST спокойно планирует движение, и совсем другое дело, когда ШД едет куда-то, и внезапно сказали "ехать по-другому". У PRU процессора есть актуальная информация. У HOST'а информация неактуальна.
Тут, на мой взгляд, разумно, чтобы HOST вычислял "общее движение", и передавал в PRU команды одно-два ближайших движения. Одно движение -- одна "трапеция". Но это, конечно, вилами по воде. Будут конкретные задачи -- посмотрим.
3) На текущий момент эмулятор PRU есть, а эмулятора КДС.lib нет.
Сейчас я в пару щелчков мышкой получаю картинки про то, какой будет разгон-торможение при различных входных параметрах.
Я даже могу сделать тест, который последовательно попробует сгенерировать 10, 11, 12, ... 100'000 импульсов и проверит, что при каждом из этих значений на выходе генерируется ровно нужное количество импульсов и т.п. Просто ноутбук ночь (или сколько там) поработает и всего делов. Зато будет ясно, что количество импульсов всегда соответствует нужному значению.
Если же выносить логику в КДС.lib (конечно, в отдалённом будущем оно звучит правильно), то сейчас я потеряю возможность тестировать код на эмуляторе. Придётся делать эмулятор КДС.lib кода.
Если вы следили за темой, то, надеюсь, заметили, что все мои программы с первого раза работали в железе.
С единственным исключением: pruAccessLib.lib мне далась не с первого, а со второго раза, т.к. я не понимал как работает эта библиотека. Так вот: переносить код в в HOST, конечно, можно, но прямо сейчас для меня это осложнит тестирование.
Интересный вопрос -- управление медленными выходами из PRU программы.
Например, выход "направление вращения" вполне можно делать медленным выходом и не "тратить" на него быстрый.
Но при этом, придётся управлять этим самым "выходом для направления" из обычного ПЛК цикла -- т.е. возможны косяки, что цикл ПЛК затянулся, и всё. Что PRU должен делать? Ждать отмашку от HOST'а, что "направление переключилось, можно двигать"?
Проще и менее хрупко смотрелось бы, если бы команды на медленный выход отдавал тот же PRU, и без ожиданий.
Если я правильно понимаю, то в случаях "проскальзываний" это пригодилось бы.
Т.е. мы подали на ШД команду "двигайся на 1000 импульсов". Он, такой, сделал 800, начинает тормозить, а ему говорят: "слушай, надо не 1000, а 850". Т.е. по факту, программе придётся затормозить, а потом отъехать назад. Тут было бы проще, если бы сам PRU код понимал и управлял "в какую сторону едем".