std 8 20 марта, 2022 Опубликовано 20 марта, 2022 · Жалоба Требуется subj для пересчета в run-time. STM32 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 20 марта, 2022 Опубликовано 20 марта, 2022 · Жалоба Требуется Функция расчета period и prescaler таймера для пересчета в run-time. STM32 Вообще-то, период (или результирующая частота) - это исходное данное вместе с тактовой частотой. У вас что в наличии? Ну и поделить для 32-битного ядра уж много лет, кмк, не проблема ;-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 20 марта, 2022 Опубликовано 20 марта, 2022 · Жалоба Задача сводится к подбору двух множителей, чье произведение дает число, наиболее близкое к заданному. Тьма же алгоритмов по разбиению числа на простые множители! Затем просто подобрать множители так, чтобы каждый не превышал 65535. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
std 8 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба 21.03.2022 в 02:09, Eddy_Em сказал: Задача сводится к подбору двух множителей, чье произведение дает число, наиболее близкое к заданному. Тьма же алгоритмов по разбиению числа на простые множители! Затем просто подобрать множители так, чтобы каждый не превышал 65535. К чему это сводится, как это написать известно. В том числе что простые тут ни причем, а причем целые. И что задача называется факторизация. И что она решается не столь примитивно (перебором, "подобрать"), что это типичная задача минимизации. Спасибо, но вопрос (если внимательно прочесть) был о готовой C функции. Дело во времени. Теплилась слабая надежда что хоть в интернете днем с огнем не найти, но может быть у кого-то из професисоналов завалялась... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 24 марта, 2022 Опубликовано 24 марта, 2022 (изменено) · Жалоба Самый простой способ — тупой перебор (как здесь или здесь), а вообще, гугол по запросу "arr psc calculation" дает очень много интересного. Советую посмотреть. Я и сам когда-то подобное делал, тоже ничего, лучше перебора, не придумал. А в задачах регулирования скорости шаговиков, делаю просто: PSC выдает максимально возможную частоту, а ARR уже вычисляется по заданной скорости. Потом происходит персчет и пользователю возвращается реальное значение скорости. Можно еще здесь почитать. Но алгоритмы уж больно зубодробильные. По-моему, для микроконтроллера проще будет таки подобрать из нескольких множителей с определенным шагом. Задача осложняется своей нечеткостью: нам нужна пара множителей, дающая как можно более близкое число к заданному, а не строгое разложение этого числа на множители. Изменено 24 марта, 2022 пользователем Eddy_Em Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 24 марта, 2022 Опубликовано 24 марта, 2022 (изменено) · Жалоба Могу предложить две функции перебора. Первая перебирает все варианты до достижения нулевой или наименьшей ошибки. Вторая перебирает, начиная с некоторого большого числа (для уменьшения количества итераций). #include <limits.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <stdint.h> #include <time.h> uint16_t factorize1(uint32_t in, uint16_t *o1, uint16_t *o2, uint16_t *niter){ uint16_t min = 0xffff, minI = 2, i; *niter = 0; for(i = 2; i < 0xffff; ++i){ ++(*niter); uint32_t a = in/i; if(a > 0xffff) continue; uint16_t d = abs(in - i*a); if(d < min){ min = d; minI = i; } if(min == 0) break; } *o1 = in/minI; *o2 = minI; return min; } uint16_t factorize2(uint32_t in, uint16_t *o1, uint16_t *o2, uint16_t *niter){ if(in < 0xffff){ *o1 = 1; *o2 = (uint16_t) in; return 0; } uint16_t x = 0x8000, d = 0; while(d < 2){ d = in/x; x >>= 1; } if(d < x) d = x; uint16_t min = 0xffff, minI = 2, i; *niter = 0; for(i = d; i < 0xffff; ++i){ ++(*niter); uint32_t a = in/i; if(a > 0xffff) continue; uint16_t d = abs(in - i*a); if(d < min){ min = d; minI = i; } if(min == 0) break; } *o1 = in/minI; *o2 = minI; return min; } int main(int argc, char **argv){ uint64_t n1 = 0, n2 = 0, p1 = 0, p2 = 0; double N = 0.; time_t t = time(NULL); //for(uint32_t i = 1; i < 0xffffffff; ++i){ while(1){ ++N; uint32_t i = lrand48() & 0xffffffff; uint16_t n, o1, o2; p1 += factorize1(i, &o1, &o2, &n); n1 += n; p2 += factorize2(i, &o1, &o2, &n); n2 += n; if(time(NULL) - t > 2){ t = time(NULL); printf("n1=%lu, n2=%lu\n", n1, n2); printf("1: <p> = %g, <n> = %g\n", p1/N, n1/N); printf("2: <p> = %g, <n> = %g\n", p2/N, n2/N); } } return 0; } Вот, оно у меня уже больше минуты тарахтит, выдает: n1=33788041246, n2=15611890071 1: <p> = 2.25199, <n> = 50895.8 2: <p> = 76.721, <n> = 23516.6 Т.е. среднее количество итераций в первом случае - около 51 тысячи. Во втором - около 23.5 тысяч. Однако, погрешность в первом случае лучше трех, а во втором - хуже 75! Второй "алгоритм" допускает приличную погрешность даже для небольших чисел. Но 51 тысяча операций деления и умножения — это, конечно, нечто! Надо пробовать через сдвиги как-то упрощать. В простейшем случае - использовать первую функцию, но начальный итератор вычислять, деля входное число на 0xffff. (тогда и проверку (a>0xffff) можно убрать) Изменено 24 марта, 2022 пользователем Eddy_Em Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба ...оно у меня уже больше минуты тарахтит, выдает... 51 тысяча операций деления и умножения "Три дня и три ночи скакал Иван Царевич... покуда скакалку не отобрали." \-8Ж Коэффициенты допустимы ж не на всём диапазоне... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 25 марта, 2022 Опубликовано 25 марта, 2022 (изменено) · Жалоба Можно и точность задавать в явном виде: uint16_t factorize(uint32_t in, uint16_t prec, uint16_t *o1, uint16_t *o2){ uint16_t min = 0xffff, minI = 2, i; uint16_t start = (uint16_t)(in / 0xffff); if(start < 2) start = 2; for(i = start; i < 0xffff; ++i){ uint32_t a = in/i; if(a > 0xffff) continue; uint16_t d = abs(in - i*a); if(d < min){ min = d; minI = i; } if(min < prec) break; } *o1 = in/minI; *o2 = minI; return min; } prec можно вычислять по заданной точности и в самой функции. Скажем, если точность 1%, то prec=1+in/100 Изменено 25 марта, 2022 пользователем Eddy_Em Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
std 8 31 марта, 2022 Опубликовано 31 марта, 2022 · Жалоба Ну, в общем, всё перебором закончилось 24.03.2022 в 16:38, Eddy_Em сказал: А в задачах регулирования скорости шаговиков А вот это интересно. С таймерами STM32 я доселе дело имел поверхностно, сигнал генерировал, но без тщания. Количество импульсов сигнала STEP и управление "полками" было реализовано программно. Прерывание по таймеру, все остальное программно. ISR всегда приводило уровень на выходном порте в гарантированно известное состояние, так как недопустимо потерять пол-импульса (полку), а также необходимо останавливать двигатель строго в определенных фазах микростеппинга и на определенной полке. Хочется выдавать STEP полностью аппаратно. Иной кандидатуры кроме как аппаратный вывод таймера пока не усматриваю. В связи с чем и вопрос. Таймеры STM32 это целая вселенная. Тщательная вычитка документации, изучение либ типа Marlin сама по себе задача не на один день. Мне бы для экономии времени получить бы добрый совет, на каком именно типе таймера сосредоточиться, какие есть методы управления и подводные камни? Может быть на что-то глянуть, короче, нужна какая-то отправная точка с таймерами и предсказуемым управлением выходом таймера для того чтобы получать строго определенное колчество импульсов STEP ШД и приводить вывод в известное состояние. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 31 марта, 2022 Опубликовано 31 марта, 2022 · Жалоба 1 час назад, std сказал: для того чтобы получать строго определенное колчество импульсов STEP ШД и приводить вывод в известное состояние. Ну "приводить вывод в известное состояние" довольно просто - надо использовать режим ШИМ(PWM). В конце периода он в строго определенном состоянии. Строго определенное количество импульсов - подсчетом в прерывании. Я не знаю что у вас за задача, когда я писал контроллер шагового двигателя, у меня в любой момент могла прилететь команда на разгон/торможение и ждать "строго определенного количества импульсов" было просто нельзя. Поэтому я считал импульсы в прерывании сответствующего канала таймера. P.S. для реализации (почти) линейного разгона/торможения шагового двигателя вам может быть полезна эта статья: Generate stepper-motor speed profiles in real time. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
std 8 31 марта, 2022 Опубликовано 31 марта, 2022 · Жалоба 8 часов назад, Сергей Борщ сказал: Ну "приводить вывод в известное состояние" довольно просто - надо использовать режим ШИМ(PWM). В конце периода он в строго определенном состоянии. Строго определенное количество импульсов - подсчетом в прерывании. Я не знаю что у вас за задача, когда я писал контроллер шагового двигателя, у меня в любой момент могла прилететь команда на разгон/торможение и ждать "строго определенного количества импульсов" было просто нельзя. Поэтому я считал импульсы в прерывании сответствующего канала таймера. P.S. для реализации (почти) линейного разгона/торможения шагового двигателя вам может быть полезна эта статья: Generate stepper-motor speed profiles in real time. Спасибо! Буду знать. Правда если я буду подсчитывать импульсы в прерывании (я же правильно понял что каждый импульс STEP - прерывание?), то прерывания в режиме микростеппинга 1/32...1/256 идут очень часто и будут все равно грузить процессор. А я хотел этого избежать, целиком полагаясь на аппаратуру таймера. Подсчитывать импульсы необходимо, поскольку в новом конструктиве хоть и будет угловой энкодер, часть старых конструкций в начале калибруется по оптическому датчику и затем поддерживает положение ротора ШД, полагаясь только на количество шагов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 1 апреля, 2022 Опубликовано 1 апреля, 2022 · Жалоба Генерирую ШИМ: по 1 таймеру на двигатель. В прерывании CCEV считаю микрошаги, если получилось целое количество шагов, проверяю — не пора ли остановиться (нет смысла тормозить двигатель в неустойчивых положениях между шагами, а напряжение удержания я всегда снимаю: не хватало еще, чтобы внутри оптических приборов была печка!). Вот - одна из моих недоделок (все оси пока работают независимо, для меня этого полностью хватает, но если соберусь ЧПУ делать, нужно тактировать все шаговики от одного таймера и заменить STM32F0 на F303 — иначе "мощей не хватит"). Умеет работать с USB (простой удобный текстовый протокол: просто открываешь терминал и пишешь команды/читаешь ответ) и CAN (тоже нормальный протокол, не извращенный вроде CANopen). На каждой оси сидит энкодер, позволяющий в т.ч. удерживать вал в заданном положении, если его кто-то начнет сдвигать с места. Правда, от люфтов это на гайка-винт не избавит (но линейные энкодеры дюже громоздкие и дорогие), но мне несложно в лабораторных условиях определить величину люфта и потом его программно выбирать, аналогично с гнутием осей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 3 апреля, 2022 Опубликовано 3 апреля, 2022 · Жалоба On 4/1/2022 at 7:14 AM, Eddy_Em said: но если соберусь ЧПУ делать, нужно тактировать все шаговики от одного таймера и заменить STM32F0 на F303 — иначе "мощей не хватит") а как вы собираетесь исполнять программу? есть axis manager? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Eddy_Em 2 3 апреля, 2022 Опубликовано 3 апреля, 2022 · Жалоба Нет, этого я еще не писал. По идее, на гитхабе есть разнообразные парсеры. Другое дело, что они скорей всего для моего случая не будут годиться, в общем, наверняка придется свое писать. Если от парсера не требовать сложных вещей (только движение по отрезкам с заданной предельной скоростью), реализуется он достаточно элементарно. Возможно, даже F0 хватит. А вот если требовать самостоятельно по коническим сечениям бегать, придется задействовать F303 и долго думать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться