PWM control of small fans

I'm experimenting with control of the speed of a small brushless fan like the ones used in PCs or power supplies. A propeller pin drives the base of a small NPN transistor. The code is quite easy:
CON
  pwmFreq = 500
  pwmFrame = 240 ' 24V in 0.1V units
  pwmBase = freqPll / (pwmFreq * pwmFrame)

PUB InitFanPwm
  asm
    fltl  #pinFan
    wrpin #%01_01001_0,#pinFan
    wxpin ##pwmFrame<<16+pwmBase,#pinFan
    drvl  #pinFan
  endasm

PUB SetFanVolt (v)
' set fan PWM in 0.1V units
  asm
    wypin v,#pinFan
  endasm

However, I'm not so happy with the audible noise generated. The fan runs best with frequencies between 200 and 1000Hz but this causes some whistling. At higher frequencies the sound is softer but the speed vs. PWM duty response gets nonlinear and and the motor has startup problems at low speed.

I guess this is caused by the cheap commutation circuit in the brushless motor. Although I have a free-wheeling diode in my driver it doesn't work really well. So the current drops to zero (fast decay) in each off-phase of the transistor and the winding inductance limits the current rise in the next on-phase.

Does anybody know how fan speed control works in PCs? They run almost quiet. Running the fan from a linear regulator (lab power supply) works much better than PWM but a linear regulator dissipates heat. A switch mode regulator with filtered DC output costs money and both solutions require much more board space than a simple transistor.

