Jump to content

pepper

Validating
  • Posts

    1
  • Joined

  • Last visited

Posts posted by pepper

  1. Hi all,

     

    This is my upgrade. Mean temperature Epoch PWM FAN regulator for Orange Pi 4/4B for Noctua NF-A4x10 5V PWM, Noctua NF-A4x20 5V PWM.

     

    $ sudo systemctl status fanepoch
    ● fanepoch.service - Mean temperature Epoch PWM FAN regulator
         Loaded: loaded (/etc/systemd/system/fanepoch.service; enabled; vendor preset: enabled)
         Active: active (running) since Tue 2021-06-22 21:24:01 CEST; 2min 28s ago
       Main PID: 13074 (epochpwmfan_op4)
          Tasks: 2 (limit: 4459)
         Memory: 516.0K
         CGroup: /system.slice/fanepoch.service
                 ├─13074 /bin/bash /usr/local/sbin/epochpwmfan_op4 -e 10
                 └─13374 /usr/bin/sleep 10
    
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: [0]53333 [1]55000 [2]53333 [3]59444 [4]53333 [5]55000 [6]52777
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: Calculate and create RPM list from DutyCycles array
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[0]: temp 82, duty_cycle 0, rpm 5000
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[1]: temp 80, duty_cycle 4705, rpm 4415
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[2]: temp 75, duty_cycle 12549, rpm 3440
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[3]: temp 65, duty_cycle 20392, rpm 2466
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[4]: temp 55, duty_cycle 23529, rpm 2062
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[5]: temp 45, duty_cycle 28235, rpm 1478
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: RPMLIST[6]: temp 0, duty_cycle 32000, rpm 1004
    čen 22 21:25:11 NAS epochpwmfan_op4[13074]: temp 51, epoch 54, target 45, duty 28235, rpm 1478

     

    Bash script epochpwmfan_op4 with installation instructions in systemd, but also works via init.d, etc...

    Spoiler
    
    #!/bin/bash
    if [ $# -eq 0 ];
     then
    cat << EOF
    Mean temperature Epoch PWM FAN regulator for Orange Pi 4/4B - peepr
    for Noctua NF-A4x10 5V PWM, Noctua NF-A4x20 5V PWM
    
    Syntax: epochpwmfan_op4 <[-c <N sec> : Classic ||-e <N sec> : Epoch]>
    
    Info: -e Define interval durations between temperature measuring and
     update/control PWM in second.
     One epoch contains 7 intervals. Default interval is 1s.
     Recommended for control PWM with mean Epochs is 3s(= 3x7=21s) to 10s(= 10x7=70s), etc..
     My recommendation is -e 10, ideal for heavy load, at ambient temperature air 21°C
     the CPU temperature will not exceed 62°C.
     
    Examples: epochpwmfan_op4 -e 10
    
    Installation instructions: look in the code
    EOF
    exit 0
    fi
    
    #INSTALLATION INSTRUCTIONS:
    #sudo cp epochpwmfan_op4 /usr/local/sbin/epochpwmfan_op4
    #sudo chmod 755 /usr/local/sbin/epochpwmfan_op4
    #sudo geany /etc/systemd/system/fanepoch.service
    #--- START ---- insert this line (uncomment!) to fanepoch.service (you can change the switches here according to your preferences in ExecStart)
    #[Unit]
    #Description=Mean temperature Epoch PWM FAN regulator
    #After=syslog.target
    #[Service]
    #Type=simple
    #User=root
    #Restart=on-failure
    #RestartSec=5s
    #ExecStart=/usr/local/sbin/epochpwmfan_op4 -e 10
    #[Install]
    #WantedBy=multi-user.target
    #---  END -----
    #sudo chmod 644 /etc/systemd/system/fanepoch.service
    #sudo systemctl daemon-reload
    #sudo systemctl enable fanepoch
    #sudo systemctl start fanepoch
    #Check status: sudo systemctl status fanepoch
    
    if [ "$(id -u)" != "0" ]; then
    echo "[!] must be root." 1>&2
    exit 1
    fi
    
    declare -i PERIOD=40000
    THA=false #no edit
    SLEEPTIME=1 #default
    declare -i temp=0
    declare -i measuretemp=0
    
    declare -i THAS=6  #temphistory_array_size
    THERMAL_ZONE0="/sys/class/thermal/thermal_zone0/temp"
    
    if [ $# -eq 2 ]; then
    SLEEPTIME=$2
    fi
    #activation only with switch -e
    if [ "$1" == "-e" ]; then
    	THA=true
    	declare -a temphistory_array
    	declare -i ACTUAL_EPOCH_MEAN_TEMP=0
    	echo "Create first Epoch array real temperature - duration $(($SLEEPTIME*(THAS+1))) sec, interval $SLEEPTIME sec"
    	for i in $(eval echo "{0..$THAS}");
    	do	temphistory_array+=($(cat $THERMAL_ZONE0))
    		echo -n "[$i]${temphistory_array[$i]} "
    		/usr/bin/sleep $SLEEPTIME
    	done
    	echo ""
    	#Calculation of the actual epoch mean
    	ACTUAL_EPOCH_MEAN_TEMP=$(((${temphistory_array[@]/%/+}0)/($THAS+1)))
    fi
    
    #Enable PWM regulation
    if [ ! -d /sys/class/pwm/pwmchip1/pwm0 ]; then
        echo 0 > /sys/class/pwm/pwmchip1/export
    fi
    
    ISENABLE=`cat /sys/class/pwm/pwmchip1/pwm0/enable`
    if [ $ISENABLE -eq 1 ]; then
        echo 0 > /sys/class/pwm/pwmchip1/pwm0/enable
    fi
    
    # Noctua PWM specification: https://noctua.at/pub/media/wysiwyg/Noctua_PWM_specifications_white_paper.pdf
    # Range PWM - minimal: 21kHz (47618ns) to maximum: 28kHz (35714ns). RECOMMENDED is 25kHz (40000ns).
    # Convert kHz to ns: https://www.google.com/search?q=period+to+frequency+calculator
    echo $PERIOD > /sys/class/pwm/pwmchip1/pwm0/period
    echo 1 > /sys/class/pwm/pwmchip1/pwm0/enable
    
    declare -a CpuTemps=(82000 80000 75000 65000 55000 45000 0)
    
    # duty_cycle 40000 = the fan stop. My fan is Noctua NF-A4x10 5V PWM
    # - GPIO [yellow cable - +5V in pin2 or pin4, black cable - GND in pin6, blue cable - PWM Signal in pin7]. Look here - run "gpio readall"
    # - My fan spins up from off to 38200ns (~250-300rpm) but that can't realistically be used.
    
    declare -a DutyCycles=(0 4705 12549 20392 23529 28235 32000)
    
    #!Calculation formula +- only for Noctua NF-A4x10 5V PWM, Noctua NF-A4x20 5V PWM!
    #! - is only but informational and does not control anything					!
    echo "Calculate and create RPM list from DutyCycles array" #for speed up script - we avoid infinte counting in a loop :)
    declare -a RPMLIST
    for i in $(eval echo "{0..$THAS}"); do
     if [ ${DutyCycles[$i]} -ne $PERIOD ]; then 
    	RPMLIST[$i]=$(echo "scale=2;5000-((23.2/2)*60)*((${DutyCycles[$i]}/10000)/0.5568)" | bc | cut -d . -f1)
     else
    	RPMLIST[$i]=0
     fi
     echo "RPMLIST[$i]: temp $((${CpuTemps[$i]}/1000)), duty_cycle ${DutyCycles[$i]}, rpm ${RPMLIST[$i]}"
    done
    
    declare -i LOOPID=0 #max. N = THAS, LOOPID controls the array updates of temperature Epochs
    declare -i PREVDUTY=0 #Previous duty_cycle (for comparsion [show rows 133] - we only write a new value, it speeds up the script)
    #And we start walking in infinite circles, this part needs to be as fast in running and well thought out as possible :)
    while true
    do		#Measure real temperature in the thermal_zone0
            measuretemp=$(/usr/bin/cat $THERMAL_ZONE0)
            if  $THA; then
    			temp=$ACTUAL_EPOCH_MEAN_TEMP
    		else
    			temp=$measuretemp
            fi        
            BRK=false
            for i in {0..6}; do
    				if [ $BRK == false ] && [ $temp -gt ${CpuTemps[$i]} ]; then
    						DUTY=${DutyCycles[$i]}
    						#echo "DUTY_CYCLE=$DUTY, PREVDUTY_CYCLE=$PREVDUTY" #debug info
    						if [ $PREVDUTY -ne $DUTY ]; then
    							echo $DUTY > "/sys/class/pwm/pwmchip1/pwm0/duty_cycle"
    							PREVDUTY=$DUTY
    							#print info only change fan speed (ideal output for syslog)
    							echo "temp $(($measuretemp/1000)), epoch $(($temp/1000)), target $((${CpuTemps[$i]}/1000)), duty $DUTY, rpm ${RPMLIST[$i]}"
    						fi						
    						#uncomment and comment [rows 137] for print info every interval
    						#echo "temp $(($measuretemp/1000)), epoch $(($temp/1000)), target $((${CpuTemps[$i]}/1000)), duty $DUTY, rpm ${RPMLIST[$i]}"
    						BRK=true #break
                    fi
            done
    		if $THA; then
    			#echo "LOOPID=$LOOPID" #debug info
    			#echo "temphistory_array[$LOOPID] ${temphistory_array[$LOOPID]}" #debug info
    			
    			#Update "Epoch" array and actual and previous mean
    			temphistory_array[$LOOPID]=$measuretemp
    			ACTUAL_EPOCH_MEAN_TEMP=$(((${temphistory_array[@]/%/+}0)/($THAS+1)))
    			if [ $LOOPID -lt $THAS ]; then
    				LOOPID+=1
    			else
    				LOOPID=0
    			fi
    		fi
    		#loop (measuring) interval: default is 1s [show row 54]
            /usr/bin/sleep $SLEEPTIME
    done

     

     

×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines