Three phase output precision problem for BLDC controller


I'm trying to make sinus controller for BLDC using Arduino Uno/Micro/Nano with BTS7960, which should spin motors smoothly with as low noise as possible, more like stepper drivers do (3 phase sin waves as PWM form). The problem is how to output signal to digital pins precisely so the motor do not produce lot of noise cause harmonics or whatever happens when square wave / PWM is fluctuating a little, even if frequency is 30..100 KHz.
I have tried to write to pins in cycle measuring time till do it - fails, seems cause of micros() performance.
Tried to use many NOPs to have more stable result just for testing purposes - still noisy, fails.
Didn't try using interrupts, don't see how they could help me about precision compared to execution inside the loop().
Hardware PWM set to 32 KHz - success, zero noise.
Okay, let's pretend PWM is the way, but how to make three phases? Must have almost exact syncronization moment at start of each wave cycle, like on the attached picture. Or maybe at the end of it, can be reversed if it helps. But keep in mind, this is not classic PWM control, zero here is 50% PWM at all three phases, kinda workaround for slow switching of BTS7960 (which have raise and fall times around 2 microseconds each).

Thanks in advance!

shouldn't each signal be the same width but start at different times (i.e. different phase)?

7711.rajne 2

Hi, @dummynull
Have you Goolged;

This is a good YouTube presentation for a Nano version.

However it is not a SineWave output project.
To produce a SineWave output on each phase you will need to duty cycle modulate each phase,
the duty cycle modulation producing the SineWave approximation.

Can you please tell us your electronics, programming, arduino, hardware experience?

Thanks.. Tom...

Not in my case sadly, your picture is for generic BLDC controller, but my goal is more like three phase stepper controller by output, just with some extra features to control dynamically current, encoder reading and so on.

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

Didn't find anything in google about my task, all projects I have seen with Arduino/AVR are regular ESC or simplest stepper drivers. There are some invertors, but they do not have requirement about low noise and not three phases.
I am not newbie at Arduino, but not much experienced with it either and the only microcontrollers which tried to use. Not a big problem for me, because I'm very skilled c++ programmer and around 25 years hobby experience with DIY radio/electronics.

i'm curious about what you're trying to do, what a "sinus" controller is. i found Sinusoidal Control of BLDCM with Hall Sensors Based on FRDM-KE04Z and Tower Board

not sure what the waveform looks like. may be higher frequency PWM being used to generate a sinusoidal waveform at a much lower frequency, but each phase seems offset, presumably centered every 120 deg.

for such a waveform, i doubt you can use the PWM outputs of an AVR since its frequency isn't high enough.

please expain

This may help;


arduino sinewave 3phase bldc

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

What exact motor are you working with, or does "more like" mean you doing something unrelated?

I have never seen a three phase anything that wasn't three identical waveforms 120 degrees separated.

Please defend your choice of target waveforms, I think a few of us here need convincing.

It is trivial to recreate the waveforms you did draw, at least until the frequency gets beyond a certain value, either square waves or sine waves variously synthesized.

But I don't think it is what you need to do.


Thank you all for replies. Let me explain more about this. First of all, this topic is in programming questions rather than motors caterory here on the forum, because do not have issues with motors and clearly understand all parts but more in depth Arduino programming. I need features of stepper motor, but without problem of RPM limit which stepper motors have (they dramatically lose torque with RPM increase). For such purpose people usually get servomotors from CNC industry, but they are bad by price, size, weight and their drivers still noisy according to videos. There are some youtube videos about boards for DIY robots which allow to use rc BLDC motors so popular everywhere now (you may find them by "BLDC robot arm", f.e.), so I would like to make similar controller for several projects. I do have rc motors of 1350 watts, rc 75 watts, 500 watts from hoverboard, CNC nema17 format 78 watts. Also similar thing used for controlling gimbal motors. Misunderstanding here seems that I did picture of waveform which is not full cycle of three phases, but what expect to see with oscilloscope after all PWM are applied, hundreds and thousands of those short square forms produce every sinus with 120 degrees shift each. I dont have any problem to write this as code, except that this require some skills beyong mine about microcontrollers. I just found how to change PWM frequency, but nothing how to make several timers to start at same moment (or to stop). I don't even know what happens when change width of PWM, if currently running somehow resets on change, this would lead to noise. When I feed pure sinus waves to BLDC from hoverboard or CNC, they are silent enough for me till maybe 600 RPM when bearing noise starts to be audible. Let's say have pseudocode like the following:
for (int i=0; i<100000; i++)
digitalWrite(pin, HIGH);
digitalWrite(pin, LOW);
it will make motor very noisy because time to execute each function fluctuates even with frequency 100Khz (less cause of functions of course). When use PWM with NE555 timer or any other hardware implementations, including Arduino one - noise disappear. The higher fluctuation, the stronger noise is. So I have to find some solution to output 3 pins somehow very precisely at ultrasonic frequency. There are projects which use ultrasonic emitters to generate directional audio and they use PWM to make it, but in my cause it's negative side effect which must to get rid off. Imagine like there are no motors, the question is just how to make those outputs precise and synced enough. Writing pins to registers do not helps too, still computing delays or measuring time ruin the process. Hope this helps to understand better. Thanks again.

