Notifications
Clear all

[Solved] BLDC Speed Control PWM Resolution?

Forum 1
(@gingerrunner)
Active Member

Hello, I'm currently following this guide: https://www.solomotorcontrollers.com/bldc-motor-arduino-closed-loop-sensorless/

I tuned the motor to the point where the startup was typically pretty smooth, now I'm just having issues with speed control.

I am using an Arduino Uno with this code to supply a PWM signal:

 

const int PWM_PIN = 3;
// Need 5k min frequency
// frequency = 1/period --> period = 1/frequency
// 1/5000 --> 0.0002s --> 0.2ms --> 200 us period
// period of 100 us --> 10k freq
// period of 50 us --> 20k freq
const int timeOn = 49;
const int period = 50;
const int timeOff = period - timeOn;

void setup() {
// put your setup code here, to run once:
      pinMode(PWM_PIN, OUTPUT);
}

void loop() {
      // put your main code here, to run repeatedly:
      // Duty Cycle Formula
      // %DutyCycle=(tOn/(tOn+tOff))*100
      digitalWrite(PWM_PIN, HIGH);
      delayMicroseconds(timeOn);
      digitalWrite(PWM_PIN, LOW);
      delayMicroseconds(timeOff);
}

 

When I tried this with a period of 200 us, I noticed no change in speed of the BLDC when varying my timeOn variable, so then I upped the frequency and noticed my PWM values below 50% duty cycle were showing differences in speed, but past 50% duty cycle there was no change in speed.

 

Other details:

Using a 12V on power supply with a 5A current limit

BLDC is this one: https://hobbyking.com/en_us/multistar-elite-3508-268kv-high-voltage-endurance-motor.html

Any and all help would be appreciated!

This topic was modified 1 month ago by GingerRunner
Quote
Topic starter Posted : 11/04/2021 5:33 pm
Topic Tags
Forum 3
(@milad)
Chief Member Moderator

Hi @gingerrunner

I believe the way you are generating PWM pulses with Arduino is not the best way, the main reason is you are trying to make the PWM pulse by Turning ON and OFF a specific PIN with a given duration ( 200 us), there are some considerations here that you need to consider:

  1. The Arduino Loop(){} section is a very low-speed low priority part of the code, there is no guarantee that the loop you are making runs exactly with 200us as any other interrupt or task can easily break it and changes the timing
  2. make sure the current Limit or "P/F" input is properly set ( the higher the voltage on P/F the lower the current)
  3. as you know for the PWM pulse that you send to SOLO, it is important to have a frequency above 5kHz and then you can vary the duty cycle, so the Frequency is not important how much is it but it must be fixed, it can be 5kHz or 50kHz or more, what matters is the duty cycle of the pulse, So be sure about the PWM generation you need to use the PWM enabled pins of Arduino and fix a frequency for each and then vary the duty cycle like the code below:

int speedDutyCycle =0;

void setup() {
// put your setup code here, to run once:
// declare pin 3 to be an output:
pinMode(3, OUTPUT); //speed adjuster
// declare pin 9 to be an output:
pinMode(9, OUTPUT);//power adjuster
TCCR2B = TCCR2B & 0b11111000 | 0x01;
TCCR1B = TCCR1B & 0b11111000 | 0x01;

}

void loop() {

if(speedDutyCycle <= 250)
  speedDutyCycle++;

// setting the desired Duty cycle on PIN 3 which is PWM enabled by varying the width from 0 to 250 linearly

analogWrite(3, speedDutyCycle);

delay(100);

}

In this code, PIN 3 on Arduino UNO which is PWM enabled is set to have a specific frequency ( to know more pls read here on Arduino website) and then inside the Main loop () we are linearly increasing the duty-cycle of PWM on PIN 3 from 0 to 250, so basically using Arduino UNO your resolution is 256 steps as it has an only 8 bit counter for PWM.

 

I will remain Available.

Regards
Milad

 

If you found the answers helpful and you could solve your problems, please kindly verify here to help others in the future.

ReplyQuote
Posted : 11/04/2021 6:06 pm
Forum 1
(@gingerrunner)
Active Member

@milad

Ah I see.  I figured there were some nuances with Arduino I was overlooking (very new to this) and that article has a lot of good information.  Thanks for the fast reply, I'll be looking into this today and seeing if I can work it all out.

ReplyQuote
Topic starter Posted : 11/04/2021 6:34 pm
SOLO Team liked
Forum 1
(@gingerrunner)
Active Member

@milad

Okay so I read up on that article a little bit and executed your code (and subsequently played around with it a little).

I looked into those Timer Control Registers out of curiosity, I'm assuming those don't really need meddled with unless you want different frequencies which as you already mentioned, does not interfere with the speed of the motor as that's just the period of the duty cycle.

 

