MOSFETS on custom ESC for BLDC are overheating really badly and I can't figure out why HELP

Hey everyone this is my first time reaching out to the community for help, and I am really stuck. Basically I am trying to make my own ESC for a BLDC before anyone says the commercial solution is cheaper and easier, I'm doing it to try learn more and make a customisable version that's all my own work so lets get into the issue.

The problem is although I'm using a 20khz Pwm signal at a variable duty on the high side input generated by direct timer control on the nano, to try "chop"/control the current and keeping the lowside fully grounded, the MOSFETs I'm using (N-channel irf1405s that are 55V and 160A rated) are getting really really hot and so is the motor like over 150 degrees Celsius hot even after only running for 30 seconds. The actually motor spins just fine however I can even change the speed using a timed step change (although I do have the hardware and did have the software for BEMF step changing too I disabled it to try simplify things since the heating issue is my main priority).

I've attached my code and schematic as well as a picture of my circuit if anyone can see something on this that I can't it would be much appreciated because I'm at my wits end here ive tried adding lots of different changes to the hard and software with no luck as at the end of it all I still can't seem to stop the MOSFETs and motor from getting really hot because of what I assume is excessive current draw (possibly building up in the coils and trying to ground through the FETS body diode? maybe?) , if I increase the duty to 70%+ the MOSFETs also just straight up explode even with dead time coded in using delay functions.

I'm using a 12V 6.5Ah lead acid battery for testing as its close to the power supply I would use the ESC with normally.

if anyone with experience in power electronics or any ideas on how to fix my heating issue is reading this please help. Thank you, Harry.

Basic code with timed steps:


int StepCounter = 1; //step counter
int RawDutyCycle = 0; //raw pot input storage variable
int Duty = 0; //duty cycle

//setup lowside pins for standalone direct port manipulation
int LowSideA = PD2; //pin D2
int LowSideB = PD5; //pin D5
int LowSideC = PD7; //pin D7

//setup highside pins to be PWM outputs at port level
int HighSideA = PD3; //OC2B D3
int HighSideB = PB1; //OC1A D9
int HighSideC = PB2; //OC1B D10

//defins all the PWM pin States neatly
#define HighSideASetON (1<<COM2A0) + (1<<COM2B1) + (1<<WGM20)
#define HighSideASetOFF (0<<COM2A0) + (0<<COM2B1) + (1<<WGM20)

#define HighSideBSetON (1<<COM1A1) + (0<<COM1B1)
#define HighSideCSetON (0<<COM1A1) + (1<<COM1B1)
#define HighSideBandCSetOFF (0<<COM1A1) + (0<<COM1B1)

void setup() {
  
  //Sets data direction of all pins
  DDRD = (1<<LowSideA) | (1<<LowSideB) | (1<<LowSideC) | (1<<HighSideA);
  DDRB = (1<<HighSideB) | (1<<HighSideC); 
  pinMode(A0, INPUT);

  //timer1 PWM pins D9 and D10 setup
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1A = (1<<COM1A1) + (1<<COM1B1) + (1<<WGM11); //phase correct pwm
  TCCR1B = (1<<WGM13) + (1<<CS11);
  ICR1 = 100; //set kHz
  OCR1A = 10; //set duty
  OCR1B = 10; //set duty

  //timer2 PWM pin D3 setup
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = (1<<COM2A0) + (1<<COM2B1) + (1<<WGM20); //phase correct pwm
  TCCR2B = (1<<CS21) + (1<<WGM22);
  OCR2A = 100; //set kHz
  OCR2B = 10; //set duty

  //Sets all 3 H-bridges to float
  TCCR1A = (0<<COM1A1) + (0<<COM1B1);
  TCCR2A = (0<<COM2A1) + (0<<COM2B1);
  PORTD = (1<<LowSideA) + (1<<LowSideB) + (1<<LowSideC);
  
}

