2h4u
Posts: 2
Joined: Sat Jan 19, 2013 6:19 pm
Location: Austria

Selfmade Case with dynamic-PWM driven Fan

Sat Jan 19, 2013 7:27 pm

Some informations about my setup:
Hardware: Raspberry Pi - 512MB (Heatsink on the CPU)
Software: Raspian
Power: 5V 1.2A
Overclocked to 1GHz
Fan: simple 2wire Fan 40mm x 40mm (http://www.neuhold-elektronik.at/catsho ... ts_id=2895)

CPU with heatsink:
Image

I bougth a case from modmypi.com https://www.modmypi.com/raspberry-pi-ca ... case-black,
but i dont wanted to destroy the case, so i made a new case to mount the fan.

Here are the results:
Image
Image
Image
Image
Image
Image
Image
Image

I used the "base" from the bought case and made a new "top". It's made of polystyrene, i love the stuff :P

The fan is powered via the GPIOs (no problems with power recognized) but because its a simple 2-wire fan I had to use a trasitor to drive the fan via PWM.

Here is a very simple circuit diagram:
Image

So, that was the hardware-part, let's start with the software.

As you can see at the fan's-seller-page, the fan can be quite loud (30,5 dBA), so PWM is a usefull tool to reduce the RPM and the noise.
Also the process should start at boot up.

(Node: First I've tried python but, whyever, the script can't load the wiringPi librarys at startup...
I also tried software-pwm, but it's to slow for the fan and makes realy strange noises.)

So here is my little C-Programm for a Hardware-PWM driven Fan:

Code: Select all

/*
Fancontrol via Hardware PWM for Raspian
Author: 2h4u
Date: 19.01.2013

Version 2:
Now with dynamic PWM regulation!
*/

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>

#include <wiringPi.h>

//-------INIT-------//
int FAN = 1;
//------------------//
int PWM_ZERO = 550;
int PWM_MAX = 1024;
//------------------//
int TEMP_ZERO = 45000;
int TEMP_PWM = 50000;
int TEMP_MAX = 70000;
//---- getTemp -----//
FILE* tempfile;
int tempCache = 0;
//------ main ------//
int sleepTime = 5;
//------------------//

int getTemp ()
{
	// Read Temp 
	tempfile = fopen ("/sys/class/thermal/thermal_zone0/temp", "r");
	fscanf (tempfile, "%d", &tempCache); 
	fclose (tempfile);
	return tempCache;
}

int checkIfItsFirstRun ()
{
	struct stat st;
	int status = 0;
	
	// Check if there is a configfile
	if(stat ("/usr/share/fancontrol/config.txt",&st) == 0)
		return 0;
    else
    {	
    	// if there is no configfile, check if there is the directory
		if(stat ("/usr/share/fancontrol",&st) == 0)
		{
			// create config.txt
			FILE *outfile = fopen ("/usr/share/fancontrol/config.txt", "a+");
			
 			if(!outfile) {
  				printf ("There was a problem opening /usr/share/fancontrol/config.txt for writing\n");
  				fclose (outfile);
  				return 1;
 			}
 			else 
 			{	// write standard config to config.txt
 				fprintf (outfile,"%s","#FAN-PIN\n1\n#Min. PWM-POWER (0-1024):\n550\n#Max. PWM-POWER (0-1024):\n1024\n#Fan stops at Temp (°C *1000):\n45000\n#Fan starts at Temp:\n50000\n#Fullspeed Fan at Temp:\n70000\n#Refresh Time (seconds):\n5\n") ;
 			}
 			fclose (outfile);
 			return 0;
		}
		else
		{
			// create fancontrol-dir + config.txt
			status = mkdir ("/usr/share/fancontrol", S_IRWXO) ;
			
			if(status != 0)
			{
				fprintf (stderr, "Unable to create /usr/share/fancontrol  %s\n", strerror (errno)) ;
				return status;
			}
			
			// now create the config.txt
			FILE *outfile = fopen ("/usr/share/fancontrol/config.txt", "a+");
			
 			if(!outfile) {
  				printf ("There was a problem opening /usr/share/fancontrol/config.txt for writing\n");
  				fclose (outfile);
  				return 1;
 			}
 			else 
 			{	// write standard config to config.txt
 				fprintf (outfile,"%s","#FAN-PIN\n1\n#Min. PWM-POWER (0-1024):\n550\n#Max. PWM-POWER (0-1024):\n1024\n#Fan stops at Temp (°C *1000):\n45000\n#Fan starts at Temp:\n50000\n#Fullspeed Fan at Temp:\n70000\n#Refresh Time (seconds):\n5\n") ;
 			}
 			fclose (outfile);
 			return 0;
		}
    }
}


int getConfig(void) 
{
    char line[256];
    int wert = 0, linenum = 0 ;
    FILE* configfile = fopen ("/usr/share/fancontrol/config.txt", "r");
    
	while(fgets (line, 256, configfile) != NULL)
	{
   		linenum++;
   		if(line[0] == '#') 
   			continue;
		// now read the configfile
   		if(sscanf (line, "%d", &wert) != 1)
    	{
    		fprintf (stderr, "Syntax error, line %d\n", linenum);
        	continue;
    	}
    	// now allocate values
    	switch( linenum ) 
		{
    		case 2:
       			FAN = wert;
        		break;
    		case 4 :
        		PWM_ZERO = wert;
        		break;
        	case 6 :
        		PWM_MAX = wert;
        		break;
    		case 8 :
        		TEMP_ZERO = wert;
        		break;
        	case 10 :
        		TEMP_PWM = wert;
        		break;
        	case 12 :
        		TEMP_MAX = wert;
        		break;
        	case 14 :
        		sleepTime = wert;
        		break;
		}
		
	}
	fclose (configfile);

    return 0;
}


int main ()	
{
  // check if wiringPi loaded correctly
  if (wiringPiSetup () == -1)
  	{
    	fprintf (stderr, "Unable to setup GPIO: %s\n", strerror (errno)) ;
    	return 1 ;
  	}
  
  checkIfItsFirstRun ();
  getConfig ();
  
  pinMode (FAN, PWM_OUTPUT) ;
  int temp = 0, pwmPercentage = 0, fanStatus = 0;
  float tempOnePercent = 0, pwmOnePercent = 0, tempPercentage = 0, pwmPercentageDump = 0, tempDump = 0;
  
  // Precalculations
  tempOnePercent = ((TEMP_MAX - (float)TEMP_ZERO) / 100000) ;
  pwmOnePercent = ((PWM_MAX - (float)PWM_ZERO) / 100) ;
  
  printf( "FAN: %i \n", FAN);
  printf( "tempOnePercent: %f \n", tempOnePercent);
  printf( "pwmOnePercent: %f \n", pwmOnePercent);
  while(1)
  {
	temp = getTemp ();
	printf( "temp: %i \n", temp);
	
		if(temp > TEMP_PWM)
		{	
			while(temp > TEMP_ZERO)
			{	// Calculate the PWM-Power
				tempDump = ((temp - (float)TEMP_ZERO) / 1000) ;
				tempPercentage = tempDump / tempOnePercent ;
				pwmPercentageDump = tempPercentage * pwmOnePercent;
				pwmPercentage = (int)( (pwmPercentageDump + PWM_ZERO)) ;
				
				

				if(fanStatus == 0)
				{	// Help the Fan to start
					pwmWrite (FAN, PWM_MAX) ;
					fanStatus = 1;
					sleep (1) ;
				}
				pwmWrite (FAN, pwmPercentage) ;
				sleep (sleepTime) ;
				temp = getTemp ();
				
				printf( "\ntemp: %i \n", temp);
				printf( "pwmPercentage: %i \n", pwmPercentage);
				printf( "tempDump: %f \n", tempDump);
				printf( "tempPercentage: %f \n", tempPercentage);
				printf( "pwmPercentageDump: %f \n", pwmPercentageDump);
			}
		}
		else
		{
			pwmWrite (FAN, 0) ;
			fanStatus = 0;
			sleep (sleepTime) ;
		}	
  }
    
  return 0 ;
}
/*
To Compile:
gcc -Wall -o fancontrol-hv2 Fancontrol-hv2.c -lwiringPi -lpthread


To Run automaticly at startup write the follwing before "exit 0" in /etc/rc.local:
/location/of/fancontrol-hv2 &

*/
The compile- & install-instructions are at the bottom of the code.

It's a simple, linear PWM-Control. The hotter the CPU, the faster the Fan.
Simple and Easy ;D


Comments, criticism, improvement suggestions,.. would be great :D

Last but not least:
Sry for my bad english

greets form Austria ;)

User avatar
bfagioli
Posts: 123
Joined: Sat Oct 27, 2012 11:49 pm

Re: Selfmade Case with dynamic-PWM driven Fan

Sun Jan 20, 2013 4:33 am

Your english is fine. I don't know if its just me but your pictures are not displaying correctly for me. I can't see what is going on because each picture looks like a small piece of a much larger image. Lastly, as a fun electronics and programming project this is very cook. It makes me want to lean more about what that PWM pin is doing. But is a CPU fan really needed? I run my Pi all the time and it never gets hot. Just barely warm.

2h4u
Posts: 2
Joined: Sat Jan 19, 2013 6:19 pm
Location: Austria

Re: Selfmade Case with dynamic-PWM driven Fan

Sun Jan 20, 2013 8:33 am

Thanks :D

hm strange.. here are the dropbox-links:
https://dl.dropbox.com/u/22659349/fan-case/IMG_0983.JPG
https://dl.dropbox.com/u/22659349/fan-case/IMG_0984.JPG
https://dl.dropbox.com/u/22659349/fan-case/IMG_0985.JPG
https://dl.dropbox.com/u/22659349/fan-case/IMG_0986.JPG
https://dl.dropbox.com/u/22659349/fan-case/IMG_0988.jpg
https://dl.dropbox.com/u/22659349/fan-case/IMG_0993.jpg
https://dl.dropbox.com/u/22659349/fan-case/IMG_1122.JPG
https://dl.dropbox.com/u/22659349/fan-case/IMG_1123.JPG


No a Fan isn't needed at all, even if you overclock your pi it's never getting hotter than 60°C ( at ~20°C room temperature ).
At least my Raspi didn't became hotter.

I have done this because I want to oc my raspi over 1GHz and don't want to melt it :P
Also I looks kinda cool ;)

