MCU reset after crossing certain Iq current

Hello everyone,

I finished my custom DRV8302 based driver 2 months ago and thought that I am done (mistake :smiley: ). While initial testing gave results that I considered good enough I recently realised I will need more torque (thus Iq current). Originally I was able to operate my motor at 20A at 2V voltage limit, but the produced torque isn’t quite enough for the robot I am building.

For further clarification: I am using position control with underlying TorqueControlType::foc_current. My driver based around DRV8302 MCU paired with IRF1404Z mosfets. I am also using lowside current sensing with only 2 shunt resistors.

My problem is that when I raise the current limit (and voltage limit with it) and force the motor to produce the maximum possible torque (should be proportional to that current limit from my understanding) the driver shuts down. More specifically the STM32F103CB on the driver just restarts.

This is very odd to me. I expect this to be some kind of hardware flaw on the driver, but why the restart? I’d say that if the driver can’t handle it, the current would simple burn the trace it goes through. Did anyone experience similar behavior?

Things I tried before posting :smiley::

  • Increasing wire thickness before the XT30 connector of the driver
  • Upgrading bulk capacitance from 1000uF to 1200uF and LOW ESR caps
  • readjusting PID values

Do you think that increasing copper weight in the PCB would help? I also revisited some of my component choices and found out that I am using 3W 10mOhm shunt resistors for current sense. But if I force 25A through it, I get 0.25V voltage drop over it resulting in 6.25W power dissipation. I know that signal is PWM so it “sees” some kind of average value but still, shouldn’t it burn?

Thanks for your time!

Adam

Are you willing to share your schematic / PCB design and specs, battery used so I can look into it further?

Yes, of course. This is my project for learning more than anything else :smiley: .

Link for the PCB and scheamatic: H-drive driver.

Regarding the other specs… I do not have any battery yet, I power the project from lab bench PSU. It is set to 20V with no current limit (it is rated for max output of 900W → 30V at 30A). The PCB was manufactured by JLC with 1oz/ft^2 copper weight, it has just 2 layers. Is there anything else you may find useful?

Thanks for the insight!

I’ve had a look through the schematic and PCB and couldn’t find anything obvious which would cause a MCU reset when the current exceeds a threshold.

Could you please measure a few things for me, so I can help narrow down the root cause of the problem? The first thing is the input voltage, I want to make sure that you are not drawing too much current from the power supply and causing it to shut down temporarily and restart. You should use an oscilloscope not a multimeter as an oscilloscope can show the fast transients.

Also, please measure the amount of ground bounce on the board. The way to do this would be to connect the scope ground to the ground pin of the XT30 connector, and probe the ground pins of the negative side of the current sense resistors / MOSFETs. Also probe the ground pin of the STM32.

Next, check whether the voltage supply to the STM32 is stable, measure the voltage with an oscilloscope between VCC (location not too important) and GND (location is important, use the one on the UART header).

Usually resistors are quite good at handling pulse overloads. The power rating of the resistor also depends on how well heat can be carried away from it, if the resistor is on a big plane you can push more power without overheating it. Finally, on average the low side FET will only be on around 50% of the time (depending on modulation used), so the power dissipation in the resistor will only be around half the value you calculated. So I do not expect the resistor to burn if you are pushing 25A through the motor, although for efficiency reasons I still suggest reducing the resistance.

Same goes for the PCB traces, a PCB is designed to withstand soldering temperatures (260 degc +), and remember the melting point of copper is 1084 degc. Since you have used pretty thick traces, they most likely won’t burn up at 25A.

Try adding a pullup resistor on the reset pin. Without ground planes, you probably have a lot of electrical noise bouncing around that could trigger it by accident.

There is already an external pullup resistor on the reset pin, you probably didn’t look closely enough. Also ST’s official recommendation is a 100nF capacitor on the reset pin, not a pullup resistor as there is already an internal one.

I already have a 10K pullup on the reset pin near the SPI header (R12).