With the linearly increasing duty cycle, I didn't really notice the motor speeding up.  For furthering testing, I did several runs with hard-coding the speedDutyCycle var to values between 0 and 255.  Past 150 (which is about a 58% duty cycle assuming 150/256 is how that works out) I don't notice any change in the motor's speed.  Even setting it to 255 didn't exceed the speeds it was achieving at 150.

My P/F current limit was previously unconnected during all my runs, as I saw other forum posts recommending to not even enable it if you want it to be non-factor.  But for giggles I decided to connect it and just write 0 as the duty cycle for it, since that should result in a current limit of 32A which I wasn't even getting close to (0.190A for my motor for the 2240RPM I can't seem to pass).  Alas, that of course didn't change the results I was seeing.

I can't help but think I am missing something very stupid here and I'm not sure what.  For reference, here is the code I was running whilst hard-coding the speeds:

int speedDutyCycle=150;

void setup() {
// put your setup code here, to run once:
// declare pin 3 to be an output:
pinMode(3, OUTPUT); //speed adjuster
// declare pin 9 to be an output:
pinMode(9, OUTPUT);//power adjuster
// Timer counter control registers
TCCR2B = TCCR2B & 0b11111000 | 0x01;
TCCR1B = TCCR1B & 0b11111000 | 0x01;

}

void loop() {

// setting the desired Duty cycle on PIN 3 which is PWM enabled

analogWrite(3, speedDutyCycle);

// setting current limit on PIN 9 which is PWM enabled.
analogWrite(9, 0);

delay(100);

}

ReplyQuote
Topic starter Posted : 13/04/2021 3:28 am
Forum 3
(@milad)
Chief Member Moderator

Hi @gingerrunner

I just checked again this code and I confirm that both on Arduino and SOLO it works pretty well, I also monitored the Output PWM stage of the Arduino from various stages and you can see 3 samples from the beginning till the end.

But some very important points:

  1. Are you having a connection between the GND pin of SOLO to GND pin of Arduino at least at a single point? without this, the signal levels can get distorted
  2. Are you truly using Pin number 3 of Arduino? I'm using Arduino UNO and pin Number 3 is shown with "~3" which means this pin is PWM enabled
  3. Do you have the possibility of monitoring Pin Number 3 of your Arduino with Scope and see how is the waveform? if you don't have a scope, you can simply connect a resistor and a LED and see if the light Dims up and down or not?
  4. another point is you confirm that when you use "Potentiometers" you have proper control over the speed based on the article you gave me above? it will be also great if you share with me your Piano switch setup and the version of Firmware you are using.

Pls be aware that the previous code saturates at 255 for the PWM duty cycle and remains there, so I had to Reset Arduino to go back to zero, if you want to have a dynamic reset of the PWM duty Cycle you can have a code like below to make sure you don't test the code only when the PWM duty cycle is at maximum:

///////////////////////////////////////

int speedDutyCycle =0;

void setup() {
// put your setup code here, to run once:
// declare pin 3 to be an output:
pinMode(3, OUTPUT); //speed adjuster
// declare pin 9 to be an output:
pinMode(9, OUTPUT);//power adjuster
TCCR2B = TCCR2B & 0b11111000 | 0x01;
TCCR1B = TCCR1B & 0b11111000 | 0x01;

}

void loop() {

if(speedDutyCycle < 254)
speedDutyCycle++;
else
speedDutyCycle = 0;

// setting the desired Duty cycle on PIN 3 which is PWM enabled by varying the width from 0 to 250 linearly

analogWrite(3, speedDutyCycle);

delay(100);

}

//////////////////////////////////////

 

as you see in the images Below, the PWM frequency on Pin ~3 is fixed at sth around 31kHz which is good for us, and the duty cycle is varying all the way from 0% to 100%.

Forum 11

Forum 12

Forum 13

So pls check the mentioned points and let me know how the process goes on.

Regards
Milad

 

If you found the answers helpful and you could solve your problems, please kindly verify here to help others in the future.

ReplyQuote
Posted : 13/04/2021 5:59 pm
Forum 1
(@gingerrunner)
Active Member

@milad

Okay, had some time to mess with this a bit more using your code with 1 change, I made the speedDutyCycle start at 100 because at lower values I was experiencing too much jittering and would likely have to re-tune a bit.

I used my oscilloscope to take some readings and it appears that the PWM is varying correctly, going from ~35% up to 100% and looping again.

But again,the motor speed doesn't seem to vary at all once it gets past 50%.  Even more interestingly, when using 12V from my power supply, the motor speed doesn't change at all, whereas with 13V I can hear it slow down by a couple hundred RPM and ramp back up.  Still, it remains the case that the speed doesn't increase past 50% in either scenario.

I'm not sure if I can attach multiple files here are copy/paste images, but I'll attach the picture of my setup labeled the best I can.

 

 

ReplyQuote
Topic starter Posted : 17/04/2021 9:09 pm
Forum 3
(@milad)
Chief Member Moderator

