Smart Fan and Power Expansion Board

From Geekworm Wiki
Jump to navigation Jump to search
Raspberry Pi Smart Fan and Power Expansion Board sku:464657

Raspberry Pi Smart Fan and Power Expansion Board sku:464657
Raspberry Pi Smart Fan and Power Expansion Board sku:464657
Raspberry Pi Smart Fan and Power Expansion Board sku:464657
Raspberry Pi Smart Fan and Power Expansion Board sku:464657
Raspberry Pi Smart Fan and Power Expansion Board sku:464657
Raspberry Pi Smart Fan and Power Expansion Board sku:464657

Overview

Smart Fan and Power Expansion Board

Features

1. Width voltage input: 6V~14V' With power switch

2. Output: DC 5V 4A with two channel outputs:

OUT1 for  external device such as servo, motor, robots, mechanical arm, intelligent card etc. (output interface: HT3.96);
Max current is 2A, and can be programming control to on/off; please refer to SAMPLE CODE 1;
OUT2 (GPIO output for raspberry pi);Max current is up to 4A if the OUT1 be closed; 
CAN'T be programming control, it will be output to raspberry pi directly if the switch be turned on;

3. Built-in temperature sensor, with active cooling fan, you can control flexibly the ON/OFF of mini fan via I2C command and GPIO programming. please refer to SAMPLE CODE 2;

4. Support hardware pwm to control fan, please refer to SAMPLE CODE 3;

Temperature range and accuracy

  • -25 ℃ ~ + 100 ℃ when the ± 2 ℃
  • -55 ℃ ~ +125 ℃ when the ± 3 ℃

5. Cooling Fan can be replaced, please refer to FAN SPECIFICATIONS;

6. Standard HAT size;

Packing List

  • 1 x Board;
  • 1 x Mini fan (with install screws)

SAMPLE CODE 1

#demonstrates how to control the output of OUT1
import RPi.GPIO as GPIO
import time

GPIO_PIN = 27

GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN, GPIO.OUT)
GPIO.setwarnings(False)
while True:
	#turn on the power output, LED is on
	GPIO.output(GPIO_PIN,GPIO.HIGH)
	print "Turn on the power output"
	time.sleep(10)
	#turn off the power output, LED is off
	GPIO.output(GPIO_PIN,GPIO.LOW)
	print "Turn off the power output"
	time.sleep(10)

Download it: File:Out1-onoff.zip

or

wget http://raspberrypiwiki.com/download/battery-fan-board/out1-onoff.py

Run this sample code, if you can found the out1 led turns on, after 10 seconds, out1 led turns off, in turn.

SAMPLE CODE 2

#coding=utf-8

import RPi.GPIO as GPIO
import struct
import smbus
import sys
import time
import os

Sensor_ADDRESS		= 0x48

#Set global alert temperature;
ALERT_CON_TEMPERATURE   = 36

#Set global CPU temperature
ALERT_CPU_TEMPERATURE   = 70

TEMP_REGISTER 	    = 0
CONF_REGISTER 	    = 1
#THYST_REGISTER 	  = 2
#TOS_REGISTER 	    = 3

#CONF_SHUTDOWN       = 0
#CONF_OS_COMP_INT    = 1
#CONF_OS_POL 	    = 2
#CONF_OS_F_QUE 	    = 3

GPIO_PIN = 12
g_on = False

def regdata2float (regdata):
	return (regdata / 32.0) / 8.0

def toFah(temp):
	return (temp * (9.0/5.0)) + 32.0

def setAlertTemp():
	g_bus.write_byte_data(Sensor_ADDRESS,TEMP_REGISTER,ALERT_CON_TEMPERATURE)

def clearAlert():
	g_bus.write_byte_data(Sensor_ADDRESS,CONF_REGISTER,0x00)

#Initialize the sensor and others.
def init():
	GPIO.setmode(GPIO.BCM)
	GPIO.setup(GPIO_PIN, GPIO.OUT)
	GPIO.setwarnings(False)
	setAlertTemp()
	clearAlert()