But this goes against the STM’s datasheet, I’ll try to remove it and add the cap as recommended.
I think I already made some of the measurements you requested (I’ll send them in the afternoon after school).

I unfortunately won’t be able to do the rest of them until friday. So I’ll post those a bit later :sweat_smile:

Sorry for the delay…

Today I tried to make the measurements @Andrew requested previously. So I disassembled the construction (I was testing it inside a robot leg), but when I connected the motor separately I was unable to reproduce it (thus → basically nothing to see on the scope except the constant voltage).

After trying for couple of minutes I discovered that the driver restarts when I push it back a lot (lot of torque going against me) and then just let go as quickly as possible. The motor just springs back super super quickly, overshoots like hell, starts shaking and then shuts down.

So it pretty much comes down to the PID tuning I think… Is there a way I can slow this “return motion” down. It behaves like a spring, which is quite good to a certain point. Can I limit the max “return speed” somehow??

From what you have said it seems you are using some kind of position control scheme. I use a custom position control scheme (see here for details) which is designed to move as fast as possible while ensuring stability and reducing oscillations as much as possible.

Usually the position control scheme needs to be tuned with the load attached, so it is normal to get oscillations if you are running the motor outside the robot leg.

It would still be helpful to see the waveforms for the new scenario where you were able to reproduce the restarts, which should still provide a good insight into the potential root cause of the shutdown issue.

I am using the default position control provided by the library. Good to know I should tune it in the leg.

Nevertheless, I gathered everything you wanted. Especially the ground bounces are quite interesting, but I can’t really asses if it’s right or wrong :smiley:

Power supply voltage before driver restart:

STM32 3.3V power measured at UART ground before restart:

Phase A ground bounce sequence few moments before restart (on resistor ground):





Phase B ground bounce sequence few moments before restart (on resistor ground):



Phase C ground bounce sequence few moments before restart (on mosfet ground):




Sorry for the load of pictures, hopefully there is some clue about what could be wrong.

One final note: while testing bit more I discovered that it has FAR lower tendency to shut itself down when the motor is hot. When it gets hot I can only force it to restart with the “let go” scenario. But when it’s cool, it is super easy. I just go against the motor and once it reaches about 20A to 25A (always a bit different) it shuts down.

Power supplies usually don’t like it when motors generate energy back toward them, so that could be what’s happening in the spring-back case, as the motor tries to slow itself down. Try probing the power supply voltage to see if it rises and then shuts itself off.

The case of pushing against the motor is probably different though, since that should only be drawing a modest amount of power from the supply.

Thank you for the pictures. I will assume you have captured the correct region of interest where the driver shuts down, as the timebase used is quite small. From what I can see the ground bounce is around 300mV (ignoring the high frequency ringing which is likely caused by suboptimal probing strategy). This is around what I expected from looking at your PCB designs and PCB specs, and it is too small to cause the MCU to reset. We can confirm that this isn’t the cause of the issue as the MCU supply voltage you measured doesn’t dip below 3.1V (STM32F103 can operate down to 2V). So I don’t think thicker copper will help.

Could you confirm again whether it is the MCU that is rebooting, or whether it is the DRV8302 triggering a fault and shutting down?

You can also check the RCC on the STM32 which will tell you the reset reason, this might provide some further insights.

On the one hand yes, the PID tuning, or even an optimized controller as Andrew suggested.

But if you’re asking about limits there are several that you can play with:

motor.velocity_limit - limit the absolute velocity

angleP.limit - same thing

angleP.output_ramp - limit acceleration

velocityPID.limit - limit Q axis current/voltage (depending on torque mode)

velocityPID.output_ramp - limit Q axis current/voltage slew

Sorry guys for the delay, I am currently on a visit at university in United States. I will try to read the fault pins of the DRV and reach back as soon as I return.

Hi guys,

so I have done some further investigation and it seems like it is truly the STM32 that is resetting.
I read nOCTW and nFault pins of DRV8302 and they all seem fine (they are pulled up to logical 1 by resistors and stay there).

