Сидел тут разбирался как marlin работает со фидрейтом/ускорением, решил опубликовать записки по алгоритму. Начинаем с момента когда мы нашли G1:
// обработчик GCODE (marlin.pde)
1) Парсим координаты XYZE
2) Парсим F (ставим next_feedrate = F и, если найденное значение больше нуля (а F можно передать отрицательное значение?) - то и текущий фидрейт тоже)
3) Если включен FWRETRACT: если авторетракт включен (M209) и если в G1 нет движений по XYZ, но есть по E то: если засасываем на больше чем MIN_RETRACT(т.е. это ретракт), поднимаем по Z на zlift, исправляем объем ретракта и фидрейт ретракта(задаются в M207); если выплевываем больше чем на MIN_RETRACT(рестарт), корректируем объем и фидрейт(M208),
но почему-то не возвращаем Z вниз4) Проверяем на попадание движения в софтовые ограничения размера платформы
5) Умножаем фидрейт на фидрейт мультиплайер (M220 Sxxx)
// планнер (planner.cpp)
6) Если буффер планировщика полный - ждем пока появица место под команду
7) Если PREVENT_DANGEROUS_EXTRUDE, он включен (M302 отключает) и температура экструдера ниже желаемой, выкидываем движение по E как если его не было (считаем что текущие абсолютные координаты равны тем, которые мы должно были получить)
8 ) Если PREVENT_LENGTHY_EXTRUDE и длина экструзии больше EXTRUDE_MAXLENGTH - как в пункте 7
9) Считаем по какой оси будет самое большое перемещение (учитывая extrudemultiply, который задается через M221 Sxxx), если это перемещение меньше чем dropsegments (configuration_adv.h), то забиваем на эту команду (текущая позиция остается прежней, соответственно следующая пройдет по гипотенузе)
10) Включаем моторы осей (если Z_LATE_ENABLE, то не включаем мотор Z) и экструдеров(всегда всех трех)
11) Проверяем что текущий feedrate не меньше чем minfeedrate для экструдирования, и mintravelrate для перемещений без E
12) Если нет движений, а тока экструзия, то размер движения = размер экструзии, иначе только по осям sqrt(X^2+Y^2+Z^2)
13) Считаем скорость перемещения (inverse_second) == фидрейт/размер движения
14.1) Если стоит OLD_SLOWDOWN и буфер заполнен меньше, чем на половину, то фидрейт уменьшается пропорционально заполнению количеством команд
14.2) Если стоит SLOWDOWN и буфер заполнен меньше, чем на половину, то считаем время сегмента в мкс (1e6/inverse_second) и он оказывается короче, чем MINSEGMENTTIME (M205 Bxxx), то замедляем движение через inverse_second
15) Для каждой оси считается текущая скорость (delta_mm*inverse_second), и если превышает макс. скорость оси(DEFAULT_MAX_FEEDRATE или M203) то замедляем всю скорость чтобы попал в эту ось (общий коэффициент speed_factor)
16) Если XY_FREQUENCY_LIMIT, проверяем была ли смена направления вращения мотора по осям, если да, то: для каждой оси выбираем самый долгий сегмент из трех, между осями выбираем меньший, и сравниваем с (1e6/XY_FREQUENCY_LIMIT), если оказывается меньше - то замедляем всю скорость (speed_factor).
17) Окончательно рассчитываем скорость с применения спид_фактора для всех осей.
18) Делим максимальное количество шагов по одной из осей на длину всего движения и умножаем на ускорение (M204 Sxxx) - это нормальное ускорение в шагах/сек^2
19) Если нормальное_ускорение*размер_сегмента_по_оси_в_шагах/максимальный_сегмент_в_шагах больше максимального ускорения по этой оси(M201) - замедляем нормальное ускорение
20) Делаем обратную 18й операцию с нормальным ускорением - это ускорение для этого блока
--Расчет поворотов
21) jerk - это вектор изменения скорости, т.е. считается как sqrt((cur_speed_x-prev_speed_x)^2+(cur_speed_y-prev_speed_y)^2+(cur_speed_z-prev_speed_z)^2)
22) Если текущий jerk>max_xy_jerk (или любой другой из max_??_jerk) - вводим замедляющий фактор
23) Максимальная скорость входа в текущий сегмент - min(скорость прошлого сегмента, jerk*замедляющий_фактор)
24) Допустимая скорость входа в текущий сегмент - такая, чтобы за размер этого сегмента с максимальным допустимым для него ускорениям мы могли замедлиться до нуля в рамках сегмента
25) Реальная скорость входа в сегмент - min((23),(24))
26) С учетом этого у предыдущего сегмента обновляется его номинальная скорость
27) Считаем алгоритм ADVANCE'а.. основная идея вот тут
http://reprap.org/pipermail/reprap-dev/ ... 03323.html (надо попробовать)
28) Пересчитываем весь план (проходим в обратном порядке, с учетом jerk'а замедляем скорости, а потом снова в хронологическом порядке и пробуем их поднять обратно)
Не знаю уж насколько это кому-то будет полезно, но у меня какое-то количество мыслей вызвало..