Random Ranting (196) · Gadgets & Tech (15) · Anime & Otaku (11) · Watches & Horology (46) · Movies & TV (6) · Photography (3)



Latest Posts Recent Comments Comrades


My blog is worth $4,516.32.
How much is your blog worth?


PIC: PWM Fan Controller

1157hrs
I spent the better part of this morning tidying up the circuit (more for deployment inside the casing) and moving the conroe box to make space for some work I have to attend to.

I decided to test the circuit by applying 12vdc to the drain, while the fan was connected to the source and ground. The results were quite dissapointing and I will detail a couple things I can investigate to get it to work.

Id-Vd characteristic of a mosfet, produced by gnuplot

This shows that once Vg > Vt (in the case of the IRF640 it’s between 2 and 4), the MOSFET will output at whatever voltage is applied (within limits) to Vd. However, the larger the gate voltage, larger the output current!

To get this to work I need to replace the 10K resistor with a 500K resistor, which will allow the A/D reading to reach 50% (i.e. 500/500+500 = 0.5*Vin). Also I feel that I should use the A/D channel one (1) to set the output frequency, as this will aid in boosting the output voltage to the required level (higher freq = higher avg voltage).

Before doing that, I decided to try something different. I’m now applying the full PWM to the gate, and the fan is connected to 12v, and the -ve terminal connects to drain, while source is coupled to ground. I’ve also included a IN4001 (power diode) to take care of back emf, thus protecting the MOSFET. /* this remains untested for now! */

I also need to make a 12V PSU to continue further testing, so this project might be neglected for a while.

0648hrs
I was thinking of soldering a wire to the RPM line and feeding that to the mainboard, but with PWM as the fan would be off during a portion of the pulse, the RPM reading gets affected and is therefore made useless!

As posted @ forums.hexus.net

This should provide ~7.7 - 10vdc to the fan, but I’ll experiment a bit and see how it goes. what’s nice is that this idea could be further extended to either use (a) a single pot to drive multiple fans or (b) have a pot per fan.

One could even throw the whole pot idea out and throw in a couple buttons, an LCD and you are left with a commercial baybus. I still like this the way it is as it *is* sleek and gets the job done. what I will do (if at all) is add a couple more PWM outputs for anyother fans that might go into the case, and have a MOSFET for each fan (obviously) with all the FETs being driven from the common PWM signal…

06-09-2006@0220hrs
I also forgot to mention, this pot like gadget (it’s actually not a proper pot) also serves as an on-off switch. It basically comprises of two 500K variable resistors that adjust independently, but equally. It also has 3 solder points that act as a dual-throw switch.

Imagine this,

a--------X---/ ---b

Next click,

a--- \---X--------b

if we connect something across ‘a’ and ‘X’, and push the switch, it will start to conduct, while ‘b’ and ‘X’ won’t. On the next click, it does the opposite, hence a toggle function.

I was thinking of routing the PWM output to ‘a’ and ‘X’ to the gate on the MOSFET, but realistically I’d want the delta running, so I’ve left the provision for connecting in (that’s why I’ve used a 5-wire ribbon cable, two (2) are used for this switch, with the other 3 were left for the pot function but only two are being used after I discovered that it wasn’t really a pot!) if I want it in the future.

05-09-2006@2106hrs
I ended up breadboarding this on a 16f88 @ 20Mhz. I had a fairly expensive ‘Volex’ 240vac/240W dimmer get struck by lightning, and thought I’d use the funky pot that came with it.

I spent the better part of the evening figuring out the pot! Yes, it’s *not* a pot haha! I now have:

Vdd —-500K variable resistor —-^——-10K —-gnd

…this is the only deviation from what I originally planned.

the ‘^’ is where I tape it to RA0/AN0. This caused the voltage divider to act ‘differently’ than planned and with some experimentation and a fair amount of code tweaks I got it to work.

Also, that Ton_ms, Ton_us stuff isn’t needed. The CCS compiler is so awesome that it takes a 16bit integer for delay_us(), so that saves me some trouble.

So, why am I doing the PWM code by hand, and am not using the in-built CAPTURE/COMPARE/PWM (CCP) module? Well I wanted to do it by hand, and after al the logic is simple,

Ton = (period * duty cycle);
Toff = (period - Ton);

On to the images!

This is the full setup, with the breadboarded circuit connected to the front faceplate:

The full setup

A closeup of the front faceplate:

Closeup of the front faceplate

The circuit in a bit more detail:

Breadboard circuit

Notice the minimum setting on the knob. The DMM on the left is showing the dutycycle percentage!

Minimum dutycycle

The scope view in larger detail, of the mimum setting. In all these images the pulse on the scope is taken from the source on the MOSFET; notice the slow decay on the waveforms…

Scope view of the minimum dutycycle