def getTemp(self):
	#msg = "Reads the temp from the sensor";
	raw = g_bus.read_word_data(Sensor_ADDRESS, TEMP_REGISTER) & 0xFFFF
	raw = ((raw << 8) & 0xFF00) + (raw >> 8)
	ret = regdata2float(raw)
	print "Current condition temperature is ", ret, "℃", "[", ALERT_CON_TEMPERATURE,"℃]"
	return ret

def getCPUtemp():
	cTemp = os.popen('vcgencmd measure_temp').readline()
	ret = float(cTemp.replace("temp=","").replace("'C\n",""))
	print "Current CPU temperature is ", ret, "℃", "[", ALERT_CPU_TEMPERATURE,"℃]"
	return ret

def checkTemperature():
	return (getTemp(g_bus) > ALERT_CON_TEMPERATURE) or (getCPUtemp() > ALERT_CPU_TEMPERATURE)

def setFan(need_to_open):
	#turn on the fan
	global g_on
	if (g_on and need_to_open) :
		return

	if (g_on == False and need_to_open == False) :
		return

	if need_to_open :
		if g_on == False :
			print "starup fan!"
		GPIO.output(GPIO_PIN,GPIO.LOW)
		g_on = True
	else:
		if g_on :
			print "Stop fan!"
		GPIO.output(GPIO_PIN,GPIO.HIGH)
		g_on = False

g_bus = smbus.SMBus(1)
init()
while True:
	print "------------------"
	print time.strftime("[%Y-%m-%d %H:%M:%S] ", time.localtime())
	setFan(checkTemperature())
	time.sleep(3);

Download it: File:Smartfan.zip

or:

wget http://raspberrypiwiki.com/download/battery-fan-board/smartfan.py

SAMPLE CODE 3

File:Samplecode3.zip

FAN SPECIFICATIONS

Side length is 30mm;

Thickness is 7mm;

PS: the thickness is not more 8mm;

Matching Acrylic Case

Sku-465240-IMG-2077.jpg

Sku-465240-IMG-2087-1.jpg

Add your comment
Geekworm Wiki welcomes all comments. If you do not want to be anonymous, register or log in. It is free.


Anonymous user #6

33 months ago
Score 0++
Can this board be used on RPi4B? Is it compatible?

Lisa

33 months ago
Score 0++
Hi,This board is no longer available, We recommend you to use X735 power management board with PWM fanX735

Anonymous user #4

61 months ago
Score 0++
Can this board be used to power the X820 expansion board?

Anonymous user #5

61 months ago
Score 0++

Hello sir, Sorry, we do not try to use it this way, so it is not syggested to use the fan and power board to power the X820 expansion board, hope to get your understanding! Best regards,

Cindy/Geekworm

Anonymous user #2

64 months ago
Score 0++
can add this to libreelec??

Admin

64 months ago
Score 0++

Hello sir, It is not tested on libreelec. We suggest that you can do a test, thank you very much! Best regards,

Geekworm

Anonymous user #1

66 months ago
Score 0++
  1. !/usr/bin/python
  2. MyRPi.ca script - ocs11@hotmail.com
  1. 2018-10-01
  1. Python script that uses multiple sources to determine the CPU and enclosure temperature
  2. and adjust the fan speed automatically
  1. Load system libraries

import RPi.GPIO as GPIO # Required to access the GPIO pin for PWM control. import time # Required for the loop delay. [time.sleep] import datetime # Required for date and time strings import sys # Required for CTRL-C clean exit. [sys.exit] import os # Required for secondary CPU temperature extraction. [os.open] import smbus # Required to read the sensor temperature

  1. User Configuration Settings

FAN_PIN = 12 # BCM pin used to drive the fan control. WAIT_TIME = 30 # Time, in seconds, to wait between each loop cycle.

fanSpeedMin = 36 # Minimum fan speed. Must be greater than 0. Use the calibration utility to get this value. fanSpeedMax = 100 # Maximum fan speed. Set to limit noise otherwise leave at 100. Maximum 100. cpuTempMin = 45 # Temperature at which to start the fan. Minimum 1. cpuTempMax = 60 # Temperature at which fan should run at [fanSpeedMax] speed. Maximum 70 (for safety).

