What is the priority of EncoderTool T4.x?
What is the priority of the EncoderTool? What is the priority of the callback function onEncoderChanged? How can the priority be changed (if necessary)? I'm getting very long ISR's on occasion, and I'm wondering why that might be. I set the physical pins to have priority 32, but I still see long ISR's. Longer than expected, and sometimes longer than the time between encoder edges.
My observation is while my system is controlling a stepper, the encoder ISR is slipping counts relative to the index pulse. In my onEncoderChanged callback if the index is active, I record the count value. The count is slipping. The value should be invariant (relative to modulo the encoder wheel). This slippage is occurring at rates of only 400 RPM with a 1024 PPR wheel (4096 edges per rev).
This is preventing the implementation of "thread to stop", which relies on accurate angular synchronization.
What is the priority of the EncoderTool? What is the priority of the callback function onEncoderChanged?
There is no such thing as a priority of the EndoderTool or its callback functions. I assume you are using the interupt based version, e.g. Encoder vs PolledEncoder? This version uses pin interrupts to detect level changes of the inputs. If such a level change leads to a change in the counting value the callback is called in the context of the original pin interrupt.
How can the priority be changed (if necessary)?
If you want to change the priority of the counting algorithm and the callback you need to change the priority of the involved pin interrupts.
I'm getting very long ISR's on occasion, and I'm wondering why that might be. I set the physical pins to have priority 32, but I still see long ISR's. Longer than expected, and sometimes longer than the time between encoder edges.
What ISR duration your are refering to? What is very long? How did you measure it? How long does the code in your callback take?
My observation is while my system is controlling a stepper, the encoder ISR is slipping counts relative to the index pulse. In my onEncoderChanged callback if the index is active, I record the count value. The count is slipping. The value should be invariant (relative to modulo the encoder wheel).
Does the count also slip if you use a minimal test program and move the encoder by hand or some motor not controlled by the same processor? Are you sure that your hardware works correctly? Cheap encoders often don't guarantee 90° phase shift which can lead to very short times between edges which might be an issue. Can you post a link to a datasheet?
This slippage is occurring at rates of only 400 RPM with a 1024 PPR wheel (4096 edges per rev).
At 90° this leads to 400rpm /60s * 4096 = 27,3kHz interrupt frequency. Depending on the processor you are using, the code in your callbacks and the code running besides the encoder this might be problematic. (The time between two interrupts at 27kHz is only 30µs.).
What is the priority of the EncoderTool? What is the priority of the callback function onEncoderChanged?
There is no such thing as a priority of the EndoderTool or its callback functions. I assume you are using the interupt based version, e.g. Encoder vs PolledEncoder? This version uses pin interrupts to detect level changes of the inputs. If such a level change leads to a change in the counting value the callback is called in the context of the original pin interrupt.
How can the priority be changed (if necessary)?
If you want to change the priority of the counting algorithm and the callback you need to change the priority of the involved pin interrupts.
I'm getting very long ISR's on occasion, and I'm wondering why that might be. I set the physical pins to have priority 32, but I still see long ISR's. Longer than expected, and sometimes longer than the time between encoder edges.
What ISR duration your are refering to? What is very long? How did you measure it? How long does the code in your callback take? The encoder callback function. Very long is occasionally longer than the next normal edge (about 32us). I set a gpio on entry to the ISR and clear it at exit. I measured the pulse width of the gpio pin using an oscilloscope with normal triggering, rising edge and infinite persistence.
My observation is while my system is controlling a stepper, the encoder ISR is slipping counts relative to the index pulse. In my onEncoderChanged callback if the index is active, I record the count value. The count is slipping. The value should be invariant (relative to modulo the encoder wheel).
Does the count also slip if you use a minimal test program and move the encoder by hand or some motor not controlled by the same processor? Are you sure that your hardware works correctly? Cheap encoders often don't guarantee 90° phase shift which can lead to very short times between edges which might be an issue. Can you post a link to a datasheet?
I used your Encoder simulator and it ran to 400KHz. No loss of counts.
There are two motors in my system. The spindle and the stepper(for the carriage). The spindle is not controlled by my Teensy. The encoder is on the spindle. The encoder is an Omron E6B2 type with open collector output. https://edata.omron.com.au/eData/Encoders/E6B2-C_DS.pdf. I have never observed glitching on the output of the encoder, there's 330 ohm pull ups to +5V. The encoder is buffered and translated to 3.3V using a 74LVC245. No glitches seen at Teensy either. (At least the last time I looked, a couple of years ago.). This is on a PCB with a proper ground plane. I am using a Teensy 4.1, which uses a 600 MHz clock.
This slippage is occurring at rates of only 400 RPM with a 1024 PPR wheel (4096 edges per rev).
At 90° this leads to 400rpm /60s * 4096 = 27,3kHz interrupt frequency. Depending on the processor you are using, the code in your callbacks and the code running besides the encoder this might be problematic. (The time between two interrupts at 27kHz is only 30µs.).
400 RPM / 60 * 4096 is the interrupt rate which is 36.6us. Due to wow or load in the spindle, it could be less, but not by much. My callback lasts 710 ns, most of the time, but when I have to pulse the stepper, it takes about twice as long. This sort of makes sense, since I have to call a function to pulse the stepper. However, I cannot account for the very long times, 7us or even longer than 36us. Can't really tell how long the long pulses are, because it runs into other pulse, if I use persistence.
In the encoder callback, I log to PSRAM the encoder count if I detect the index signal. Later, I read back the log. The index count is wandering, far too much for a machining application. (1000's of counts over less than 5 minutes.). Can't machine a thread if the thread start angle is effectively a random number. Even without logging (and PSRAM activity) the thread sync just isn't working. Yes, I sync when the angle = theta0, but theta0 isn't constant, with respect to the index pulse. Since the index pulse is fixed on the encoder wheel, (once per revolution) the count should be the same at the index (modulo the resolution of the wheel). What I observe is the thread cut starts at a random angle and never repeats.
Think I found a problem... (Maybe the problem?) I set the interrupt priority after the Encoder.begin statement. Then the priority would be the default 128, correct?
No, moving the NVIC priority doesn't solve the problem. Somehow the onChange callback routine lasts way too long. Something is blocking. (Perhaps not in your code.) But I'm losing counts. Not good. Kills my application.
Weird indeed. The EncoderTool does nothing in the background which could block the onChange callback. Even if one of the pin interrupts would trigger again it couldn't block the callback since the interrupt would run on the same priority. I assume something in your application uses interrupts with a higher priority causing the issues. Maybe some timers?
Again: can you try to do a very simple test program from scratch? In the callback function just check if the index pulse is active and if so, write the counter value to a RAM based array. After some reasonable time print the array. If you still observe count losses I can have a closer look with my own hardware.