void loop() {
  
  RawDutyCycle = analogRead(A0); //read the pot
  int WaitTime = map(RawDutyCycle, 0, 1023, 10000, 500);
  Duty = 50;
  OCR1A = Duty; //set duty
  OCR1B = Duty;
  OCR2B = Duty;
  
  delayMicroseconds(WaitTime);
  
  switch(StepCounter){

    case 1: //step1
    TCCR1A = HighSideBandCSetOFF;
    PORTD = (1<<LowSideA) + (0<<LowSideB) + (1<<LowSideC);
    TCCR2A = HighSideASetON;
    StepCounter = 2;
    break;

    case 2: //step2
    TCCR1A = HighSideBandCSetOFF;
    PORTD = (1<<LowSideA) + (1<<LowSideB) + (0<<LowSideC);
    TCCR2A = HighSideASetON;
    StepCounter = 3;
    break;

    case 3: //step3
    TCCR2A = HighSideASetOFF;
    PORTD = (1<<LowSideA) + (1<<LowSideB) + (0<<LowSideC);
    TCCR1A = HighSideBSetON;
    StepCounter = 4;
    break;

    case 4: //step4
    TCCR1A = HighSideBandCSetOFF;
    PORTD = (0<<LowSideA) + (1<<LowSideB) + (1<<LowSideC);
    TCCR1A = HighSideBSetON;
    StepCounter = 5;
    break;

    case 5: //step5
    TCCR1A = HighSideBandCSetOFF;
    PORTD = (0<<LowSideA) + (1<<LowSideB) + (1<<LowSideC);
    TCCR1A = HighSideCSetON;
    StepCounter = 6;
    break;

    case 6: //step6
    TCCR1A = HighSideBandCSetOFF;
    PORTD = (1<<LowSideA) + (0<<LowSideB) + (1<<LowSideC);
    TCCR1A = HighSideCSetON;
    StepCounter = 1;
    break;
  }
}

From where does the electrical design come?
It doesn't look good using N channel MOSFETs like that. An N channel can switch the low side but not the high side.

I'm using ir2101 h bridge drivers to high side switch the MOSFETS so I don't know what you mean sorry dude I wish it was that simple.

If the MOSFETs are overheating, the gates are not being driven properly, or you forgot to mount them on heat sinks.

There is far too little useful information in your post.

This is not a project for an amateur.

Its been a number of years since I designed our brushless motor controller.

However looking at your circuit, its not clear how your Virtual Zero is created and how the Phase Voltages are sensed. I seem to recall there was some small capacitance on the feedback for noise abatement.

You didn't mention if the motor is spinning and if so is it smooth or staccato?

FET 1, 4 and 6 are the ones I find strange.

Quoting @jremington
If the MOSFETs are overheating, the gates are not being driven properly.

The gates to FET1, 4 and 6 as I think.

Not an issue, this is exactly how to use MOSFETs with a high-low gate driver chip - read the IR2101 datasheet.

I suspect the problem is either shoot-through or incorrect phasing.

You don't happen to have waveforms from the phases? Or even current sensing in the phases?

If its shoot-through you need to change the timing so that LIN and HIN have enough dead-time between then - the IR2101 isn't a great chip as it doesn't have built-in shoot-through prevention (lots of gate driver chips do have this very handy feature).

If it phasing then getting it wrong and you might be treating the motor as a heater, accounting for excessive currents and heating. The phasing should always be leading by 90 degrees (electrically), so the rotor is being pulled round (rather than held in position like a stepper). Otherwise you aren't turning that current efficiently into rotation, but mainly into heat.

A quick browse of your code suggests you are not using BEMFA/B/C in a feedback loop - this is required, the timing comes from the motor, not from the code. The code uses the motor speed in a control loop to adjust the PWM drive level, the motor's natural speed should be commutating the phases.

The only time open-loop control is used is to get the motor moving from standstill, with an accelerating frequency for a fraction of a second, thereafter you have to close the loop before the motor burns out...

[ BTW there is open-source BLDC driver and ESC code around - worth looking at examples that do this closed-loop control for inspiration ]

obviously didn't read enough of the spec.....

Hey I’m using the resistor block shown in the diagram to get the virtual zero but thats not my issue I understand how to do that and had it working until I decided the heating problem was more important so I removed it until i can fix that issue