Comments

  • cgraceycgracey Posts: 12,677
    edited 2020-03-18 - 09:32:12
    Can you use pulse-density modulation (NCO DUTY) to make the frequency much higher, but average to an analog level?

    You could try using DAC mode (990 ohm) that changes only to set the speed. If you are using an NPN, you might get a good linear range by driving the DAC pin right into the base.

    Also, try the PWM mode, as is, but with 1.5k-ohm drive mode on the pin.
  • The motor speed is proportional to the average voltage. Torque is proportional to average current. If I drive a NPN transistor with the emitter tied to ground I get some sort of current amplifier with a very bad gain tolerance because I don't know the exact current gain and I can't measure the actual (collector) current.

    I could build something that behaves more like a voltage amplifier by adding a feedback resistor between C and B. However, for a linear amplifier I'd need a much bigger transistor because of the heat generated. 24V * 0.2A = 4.8W half of it (= 2.4W) would be dissipated by the transistor in worst case. This required at least a DPAK. Currently I'm using a small SOT-23 one.

    BTW, I'm not sure if I've understood how the resistor modes of the P2 pins work. Those are series resistors, correct? So if I want an open collector driver with pullup I have to actively drive the pin high with series resistor instead of letting it float with pullup, right?
  • I think, a linear regulator (voltage or current amplifier driven by DAC) is too inefficient.

    A good cost vs. performace compromise might be a pulse-density NCO output driving a small high-speed MOSFET + free-wheeling diode and an LC filter to smoothen the output. This way the fan would see nearly DC and noise would be reduced.
  • Ah, I just saw that the NCO mode now supports a clock prescaler (base period). At the P1 the DUTY counter mode always ran at the full system clock speed. 180MHz would be too high for the driver MOSFET. I dont want an FM broadcast station :wink: But running near 1MHz would allow for a very small LC filter and keeping switching losses acceptable.
  • ManAtWork wrote: »
    ...BTW, I'm not sure if I've understood how the resistor modes of the P2 pins work. Those are series resistors, correct? So if I want an open collector driver with pullup I have to actively drive the pin high with series resistor instead of letting it float with pullup, right?

    The resistors are on the chip. There are two three-bit selector fields for what kind of impedance you want for both high and low outputs. You could make low float (LLL = %111) and high drive via a 1.5k resistor (HHH = %001).

    I'm working on the documentation for this now, so that I can get some constant symbols into the Spin2 compiler.
  • ManAtWorkManAtWork Posts: 568
    edited 2020-03-18 - 11:08:46
    Thanks for explaining. But I think an external resistor to the transistor base is better. If somebody happens to short the fan wires the transistor usually fails shorted and the resistor hopefully fails high-impedance or at least limits the current to 24V/1.5k=16mA so that the P2 has a chance to survive.

    I've done a quick simulation. A filter with a 10µH inductor and 100nF cap is enough to limit voltage ripple to 1V at 1MHz. However, current ripple would be quite large (0.4A). 22µH and 1µF gives much better results.
    604 x 329 - 9K
  • I suspect that some of the noise and other quirks may be due to the interaction between your PWM input and the switching of the 3 phases of the BLDC fan motor. Take a look at this wikipedia info.
  • Ok, according to the wiki article PCs use a PWM frequency of 25kHz. If you have speed sensor feedback you can compensate the non-linearity and startup at low voltage/duty is also no problem as you can increase the duty cycle until you see pulses at the sensor pin.

    Unfortunatelly I have to use 24V fans and speed signal is not available for most of them. An additional 12V regulator only for the fan is too expensive. Ok, I could roll my own with PWM output from the P2 and voltage feedback via an ADC pin, but that's also overkill.

    I'll try out the LC filter solution tomorrow. I found out that I only have MOSFETs that are either rated only for 20V or have a gate threshold of >4.5V and can't be driven directly by a P2 pin.
  • What about measuring the temperature of the device cooled?
  • Yes, I do that anyway. The slave processor on the high voltage side measures temperature and transmits the results over serial communication. The P2 acts accordingly and sets the speed of the fan depending on temperature.

    So it doesn't matter much if the speed of the fan is exactly proportional to the PWM duty cycle. The control loop will self adjust. But it makes a bad impression if the fan is whisteling and humming without actually running.
  • @ManAtWork

    Pretty cool.
  • Ok, I've tested it with two fans (Matsushita SF92 24V 0.19A and Sunon MF50152V1 24V 0.05A) and three different inductor values. It works best with 68µH. The buck regulator is always in continous current mode and the speed vs duty cycle is quite linear. With 22µH the current gets non-continous. So for example, a duty cycle of 20% results in an average voltage of >10V at the fan instead of ~5V. With 10µH it still works but the speed vs. duty curve gets quite distorted. In all cases the fan runs quietly and smoothly and without startup problems. The 24V fans start at about 5V. All components cost around $0.20. The 10µH choke has the advantage of a much smaller footprint (1210 compared to 6x6mm for the 68µH).
    691 x 477 - 9K
  • I've chosen 1MHz PWM sawtooth mode instead of NCO duty mode. The NCO mode would have unpredictable on and off-times which would lead to higher than necessary current ripple. PWM at 1MHz has only 1/180 or ~0.5% resolution but I think that's enough for fan speed control.
    CON
      pwmFreq = 1_000_000
      pwmFrame = pllFreq/pwmFreq
      pwmBase = 1
    
    PUB InitFanPwm
      asm
        fltl  #pinFan
        wrpin #%01_01001_0,#pinFan
        wxpin ##pwmFrame<<16+pwmBase,#pinFan
        drvl  #pinFan
      endasm
    
    PUB SetFanVolt (v)
    ' set fan PWM in 0.1V units
      v:= v*pwmFrame/240
      asm
        wypin v,#pinFan
      endasm
    
    It surely also works with 12V. Just replace the 240 with 120.
  • ManAtWork, have you thought about the PWM switch-mode power-supply mode? It can regulate voltage (via divider, using level sense) or current (via shunt to GND, using level sense).
  • TubularTubular Posts: 3,886
    edited 2020-03-20 - 08:27:01
    Chip you once drew a circuit showing how you imagined that working. Could you do it again?

    I think your original drawing is buried in some obscure thread that can't be easily searched.

  • Yes, at least I've noticed that something like switch mode power supply mode exists. However, at the moment, I don't understand how it works, so I decided to focus on the main task (servo motor control) until more documentation is available.

    It surely sounds interesting and maybe it could be used to implement a PFC stage, later.
  • I will look for the drawing. It was hand-written.
  • Yes I think it was hand written too.
    I found this description
    https://forums.parallax.com/discussion/comment/1362413/#Comment_1362413
  • I can imagine a hurdle to be that the bldc-controler itself is a switcher that relies on a dc supply. The moment the supply has some ripple it might interfere with the motor control which often is sensorless in a very crude way as fans are often not regular 3 phase motors to make them just cheap
  • Sample/Hold-ADC have those problems. They catch up noise very easily, especially short spikes of high voltage switching when they happen to exactly hit the sample time. Sigma-Delta-ADCs are almost immune to that effect because they integrate the input signal over a longer period. If the sampling period is equal to the PWM period, the integrator makes a notch filter that has a zero point at the PWM frequency. That almost perfectly cancels out all switching noise. The average of all positive and negative spikes of one period is zero.

    Of course there is ripple on the DC bus. Low frequency ripple (100 or 120Hz) is quite high (~50V) but is suppressed by measuring the bus voltage and applying an inverse feed forward to the PWM ratio.

    Fan PWM and internal DC/DC-converters work at frequencies well above the pass-band of all ADC input filters.

    And yes, the internal circuits in the BLDC fans are really bad. It's just a hall sensor based block commutation logic. But the winding resistance is so high that it doesn't hurt.
  • ManAtWork wrote: »
    Yes, at least I've noticed that something like switch mode power supply mode exists. However, at the moment, I don't understand how it works, so I decided to focus on the main task (servo motor control) until more documentation is available.

    It surely sounds interesting and maybe it could be used to implement a PFC stage, later.

    There are quite a few step down switching regulator chips available that would be suitable, and they are not much harder to deal with than a typical linear regulator. Take a look at this data sheet. I'm not suggesting you use that particular one, it just happened to come up near the top of the list. it is a bit pricey, but there are several for under $1.00. There are also TO220 sized modules available.
  • Yes, I know. My favorite ones are the LMR14206 for up to 40V and 0.5A or the LM5007 for up to 75V or the AP3402 for <=5V. They are all under $1. You could trim the output voltage by feeding bias current into the tap node of the feedback voltage divider. But it's still overkill for fan speed control when a simple MOSFET + LC filter also does the job. Components that aren't there not only cost no money, they also can't fail and don't have to be assembled and tested.
  • @ManAtWork

    I tried your code in flexgui. Got an error. Did I miss something??
    Found your project interesting.
    Thanks
    Martin

    "C:/Users/bsa/Desktop/flexgui 4.0.3/flexgui/flexgui/bin/fastspin" -2b -l -O1 -I "C:/Users/bsa/Desktop/flexgui 4.0.3/flexgui/flexgui/include" "C:/Users/bsa/Desktop/parallax/PROP_2/SMPART PINS/man at work/pwm brushless motor.spin"
    Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
    Version 4.0.3 Compiled on: Nov 9 2019
    pwm brushless motor.spin
    C:/Users/bsa/Desktop/parallax/PROP_2/SMPART PINS/man at work/pwm brushless motor.spin:5: error: Unknown symbol pllfreq
    child process exited abnormally
    Finished at Sat Mar 21 14:16:11 2020

  • pilot0315,
    You appear to be running a fairly old release of flexgui. If you updated to the latest it would probably fix your issue.
  • pilot0315 wrote: »
    I tried your code in flexgui. Got an error. Did I miss something??

    ...error: Unknown symbol pllfreq

    Simply replace "pllfreq" with your system clock frequency. I've defined it because "clkfreq" can't be used in constant expresssions.

  • During compilation, constants CLKMODE_ and CLKFREQ_ are generated the Spin2 compiler. They can be used by PASM code.
  • @cgracey
    @ManAtWork

    I will try that, thanks.
Sign In or Register to comment.