Does TyCommander handle FTDI? Or am I doing something wrong?

had installed PSRAM on this controller
Great to have - I noted that for RAM logging on prior page p#73 along with ways to shorten the test to only the critical START and RESTART on the beginning. Maybe shorter stock if the cutter can't retract safely and quickly as noted to allow the tool to mark progressively farther without going deeper into danger of destruction.

Lots of feedback on the math - but seems if the starting conditions from encoder values engage at the same point from pass to pass for tool advance to contact then it should work. If not, then there is 'flex' or error in the readings and actuation timing. It is only that contact instant that determines what follows. So, collecting every sensed value for contact and 1 revolution, and doing the several repeats the data can be compared and the results seen engraved on the stock.
 
Great to have - I noted that for RAM logging on prior page p#73 along with ways to shorten the test to only the critical START and RESTART on the beginning. Maybe shorter stock if the cutter can't retract safely and quickly as noted to allow the tool to mark progressively farther without going deeper into danger of destruction.

Lots of feedback on the math - but seems if the starting conditions from encoder values engage at the same point from pass to pass for tool advance to contact then it should work. If not, then there is 'flex' or error in the readings and actuation timing. It is only that contact instant that determines what follows. So, collecting every sensed value for contact and 1 revolution, and doing the several repeats the data can be compared and the results seen engraved on the stock.
I had built this PCB in 2022, forgot I had PSRAM on it! Unfortunately, I don't have a stepper on the X axis to auto retract, I'm relying on my algorithm to softly arrive at a stop. It exponentially decreases the velocity coming to a stop, which gives much lower position error than a linear velocity achieves. I have my hand near the E stop button often during testing, as things can go south in an instant. Can't daydream during testing, this requires 100% attention to ensure my safety and the machine's.

If there's no math errors, and I'm not missing or slipping counts, it comes down to actuation delays or actuation jitter. Definitely been an interesting challenge!
 
Just a thought - use delrin or similar free-machinging polymer whilst debugging, less likely to break a tool. Could even use a pencil at a pinch!

Going back the angle calculations, you can map a rotation to 0.0--1.0 range, i.e. divide degrees by 360 on input, then the functions round(), floor() and ceiling() are very handy, you can convert to 0..1 range with x-floor(x), or -0.5 to 0.5 range with x-round(x).

If you wire an LED to the index pulse output you can check that the indexing is repeatable by slowly turning (by hand?).
 
Just a thought - use delrin or similar free-machinging polymer whilst debugging, less likely to break a tool. Could even use a pencil at a pinch!

Going back the angle calculations, you can map a rotation to 0.0--1.0 range, i.e. divide degrees by 360 on input, then the functions round(), floor() and ceiling() are very handy, you can convert to 0..1 range with x-floor(x), or -0.5 to 0.5 range with x-round(x).

If you wire an LED to the index pulse output you can check that the indexing is repeatable by slowly turning (by hand?).
Good idea on the delrin. I bought some off Amazon, of all places, when it was marked down cheap. Supposedly it was 1" (25.4mm), but in reality it was 27mm! But it's good stock to play with. That's what I use to avoid wasting metal. Crashes are pretty benign that way. I have done the pencil trick, actually a fine marker, when I first started out. If I could change color without loss of the tip position, it might be a good way to visualize results. (Lining up the tip to a few microns is really hard.) First pass would be red, then blue for successive passes? Standard markers come off with isopropyl alcohol.

Have received some good ideas from the kind people here.

Just today, I was able to verbalize (it was in my mind, but not written down) the key assumptions I'm making. Need to write up what they are, and how errors or deviations in them might show up behaviorally. Basically a backdoor error sensitivity analysis. Not much need to spend time on things that only contribute very minor sources of error. Might take me an hour or so to see what the big error players are. If nothing else, it may give some insight as what data to capture.

Next time I disassemble the housing, I'll see if I can wire up a LED. It won't be very bright, as Teensy's drive current isn't much.