Hey I’m not sure I understand how to set the phasing up correctly. Is it something done in the code or hardware? And il have to get a scope. Do you know of any resources i can learn more about the phasing from ?

I'm sure if you google you will find many resources. If I recall Microchip had a good app note for one of their DSP processors that had some special capability for BLDC drive.

You will need an oscilloscope.

The motor spins fine like it rotates smoothly and doesn't jitter, the speed can even be changed via the delay function which is shown in the code the only problem is it gets very very hot.

I’ve not looked in detail at your timer controls, but I did notice that the case statement appears to lack symmetry .

This appears once only. I’d have expected twice.

This appears 5 times and I’d have expected 4.

Of course, there may be a good reason which I have missed.

Hi, @hary_casuallyloaded
Please post your code in code tags.

Do you have a scope to check your gate signals and timing?

Where are your protection fuses to the battery supply, it can output 100s of Amps into a short, hence blow the guts out of everything, including PCB and components.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

Hi,
Googling IR2102 H-bridge I see many example circuits like yours, BUT, they use UltraFast diodes and not the generic 1N4148 in the gate circuits.

20kHz is switchmode power supply territory and I have never seen a 1N4148 used in them, always a fast type diode.

I know the example below uses a different driver to yours but the gate drive is in principle the same.


UF4007 are Ultrafast Diodes.
Also note gate to source resistors.
https://www.onsemi.com/products/discrete-power-modules/rectifiers/uf4007

I you may need to have current limit/monitoring circuitry to protect your motor and controller.

Can you please post image(s) of your project so we can see your component layout?
If you have a PCB, can you please post an EXPORTED jpg image of it too?

Tom.... :smiley: :+1: :coffee: :australia:

As I said you need to use closed loop control for such a motor (except during the brief start-up time).

The back EMF is sensed to determine the actual position of the rotor and used to time commutation. That way the drive phase can be kept correct and the back-EMF will act to limit the current drawn when running.

Your code assumes you can select when to commutate without refering to the rotor position - you can't with this class of motor (its not a stepper motor). The winding resistance in these motors is so small that with getting this right the currents that flow are extremely large and will burn out the motor and the MOSFETs in a short space of time.

As I said find an open source ESC or BLDC driver to see how its done, or mug up on motors - plenty of resources out there. Some BLDCs have Hall sensors to determine the phasing, but most RC motor don't and you have to use that resistor array to measure the back-EMF on the idle winding instead (which only works above a certain speed).

If you look at a brushed DC motor you'll see how the physical commutator fixes the phase between the permanent magnet field and the armature's field at 90 degrees of so. In a brushless motor the same thing has to be done by external switching.

Hi,
Not sure but these YouTube videos may help.

Tom... :smiley: :+1: :coffee: :australia:

I did a quick exercise to put the outputs H1,L1,H2,L2,H3 and L3, based on the code and schematic in post #1, through a logic analyser.

There does appear to be a significant amount of shoot-through, that is where both Hx and Lx are on simultaneously, and as suggested by @MarkT

1 Like

yeah I do have a small scope I will be posting the photos of the results when I get a chance to work on it tomorrow and as per the comment by @6v6gt I will go over the steps code again and possibly just write the TCCRA1 and TCCRA2 registers to just straight 0 instead of messing with the respective COMxx and COMxx bits to turn it off. Also in respect to your following comment thank you so much Ive been thinking I should go to a jaycar and get a bunch of diodes and a THT 30a fuse holder to try or maybe just go online. So anything ultrafast will work? and is there some maths I can do to help me find the best one? Again thank you for taking the time to try help me with this.

yeah I have read a bit about that and its logical because staying on a step longer than needed makes no sense and I understand everything your saying up until

armature's field at 90 degrees or so. In a brushless motor the same thing has to be done by external switching

how do I determine when to undertake this switching and what FETS do I switch is it related to the back emf and the steps timing or something else? ive googled BLDC phasing and read some but still can't get any good idea of it. thanks for giving me a new path to consider though and il do some further research and testing.