Next I tried to read the RCC->CSR register of STM32 to find out the cause of the reset. When I go against the motor and cause the reset I get RCC_CSR_PORRSTF value from the register, which points to power-on/power-down reset. Meaning that there is really some kind of voltage brown out probably.

Code I used to read the reset cause:

  uint32_t csr = RCC->CSR;

  if (csr & RCC_CSR_LPWRRSTF) Serial.println("Low-power reset");
  if (csr & RCC_CSR_WWDGRSTF) Serial.println("Window watchdog reset");
  if (csr & RCC_CSR_IWDGRSTF) Serial.println("Independent watchdog reset");
  if (csr & RCC_CSR_SFTRSTF)  Serial.println("Software reset");
  if (csr & RCC_CSR_PORRSTF)  Serial.println("Power-on reset");
  if (csr & RCC_CSR_PINRSTF)  Serial.println("NRST pin reset");
  
  // reset reset register :D
  RCC->CSR |= RCC_CSR_RMVF;

I also removed my duplicate pullup resistor on NRST and added 0.1uF capacitor betweeen NRST and GND, but I had no luck with that as well (it might be a tiny bit better, meaning it shuts down after slightly longer time, but honestly I cannot really tell).

So I tried to repeat the measurement of STM32 VDD voltage and managed to get something more reasonable with increased timebase (the amount of noise is still ridiculous, I need to have long wires between probes and pads while testing).


Voltage here gets somewhere to 2.8-ish range when the restart occurs. It is still strange, since STM32F103 brownout range should be even lower (@Andrew mentioned 2V). I might try to power the processor from external 3.3V, but that is not really a solution for me.

Any ideas?

EDIT:
I am probably a bit confused about the scope measurement (I had like 2 classes of using scope + zero other experience :smiley: ). When I lower the falling edge trigger threshold to 2.5V in single trigger mode I get drop under 2V.


What is the correct scope settings for this type of non-periodic measurement?

Thanks

I’ve checked your PCB artwork design.
Since it’s a 2-layer board carrying a large current — around 25 A (peak) — I suspect a significant transient voltage difference may be occurring between the left and right ends of the pcb-ring.

Adding capacitors at specific points probably won’t solve this issue.
I believe a more effective approach would be to add a thick wire along the high-current return path on the bottom layer (as indicated by the red arrow) to minimize that potential difference.

I hope this insight helps you move closer to completing your project!

So it seems your previous results are invalid as you probably didn’t trigger the scope at the point where the MCU reset happened. I can help you with how to use the oscilloscope correctly so you can provide the correct measurements next time.

There are 2 main things you need to do to capture the correct region of interest. The first is the vertical settings. You should be setting the gain (volts per division) and offset settings of the scope before the measurement so that the signal always stays fully on the screen. You can usually take a guess at this, and if your guess was wrong, adjust and re-measure. Once the measurement has been acquired, most scopes will still let you change these settings, but it will re-use the existing data which might be affected by clipping / quantization and therefore be inaccurate. I suspect you may have adjusted the offset after the measurement in your most recent screenshots, as the bottom part of the waveforms look unusually flat. Always re-measure after changing the scope settings to avoid this.

The second is the horizontal settings. Most modern digital oscilloscopes have a decent amount of memory to capture a lot of data in the horizontal axis, unlike the vertical axis. Therefore you can zoom in quite a bit in the horizontal axis before experiencing any artifacts caused by lack of data points. For single events like this, I usually go and set the memory depth to the maximum and use the biggest timebase which still maintains an acceptable sample rate (around 10x the highest frequency you expect to measure). This strategy gives the best change of actually capturing the event and what happened before and after. After the event is captured, you can then zoom in to the interesting parts to see the details.