By any chance, do you (or any one on this forum) know of an inexpensive way to capture high speed video? So I can watch the motion (in slow motion) to see what's physically happening? I'd like to put a timing mark on the end of the rod and capture the timing mark at the instant Z = zstart. (And capture what the program thinks it is!)
 
I meant use a pencil as workpiece, but actually your method makes sense too. Encoders are usually open-collector output and can drive an LED.
 
An iPhone can do 240fps in slo mo mode.

If you wired up an LED to a Teensy pin, and switched it on at count%4096=0, and off again at =1, it should illuminate a reference mark once per rev at 6.6667Hz, ideally always in the same place. If you lost sync the mark would appear somewhere else, though you might not spot a small error very easily, or indeed at all.

One of these might help? (Full disclosure, never tried one myself…)
1753472128999.jpeg
 
If you wired up an LED to a Teensy pin, and switched it on at count%4096=0, and off again at =1, it should illuminate a reference mark once per rev at 6.6667Hz, ideally always in the same place. If you lost sync the mark would appear somewhere else, though you might not spot a small error very easily, or indeed at all.
Good idea. I will add a buffer though, so the LED can be bright.

Wish I had put a heck of a lot more test points and buffers on my PCB. Reworking the board for this isn't that easy.
 
Could be instructive to run a separate function to check if there's apparent angle drift between the index, which is absolute, and whatever angle was the arbitrary origin. The encoder count modulo 4096 ought to be static at the index pulse rising edge (or falling). If it isn't static, there's loss of counts. Won't know the cause, but will know there's an issue. It's good to verify what's real and what is merely conjecture.
@clinker8, you said the above in post #100 of this thread. Isn't that equivalent to making a visual indicator, and more accurate? I'd do that first. I think all you need is an interrupt on index rising edge, compute (count % 4096), save the value on the first execution, and confirm it's the same (or not) on each subsequent interrupt.
 
Good thing about non metallic testing is no metal chips flying into makeshift test hardware.

Question: Is the 'cutting tool'/marker aligned perfectly on the work material horizontal X axis?
 
@clinker8, you said the above in post #100 of this thread. Isn't that equivalent to making a visual indicator, and more accurate? I'd do that first. I think all you need is an interrupt on index rising edge, compute (count % 4096), save the value on the first execution, and confirm it's the same (or not) on each subsequent interrupt.
You can tell I'm rambling... Had a poor night's sleep, so I'm a bit off my game. You are right, in a perfect world. However, doing this in code, might be misleading, because it could affect execution, if my timing is too tight.

@h4yn0nnym0u5e 's suggestion of a strobe ought to give an indication with zero code and zero impact on execution time. Downside is a LED driver with sufficient brightness. Precession of the strobe mark is a dead giveaway of an issue. Gee, wonder if I could use an old engine strobe light? Have have issues with the triggering.

I may end up doing both.
 
Good thing about non metallic testing is no metal chips flying into makeshift test hardware.

Question: Is the 'cutting tool'/marker aligned perfectly on the work material horizontal X axis?
Non conductive means it's tough to rig up a first contact switch... But your point is well taken about chips.

Perfectly? (Nothing is perfect if you look closely enough.) I'd say it's within 0.01 to 0.02 mm. (0.001" or less) Typically I sandwich a steel rule between the work piece and the cutter tip and adjust so the rule is dead vertical. You can tell if the cutter is above or below the center line by the tilt of the rule.
 
You can tell I'm rambling... Had a poor night's sleep, so I'm a bit off my game. You are right, in a perfect world. However, doing this in code, might be misleading, because it could affect execution, if my timing is too tight.

@h4yn0nnym0u5e 's suggestion of a strobe ought to give an indication with zero code and zero impact on execution time. Downside is a LED driver with sufficient brightness. Precession of the strobe mark is a dead giveaway of an issue. Gee, wonder if I could use an old engine strobe light? Have have issues with the triggering.

I may end up doing both.
If you’re concerned about 1 extra interrupt per rev, or about 6.7/sec at 400 rpm, how can you tolerate adding up to 300,000 interrupts/sec for a UART at 3Mbps?

Also, I still don’t understand why you can’t easily switch from EncoderTool to QuadEncoder. I’m thinking that in each place that you check your current angular position, you could replace that variable access with a call to a function that does QuadEncoder::read() and computes and returns a value in the same units as your existing variable.
 
Perfectly?
Opps ... Properly - yes that sounds like good effort at Proper alignment :)