The maximum setting, notice how the pulse is on longer!

Maximum dutycycle

…and the scope in more detail :)

Scope view of the maximum dutycycle

05-09-2006
Another twist I thought of was to get rid of the pot, and instead add two switches. Now the beautiful thing about this is one could throw in some of them Qprox touch sensitive switches if they wish. Now rather than having to rewrite the whole program, we throw out the A/D sampling bits and load up a constant value (say 594) into our ‘fake’ ad_reading register (I know, it’s 16 bits :p).

We can have the switches connected to RB4-7, and use the RBIE interrupt and then take a snapshot and decide which ’switch’ caused the interrupt. In the ISR we assign to each switch a +ve value and -ve value, thereby increasing or reducing the ad_reading value, thereby controlling the speed. Another nice twist, we can test for the case of both switches being held down for a while, and have that cause the PIC to commit the current value of the ad_reading to be saved into EEPROM, so on the next power up it will start the fan at the new value!

I do realise that you pretty much get the same effect from having a pot, as long as it is not messed with, and we can extend the current code to load up a temp value at bootup() and then after sticking to a fixed duty cycle PWM, start reading the A/D…but this doesn’t feel as elegant to me.

In the end I see my self going with the 4x LEDs + pot system, as it’s clean and not OTT for the task at hand…

04-09-2006
Considering that I’ve fitted a noisy delta ’screamer’ in my Core 2 Duo box, I decided to set about making a simple PWM signal generator based on pot position.

Note to self, make this a schematic!:
vcc to one pot leg, vss to other. wiper to AN0 on pic. PWM pin to 2x 1n4148s *to drop 1.2v* to Vgs of IRF640 (Vgth=4vmax, 2vmin). 12vdc to drain, source to + of fan, fan -ve to gnd.

I tend to use bits of code to simulate in gcc, before moving to the MCU directly, this way I can test highlevel bits quite easily ;).

:: Program Initialising ::
---------------------------

Enter Voltage: 5

PWM Period: 5000us
A/D Value (10-bit resolution): 1020
Duty cycle: 99.609375 Percent
Ton: 4980us
Toff: 19us

Ton_ms: 4 ms
Ton_us: 980 us

Toff_ms: 0 ms
Toff_us: 19 us

While searching about, I found that most people use a 30 - 200Hz signal when driving a fan, so I went with 200Hz for the first test, 1/200 = 5×10^-3s or 5000us.

In the example above you can see that I’ve split the output into milliseconds and microseconds. The reason is that most (I think all, CCS, Hi-TECH, CC5X) compilers can only handle a limited variable in their delay_us() functions. Anything too high and you’ll run into problems. I might even take the Ton/Toff_us values and rrf one place, which is the same as dividing my two, and calling the delay_us command twice, but this will further add to the ‘error’ due to rounding.

More simulation:

:: Program Initialising ::
---------------------------

Enter Voltage: 3 

PWM Period: 5000us
A/D Value (10-bit resolution): 612
Duty cycle: 59.765625 Percent
Ton: 2988us
Toff: 2011us

Ton_ms: 2 ms
Ton_us: 988 us

Toff_ms: 2 ms
Toff_us: 11 us

I also looked up the datasheet for the ’screamer’ and it says that the min voltage is 7v. A bit from my code:

/*
	To limit the output avg. voltage, we can force the ad_reading
	to a set amount.  To drive a fan at minimum 7v, 7/12 * 100 = 58%

	Likewise, 58% of 5V = 2.91V,

		:: Program Initialising ::
		---------------------------

		Enter Voltage: 2.915

		PWM Period: 500us
		A/D Value (10-bit resolution): 594
		Duty cycle: 58.072262 Percent
		Ton: 290.361328us
		Toff: 209.638672us
*/

	if(ad_result < 594)ad_result=594;

So if the voltage is below 2.915v, the system will ensure that the PWM stays at ~58% duty cycle, ensuring that the fan will be running, albeit slowly…which is what we want though.

I initially thought of displaying this info over rs232 to an LCD, which is quite simple but then again, it might be a bit overkill, so having 4 leds drilled into one of the faceplates on the case, and have them light up based on duty ratio is also quite simple, and is probably how I’ll do it in the end.

75% = ad_result < 765
50% = ad_result < 510
25% = ad_result < 255 // This will never happen as we are limiting to a 7 to 12v, or 2.916 to 5v scale…

Therefore this will have to be readjusted to a 594 to 1024 scale, and represented on the LEDs:

915 to 1024 = 100%
808 to 914 = 75%
701 to 807 = 50%
596 to 700 = 25%

These are just some random thoughts, so what happens in the end all depends on how much time I have to implement bits n’ pieces.

Related Posts & Articles


Google Search


RSS/Meta Articles