
Controlling 4-Wire PWM Fan
Started by MattEric, Feb 14 2011 03:41 AM
2 replies to this topic
#1
Posted 14 February 2011 - 03:41 AM
Anybody have any experience controlling a 4-wire fan with built in PWM? I bought such a fan thinking that distributing the PWM to the fan might be smart rather than using the Netduino's PWM capability but now i'm stumped about what signals are required to talk to the fan. Any documentation i've been able to find involves a programmable pwm controller which also monitors temp sensors, and i really don't want all that as i plan to be monitoring temp sensors separately and wish to implement my own control logic. Is there a way to control the PWM Fan directly w/o a controller? I think i can read japanese better than a data sheet, but attached is the sheet for the fan i bought complete with minimal and cryptic information, notably on pages 7 & 8.
Matt
#2
Posted 16 February 2011 - 07:07 PM
I didn't read the datasheet complelty, but my guess is that 1 pin is power (+12V) on pin is GND, one pin is TACH, and the last pin is the PWM pin, which goes to a transistor which allows/cuts power to the fan.
Basically, I'll bet you can leave TACH floating (unless that's the process variable in your loop), GNd -> GND, +12 or whatever to +12, and then hook the Netduino's PWM pin to PWM on the fan.
- Chris Walker likes this
#3
Posted 03 March 2011 - 06:39 AM
Yep, i just hooked up the wires and it worked. I had a misunderstanding of what a PWM fan is, thinking that it had some sort of controller built in that provided the duty cycle given the right incantations, but it just is "PWM enabled" where it has some sort of FET or solid state relay that allows a PWM signal to control the fan. Which the Netduino PWM does. I first used SetDutyCycle() but the specs of the fan i have say the PWM data signal operates best at 25kHz, so i set the frequency using SetPulse(). As Philip pointed out here http://forums.netdui...pwm-demystified, I discovered that SetDutyCycle() only seems to work properly at the default 10kHz frequency, so i ended up using SetPulse() to set the duty cycle as well. The code i am using follows which is basically my customized version Dab's posting controlling an LED with Netduino's PWM http://forums.netdui.../103-pwmsample/.
using System; using System.Threading; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.Netduino; using PWMDevice; namespace BlowerPWM { public class Program { // Constants const int cTimerPeriod = 150; // milliseconds const short cInitialDutyCycle = 20; // 20% is minimum duty cycle guaranteed to start blower const short cDutyCycleDelta = +1; // begin by increasing duty cycle by one const int ckHz = 25; // blower spec says pwm control data is best run at 25kHz public static void Main() { // Create a blower control object PWMDeviceControl blowerControl = new PWMDeviceControl(cInitialDutyCycle, cDutyCycleDelta, ckHz); // Create a System.Threading.Timer instance and pass it the timer callback method Timer timer = new Timer(new TimerCallback(blowerControl.AdjustDutyCycle), null, // data object (not used) cTimerPeriod, // time to first call back cTimerPeriod); // time period between call backs Thread.Sleep(Timeout.Infinite); } } }
using System; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.Netduino; namespace PWMDevice { /* This class defines a basic controller for a PWM device that combines a Netduino PWM and a button * for the user to adjust the duty cycle. The duty cycle will increase by a constant amount as the * user presses the button. When the max duty cycle percentage is reached, continued pressing * decrements the duty cycle until the minimum is reached when the direction of change is reversed again. */ class PWMDeviceControl { const short cMaxDutyCycle = 100; // percentage const short cMinDutyCycle = 7; // percentage; blower stops below 8% private short dutyCycle; // percentage private short dutyCycleDelta; // amount to change the duty cyclc; can be + or - value private PWM pwm; // Netduino's PWM private Button button; // UI for control of duty cycle private uint period; // period of PWM in microseconds private uint kHz; // frequency of PWM in kHz // Constructor public PWMDeviceControl(short initialDutyCycle, short initialDutyCycleDelta, uint kHz) { dutyCycle = initialDutyCycle; dutyCycleDelta = initialDutyCycleDelta; this.kHz = kHz; pwm = new PWM(Pins.GPIO_PIN_D5); // Netduino's PWM; Pin 5 is PWM enabled button = new Button(); // button for user control of duty cycle period = 1000 / kHz; // set period to match requested frequency pwm.SetPulse(period, (uint)(initialDutyCycle * 10 / kHz)); // set duration to match intial duty cycle //pwm.SetDutyCycle((uint)dutyCycle); // can't seem to use this when using SetPulse() Debug.Print("Initial duty cycle: " + dutyCycle.ToString()); } /* This public method is called back by a timer or other event. If the user is pressing * the button, it increments or decrements the duty cycle by the amount dutyCycleDelta * as well as changes the direction of inc/dec when the max or min duty cycle is reached.*/ public void AdjustDutyCycle(Object obj) { if (button.Pressed) { dutyCycle += dutyCycleDelta; // increment/decrement the duty cycle pwm.SetPulse(period, (uint)(dutyCycle * 10 / kHz)); //pwm.SetDutyCycle((uint)dutyCycle); // can't use this when using SetPulse() Debug.Print("Duty cycle: " + dutyCycle.ToString()); // check if at min or max duty cycle and change direction if so if (dutyCycle >= cMaxDutyCycle || dutyCycle <= cMinDutyCycle) dutyCycleDelta = (short)-dutyCycleDelta; } } } }
using System; using Microsoft.SPOT; using Microsoft.SPOT.Hardware; using SecretLabs.NETMF.Hardware; using SecretLabs.NETMF.Hardware.Netduino; namespace PWMDevice { class Button { public bool Pressed {get; private set;} private InterruptPort port; // Constructor public Button() { Pressed = false; // assumes button is released on start up port = new InterruptPort(Pins.ONBOARD_SW1, // Netduino's onboard button true, // glitch filter, no noticeable effect Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth); port.OnInterrupt += new NativeEventHandler(AdjustButtonState); } // adjusts button state to pressed or not pressed; this is the button interrupt handler private void AdjustButtonState(UInt32 data1, UInt32 data2, DateTime time) { port.DisableInterrupt(); Pressed = (data2 == 0); port.EnableInterrupt(); } } }
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users