Open programmeddeath1 opened 4 days ago
You could try to reduce the forward planning time to a bare minimum using setForwardPlanningTimeInMs(uint8_t ms)
. If the motor behaves strangely, then the queue has run out of commands. I would assume, that on esp32 5ms could still work. It must be for sure larger than 4ms stepper task cycle time.
On the other side, with this high degree of control of the motion is the ramp generator in use at all ?
Another try is to reduce the stepper task cycle time below 4ms. This can be done only by changing the code in this function: https://github.com/gin66/FastAccelStepper/blob/e57f7b4fe676d5ea3ee44a0048b92d1770e5c7da/src/StepperISR_esp32.cpp#L107
If this is e.g. 1ms and forward planning time is e.g. 2ms, this should be quite performant. If the cpu can cope with this load is another question. I think you need to ensure, that wifi and stepper are running on different cores.
If this is successful, then I can extend engine.init with cycle time as an optional parameter
Hi Thank you for your quick response!
1) Do i have to set setForwardPlanningTimeInMs for each stepper ?. Any reference or example would be helpful.
2) Also I will incrementally test with 15 ms 10 ms and then go to 5ms. For now even reaching 8ms, would be a great improvement in performance for me. The end goal being trying to push the device and see how performant it gets, I will later test in a more controlled environment, for going below 5ms, where changes need to be made in the ISR Code.
3) Regarding your question, I too had a doubt since you have mentioned the in the readme regarding multi-axis control that the library's ramp generator would be less useful and its recommended to implement low-level access directly using the library, At what point would the ramp generator prove insufficient? would that depend on how low I am going with my cycle time?
Yes. The forward planning time needs to be set for each stepper and will be kept. In case a new stepper is allocated afterwards, then the forward planning time will be adjusted for all allocated steppers again. This will overwrite any earlier setting. If the forward planning time is set after all steppers are allocated, then the new value will be used and not overwritten anymore. This mean, if the steppers are allocated and configured in a loop, then the forward planning time need to be set in a second loop following the stepper allocation loop.
Thanks for your support in testing this functionality to the limits. Until now, I have only found a simulator for avr uCs. Great would be an esp32 simulator, so I can set up automated testing to check some of these advanced API features. Until then, those advanced features are only by design and not tested by me.
As I understand your use of FastAccelStepper the ramp generator will always ensure the limits for maximum acceleration and maximum speed. By design this is independent from the cycle time - unless there is any hardcoded value or implicit assumption in the code, which I do not believe, but am not 100% sure about. So there is no point, where the ramp generator will be insufficient. Just that the expectation of how the steppers should perform and the actual executed steps may not match, because of the constraints the ramp generator imposes on the stepper movements.
My expectation of the ramp generator is, that independent of the rate or magnitude of the changes in position/speed/acceleration, the stepper must always run within the limits of max speed/acceleration and always on the shortest round to the targeted position or speed.
I tried adding ForwardPlanningTime as below -
engine.init();
for (int num = 0; num < MOTOR_COUNT; num++) {
// Input for Limit Pins
pinMode(MOTOR_LIMIT_PINS[num], INPUT_PULLUP);
stepper[num] = engine.stepperConnectToPin(MOTOR_PUL_PINS[num]);
if (stepper[num]) {
stepper[num]->setDirectionPin(MOTOR_DIR_PINS[num]);
// You might also need to set enable pin if you have one
setMotorSpeedInMMPerSec(num, SPEED_IN_MM_S);
setMotorAcceleration(num, ACCEL_IN_MM_S);
}
}
// Set future planning time limit for lower control cycles
for (int num = 0; num < MOTOR_COUNT; num++) {
stepper[num]->setForwardPlanningTimeInMs(10);
}
I tried with values 5, 10, 15. I didn't see any difference in my motion. I will attach videos of my execution to help you understand what the issue could be: Control Cycle = 0.02 secs
https://github.com/user-attachments/assets/c4eb0143-4654-4871-93a6-91e463d952ac
Control Cycle = 0.01 secs
https://github.com/user-attachments/assets/e4a2d040-e190-478e-9d35-9cd4be0da6cd
Control Cycle = 0.01 secs with fixed delay of 3ms
https://github.com/user-attachments/assets/a89207d0-1fc0-4413-aa99-1c7b8d61ae9a
The control Cycle of 0.01secs run with fixed dalay of 3ms, shows that the motion plan generates points based on smaller control cycle and follows the actual C path, but the execution at the esp end is suspect. Note: Just download the videos and play for now, for some reason its not playing on github directly
Thanks for sharing the video. Gives an idea, how you use the system.
Your sequence of the initialization is ok: First the motor, then the forward planning time
From the code in FastaccelStepper I only see, that in this line the condition should be put in brackets ()
https://github.com/gin66/FastAccelStepper/blob/e57f7b4fe676d5ea3ee44a0048b92d1770e5c7da/src/FastAccelStepper.cpp#L386
Besides this, I cannot find anything suspicious in the code. If I find time the next days, I will make a test case running on simavr to check, that this function works as expected.
From the video I am not convinced, that the issue is related to FastAccelStepper. It could be network performance via UDP. This connection may lag due to WiFi communication, esp32 UDP/wifi stack implementation or esp32 task management. I assume, there is no flash write somewhere in the code. Perhaps it is a good idea to add a timestamp to the UDP commands and check on esp32 side, if expected UDP commands have arrived too late.
https://github.com/user-attachments/assets/8a64b1f6-24f5-412b-a932-7d2270bc7a50
https://github.com/user-attachments/assets/70b4aca0-068f-441b-9f00-47cba3e71899
I have tracked the message communication and acknowledgment times, for both the control cycles, and even control cycles as low as 0.005, the messages do not lag, The ack1 is sent as soon as the esp receives the message, and ack2 is sent after the fastaccelstepper setPoint/vel/accel commands for the 3 motors and vacuum triggers on the GPIO are executed -
Thanks for checking, that UDP is not the issue. So there are two possibilities:
()
around the conditionAs mentioned, that I can add a test case only within a few days to check the general function. Besides the mentioned brackets, which may be the root cause, I am confident, that the feature is working on FastAccelStepper side.
1) Sure, Ill make the changes and test once with the brackets around the condition but Im not sure if this can change anything since the order precedance is the same even with the brackets.
2) Regarding skipping the ramp generator and generating the commands directly from the UDP commands, can you provide any references as to how to go about this? I checked your low-level access comments and got a gist of it, but some reference would be really helpful.
If we can identify that FastAccelStepper is not the issue, then we might have to investigate on the driver and motor end. Most AC Servo drivers come with response times in the range of 10us, so that was planned to be my last option to investigate if we are reaching physical limits of the motors in terms of response times. You can check on your end as and when you get time, ill make the changes and see if it yields me any results
On master branch I have added a test case to check, if
setForwardPlanningTimeInMs()
works as expected and I have added the mentioned brackets for clarity. From my side, I do not see the reason for the observed behavior. Sorry for this.
From the video it appears, the stepper gets the command to stop or decelerate during movement. This does not hint to servo driver response time or physical limits of the motor.
In your first post, it can be observed, that the acceleration is in consecutive calls jump around the three values -21.37/0/+21.37. Could it be, that those initiate those stops ?
As this pick and place robot performs a complex motion for the steppers, it is not so obvious, what is correct behavior. How to determine, if the generated positions being sent via UDP are correct ?
I have a esp32 controlling 3 AC Servo motors of a delta robot with a maximum RPM of 3000 and an entire motion plan sent to the esp32 over UDP at a rate 1.12ms per message.
I am trying to execute motions on the esp32 using FastAccelStepper at two different control cycles - 0.02 (ie a point every 20ms) and 0.015( a point every 15ms) run at a max velocity of 1500 RPM. The motion plan for the two control cycles for the same positions is as follows -
CC = 0.015
as I reduce the control cycle to 0.01 and lower the motion seems laggy during the return motion, i.e it seems like it is jumping steps or getting overridden by the next point. My objective is to achieve as low a control cycle as possible for smoother motions, We were earlier using UART and thought that was the bottleneck, but we have shifted currently to UDP and are sending msgs at 1.12ms times, so the current bottleneck now seems to be the way FastAccelStepper generates the motion and whether it is able to update at such high frequencies.
Your input would be greatly appreciated as you would have a better understanding of its capabilities, I am not able to figure out what the issue could be.
Thank you for your help in advance!