Master of magic
Oct. 6th, 2017 01:16 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Наткнулся в некоей чужой системе на красиво реализованный ramp-up шагового мотора. Код утянут с общедоступного Атмеловского, а тот, в свою очередь, основан вот на этой публикации за авторством David Austin. А коль всё и так известно, то можно и рассказать.
В двух словах задачка формулируется следующим образом: чтобы обеспечить линейный разгон мотора, время каждого шага должно расчитываться как
. Брать корень на каждом шаге -- это очень накладно. И, как будто проблем мало, вычитание приводит к потере точности.
David красиво сводит задачу к отношению времён двух смежных пульсов, которое аппроксимирует первыми членами ряда Тейлора, получая магическое Cn = Cn-1 -- 2Cn-1/(4n + 1). И это прекрасно работает в текущем коде системы, обеспечивая линейный и предсказуемый рамп как вверх, так и вниз.
Вот только... линейный разгон -- плохое решение, сразу по многим причинам. Во-первых это долго. Мотор мучительно пробирается через низкочастотные резонансы. Запас по моменту на низких оборотах не используется, а нехватка его на высоких вынуждает снижать ускорение. Торможение с больших оборотов перегружает питание. И так далее, и так далее... Гораздо лучше получается, если вести разгон, задавшись постоянством энергии, добавляемой в систему на каждом шаге, то есть Δv2 = const. При этом (не было печали) длительность пульса начинает зависеть не от квадратного, а от кубического корня от номера.
Так вот чего я придумал: если волшебную формулу изменить на Cn = Cn-1 -- Cn-1/(3n + 1), то рамп становится правильным, корнеквадратичным. Пока получено и проверено эмпирически, завтра надо аккуратно теорию расписать, тоже через разложение в ряд Тейлора :).
В двух словах задачка формулируется следующим образом: чтобы обеспечить линейный разгон мотора, время каждого шага должно расчитываться как

David красиво сводит задачу к отношению времён двух смежных пульсов, которое аппроксимирует первыми членами ряда Тейлора, получая магическое Cn = Cn-1 -- 2Cn-1/(4n + 1). И это прекрасно работает в текущем коде системы, обеспечивая линейный и предсказуемый рамп как вверх, так и вниз.
Вот только... линейный разгон -- плохое решение, сразу по многим причинам. Во-первых это долго. Мотор мучительно пробирается через низкочастотные резонансы. Запас по моменту на низких оборотах не используется, а нехватка его на высоких вынуждает снижать ускорение. Торможение с больших оборотов перегружает питание. И так далее, и так далее... Гораздо лучше получается, если вести разгон, задавшись постоянством энергии, добавляемой в систему на каждом шаге, то есть Δv2 = const. При этом (не было печали) длительность пульса начинает зависеть не от квадратного, а от кубического корня от номера.
Так вот чего я придумал: если волшебную формулу изменить на Cn = Cn-1 -- Cn-1/(3n + 1), то рамп становится правильным, корнеквадратичным. Пока получено и проверено эмпирически, завтра надо аккуратно теорию расписать, тоже через разложение в ряд Тейлора :).
UPD: Расписал, да, сходится, только коэффициенты всё же не 1 и 3, а 2 и 6, или Cn = Cn-1 -- 2Cn-1/(6n + 1), так как taylor{(1+-x)^2/3, 0} -> 1 +- 2/3x -1/9x^2 + O (x^3), а дальше тривиально. Ну чё, я молодец :)