not sure that i can help, but am curious

are you trying to use PWM to generate sinusoidal waveforms or are you just trying to generate 3 PWM signals 120 degs apart?

if the latter, and presumably easier, don't the PWM pulses need to be centered 120 deg apart and not start 120 deg apart? i don't believe you can use analogWrite() to generate this timing

if the former, isn't the duty cycle of the PWM pulse varying each cycle to generate the proper effective amplitude to simulate the sinusoidal waveform? and of course, the duty cycle is different for each phase. and again, the peak of each waverform is centered 120 deg apart

in both cases, doesn't the frequency of the waveforms determine the RPM (or limit the rpm)?
Difficult to draw PWM as lines in 3d application, but I tried :smiley:
Yes, PWM control amplitude of signal for inductive load or RC chain. Frequency of wave forms do determine RPM, but i mentioned stepper motors with their RPM limit because the way they are made gives this limitation. It is possible to spin them to 4000 RPM for example, but blow of wind can stop them at any moment, they are powerful only at very low RPM, that's why I need to do similar functionality, but with BLDC motors.
I try to use PWM, hardware or software emulated to create 3 wave forms which have 120 degrees phase shifts, like on the the picture above. My first picture is how i want to apply PWM if zoom in to it. To simplify this, when you have just two wires, one of them should be connected to PWM, another to ground or vcc. If you set both wires to PWM, then at least one must have inverted signal of PWM. But if they are different PWM, the moment when one wire have - and another have + voltage is turning to weird & logic operator math. With 3 phases it is even worse, so I have to sync all timers to be sure their output have around zero shift by phase of square wave. Do not know if this is possible via hardware PWM or maybe they are always synced when frequency set to the same one.

@dummynull image.
tIIobjk (1)

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

1 Like

seems like your primary problem is using PWM to synthesize sinusoids at different phases.

seems like a secondary issue is using paired PWM outputs to synthesize positive and negative cycles (presumably using MOSFETs and bipolar power). would think one output in pair would be off depending on polarity

presumably, a pulse is periodically generated on each of 3 (assuming uni-polar). its width (turnoff time) varies with amplitude of sinusoid at the time of the pulse which also varies with frequency of waveform. presumably there are fewer pulses per cycles as waveform frequency (rpm) increases.

i would work out math to do the above on a laptop, generating plots of waveforms and integrated values of pulses to confirm waveform shape. then apply that to target with real-time limitations

That thing is simple, just grab and interpolate sin from table, but the issues I described in first post are not fixable by my knowledge of Arduino/AVR programming. Only can apply LC filter at each of 3 outputs, but for powerful motors metal powder rings are very big for such low frequency which Arduino PWM can generate (also they heating a lot).

So Arduino Uno, Nano, Micro can't work?

It probably can ... just noticed he's using the BTS7960 motor driver.

Here is another attempt to explain problems with implementation. I am not sure if hardware PWM do have such sync issues, but i don't see reason why not, if timers are different and modified not at the same moment. I can use external pwm and on input pin level change do interruption, but that leads to second problem anyway.

your saying the PWM frequency is too low -- audible?

if so, what do you think the minimum PWM frequency is?

not following drawings. shouldn't there be 3 phases? if not, what is tolerance between pulse (nsec, usec, msec)?

Do you require the three waveforms to have the same frequency or they can be different?

Too low PWM frequency then it's audible. Or if PWM is unstable, it's also audible, even if frequency is very high. This probably confusing for non familiar people, so check this video about directional sound via ultrasonic transmitter: Turning Sound Into a Laser - YouTube
EDIT: can't remember now, PWM by default in Arduino is very low, around 500 Hz, i set it to 32 KHz.

Better if they have all same frequency or twice lower/higher, so no need to bother much with code to mix them properly. As I know timers can run at 32 KHz (except one with 60+ KHz?), so that probably not an issue.