diagCon = 0 # Set to [1] to enable diagnostic output to the console. [0] to diable. diagLog = 1 # Set to [1] to enable diagnostic output to a log file. [0] to diable. fanStatusLog = "/tmp/fanStatus" # Diagnostic Log file path and filename.

  1. I2C Temperature LM75 sensor onboard Fan/power hat
  2. i2cdetect -y 1
  3. 0 1 2 3 4 5 6 7 8 9 a b c d e f
  4. 00: -- -- -- -- -- -- -- -- -- -- -- -- --
  5. 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  6. 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  7. 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  8. 40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- <- 0x48 LM75 Temperature Sensor
  9. 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
  10. 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- <- 0x68 DS3231 RTC Module
  11. 70: -- -- -- -- -- -- -- --

checkLM75 = 1 # Enable (1) or disable (0) the LM75 sensor check sensorAddress = 0x48 # I2C Address of the temperature sensor tempRegister = 0 # In progress I2Cbus = smbus.SMBus(1) # 0 or 1 depending on the RPi. 0=/dev/i2c-0 1=/dev/i2c-1

  1. End of typical user configuration. Changing the code below may result in unexpected behaviour.
  1. Initialize runtime variables

PWM_FREQ = 50 # [Hz] Do not change. See documentation. cpuTemp = 0 # CPU Temperatue cpuTempOld = 0 # CPU Temperature on the last cycle fanSpeed = 0 # Fan Speed fanSpeedOld = 0 # Fan Speed on the last cycle fanRunning = 1 # Boolean to store if the fan is running or not

def regdata2float (regdata): return (regdata / 32.0) / 8.0

def getCPUtemp1(): if (diagCon): print "Trying to acquire CPU Temperature (Primary)." if (diagLog): fileLog.write ( "Trying to acquire CPU Temperature (Primary).\n" ) cpuTempFile = open("/sys/class/thermal/thermal_zone0/temp","r") # Open system file Read-Only cpuTemp1 = int(float(cpuTempFile.read())/1000) # Retrieve the system temperature value cpuTempFile.close() # Close the system file return cpuTemp1

def getCPUtemp2(): if (diagCon): print "Trying to acquire CPU Temperature (Secondary)." if (diagLog): fileLog.write ( "Trying to acquire CPU Temperature (Secondary).\n" ) cpuTemp2 = os.popen('vcgencmd measure_temp').readline() return float(cpuTemp2.replace("temp=","").replace("'C\n",""))

def getSensorTemp(self):

  1. Read the temperature from the I2C LM75 sensor

if (diagCon): print "Trying to acquire LM75 Sensor Temperature." if (diagLog): fileLog.write ( "Trying to acquire LM75 Sensor Temperature.\n" ) raw = I2Cbus.read_word_data(sensorAddress, tempRegister) & 0xFFFF raw = ((raw << 8) & 0xFF00) + (raw >> 8) ret = regdata2float(raw) if (diagCon): print "LM75 Sensor Temperature is ", ret, "C" if (diagLog): fileLog.write ( "LM75 Sensor Temperature is " + str(ret) + " C\n" ) return ret

  1. Verify the configuration values

if ((cpuTempMin >= cpuTempMax) or (cpuTempMin < 1) or (cpuTempMax > 70)): print "Invalid cpuTempMin or cpuTempMax value has been configured. Please read the documentation. Aborting." exit(0) if ((fanSpeedMin >= fanSpeedMax) or (fanSpeedMin < 0) or (fanSpeedMax > 100)): print "Invalid fanSpeedMin or fanSpeedMax value has been configured. Please read the documentation. Aborting." exit(0)

  1. Initialize the GPIO subsystem

GPIO.setmode(GPIO.BCM) GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW) GPIO.setwarnings(False) fan = GPIO.PWM(FAN_PIN,PWM_FREQ) fan.start(0);

  1. Main runtime loop

