nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Temp controlled Rpi fan code

Tue Jan 19, 2016 8:42 pm

Hey peeps,

I'm in the progress of making a mod to my RPi case with fan.

Fan specs: 5v, 0,20mA

Manufacturer instructions were to connect red cable to 5v and the black cable to ground but since it's not recommended and causes too much fan noise I'm going to use a transistor and some python programming to control fan speed.

The transistor I'm using is BC337-40. I tested and it works. I send PWM signals to the GPIO pin, that is connected to the transistor, and fan speed changes accordingly. Here's the code I wrote to test:

Code: Select all

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(2,GPIO.OUT)
p=GPIO.PWM(2,50)
p.start(50)
time.sleep(10)
p=GPIO.PWM(2,100)
p.start(100)
time.sleep(10)
p.stop()
GPIO.cleanup()
This video helped me a lot to start up: https://www.youtube.com/watch?v=Ra1CY-zaDj4 But I didn't like the way the guy handled code part. He activates the fan to 100% once CPU reaches a certain temp and deactives if it's below that value.

Basically I'd like to tell RPi to spin the fan faster if the CPU gets hotter. For instance;

CPU temp(C) - Fan Speed(%)
30 - Fan turned off
40 - Fan 20%
50 - Fan 30%
55 - Fan 40%
60 - Fan 50%
65 - Fan 60%
70 - Fan 80%
75 - Fan 100%

I'm very new to Python and don't know how to create something like "Switch case statement" in Arduino C++. I also want this code to start automatically and run all the time.

asandford
Posts: 1998
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 9:14 pm

The PI doesn't require cooling in normal operation (and in reasonable conditions), if the SoC does manage to overheat, it'll throttle back to avoid damage.

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 9:38 pm

asandford wrote:The PI doesn't require cooling in normal operation (and in reasonable conditions), if the SoC does manage to overheat, it'll throttle back to avoid damage.
I'm running BOINC so I need cooling.

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 9:47 pm

Python doesn't provide a switch case function. You can set it up as a dictionary for lookup (associative array), or what most do is just use an "if..elif..else" block to provide the same thing if you don't have too many cases to deal with.

This is part of a Python script I use to show the current CPU temp on a 24 segment bar graph. The temp is displayed on the first 8 bars of the graph and each "if/elif/else" works as a case statement to turn on the correct segment according to the temperature.

Code: Select all

while True:
    # CPU temperature
    CPU_temp = getCPUtemp()
    if CPU_temp > 70.0:
        segT = 8
    elif CPU_temp > 60.0:
        segT = 7
    elif CPU_temp > 50.0:
        segT = 6
    elif CPU_temp > 45.0:
        segT = 5
    elif CPU_temp > 40.0:
        segT = 4
    elif CPU_temp > 35.0:
        segT = 3
    elif CPU_temp > 30.0:
        segT = 2
    else:
        segT = 1
The "CPU_temp" sets the top bar (segment T) that should be lit, or in your case to determine the fan speed desired. The "segT" value is then used in another function to actually turn on the LED, and blank any above it when the temp drops, or in your case actually control the fans speed.
That should give you some ideas for controlling the fan speed, as it would be similar.

asandford
Posts: 1998
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 9:53 pm