mado79
Posts: 1
Joined: Tue Dec 18, 2012 10:04 pm

Re: Selfmade Case with dynamic-PWM driven Fan

Mon Sep 30, 2013 6:06 pm

what are the characteristics of the transistor?
Good job!!

Huub
Posts: 15
Joined: Mon Jun 16, 2014 10:01 am

Re: Selfmade Case with dynamic-PWM driven Fan

Fri Jun 27, 2014 9:02 pm

2h4u wrote:Last but not least:
Sry for my bad english

greets form Austria ;)
Hello, I'm using your awesome mod, but I have a question. I'm using a PNP transistor, so the PWM need to be inverted. I'm looking over the code, but I'm not very good at raw code or C. Could you please tell me if there is an easy way to invert the PWM (0=max speed)?

Mineralquellen
Posts: 1
Joined: Fri Oct 24, 2014 3:33 pm

Re: Selfmade Case with dynamic-PWM driven Fan

Fri Oct 24, 2014 3:38 pm

Hi, i Tried your script with the given transistor and it worked really well! Now I decided to try another fan, a. 5V pwm fan...when I just connected the pwm pin from the fan to the pwm pin as before it just didn't work. The fan is running all the time at max speed....any ideas about that? I just don't get it :(
Greetz from Berlin

FallChallenge
Posts: 18
Joined: Wed Feb 01, 2012 2:28 pm
Contact: Website

Re: Selfmade Case with dynamic-PWM driven Fan

Sat Dec 27, 2014 2:33 am

What kind of transistor do you recommend? :D

kavierkoo
Posts: 13
Joined: Sun Sep 06, 2015 5:04 pm

Re: Selfmade Case with dynamic-PWM driven Fan

Thu Sep 17, 2015 2:27 pm

Could I know did you use any resistor? in my case im using a 5v 0.2A 3cmx3cm fan, could I use the same code above? lastly could also recommend any transistor that suits this project?

Return to “Other projects”