Maybe UART ISR is lower priority, or shorter than USB? Code in p#19 had comment about UART interrupts.
Using PSRAM for bulk data writes during critical times, then upload 'off the clock' would likely be best.

Assuming there isn't bus contention. The PSRAM will get covered by 32KB data cache - then it will start having to hit the PSRAM with SDIO for actual storage.
Might be good to empty the cache before each data intensive LOG start so at least first 32KB is Zero Wait:
Code:
extern "C" uint8_t external_psram_size;

  uint8_t size = external_psram_size;

  memory_begin = (uint32_t *)(0x70000000);
  memory_end = (uint32_t *)(0x70000000 + size * 1048576);

  arm_dcache_flush_delete((void *)memory_begin,(uint32_t)memory_end - (uint32_t)memory_begin);
 
why you can’t easily switch from EncoderTool to QuadEncoder
I seem to recall (can’t immediately find the post) it’s that QuadEncoder doesn’t provide the per-edge callback that’s needed to drive the stepper in exact sync with the spindle. Of course it does its counting in hardware, so doesn’t need to involve the CPU … not sure if that would be an option.

We’ve been glibly talking of “400 rpm spindle speed”, but I guess that’s actually subject to small real-time variation, so you have to close the loop between spindle and stepper, rather than let the stepper free run once it’s been started at the right point.

Or I may have misunderstood entirely … has been known to happen o_O
 
I seem to recall (can’t immediately find the post) it’s that QuadEncoder doesn’t provide the per-edge callback that’s needed to drive the stepper in exact sync with the spindle. Of course it does its counting in hardware, so doesn’t need to involve the CPU … not sure if that would be an option.
Exact sync with the encoder events is required. And exact timing of the stepper pulses with the physical encoder is required. At the moment, I can't comprehend how to implement the Bresenham algorithm (for the stepper) inside of QuadEncoder.
We’ve been glibly talking of “400 rpm spindle speed”, but I guess that’s actually subject to small real-time variation, so you have to close the loop between spindle and stepper, rather than let the stepper free run once it’s been started at the right point.
Correct. The spindle is running open loop and is subject to load variation (depth of cut, feed rate, etc). The stepper algorithm is a closed loop control around the encoder position. If the encoder moves D counts, the stepper moves N steps, no matter what the spindle speed is. If the loop is not closed, one can get what is called drunken threads, one's that have variable thread pitch. Such threads are a funny curiosity, but useless, since they are not functional.

The feed to stop mode has been tested to 2200 RPM. But feed to stop doesn't require angle sync. The lathe just cuts at 0.010"/rev, or whatever it's set to, and gracefully comes to a stop point, which is set by the operator.

And BTW, the key algorithm for slowing is inside that EncoderTool callback. That's because I know the positions of Z and theta and actually change the N/D ratio on the fly over the distance of a mm. The last mm of thread is placed by the shoulder of the thread where there's typically a groove, so the cutter cuts air, rather than metal. The finished thread is true pitch. The controlled drunkenness is not observable, as it's in the groove region. I do this exponentially decreasing crawl in both feed to stop and thread to stop. So at the end of a thread I break sync, (changing the N/D ratio breaks sync) so I need to reestablish it for every thread pass.
Or I may have misunderstood entirely … has been known to happen o_O
Think you have the gist of it.:)

I'm tickled that there's some interest in this. Thanks.
 