nautilus27 wrote: I'm running BOINC so I need cooling.
No you don't. Running BOINC on a PI is futile as AFAIA the GPU isn't used (it wasn't the last time I checked - I had a PI2 running it and it did SFA), and even if it was it would throttle back to avoid damage. Unless you are running the Pi in 'extreme' environments, then cooling is not required.

The SoC was designed to be used in phones and media sticks, and none of them have fans (temperature controlled or otherwise).

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 9:59 pm

JimmyN wrote:Python doesn't provide a switch case function. You can set it up as a dictionary for lookup (associative array), or what most do is just use an "if..elif..else" block to provide the same thing if you don't have too many cases to deal with.

This is part of a Python script I use to show the current CPU temp on a 24 segment bar graph. The temp is displayed on the first 8 bars of the graph and each "if/elif/else" works as a case statement to turn on the correct segment according to the temperature.

Code: Select all

while True:
    # CPU temperature
    CPU_temp = getCPUtemp()
    if CPU_temp > 70.0:
        segT = 8
    elif CPU_temp > 60.0:
        segT = 7
    elif CPU_temp > 50.0:
        segT = 6
    elif CPU_temp > 45.0:
        segT = 5
    elif CPU_temp > 40.0:
        segT = 4
    elif CPU_temp > 35.0:
        segT = 3
    elif CPU_temp > 30.0:
        segT = 2
    else:
        segT = 1
The "CPU_temp" sets the top bar (segment T) that should be lit, or in your case to determine the fan speed desired. The "segT" value is then used in another function to actually turn on the LED, and blank any above it when the temp drops, or in your case actually control the fans speed.
That should give you some ideas for controlling the fan speed, as it would be similar.

Thanks!

Do I have to use any libraries for this code or it works like this if I copy & paste?

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 10:09 pm

asandford wrote:
nautilus27 wrote: I'm running BOINC so I need cooling.
No you don't. Running BOINC on a PI is futile as AFAIA the GPU isn't used (it wasn't the last time I checked - I had a PI2 running it and it did SFA), and even if it was it would throttle back to avoid damage. Unless you are running the Pi in 'extreme' environments, then cooling is not required.

The SoC was designed to be used in phones and media sticks, and none of them have fans (temperature controlled or otherwise).
I have 4x overclocked Raspberry Pi 2s stacked on top of each other using a stackable case and they bring a hefty amount of credits when they run 7/24. You need to get your facts straight. Sure a decent quad core x86 CPU or a GPU can beat them but that's not the point. 4x Raspberry Pi 2s consume a fraction of the power of those systems and I don't want to decrease the lifespan of my laptop by running Boinc on it (a constant 80 degrees Celcius!). A Raspberry Pi on the other hand is expendable...

If you utilize 4 cores at 100% of an overclocked Raspberry Pi 2 with heatsink, it reaches up to 65 degrees. (OC settings: 1Ghz core, 500Mhz L2 cache and 500Mhz ram, over_volt=6). The fan cuts the temp in half...

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 10:11 pm

You can just copy and paste.
The only thing you'd need would depend on how you're fetching the CPU temp. If you're doing that already you're good to go.

What I'm doing in this script is "import os" at the top, and then using this bit to get just the floating point number, otherwise it returns "temp=" plus the value, so I strip off the text and just keep the value.

Code: Select all

  # Return CPU temperature as float                                     
def getCPUtemp():
    cTemp = os.popen('vcgencmd measure_temp').readline()
    return float(cTemp.replace("temp=","").replace("'C\n",""))

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 10:37 pm

It's designed to get hotter -- 85 degrees or more. But maybe the other stuff in the rack is not as robust.

Still, it's your choice and an interesting project.

You could build a PID controller for it. There's probably a whole lot of resources out there to draw on but it's easy enough to get started.

First, you need accurately timestamped temperature data, since if you get any jitter in the timing then the algorithm won't work well. Take the time since the last execution; don't try to use sleep.

Then calculate the error as the difference between the existing temperature and the maximum temperature you want and divide by the time since the last measurement. That's your proportional factor.
Add the errors together to make a running total. That's your Integral factor.
Subtract the error from the previous error. That's your derivative factor.

Then you take three numbers you will have to select and tune by hand: the proportional, integral and derivative coefficients.

Multiply the factors by the coefficients and then add up all three numbers. That is the value that you set your fan speed to.

time = timenow()
timedifference = previoustime - time
error = error/timedifference
totalerrors = totalerrors + error
Output = P * error + I * totalerrors + D * (previouserror - error)
previouserror = error
previoustime = time

You will need to clip the output value to the maximum and minimum values that you can set the fan speed to:

if output > max_fan_setting: output = max_fan_setting
if output < 0: output = 0

First set I and D to zero and tune P so that the temperature rises to the setpoint and settles near it (it will be a little high).
Then increase I to reduce that error to a minimum. You will need to adjust P at the same time because they are interrelated.
You can use D to reduce the rate at which the temperature changes because if it moves too fast then you will get oscillation. Otherwise leave D at zero; it's often not needed.

asandford
Posts: 1998
Joined: Mon Dec 31, 2012 12:54 pm
Location: Waterlooville

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 10:38 pm

nautilus27 wrote: If you utilize 4 cores at 100% of an overclocked Raspberry Pi 2 with heatsink, it reaches up to 65 degrees. (OC settings: 1Ghz core, 500Mhz L2 cache and 500Mhz ram, over_volt=6). The fan cuts the temp in half...
And the SoC can run at up to ~85 before it starts to limit.

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Tue Jan 19, 2016 10:50 pm

asandford wrote:
nautilus27 wrote: If you utilize 4 cores at 100% of an overclocked Raspberry Pi 2 with heatsink, it reaches up to 65 degrees. (OC settings: 1Ghz core, 500Mhz L2 cache and 500Mhz ram, over_volt=6). The fan cuts the temp in half...
And the SoC can run at up to ~85 before it starts to limit.
Yeah and modern CPUs in our PCs build to take at least 105c. It'll throttle after that. But we don't sit idle when it runs near that.. let alone 90 degrees. I personally find it very dangerous to run my CPU even at 70C all the time.

I'm kind of experienced in PC hardware, overclocking and cooling areas so you can trust me ;)

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Wed Jan 20, 2016 1:35 am

OK, so here's my final code. I managed to successfully ramp up fan speed based on CPU temps. But now the script itself uses too much CPU... Like 30%.. Is there anything I can do to stop this? Also how can I run this in background? The script runs as long as the terminal window is open.

Code: Select all

import RPi.GPIO as GPIO
import time
import os

  # Return CPU temperature as float
def getCPUtemp():
    cTemp = os.popen('vcgencmd measure_temp').readline()
    return float(cTemp.replace("temp=","").replace("'C\n",""))

GPIO.setmode(GPIO.BCM)
GPIO.setup(2,GPIO.OUT)
GPIO.setwarnings(False)
p=GPIO.PWM(2,100)

while True:

    CPU_temp = getCPUtemp()
    if CPU_temp > 70.0:
         p.start(100)
    elif CPU_temp > 60.0:
         p.start(60)
    elif CPU_temp > 50.0:
         p.start(40)
    elif CPU_temp > 45.0:
         p.start(30)
    elif CPU_temp > 40.0:
         p.start(20)
    elif CPU_temp > 35.0:
         p.start(15)
    elif CPU_temp > 30.0:
         p.start(10)
    else:
         p.stop()

GPIO.cleanup()

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: Temp controlled Rpi fan code

Wed Jan 20, 2016 2:45 am

You need to slow it down a bunch, it's whirling devilishly constantly updating the temp and getting nowhere. I added a "time.sleep" value at the bottom for you. I have it in my script it's just later on after I've also set the other two sections of the bar graph for CPU and RAM use, so it wasn't in the section I pasted.

What I added at the bottom will only query the temp and update the fan speed once every minute, change it to suit yourself. Updating a fan speed doesn't require a nano second response, and you'll have a temp range between any fan speed change anyway.

Code: Select all

import RPi.GPIO as GPIO
import time
import os

  # Return CPU temperature as float
def getCPUtemp():
    cTemp = os.popen('vcgencmd measure_temp').readline()
    return float(cTemp.replace("temp=","").replace("'C\n",""))

GPIO.setmode(GPIO.BCM)
GPIO.setup(2,GPIO.OUT)
GPIO.setwarnings(False)
p=GPIO.PWM(2,100)

while True:

    CPU_temp = getCPUtemp()
    if CPU_temp > 70.0:
         p.start(100)
    elif CPU_temp > 60.0:
         p.start(60)
    elif CPU_temp > 50.0:
         p.start(40)
    elif CPU_temp > 45.0:
         p.start(30)
    elif CPU_temp > 40.0:
         p.start(20)
    elif CPU_temp > 35.0:
         p.start(15)
    elif CPU_temp > 30.0:
         p.start(10)
    else:
         p.stop()
    time.sleep(60)

GPIO.cleanup()

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: Temp controlled Rpi fan code

Wed Jan 20, 2016 3:17 am

To run it in the background you could add it to crontab and use "@reboot" to run it when the Pi boots up. I don't think the user crontab will allow the "@reboot", so put it in root's crontab.

Code: Select all

sudo crontab -e
That will open the file for editing, and add this line at the bottom

Code: Select all

@reboot /path/to/my/script.sh
Or you could start it when the Desktop starts using autorun, or add it to .bashrc to have it start when you login. But you'll probably want it to start early so either crontab or rc.local. There are a lot of ways to start it up, to stop it you'll have to open a terminal and kill the process.

User avatar
rpdom
Posts: 16087
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Temp controlled Rpi fan code

Wed Jan 20, 2016 7:45 am

nautilus27 wrote:[I'm kind of experienced in PC hardware, overclocking and cooling areas so you can trust me ;)
The Pi is not PC hardware. I'm also experienced in PC hardware, overclocking and the like. I also know a fair bit about the ARM chips and the Pi. The 85 degree limit that has been set is fairly conservative. The chip will run without issue at much higher temperatures with no additional cooling, although it may reduce the lifespan a bit.

Running at close to 85 degrees may reduce the life of your Pi from 35 years to 25 years. Is that a risk you are prepared to take? Is it worth the cost of the fan, faffing around with software and hardware to control it and the cost of the extra power to run it?

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Thu Jan 21, 2016 12:25 am

JimmyN wrote:To run it in the background you could add it to crontab and use "@reboot" to run it when the Pi boots up. I don't think the user crontab will allow the "@reboot", so put it in root's crontab.

Code: Select all

sudo crontab -e
That will open the file for editing, and add this line at the bottom

Code: Select all

@reboot /path/to/my/script.sh
Or you could start it when the Desktop starts using autorun, or add it to .bashrc to have it start when you login. But you'll probably want it to start early so either crontab or rc.local. There are a lot of ways to start it up, to stop it you'll have to open a terminal and kill the process.
Hi,

I did add the crontab but the script is not running. Btw my script is not .sh but .py

nautilus27
Posts: 71
Joined: Fri May 22, 2015 9:38 pm

Re: Temp controlled Rpi fan code

Thu Jan 21, 2016 10:26 am

I tried to follow another instruction: http://www.opentechguides.com/how-to/ar ... start.html

I get this error message

Code: Select all

-bash: import: command not found
-bash: import: command not found
-bash: import: command not found
-bash: /home/pi/fan.py: line 6: syntax error near unexpected token `('
-bash: /home/pi/fan.py: line 6: `def getCPUtemp():'

JimmyN
Posts: 1109
Joined: Wed Mar 18, 2015 7:05 pm
Location: Virginia, USA

Re: Temp controlled Rpi fan code

Thu Jan 21, 2016 11:38 am

I'm sorrry I messed you up there, it's obviously a Python script, don't know what I was thinking, or maybe I wasn't thinking. :oops:

The crontab line needs to include a full path to Python. And the "-bash" errors you got were because it was trying to run it as a shell script, it's missing the "shebang" line.

This should work better to start it up, we'll actually use Python to run it this time. :D

Code: Select all

@reboot /usr/bin/python /path/to/my/script.py
And add this line to the top of the script, just for good measure. It's good practice to always include it.

Code: Select all

#!/usr/bin/python

import RPi.GPIO as GPIO
import time
import os
....
.....
....
Sorry about that.

hrostami
Posts: 6
Joined: Wed Dec 27, 2017 7:16 am

Re: Temp controlled Rpi fan code

Wed Dec 27, 2017 7:52 am

Hey Buddy, I actually made a video about it>> click on this link: https://www.youtube.com/watch?v=1ex2e7ik0uA
In this method you consider the fan as a DC motor an you control it with a S8050 transistor. for the connections take a look at my youtube video, and here is the code:

Code: Select all

#!/usr/bin/env python3
# coding: utf-8
# Author: Edoardo Paolo Scalafiotti>> Fixed and updated by HRM Tech
import os
import time
import signal
import sys
import RPi.GPIO as GPIO
pin = 36 # The pin ID, edit here to change it
maxTMP = 50 # The maximum temperature in Celsius after which we trigger the fan
GPIO.setmode (GPIO.BOARD)

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(pin,GPIO.OUT)
    GPIO.setwarnings(False)
    return()
def getCPUtemperature():
    res = os.popen('vcgencmd measure_temp').readline()
    temp =(res.replace("temp=","").replace("'C\n",""))
    print("temp is {0}".format(temp)) #Uncomment here for testing
    return temp
def fanON():
    setPin(True)
    return()
def fanOFF():
    setPin(False)
    return()
def getTEMP():
    CPU_temp = float(getCPUtemperature())

    if CPU_temp>maxTMP:
        fanON()

    else:
        fanOFF()

    return()
def setPin(mode): # A little redundant function but useful if you want to add logging
    GPIO.output(pin, mode)
    return()
try:
    setup()
    while True:
        getTEMP()
        time. sleep(8) # Read the temperature every 5 sec, increase or decrease this limit if you want
except KeyboardInterrupt: # trap a CTRL+C keyboard interrupt
	GPIO.cleanup()
Good Luck

hrostami
Posts: 6
Joined: Wed Dec 27, 2017 7:16 am

Re: Temp controlled Rpi fan code

Wed Dec 27, 2017 8:01 am

nautilus27 wrote:
Tue Jan 19, 2016 8:42 pm
Hey peeps,

I'm in the progress of making a mod to my RPi case with fan.

Fan specs: 5v, 0,20mA

Manufacturer instructions were to connect red cable to 5v and the black cable to ground but since it's not recommended and causes too much fan noise I'm going to use a transistor and some python programming to control fan speed.

The transistor I'm using is BC337-40. I tested and it works. I send PWM signals to the GPIO pin, that is connected to the transistor, and fan speed changes accordingly. Here's the code I wrote to test:
........
I don't have an Idea to control it's speed but here is how to make cputemp automatic fan and I'm using this method for about a month now, here it is:
in this method consider the fan as a normal DC motor and control it with a S8050 transistor. I made a video about it, click on this link and checkout connections and step by step tutorial: https://www.youtube.com/edit?o=U&video_id=1ex2e7ik0uA

and here is the code:

Code: Select all

#!/usr/bin/env python3
# coding: utf-8

import os
import time
import signal
import sys
import RPi.GPIO as GPIO
pin = 36 # The pin ID, edit here to change it
maxTMP = 50 # The maximum temperature in Celsius after which we trigger the fan
GPIO.setmode (GPIO.BOARD)

def setup():
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(pin,GPIO.OUT)
    GPIO.setwarnings(False)
    return()
def getCPUtemperature():
    res = os.popen('vcgencmd measure_temp').readline()
    temp =(res.replace("temp=","").replace("'C\n",""))
    print("temp is {0}".format(temp)) #Uncomment here for testing
    return temp
def fanON():
    setPin(True)
    return()
def fanOFF():
    setPin(False)
    return()
def getTEMP():
    CPU_temp = float(getCPUtemperature())

    if CPU_temp>maxTMP:
        fanON()

    else:
        fanOFF()

    return()
def setPin(mode): # A little redundant function but useful if you want to add logging
    GPIO.output(pin, mode)
    return()
try:
    setup()
    while True:
        getTEMP()
        time. sleep(8) # Read the temperature every 5 sec, increase or decrease this limit if you want
except KeyboardInterrupt: # trap a CTRL+C keyboard interrupt
	GPIO.cleanup()

hope it was useful!

Return to “Python”