Since scopes don’t have infinite memory and even if you have a very large memory you don’t want to look through millions of data points, scopes come with a trigger feature which helps start the measurement at the correct time. The most common trigger type is an edge trigger, which starts the measurement when the voltage level crosses the trigger level, rising / falling or both depending on setting. The scope can also capture a bit of data before the trigger event. To set the trigger correctly, you want to identify which voltage will change significantly to cross a threshold around when the event of interest occurs, but doesn’t cross that threshold frequently when the event isn’t happening to avoid capturing uninteresting events. This varies case by case and requires a bit of thought. In your case, based on the readout from the RCC CSR register you can probably assume the power rails are a good candidate for the trigger. Another option is to create the trigger source yourself by toggling a spare GPIO pin of the MCU during boot, and using another channel of the scope to trigger off that.

Finally there is the trigger mode which has 3 options. AUTO means it will capture new events if the trigger condition hasn’t been met for a while, and capture on valid trigger events. NORMAL means capture on trigger condition only. SINGLE means capture on first trigger condition and ignore subsequent ones.

For this case it’s best to use the SINGLE mode, with the trigger set to falling edge with the trigger level at 2.0V, on the 3.3V rail signal. Use the other channels of the scope with more probes to capture the other signals of interest, keeping the first probe on the 3.3V rail signal (otherwise you lose the trigger). Keep in mind that the GND clips on all scope channels are shorted together. Start with a 1ms/div timebase and zoom in if you see anything interesting (especially near the start of the voltage dip).

You can also try and measure the 3.3V output across the DRV8302 buck output capacitor (use the negative of the capacitor for the GND reference) and see if there’s a significant voltage drop there or whether it’s localized on the STM32. Also the switch node of the buck might be interesting to look at (need to zoom in for that one).

Thank you for the great scope tutorial… Probably took more from it than I took from 3 months of school course :smiley: .

I remeasured all the important things using channel 1 as the trigger with falling edge under 2.0V and channel 2 to get all the other measurements. Unfortunately I still can’t really tell what’s wrong…

I also tried to solder thick wires just like @cronos_sv suggested, but that did not introduce any improvement sadly.

STM32 VDD drop measured at UART ground (hopefully correctly this time :smiley: ):

Buck converter drop measured at buck output cap C11 ground:

Main PSU behavior during restart:


And finally ground bounce at phase B grounded resistor:

I also tried to measure the switching node as @Andrew suggested and it really stops “switching” for the time of the voltage drop.

Thank you for the updated measurements. You seem to have followed my advice pretty well, but from the screenshots it looks like your memory depth is set to 10kpts, which is a little on the low end. This is fine for most measurements, but the switching node measurement is probably inaccurate due to too low memory depth settings. If you could just repeat that one while setting the memory depth to the maximum, and use an appropriate timebase so the sample rate is at least 20MSa/s that would be great.

From the screenshots provided it seems like ground bounce is not the cause of the issue as the amplitude seems to be around 300mV (ignoring the spikes which is most likely noise coupled in from another source), although it is higher than I would personally tolerate.

The input voltage seems to remain stable when the voltage drop happens, however there is a very large ripple on the input voltage around 4V peak to peak, which might negatively influence the buck converter. This level of ripple is higher than I would tolerate, but I can’t say whether it is the root cause or not without doing more testing. To reduce the ripple, you can add even more big and low ESR capacitors as close as possible to the MOSFETs. I like tantalum polymers but aluminum polymers are also good. Ceramics aren’t very useful here as the capacitance derates like crazy once voltage is applied.

I suspect what is happening is that something is causing the buck converter to shut down temporarily, another potential cause could be that some internal protection feature got tripped. Some better screenshots of the switch node waveform, one zoomed out and another zoomed into the point just before the buck converter stops switching and showing the PWM clearly would provide more insights.

You can also try probing the feedback pin of the buck converter although be careful with that one as probing it might introduce noise into the feedback pin and cause issues.

A temporary fix would probably be to power the 3.3V externally as that would eliminate the voltage drop when the buck stops switching.