Maybe UART ISR is lower priority, or shorter than USB? Code in p#19 had comment about UART interrupts.
The UART ISR is interruptible by the encoder, because I set the priority that way. USB, on the other hand, can block all interrupts, even though it's only priority 128. It can block priority 32 (encoder). And the blockage is inside of a loop in the USB code, so the duration could be variable or long. It's not playing fair, (as an ISR,) USB's assuming there's nothing more important in the system. That's an erroneous assumption. (Good practice should minimize global blocking time spans.)

USB is very handy for most things, but not when it can prevent proper machine control. Preventing pulse callback interrupts, or delaying stepper pulses should never happen. That's why I'm going with HWSerial, not USB for this application.
 
USB, on the other hand, can block all interrupts
That isn't nice - but if USB is to be used that may be needed to keep the host happy - or just to get the job done right.

Good that UART ISR plays better. Though the 1062 MCU has tiny FIFO's and interrupts every 1-2 bytes.

If you can craft the test period properly and stuff a boatload in PSRAM then push out to USB or UART on the return stroke before the next pass it should work. PSRAM SDIO does add a chore to the MCU - not sure if it ties up any critical buses in the process that might cause issues here? But oddly PSRAM writes are 3X faster than read due to indexing process.
 
That isn't nice - but if USB is to be used that may be needed to keep the host happy - or just to get the job done right.
Not sure if required for the host or not. But behaviorally, blanking higher priority interrupts is not good for real time machine control.
Good that UART ISR plays better. Though the 1062 MCU has tiny FIFO's and interrupts every 1-2 bytes.

If you can craft the test period properly and stuff a boatload in PSRAM then push out to USB or UART on the return stroke before the next pass it should work. PSRAM SDIO does add a chore to the MCU - not sure if it ties up any critical buses in the process that might cause issues here? But oddly PSRAM writes are 3X faster than read due to indexing process.
Yeah, that's the plan - cram data into PSRAM and read out later. Not sure if I'll turn off the spindle to do that or not. Having the spindle static would reduce the ISR load. I can turn off the spindle motor and not lose position, as my controller is independent of the spindle. Or I could log each pass as a file, closing the file when it gets to the stop (or sooner, to save memory). Then later upload all the passes for that experiment. It would be 4-8 files. I'd think that a second or two of data for each trial would be sufficient.

Have a plan now. Have to get to work on it.
 
@clinker8, can you point to where USB blocks interrupts for a significant time? I've found one point where they're turned off for a supposed maximum of ~4µs, assuming a 600MHz clock (usb.c, in schedule_transfer()).
 
@clinker8, can you point to where USB blocks interrupts for a significant time? I've found one point where they're turned off for a supposed maximum of ~4µs, assuming a 600MHz clock (usb.c, in schedule_transfer()).
Could be that I may be misinterpreting things. I just did a recursive grep in cores/teensy4 for '__disable_irq' and found 4 instances in usb.c. (35 instances total)
Code:
./usb.c:216:    __disable_irq(); // secure mode NXP ROM reboot
./usb.c:374:    __disable_irq();
./usb.c:943:    __disable_irq();
./usb.c:1080:    __disable_irq();
The one at line 943 is concerning to me, as there's a do while statement before the __enable_irq on line 972. If one has to wait up to 2400 cycles, that's 2400 x 6.6ns = 15.84 us. That's a long time to blank. If I'm at 1000 RPM, my interrupts will be blanked. 1000 RPM --> 14.65us interrupt rate.

I know some other folks (not on this forum) that have advised me not to use Teensy usb serial in real time control. Whether that's just based on schedule_transfer, I don't know.

Perhaps I'm being too cautious, but every once in a while, while logging on USB, the system would hang up, or make an awful noise. Not often, but a handful of times in 3 years. Sometimes it's recoverable, other times not. Now that can just be me writing low quality code, but after several years of testing and refinement, I'm not so sure, especially with line 943.
 
The one at line 943 is concerning to me, as there's a do while statement before the __enable_irq on line 972. If one has to wait up to 2400 cycles, that's 2400 x 6.6ns = 15.84 us. That's a long time to blank. If I'm at 1000 RPM, my interrupts will be blanked. 1000 RPM --> 14.65us interrupt rate.