try: while (1): # Repeat until CTRL-C is pressed.

  1. Reset variables at beginning of loop

cpuTemp = 0 now = datetime.datetime.now() timeNow = now.strftime("%Y-%m-%d %H:%M:%S") if (diagCon): print timeNow if (diagLog): fileLog = open(fanStatusLog,"w") fileLog.write ( timeNow + "\n" )

  1. Try method 1 to acquire CPU Temperature

cpuTemp = getCPUtemp1()

  1. If method 1 failed, try method 2 to get CPU temperature

if ((cpuTemp <= 0) or (cpuTemp > 120)): cpuTemp = getCPUtemp2()

  1. Check to make sure we have a reasonable CPU temperature to work with

if ((cpuTemp <= 0) or (cpuTemp > 120)): print "Unable to read the CPU Temperature [cpuTemp]. Incompatible system architecture or Linux version. Aborting." exit(0) if (diagCon): print "CPU Temperature: ", cpuTemp if (diagLog): fileLog.write ( "CPU Temperature: " + repr(cpuTemp) + "\n" )

  1. Calculate the appropriate fan speed based on the current CPU temperature

if (cpuTemp > cpuTempMin): cpuTempPerc = (((cpuTemp - cpuTempMin) * 100) / (cpuTempMax - cpuTempMin)) fanSpeed = (((fanSpeedMax - fanSpeedMin) * cpuTempPerc ) / 100 ) + fanSpeedMin if (diagCon): print "Calculated cpuTempPerc:", cpuTempPerc, "% fanSpeed:", fanSpeed if (diagLog): fileLog.write ( "Calculated cpuTempPerc: " + str(cpuTempPerc) + "% fanSpeed: " + str(fanSpeed) + "\n" )

  1. Enforce maximum fan speed

if ((fanSpeed > fanSpeedMax) or (cpuTemp >= cpuTempMax)): if (diagCon): print "Setting fanSpeed [", fanSpeed, "] -> fanSpeedMax [", fanSpeedMax, "] based on fanSpeedMax or cpuTempMax" if (diagLog): fileLog.write ( "Setting fanSpeed [" + str(fanSpeed) + "] -> fanSpeedMax [" + str(fanSpeedMax) + "] based on fanSpeedMax or cpuTempMax\n" ) fanSpeed = fanSpeedMax

  1. If fanSpeed is at or below the minimum, stop the fan

if (((fanSpeed < fanSpeedMin) or (cpuTemp <= cpuTempMin)) and (fanRunning != 0)): if (diagCon): print "Changing Duty Cycle [", fanSpeedOld, "] -> [Off] Cooling not required." if (diagLog): fileLog.write ( "Changing Duty Cycle [" + str(fanSpeedOld) + "] -> [Off] Cooling not required\n" ) fanSpeed = fanSpeedMin fanSpeedOld = fanSpeedMin fanRunning = 0 fan.ChangeDutyCycle(100)

  1. If the calculated speed is different from the last cycle, set the fan speed

if ((fanSpeed != fanSpeedOld)): if (diagCon): print "Changing Duty Cycle [", fanSpeedOld, "] -> [", fanSpeed, "]" if (diagLog): fileLog.write ( "Changing Duty Cycle [" + str(fanSpeedOld) + "] -> [" + str(fanSpeed) + "]\n" ) fanRunning = 1 fan.ChangeDutyCycle(100-fanSpeed)

fanSpeedOld = fanSpeed if (checkLM75): getSensorTemp(I2Cbus)

  1. Wait until the next loop cycle

if (diagCon): print if (diagLog): fileLog.close() time.sleep(WAIT_TIME)

  1. If a keyboard interrupt occurs (ctrl + c), set the GPIO to 0 and exit the program.

except(KeyboardInterrupt): print "Fan speed control script interrupted by the user. CTRL-C was pressed." GPIO.cleanup() if not fileLog.closed: fileLog.close() sys.exit()

  1. End of Script

Anonymous user #3

63 months ago
Score 0++
Thanks for script! It works at RPI b3+.