Interrupts in a motor controller? - Page 1
Forum section: electronics / beginners

author: frmdstryr
author_rank: Contributor
timestamp: August 08, 2022, 01:52:43 pm
content: There's a thread on HN today about someones stm32 BLDC driver and a commenter mentions "you're using interrupts in a motor controller!?!" (https://news.ycombinator.com/item?id=32381448)Is it considered bad practice to use interrupts with motion control? Does that only apply to bldc/FOC that mainly use pwm?I've written a simple 3 axis stepper motor controller but it used timers to generate the step signals in the IRQ. It seems to work pretty well up to about 200khz but I'm always open to better/simpler ways to do things. Since I'm relatively new to it all (and work alone) any comments or input from those with more experience?

author: tszaboo
author_rank: Super Contributor
timestamp: August 08, 2022, 02:39:37 pm
content: It usually isn't considered bad practice up until the point when your motor is suddenly on fire.Same goes for breakpoints.Then the engineering team learns and stops doing it.

author: frmdstryr
author_rank: Contributor
timestamp: August 08, 2022, 03:05:38 pm
content: Sounds like a bad practice then... so what is the alternative? A giant polling loop? Always masking other interrupts and running them in a statically-allocated stack or something?

author: eugene
author_rank: Frequent Contributor
timestamp: August 08, 2022, 08:45:34 pm
content: Seriously? So if I have a motion system with closed loop control that updates once per ms, I can't just setup a timer to trigger an interrupt every ms that sets a flag telling the main loop it's time for a time step?How is it supposed to be done? Do I need to check the contents of a free running counter every time through the main loop?I can't agree with the "No Interrupts!" rule. If a periodic timer interrupt that consumes 25 clock cycles is going to make my code fail somehow, then there's something wrong with my code.

author: langwadt
author_rank: Super Contributor
timestamp: August 08, 2022, 08:58:17 pm
content: Quote from: frmdstryr on August 08, 2022, 01:52:43 pmthe commenter is talking nonsense

author: Benta
author_rank: Super Contributor
timestamp: August 08, 2022, 10:08:24 pm
content: That's the most ridiculous thing I've heard.Interrupts are an integrated part of real-time processing, and setting the timing and priorities correctly is a standard task of any developer.Where it can get "hairy" is during debugging, where single-stepping a routine while the power stage is on is a really bad idea.Most of the "DMC" microcontrollers have timers that can fix this by disabling the outputs correspondingly.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: August 08, 2022, 10:22:31 pm
content: There is NO such thing as "good" or "bad" practice, only more or less appropriate for a given set of requirements.Interrupts generally should be used where events need to be serviced in a predictable (typically short) timescale.For a hard realtime application like a motor controller, use of interrupts would seem to be a pretty appropriate, if not essential, way of doing things, depending on the nature of the hardware peripherals being used.I once had a client who forbade his in-house programmer from using interrupts, because he ( the boss) didn't understand them.Needless to say the final application ended up an unreliable dumpster fire due to unpredictibility of polled loop response times.Fortunately as an external consultant I was in a position to tell him that he was being an idiot.

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: August 08, 2022, 10:24:32 pm
content: While you may well be able to do a perfectly good BLDC controller without interrupts, as soon as you want to add things like communications interfaces, user interfaces or other features, unpredictability of realtime response can easily make things come unstuck ( or catch fire)

author: thm_w
author_rank: Super Contributor
timestamp: August 08, 2022, 11:33:59 pm
content: The blog is from a guy who makes this product:https://mjbots.com/collections/servos-and-controllers/products/moteus-r4-11Looks quite cool.Would not be realistic to make something this complex without interrupts.QuoteTLDR of article: enabling multiple ADCs at once seemed to cause a problem, so he changed them to sequential initialization.

author: frmdstryr
author_rank: Contributor
timestamp: August 09, 2022, 01:23:44 am
content: Thank you all for the comments. I had not thought about the debugging aspect (so far I've only used interface chips which have shoot though safety at the hw level). Also meeting deadlines some sort of with comm interface seems like it would be a challenge without interrupts.Some searching let me to this articlehttps://www.cis.upenn.edu/~lee/06cse480/lec-emsoft-analysis-p1.pdfwhich had an interesting chart showing how interrupts could in theory overload the cpu (I'm not sure what would cause it).That and the stack overflow reasons mentioned do seem to give some validity to the argument.