I know some other folks (not on this forum) that have advised me not to use Teensy usb serial in real time control. Whether that's just based on schedule_transfer, I don't know.

Perhaps I'm being too cautious, but every once in a while, while logging on USB, the system would hang up, or make an awful noise. Not often, but a handful of times in 3 years. Sometimes it's recoverable, other times not. Now that can just be me writing low quality code, but after several years of testing and refinement, I'm not so sure, especially with line 943.

Disabling of interrupts for ~15 us is consistent with delay I have measured in a system with a high-priority timer interrupt. I did a lot of testing to show that as long as USB serial wasn't used, the delay in executing the timer ISR was close to 0, so I agree it's not okay to log to USB serial if your system cannot tolerate interrupts being disabled for those relatively short periods. Note that writing to flash on T4.x (including emulated EEPROM) also disables interrupts, and for much longer, so should not be done while a critical control loop is active.

This brings me back to a topic we've gone back and forth on several times, and that is QuadEncoder (no encoder interrupts) versus EncoderTool (interrupt on every edge of A and B). As a thought experiment, consider these alternatives for your lathe running at 400 rpm:
  • EncoderTool, with edge interrupt @ 27 kHz, ISR updates encoder count and does stepper micro-pulse per ELS ratio
  • QuadEncoder, with IntervalTimer @ 27 kHz, ISR reads encoder count and does stepper micro-pulse per ELS ratio
While not 100% identical in terms of timing, wouldn't these two systems be equivalent? I think the answer is yes, and then you would have the following additional benefits:
  • no possibility to lose encoder counts, even when interrupts are disabled
  • writing to USB serial would be okay as long as 15-us delay in stepper pulse is tolerable
  • integrated detection of encoder edge error
  • integrated support for encoder index pulse
If you need to support higher spindle speeds, the IntervalTimer interrupt frequency could be set higher. It would never have to be higher than the highest encoder edge frequency, and I think you would find that it only needs to be as high as the highest stepper micro-pulse frequency.
 
The one at line 943 is concerning to me, as there's a do while statement before the __enable_irq on line 972. If one has to wait up to 2400 cycles, that's 2400 x 6.6ns = 15.84 us. That's a long time to blank.
Yes, that does look like code that was written in a hurry with the intention of coming back to fix later ... i.e. never. The comment is out of date, as Paul's annotated Reference Manual is revision 3, it doesn't seem to comply with the equivalent rev 3 paragraph (42.5.6.6.3, p 2420), and the 2400-cycle apparent timeout seems to have been plucked from thin air. Could be a chip erratum, of course.

In other news ... I think your timing calculation is a bit off. 2400 cycles at 600MHz is 4µs by my reckoning; still not great, but possibly not disastrous. Then again, based on your experience, it's probably sensible to avoid using USB - "never argue with the data":
 
In other news ... I think your timing calculation is a bit off. 2400 cycles at 600MHz is 4µs by my reckoning; still not great, but possibly not disastrous. Then again, based on your experience, it's probably sensible to avoid using USB - "never argue with the data":
Hmm, yeah, for some reason I had in my head a cycle was 6.6ns. Ooops. o_O It's 1.66ns. My bad.
Still, it's not friendly, by overriding everything, independent of priority.
 
Disabling of interrupts for ~15 us is consistent with delay I have measured in a system with a high-priority timer interrupt. I did a lot of testing
That’s interesting - I wonder why not 4us? Maybe there’s another culprit…
the IntervalTimer interrupt frequency could be set higher
There’s still a risk of missing an IntervalTimer interrupt, of course … but you always have ARM_DWT_CYCCNT available as a reference.
 
That’s interesting - I wonder why not 4us? Maybe there’s another culprit…

There’s still a risk of missing an IntervalTimer interrupt, of course … but you always have ARM_DWT_CYCCNT available as a reference.

I will have to go back to see what I measured. I know it was small, but not insignificant, relative to the 100-us control cycle of that system.
 
Back
Top