Hi @gingerrunner

some point came to my mind, just wanted to know if you have set the number of Poles of your motor on 12 or 14 as mentioned in datasheet of your Motor? You can do this by connecting to your SOLO through its USB port and in the Motion terminal set the correct value for the number of Poles of your motor, because by default the number of Poles on SOLO is set at 8 for brushless Motors, and if you want to have precise speed control you must put the correct value for that, in case of wrong value the speed control resolution and references are not correct, so maybe this is the cause that you can't control the speed in an acceptable range.

Just to remind you, the Number of Poles for a brushless motor = The number of magnets mounted on the Rotor of the Motor 

So you can also count those magnets which I think are visible for your motor and set it precisely as the datasheet says 12 or 14 which is strange...

Another point is this, as I see from your wiring you are using a resistor for DIR input of SOLO UNO, but it's not necessary and it was necessary only for SOLO BETA models, in SOLO UNO the DIR pin is 5V tolerant, so you can connect it directly, BTW, we will update the wiring diagrams on our website soon, but if you look at SOLO UNO DATAsheet you'll see there the DIR pin is directly connected to Arduino ( Despite SOLO BETA models where you need a resistor).

I will remain available

Regards
Milad

 

 

If you found the answers helpful and you could solve your problems, please kindly verify here to help others in the future.

ReplyQuote
Posted : 18/04/2021 3:08 pm
Forum 1
(@gingerrunner)
Active Member

@milad

I changed the poles parameter using the motion terminal and read the value back using "read all params" just to be sure that it was set (there are 14 poles on my particular motor).  Unfortunately I did not see a change.  I'll have to test with my oscilloscope again to confirm it, but the speed didn't change past a certain point for a long time before the speed went back to 0 and started ramping up again, so if I had to guess it's still maxing out at 50% duty cycle.

Certainly a vexing issue...It has to be something so trivial that's wrong here, it always is haha!

ReplyQuote
Topic starter Posted : 23/04/2021 4:13 am
Forum 3
(@milad)
Chief Member Moderator

Hi @gingerrunner,

Ok, but here there are a couple of things to notice:

  1. In your first post, you've mentioned that you are using a Motor with KV of 268 (RPM/V), this means at 12V of supply ideally this motor is able to reach a max speed of 3216RPM (268 * 12), however on the other hand as you observe around 50% duty-cycle, while you are selecting Normal BLDC-PMSM motor in an analogue mode, the "S/T" input from 0V to 5V ( 0% duty to 100%) will control the speed from 0RPM to 8000RPM, so 50% of duty cycle will result around 4000RPM which is very close to a max speed of your motor at 12V, so even if you keep increasing the duty cycle on S/T input the motor can't follow and SOLO can't push it further.
  2. As I see, on that page for the motor it says it supports up to 6s batteries, which means something around 24V, that means your motor reaches to the max speed of 6423RPM at 24V(24V * 268 RPM/V), so if you want to go further you need to increase the input voltage all the way up to 24-26V and see how things changes.
  3. You can also increase little by little the PWM frequency ( switching frequency) in Motion Terminal and as you see by default in your case when you are in Normal Brushless motor is set at 20kHz, you can increase this value all the way up to 80kHz with steps of 5kHz and see how the behaviour and the quality of speed controlling changes.

so pls check what has been mentioned and keep me posted here, I will remain available.

Regards
Milad

 

If you found the answers helpful and you could solve your problems, please kindly verify here to help others in the future.

ReplyQuote
Posted : 23/04/2021 1:35 pm
Forum 1
(@gingerrunner)
Active Member

@milad

Sorry, was finishing up a class the past couple weeks.

I did some more testing and it appears you were correct.  I considered the KV rating as a theory early on but the RPMs I was getting seemed so low that I discounted in early.  At 12V input, and a 268 KV rating, I would expect 12V*268RPM/V=3216RPM, now I know KV rating is just an ideal scenario, but I was only netting around 2500RPM max.

However after increasing the voltage I am now seeing a wider range of speeds...I suppose the "fudge factor" for a KV rating is more 80% instead of 90%.

This issue can be counted as resolved, if there is a function for that sort of thing! 😀

Thanks for your help and patience!  I really appreciate it and now this little pet project of mine can go forward!

ReplyQuote
Topic starter Posted : 11/05/2021 2:05 am
Forum 3
(@milad)
Chief Member Moderator

Hi @gingerrunner,

Thanks for reporting back on your progress and letting us know that your issue is solved, highly appreciated, Yes, the KV ratings for most of the low-cost motors are not that accurate, but still that linear relationship holds some how which is good. I will remain available and feel free to ask your other questions here in our forum.

Regards
Milad

 

 

If you found the answers helpful and you could solve your problems, please kindly verify here to help others in the future.

ReplyQuote
Posted : 11/05/2021 7:16 am
Share: