Closed KentDub closed 5 years ago
Thanks for the diagnosis and pull request. I think a cleaner solution would be to avoid casting the unsigned char to an int, that was sloppy on my part. From inspection it looks like changing
void SwitecX12::step(int dir)
to
void SwitecX12::step(char dir)
should work.
Thank you KentDub! Your solution works, also for ESP32! guyc, I tried yours too, but it doesnt appear to work.
Actually, that solution doesnt quite work. When moving CW, it works. But CCW, "vel" stays at 1, so it moves very slowly. Looking for a solution, but help would be appreciated.
I could help this weekend or next week
Get Outlook for iOShttps://aka.ms/o0ukef
From: R5fan notifications@github.com Sent: Thursday, October 26, 2017 6:27:18 AM To: clearwater/SwitecX25 Cc: Kent Williams; Author Subject: Re: [clearwater/SwitecX25] Fix char/int conversion issue (#11)
Actually, that solution doesnt quite work. When moving CW, it works. But CCW, "vel" stays at 1, so it moves very slowly. Looking for a solution, but help would be appreciated.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/clearwater/SwitecX25/pull/11#issuecomment-339622533, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AMAS1vwa9C5FbFruNa2tXWfYO_70yfN0ks5swF6GgaJpZM4NoYnx.
Thanks. I got it working now, but Im running in to another problem.
Occasionally, currentStep will go negative (and rollover, since its an unsigned int), and the stepper will get stuck moving CCW. Im not sure I understand why; I was monitoring dir, and it always was -1,0 or 1, and nothing else defines currentStep. I suspect it has to do something with the fact Im calling update() in a timer interrupt, but I have to do that since my display library is blocking and takes forever to refresh. (edit: scratch that, I disabled my display and put update in the main loop, and it still happens)
As a temp solution, I made currentStep a signed integer, but if its negative, it will keep getting more negative. So I reset it to zero if its negative, but I'll lose steps this way.
If it helps, I added some debug code in the main loop that puts out CurrentStep every 100ms , and inside the library I test if if CurrentStep goes negative, or if dir is anything other than -1,0 or 1, and if so, I output some extra variables. This is the output:
motor1.currentStep863 motor1.currentStep1045 motor1.currentStep1178 motor1.currentStep1334 motor1.currentStep1638 motor1.currentStep2287 motor1.currentStep1380 motor1.currentStep1064 motor1.currentStep45 currentStep-1 targetStep93 dir:-1 vel:1 currentStep-2 targetStep95 dir:-1 vel:1 currentStep-3 targetStep97 dir:-1 vel:1 currentStep-4 targetStep99 dir:-1 vel:1 currentStep-5 targetStep101 dir:-1 vel:1
Before I changed currentStep to a signed integer, it would become like 4294954174, but that gives the same problem.
Not sure if this is the case, but in programming it is possible to not only have 0, but also -0. That leaves possible states as -1, -0, 0, 1.
Get Outlook for iOShttps://aka.ms/o0ukef
From: R5fan notifications@github.com Sent: Thursday, October 26, 2017 8:19:00 AM To: clearwater/SwitecX25 Cc: Kent Williams; Author Subject: Re: [clearwater/SwitecX25] Fix char/int conversion issue (#11)
Thanks. I got it working now, but Im running in to another problem.
Occasionally, currentStep will go negative (and rollover, since its an unsigned int), and the stepper will get stuck moving CCW. Im not sure I understand why; I was monitoring dir, and it always was -1,0 or 1, and nothing else defines currentStep. I suspect it has to do something with the fact Im calling update() in a timer interrupt, but I have to do that since my display library is blocking and takes forever to refresh.
As a temp solution, I made currentStep a signed integer, but if its negative, it will keep getting more negative. So I reset it to zero if its negative, but I'll lose steps this way.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/clearwater/SwitecX25/pull/11#issuecomment-339647425, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AMAS1unTV6Ok6VNbpJMoe2ZFOIDSrVCUks5swHi0gaJpZM4NoYnx.
Thats not the problem here I think (I checked for dir being different from -1,0,1 just to make sure there was no anomaly like you had, with dir becoming like 255. A large negative number could have explained the negative currentStep. But thats not the case with me. -0 would not cause problems, and wasnt detected).
But Ive come up with a rather ugly solution. Besides casting currentStep as a signed int, in the step function I also added this:
if (currentStep<0) {
stepTo(0);
}
If I understand correctly, stepTo would maintain proper step count. stepTo is blocking, but these are always tiny movements, probably just 1 step. Its not pretty, but for now, it does the job.
Did a little more digging; it appears currentStep can go negative if the stepper overshoots its target. And with the default settings, it can overshoot the target by a lot if you're moving fast. This gave me some additional problems as my needle is not able to move the full range of the stepper, overshooting would cause the needle to bump in to the edges of my housing and I would lose steps. I worked around that by changing this:
if (delta>0) { // case 1 : moving towards target (maybe under accel or decel) if (delta< vel ) {
into
if (delta>0) { // case 1 : moving towards target (maybe under accel or decel) if (delta/5 < vel ) {
So it starts decelerating much sooner. Again, kind of a ugly hack. I actually think a separate deceleration table is warranted here, and deceleration would ideally begin earlier when you are approaching the limits of the stepper (or your gauge), as overshooting in the middle isnt really a problem, but this works well enough. In fact, with that change, Ive not seen currentstep go negative anymore, but you never know. Combined with my previous modifications, Im now getting this: https://www.youtube.com/watch?v=abkQcF7Kuv4
Im happy with that. Fast enough, smooth, no overshooting or bumping in to the edges or losing steps.
Wow that does look good. What driver are you using?
At a min put the 5 into a constant and add comments. I like your idea of a deceleration table.
Get Outlook for iOShttps://aka.ms/o0ukef
From: R5fan notifications@github.com Sent: Monday, October 30, 2017 4:52:57 AM To: clearwater/SwitecX25 Cc: Kent Williams; Author Subject: Re: [clearwater/SwitecX25] Fix char/int conversion issue (#11)
Did a little more digging; it appears currentStep can go negative if the stepper overshoots its target. And with the default settings, it can overshoot the target by a lot if you're moving fast. This gave me some additional problems as my needle is not able to move the full range of the stepper, overshooting would cause the needle to bump in to the edges of my housing and I would lose steps. I worked around that by changing this:
if (delta>0) { // case 1 : moving towards target (maybe under accel or decel) if (delta< vel ) {
into
if (delta>0) { // case 1 : moving towards target (maybe under accel or decel) if (delta/5 < vel ) {
So it starts decelerating much sooner. Again, kind of a ugly hack. I actually think a separate deceleration table is warranted here, and deceleration would ideally begin earlier when you are approaching the limits of the stepper (or your gauge), as overshooting in the middle isnt really a problem, but this works well enough. In fact, with that change, Ive not seen currentstep go negative anymore, but you never know. Combined with my previous modifications, Im now getting this: https://www.youtube.com/watch?v=abkQcF7Kuv4
Im happy with that. Fast enough, smooth, no overshooting or bumping in to the edges or losing steps.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/clearwater/SwitecX25/pull/11#issuecomment-340380110, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AMAS1gHtnuRsDkYORI3DBwC_Y1j2R9Hgks5sxY5pgaJpZM4NoYnx.
thanks. Im using a AX1201728SG, that helps a lot. Part of of smoothness also comes from interpolation; my needle lags incoming data by one data frame, and on every frame, I calculate the difference in value and time between data frames, and on every step, I adjust the target by interpolating the position using the calculated speed to maintain constant velocity for the target. That puts a significant load even on my ESP32, as Im doing that in an timer interrupt routine (graphics libraries are blocking!) but its worth it for applications like this, especially when the data is fed relatively slowly (<10Hz). Writing this, I do realize im kinda doing this work twice now, and I should probably try to integrate this more closely with the library by passing it a velocity variable and making it use that as maximum speed.
as for making the 5 a constant; Im still testing and tweaking, but you probably would want it to be a function of the acceleration (and thus velocity) table. I think, Im not sure really.
Would you be so kind as to share your code? I like your approach and interpolation could fix an issue I’ve been having as well.
How does your smoothness look when feeding it very minor changes (like a needle that is fluctuating between a few degrees / “idle”)
Reason for constant is simply the name reminds you of what the number represents. Function sounds like best approach ultimately.
Get Outlook for iOShttps://aka.ms/o0ukef
From: R5fan notifications@github.com Sent: Monday, October 30, 2017 11:17:58 AM To: clearwater/SwitecX25 Cc: Kent Williams; Author Subject: Re: [clearwater/SwitecX25] Fix char/int conversion issue (#11)
thanks. Im using a AX1201728SG, that helps a lot. Part of of smoothness also comes from interpolation; my needle lags incoming data by one data frame, and on every frame, I calculate the difference in value and time between data frames, and on every step, I adjust the target by interpolating the position using the calculated speed to maintain constant velocity for the target. That puts a significant load even on my ESP32, as Im doing that in an timer interrupt routine (graphics libraries are blocking!) but its worth it for applications like this, especially when the data is fed relatively slowly (<10Hz). Writing this, I do realize im kinda doing this work twice now, and I should probably try to integrate this more closely with the library by passing it a velocity variable and making it use that as maximum speed.
as for making the 5 a constant; Im still testing and tweaking, but you probably would want it to be a function of the acceleration (and thus velocity) table. I think, Im not sure really.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/clearwater/SwitecX25/pull/11#issuecomment-340477062, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AMAS1iWPywNQ4cKIndOSFdBEyvAzrDgEks5sxeimgaJpZM4NoYnx.
I too would be very interested as I am working on a GPS speedo and that is much smoother than I have ever managed. Great work.
toby
On 30 October 2017 at 16:44, KentDub notifications@github.com wrote:
Would you be so kind as to share your code? I like your approach and interpolation could fix an issue I’ve been having as well.
How does your smoothness look when feeding it very minor changes (like a needle that is fluctuating between a few degrees / “idle”)
Reason for constant is simply the name reminds you of what the number represents. Function sounds like best approach ultimately.
Get Outlook for iOShttps://aka.ms/o0ukef
From: R5fan notifications@github.com Sent: Monday, October 30, 2017 11:17:58 AM To: clearwater/SwitecX25 Cc: Kent Williams; Author Subject: Re: [clearwater/SwitecX25] Fix char/int conversion issue (#11)
thanks. Im using a AX1201728SG, that helps a lot. Part of of smoothness also comes from interpolation; my needle lags incoming data by one data frame, and on every frame, I calculate the difference in value and time between data frames, and on every step, I adjust the target by interpolating the position using the calculated speed to maintain constant velocity for the target. That puts a significant load even on my ESP32, as Im doing that in an timer interrupt routine (graphics libraries are blocking!) but its worth it for applications like this, especially when the data is fed relatively slowly (<10Hz). Writing this, I do realize im kinda doing this work twice now, and I should probably try to integrate this more closely with the library by passing it a velocity variable and making it use that as maximum speed.
as for making the 5 a constant; Im still testing and tweaking, but you probably would want it to be a function of the acceleration (and thus velocity) table. I think, Im not sure really.
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/ clearwater/SwitecX25/pull/11#issuecomment-340477062, or mute the thread< https://github.com/notifications/unsubscribe-auth/ AMAS1iWPywNQ4cKIndOSFdBEyvAzrDgEks5sxeimgaJpZM4NoYnx>.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/clearwater/SwitecX25/pull/11#issuecomment-340506703, or mute the thread https://github.com/notifications/unsubscribe-auth/AAF1B1msWcnnplAmSYM2o6UWXvEv2g_0ks5sxfz1gaJpZM4NoYnx .
In fairness, no, it does not work quite that smooth when Im feeding it 'jittery' data from the actual sensor board -yet? Curing that jitter was why i tried this approach. It works very well for random generated data, even at low update frequencies of a few hertz, but when I connected it to the openvario instrument, the result was less impressive. I havent yet had time to find out why; it could very well be something in my serial code messing with the timings/interrupts, it could be that my approach is misguided, or needs tweaking.
As for sharing my code; first a few major caveats; Im new to arduino! Im so new I had to google to find out how to even make a repository on github. And Im in way over my head doing multithreading, multiple timing interrupts and what have you, when I barely understand the basics of C. But you asked for it, so here it is: https://github.com/R5fan/OpenVarioIndicator
Most of the 'magic' happens in the stepper timing interrupt, using data prepared in smoothvario function where I do the floating point stuff. I found out the hard way that you shouldnt do FP in an interrupt :p.
Any other questions Im sure you'll have, post them in that github repo and I'll be happy to help where I can.
okay, I did have a problem with my serial reads, which is fixed now, and uploaded to my github. This is what it looks like now with fluctuating 'live' data: https://youtu.be/oPXHvdmj_Jw
You will see it bounce a few times, but thats when Im actually tapping the sensor repeatedly. The LCD on the left is the openvario board, and it will do the same. For my application, I dont want to smooth it more than that, but if you do, consider a low pass filter.
If Im honest, with microstepping and my increased deceleration, it works pretty well as is and there isnt a great deal of difference between setting the target upon getting the dataframe , and interpolating + retargetting in every ISR, but it does help. It would probably help more if I took the acceleration table in to account, so instead of interpolating linearly, I would actually calculate how long it should take to reach the target, but thats a little too much work and if I do that, I might as well ditch this library and rewrite it from scratch.
If your results are far worse than mine, using the same or similar controller, I suggest you start by checking if you are calling update() often enough (microstepping means you need to call it 4x as often!) and applying the increased deceleration 'patch' I posted above. The latter also helps to slow the needle down when you are getting small alternating/fluctuating changes and prevents the needle from oscillating.
On an Arduino Due, advance() will send 255 to step(dir) instead of the methods expected -1. This will cause the motor to never reverse and the current step to continue to grow away from the target.
I'm a new C programmer (I come from C# world), and this doesn't seem to be the cleanest way --- but it works well. In the C# world we don't use char's to store numbers ;)
This extra little line would be nice for other Due users out there to have the library execute as expected.