author: Kasper
author_rank: Frequent Contributor
timestamp: August 09, 2022, 05:15:26 am
content: Quote from: frmdstryr on August 09, 2022, 01:23:44 amI did this years ago with my first try at motor control. Put too much code in the interrupt service routine and then had the encoder in the motor trigger the interrupt, many times per rotation.Time to run ISR was greater than time between ISR triggers.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 09, 2022, 06:12:04 am
content: Quote from: frmdstryr on August 08, 2022, 01:52:43 pmOf course not. It's the opposite, interrupts are the key to writing predictable and low-latency real-time code on microcontrollers. Almost always the control loop calculations and performed in ISR, triggered by PWM generation counter per every cycle (or sometimes every n cycles), or ADC finishing conversion, or similar.There can be additional interrupt sources for things like instantaneous overcurrent.Somebody just has no idea whatsoever what they are talking about.There are usually no other choices, really. Sometimes in very simple applications, OR with very capable MCU peripherals, you can actually make the thing run solely on the peripherals without any software control after the initialization, but usually not with motor controllers.Debugging a real-time system which can blow up if the timing goes awry always requires understanding; setting a breakpoint in a wrong place will kill the thing regardless of whether one used interrupts or some hand-timed polling loop. There is no other way around this but to actually understand how to debug the motor controller code. Personally, I don't use general purpose debuggers but instead add instrumentation to my code, so that it's always obvious (by just looking at the code) what is happening and where.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 09, 2022, 06:28:05 am
content: Quote from: Kasper on August 09, 2022, 05:15:26 amYeah, I don't like to configure encoders to directly act as interrupt sources exactly because noise and mechanical resonances can give unexpected triggers.Instead, I just sample encoders at fixed intervals at frequency significantly higher than the expected encoder value change rate. In practice, do it in the very same periodic ISR where FOC is calculated.After all, what use do you have for encoder readings between calculations? Encoder position being just an input to control algorithm - better sample it just before calculation.Luckily, algorithms like FOC (or speed PID controllers) are so simple that given any 32-bit MCU, you can pretty much calculate them at 20-30kHz or even more often with a lot of CPU time to spare.

author: tszaboo
author_rank: Super Contributor
timestamp: August 09, 2022, 02:30:17 pm
content: Quote from: mikeselectricstuff on August 08, 2022, 10:24:32 pmExactly this. Using interrupts is possible, if you investigate fault conditions, and prepare for them.Like having "too much communication" starve the control loop from executing. Or having EMC generating too much pin change interrupts.The whole motor control has to be predictable, and the frequency of it must be fast enough.It all requires careful planning before writing code, which I haven't seen done any time by 99% of programmers. And testing.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 10, 2022, 01:46:24 pm
content: Quote from: tszaboo on August 09, 2022, 02:30:17 pmIt seems you have some weird definition for "interrupt", different from the rest of us. Probably the original "do not use interrupts" poster has the same weird idea.In actual reality, interrupt is exactlythetool to generate that reliable timing. In a motor controller, a timer interrupt is very typical way of doing it. Pin change interrupt would indeed be very iffy and used with caution / good understanding.

