Adding capabilities to my ELS system

Would it prove anything useful if you treated it like a typical lathe and always engaged the lead screw on the same number on the thread dial? That's how you sync up on a typical manual lathe assuming TPI and inch lead screw. Maybe you've tried this already.
I see the same type of errors, no matter where or how engaged. I've even statically moved the carriage back to 1 (well to the right of the start) and engaged there. So always engaging on 1, doesn't seem to change the error pattern. At least for me, this has been puzzling.
 
Dang. I can't use the same pins for two different interrupts. What a brain fart! So I have to add wires and hope my SW encoders will work on the new pins. Good thing I branched the code, this looks messy.
 
If I can swing it, I will try to integrate in the HW encoder to check for slipped counts. If I detect any, that's a clue and source of error. I know I can do that for the spindle, not sure if I can do that for Z. Hopefully I used the correct pins on my PCB. If the count slips a lot, that's the smoking gun. If one count, that doesn't account for the errors I am seeing.
I can probably provide some guidance on the HW encoder configuration. I'm also reading them without using the library I use to configure them. Actually quite simple to do, once they are set up.

Which I/O pins are all of your encoders going into?
 
I can probably provide some guidance on the HW encoder configuration. I'm also reading them without using the library I use to configure them. Actually quite simple to do, once they are set up.

Which I/O pins are all of your encoders going into?
Post #337 is the I/O map of my PCB. But that's before I realized I can't have both a HW and SW encoder on the same pin. So the first two columns are as wired on my PCB. I was thinking of swapping the Z DRO inputs with the X, since I could use Quad Encoder on pins 30 & 31.

But now I need to map some pins for the SW encoders to run my code. I haven't thought of a clean mapping from the SW encoders to the HW. The HW encoder library (as written) can't do the motor control function. Could it do it eventually, probably. At the moment, not a chance. Their paradigms are totally different.

For now, I want to run the encoders in parallel (somehow) for diagnostics. Just hoping the added burden doesn't impair the system. I have no idea what the root problem is. All I know is behaviorally is that the thread doesn't start at the same place every time. Exactly why, I don't know. Beyond that all I have is conjecture.

I have a timing pulse, that seems to vary. It used to be on the order of 1-2 encoder tick times. Now it seems to be much longer. That's not necessarily bad, but it's different. It now varies 1-5 encoder tick times. But even that variable delay is insufficient to cause the thread to shift as much as I see. One rev = ~ 150 ms. I'm seeing equivalent delays of 10-75ms, but 5 encoder tick times is only 182us.

It's as if my display routines are interfering, only they can be that long. But the display updates are low priority mainline routines. Display updates are bypassed during the critical sync time interval, for several rotations of the spindle. (300ms). (blank time is calculated based on the time for one revolution at the current RPM)
 
If you have any concerns about variation in timing caused by something like the display library, in the timing sensitive routine I often do something along the lines of

Code:
time = cycle_clock();  // where cycle_clock is whatever it takes to retrieve current hi res time

if((delay = (time - prev_time)) > reasonable_delay) {
   printf("unexected delay %lld in subroutine xxxx\n",delay);
}

prev_time = time;
You can modify it slightly and capture "max delay" and print out a new "max delay" every time you exceed the previous max delay. This does a good job of flagging sudden timing oddities without creating excessive diagnostics. Another slight variation will give you the time between two points in the code rather than the loop/iteration time between the same point. Surprising how many insights I've found by having this scattered around.

Even fairly easy to create an inline function/subroutine that does this, just declare prev_time to be static. That way it becomes one line that can be commented out quickly.

For the PICO library use of the onboard USB channel for printf, I've found some real extremes. Probably the whole thing blocking when something on the far end (host computer) gets sidetracked.
 
Last edited:
If you have any concerns about variation in timing caused by something like the display library, in the timing sensitive routine I often do something along the lines of

time = (clock);
if((delay = (time - prev_time)) > (reasonable delay)) {
printf("unexected delay %lld in at subroutine xxxx\n",delay);
}
prev_time = time;

This does a good job of capturing outliers. You can modify it slightly and capture "max delay" and print out a new "max delay" every time you exceed the previous max delay. This does a good job of flagging sudden timing oddities without creating excessive diagnostics.
I may do something like that. What's puzzling me is that I prevent entry to display routines during syncing with a volatile "kill display" flag. I lock out the display for the critical time interval between when the stepper paused and several revolutions after I achieve sync. Sync seems to happen within a single revolution.

Maybe something is happening post sync, but before the cutter hits the work piece. I can blank longer, say 5 revolutions. Or I can pause the stepper right at the work piece and see if the pitch changes in the beginning.
 
IIRC, you're using the Adafruit display library? Have you combed through that carefully to be sure it (via a prior invocation perhaps) is not creating any timing artifacts (i.e., some sort of interrupt or time-related callback). It could be as obscure as using heap data such as malloc, and one of those calls triggering some sort of housekeeping routine.

Regardless, the above code in your timing sensitive routines will give you confidence that it is / isn't a time related issue vs. some other logic problem.
 
IIRC, you're using the Adafruit display library? Have you combed through that carefully to be sure it (via a prior invocation perhaps) is not creating any timing artifacts (i.e., some sort of interrupt or time-related callback). It could be as obscure as using heap data such as malloc, and one of those calls triggering some sort of housekeeping routine.

Regardless, the above code in your timing sensitive routines will give you confidence that it is / isn't a time related issue vs. some other logic problem.
I'm using a Teensy library that was forked from an Adafruit library. I grepped for interrupt and disable in the Teensy library and found that the normal display doesn't use interrupts. However, if called from an ISR, subsequent SPI transactions will take on the same interrupt priority as the ISR. I only call the display every 40ms, if there's a change, but it's in the main loop. The display library does support DMA, which does use interrupts, but I don't call any display DMA commands in my code. But I'm not sure if there's some razzle dazzle going on, so a timer is a good idea.

Reading back my NVIC entries, shows that DMA priority is set to 128. All my ISRs are higher priority, with my encoders at 32. My other timers are at 48 or 64. I set FTDI serial to 96, but I don't have a cable yet.

I'm going to log a binary tag and timestamp in my code, just to ensure that things make sense. Have to be careful I don't saturate the link. I'm basically trying to profile the code. And finding when a routine takes too long.
 
While it is hard to be completely sure of any code you didn't write (or even code that you did!), sounds like you've made a decent search of the display library. Good luck chasing this down.
 
My marker will be uint16_t, and the timestamp uint64_t. That's 10 bytes. Can't use 32bits for the timestamp, since a rollover occurs every 7 seconds. So if my average logging rate is slower than once per 33.3us, it should fit on FTDI. I'll have to do some spot checks on those rates. Some functions are faster than that.
 
Back
Top