author: frmdstryr
author_rank: Contributor
timestamp: August 10, 2022, 03:02:13 pm
content: QuoteAssuming sufficient stack space I think interrupt priority could solve the potential starvation issue.But polling or the software interrupt emulator (in the paper from CMU above) are the only ways I can think of to address to interrupt overload problems or do any mcus (i've only used arm) have builtin hw to throttle interrupts?From reading the comments from everyone it sounds like any external interrupt could cause an overload/lock up, but software sources (eg timers) are relatively safe?I don't know how a polling loop would work. Low priority tasks would need to yield to high ones somehow, is this done by something like FreeRTOS or similar?This is great feedback, thank you all!

author: Siwastaja
author_rank: Super Contributor
timestamp: August 10, 2022, 03:14:30 pm
content: Quote from: frmdstryr on August 10, 2022, 03:02:13 pmThey all do in some form because you always have a way to selectively disable an interrupt source, and have timers.So if you need to wire something to an external interrupt pin, all you need to do is, in the ISR, disable that interrupt source and set a timer to give another interrupt later, where you re-enable the interrupt source. Not difficult, but obviously this should make you think whether you could just periodically read the input to begin with in a timer ISR - of course increasing reaction jitter and latency in the process, but making everything just simpler.This is the structure of basically all motor controllers I have done:init:configure a timer to:* generate PWM* generate triggers for ADC* generate interrupt requestsconfigure ADC to accept triggerspossibly configure DMA for ADCconfigure analog comparator (or just ADC watchdog feature)enable the timertimer ISR:* read out current from ADC (sometimes just from ADC register, sometimes from memory if DMA was used)* read encoder position (just from IO pins, or possibly from a counter peripheral)* do all FOC + speed control calculations* update PWM registers with new valuesovercurrent ISR (higher priority):either* update PWM registers and set some flag for the timer ISR that this kind of extra current limitation had to happenor* turn the thing off and error outAll you really need to do is to verify timer ISR never takes too long not to finish before the next cycle. Thankfully, it is typically easy to write this ISR in quite linear fashion without a lot of branching.

author: tszaboo
author_rank: Super Contributor
timestamp: August 10, 2022, 03:47:02 pm
content: Quote from: Siwastaja on August 10, 2022, 01:46:24 pmYou don't have time to schedule your system with interrupts. The ADC will run at somewhere between 1-10 MSPS, and your control loop faster than your motor. The interrupts are either "Someone pressed the emergency stop button, or something else went wrong" or I received a complete CAN message to change the speed. You do timings by polling the timer register, because there is really not enough time to wait ~12 clock cycles for an interrupt just for the timings to look good.Or maybe you have one of these special edge cases, where you have a 100+MHz microcontroller with a motor that runs really really slow. In that case, do whatever.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 10, 2022, 06:40:54 pm
content: Quote from: tszaboo on August 10, 2022, 03:47:02 pm1) Are you serious?2) Have you ever built a motor controller, or have any idea how one works and what kind of frequencies and calculations are involved?3) Are you really, really serious?I'm asking before replying more in detail. I'm just so surprised anyone is even suggesting what you do. Polling for a timer register to save ~10 CPU cycles on a motor controller sounds so totally ridiculous to someone who designs motor controllers. Besides, what you suggest is a timing disaster: if you handle CAN messages on interrupts, then you totally ruin your precision polled timing. You have the whole thing the wrong way around; you totally can process CAN messages on the polling loop because they are less timing critical.

author: tszaboo
author_rank: Super Contributor
timestamp: August 10, 2022, 07:10:49 pm
content: Quote from: Siwastaja on August 10, 2022, 06:40:54 pmI really tried to make it as ridiculous as possible, but apparently Poe's law is still valid.OP: This being said, you totally can set the motor on fire with a breakpoint.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 11, 2022, 11:39:54 am
content: Quote from: tszaboo on August 10, 2022, 07:10:49 pmIt wasn't ridiculous enough! I have seen people brag in power point presentations how they sample motor current at 10MSPS. OTOH, I suspected parody and that's why I asked.Of course, we know that motors have huge amount of inductance, so any output change you do cannot produce any significant change in timescale below some tend of µs. Some 100krpm ferrite- or air-cored micromotors might be different, of course, frequencies of interest approaching DC/DC convertes. Because usual motors are basically huge inductors, and the inverter half-bridge always gives a path for the current, it makes no sense to monitor current more often, or do calculations frequently, as current physically cannot change fast.So we can do all the control in a 5-10kHz repeating ISR just fine. Often we use PWM frequencies tad over 20kHz to prevent audible whine, while 10kHz could be a sweet spot with totally eliminated torque ripple yet still very low switching loss.Exception to that rule is, if we want to sense an actual electrical short circuit (which bypasses the motor inductance) of the output, in which case only stray inductance limits dI/dt, we will want to have bigger current sense bandwidth, and react quickly to it. But this special case is best handled with analog comparator input directly suspending PWM, or triggering the highest-priority interrupt to do that - usually no need to recover from there, just turn it off.I liked the idea of polling if(TIM->CNT > 10000) to avoid a dozen cycles of ISR latency, when you could just configure compare match to trigger the interrupt at CNT=9990, though.