latest changes
This commit is contained in:
		
							
								
								
									
										126
									
								
								fancontrol.pl
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								fancontrol.pl
									
									
									
									
									
								
							| @@ -3,25 +3,9 @@ use strict; | |||||||
| use warnings; | use warnings; | ||||||
| use List::Util qw[min max]; | use List::Util qw[min max]; | ||||||
|  |  | ||||||
| # This script controls SuperMicro server fan speeds via IPMI in response to CPU and SYS temperatures. | my $min_temp_change     = 3; # °C minimum change to actually cause a fan speed update | ||||||
| # A fork of https://github.com/missmah/ipmi_tools by Layla Mah <layla@insightfulvr.com> | my $min_power_change     = 30; # W, minimum change to do something | ||||||
|  | my $seconds_to_sleep    = 4; # Number of seconds to sleep between update loops | ||||||
| # Sensor treshold reset to allow slower fans |  | ||||||
|  |  | ||||||
| `ipmitool sensor thresh FANA lower 0 100 200`; |  | ||||||
| `ipmitool sensor thresh FANB lower 0 100 200`; |  | ||||||
| `ipmitool sensor thresh FAN1 lower 0 100 200`; |  | ||||||
| `ipmitool sensor thresh FAN2 lower 0 100 200`; |  | ||||||
| `ipmitool sensor thresh FAN3 lower 0 100 200`; |  | ||||||
| `ipmitool sensor thresh FAN4 lower 0 100 200`; |  | ||||||
| `ipmitool sensor thresh FAN5 lower 0 100 200`; |  | ||||||
|  |  | ||||||
| # cache SDR data for faster access |  | ||||||
| `rm /opt/ipmi-cache.sdr`; |  | ||||||
| `while ipmitool sdr dump /opt/ipmi-cache.sdr; [ $? != 0 ]; do sleep 2; done`; |  | ||||||
|  |  | ||||||
| my $min_temp_change     = 2; # °C minimum change to actually cause a fan speed update |  | ||||||
| my $seconds_to_sleep    = 2; # Number of seconds to sleep between update loops |  | ||||||
|  |  | ||||||
| # 0x64 = 100, 0x00 = 0. | # 0x64 = 100, 0x00 = 0. | ||||||
| # CPU Temp -> Fan Speed Mappings | # CPU Temp -> Fan Speed Mappings | ||||||
| @@ -31,58 +15,51 @@ my %cpu_temp_to_fan_speed; | |||||||
|    $cpu_temp_to_fan_speed{70} = 0x56; |    $cpu_temp_to_fan_speed{70} = 0x56; | ||||||
|    $cpu_temp_to_fan_speed{65} = 0x52; |    $cpu_temp_to_fan_speed{65} = 0x52; | ||||||
|    $cpu_temp_to_fan_speed{60} = 0x48; |    $cpu_temp_to_fan_speed{60} = 0x48; | ||||||
|    $cpu_temp_to_fan_speed{55} = 0x46; |    $cpu_temp_to_fan_speed{55} = 0x44; | ||||||
|    $cpu_temp_to_fan_speed{50} = 0x42; |    $cpu_temp_to_fan_speed{50} = 0x40; | ||||||
|    $cpu_temp_to_fan_speed{45} = 0x40; |    $cpu_temp_to_fan_speed{45} = 0x36; | ||||||
|    $cpu_temp_to_fan_speed{40} = 0x36; |    $cpu_temp_to_fan_speed{40} = 0x32; | ||||||
|    $cpu_temp_to_fan_speed{35} = 0x34; |    $cpu_temp_to_fan_speed{35} = 0x30; | ||||||
|    $cpu_temp_to_fan_speed{30} = 0x32; |    $cpu_temp_to_fan_speed{30} = 0x28; | ||||||
|  |  | ||||||
| # SYS Temp -> Fan Speed Mappings | # SYS Power -> Fan Speed Mappings | ||||||
| my %sys_temp_to_fan_speed; | my %sys_power_to_fan_speed; | ||||||
|    $sys_temp_to_fan_speed{66} = 0x64; |    $sys_power_to_fan_speed{650} = 0x64; | ||||||
|    $sys_temp_to_fan_speed{60} = 0x60; |    $sys_power_to_fan_speed{575} = 0x60; | ||||||
|    $sys_temp_to_fan_speed{57} = 0x42; |    $sys_power_to_fan_speed{525} = 0x56; | ||||||
|    $sys_temp_to_fan_speed{55} = 0x40; |    $sys_power_to_fan_speed{500} = 0x54; | ||||||
|    $sys_temp_to_fan_speed{52} = 0x36; |    $sys_power_to_fan_speed{475} = 0x52; | ||||||
|    $sys_temp_to_fan_speed{50} = 0x34; |    $sys_power_to_fan_speed{450} = 0x50; | ||||||
|    $sys_temp_to_fan_speed{47} = 0x32; |    $sys_power_to_fan_speed{425} = 0x48; | ||||||
|    $sys_temp_to_fan_speed{45} = 0x30; |    $sys_power_to_fan_speed{400} = 0x46; | ||||||
|    $sys_temp_to_fan_speed{30} = 0x28; |    $sys_power_to_fan_speed{375} = 0x44; | ||||||
|  |    $sys_power_to_fan_speed{350} = 0x42; | ||||||
|  |    $sys_power_to_fan_speed{325} = 0x40; | ||||||
|  |    $sys_power_to_fan_speed{300} = 0x36; | ||||||
|  |    $sys_power_to_fan_speed{275} = 0x34; | ||||||
|  |    $sys_power_to_fan_speed{250} = 0x32; | ||||||
|  |    $sys_power_to_fan_speed{225} = 0x30; | ||||||
|  |    $sys_power_to_fan_speed{200} = 0x28; | ||||||
|  |    $sys_power_to_fan_speed{175} = 0x26; | ||||||
|  |    $sys_power_to_fan_speed{150} = 0x24; | ||||||
|  |    $sys_power_to_fan_speed{125} = 0x22; | ||||||
|  |    $sys_power_to_fan_speed{100} = 0x20; | ||||||
|  |  | ||||||
| my $g_current_sys_fan_duty_cycle = 0; | my $g_current_sys_fan_duty_cycle = 0; | ||||||
| my $g_current_cpu_fan_duty_cycle = 0; | my $g_current_cpu_fan_duty_cycle = 0; | ||||||
| my $g_current_sys_temp = 0; |  | ||||||
| my $g_current_cpu_temp = 0; | my $g_current_cpu_temp = 0; | ||||||
|  | my $g_current_sys_power = 0; | ||||||
| my $g_last_set_cpu_temp = 0; | my $g_last_set_cpu_temp = 0; | ||||||
| my $g_last_set_sys_temp = 0; | my $g_last_set_sys_power = 0; | ||||||
|  |  | ||||||
| sub UpdateFanSpeed { | sub UpdateFanSpeed { | ||||||
|   # Gather statistics for fan speed and CPU Temp |   my $current_cpu_temp = `sensors \$(sensors | grep k10temp) | grep 'Tctl:' | cut -c 16-17 | tr -d '\n'`; | ||||||
|   my $ipmi_output = `ipmitool sdr list full -S /opt/ipmi-cache.sdr`; |   my $current_sys_power = `sensors \$(sensors | grep corsairpsu) | grep 'power total:' | cut -c 14-16 | tr -d '\n'`; | ||||||
|   my @vals = split( "\n", $ipmi_output ); |  | ||||||
|  |  | ||||||
|   my $current_cpu_temp = 0; |  | ||||||
|   my $current_sys_temp = 0; |  | ||||||
|   my $cpu_temp_difference = 0; |   my $cpu_temp_difference = 0; | ||||||
|   my $sys_temp_difference = 0; |   my $sys_power_difference = 0; | ||||||
|  |  | ||||||
|   foreach my $value (@vals) { |  | ||||||
|  |  | ||||||
|     if( $value =~ /^(CPU\sTemp).*\s(\d+)\s.*degrees\sC.*/gi ) { |  | ||||||
|       my      $cpu_temp = $2; |  | ||||||
|       $current_cpu_temp = max( $cpu_temp, $current_cpu_temp ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if( $value =~ /^(System\sTemp).*\s(\d+)\s.*degrees\sC.*/gi ) { |  | ||||||
|       my      $sys_temp = $2; |  | ||||||
|       $current_sys_temp = max( $sys_temp, $current_sys_temp ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   } # foreach my $value (@vals) |  | ||||||
|  |  | ||||||
|   $g_current_cpu_temp = $current_cpu_temp; |   $g_current_cpu_temp = $current_cpu_temp; | ||||||
|   $g_current_sys_temp = $current_sys_temp; |   $g_current_sys_power = $current_sys_power; | ||||||
|  |  | ||||||
|   my $desired_cpu_fan_speed = 0x0; |   my $desired_cpu_fan_speed = 0x0; | ||||||
|   my $desired_sys_fan_speed = 0x0; |   my $desired_sys_fan_speed = 0x0; | ||||||
| @@ -90,20 +67,15 @@ sub UpdateFanSpeed { | |||||||
|   my @cpu_temps = keys %cpu_temp_to_fan_speed; |   my @cpu_temps = keys %cpu_temp_to_fan_speed; | ||||||
|   for my $cpu_temp (@cpu_temps) { |   for my $cpu_temp (@cpu_temps) { | ||||||
|     if( $current_cpu_temp >= $cpu_temp ) { |     if( $current_cpu_temp >= $cpu_temp ) { | ||||||
|       # If the current CPU temperature is higher than the temperature enumerated by this hash lookup, |  | ||||||
|       # Then set the desired fan speed (if our value is larger than the existing value) |  | ||||||
|       $desired_cpu_fan_speed = max( $cpu_temp_to_fan_speed{ $cpu_temp }, $desired_cpu_fan_speed ); |       $desired_cpu_fan_speed = max( $cpu_temp_to_fan_speed{ $cpu_temp }, $desired_cpu_fan_speed ); | ||||||
|       # print "The fan speed setting for CPU Temp $cpu_temp *C is $cpu_temp_to_fan_speed{$cpu_temp} % duty cycle\n"; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   my @sys_temps = keys %sys_temp_to_fan_speed; |   my @sys_powers = keys %sys_power_to_fan_speed; | ||||||
|   for my $sys_temp (@sys_temps) { |   for my $sys_power (@sys_powers) { | ||||||
|     if( $current_sys_temp >= $sys_temp ) { |   #for my $sys_temp (@sys_temps) { | ||||||
|       # If the current gPU temperature is higher than the temperature enumerated by this hash lookup, |     if( $current_sys_power >= $sys_power ) { | ||||||
|       # Then set the desired fan speed (if our value is larger than the existing value) |       $desired_sys_fan_speed = max( $sys_power_to_fan_speed{ $sys_power }, $desired_sys_fan_speed ); | ||||||
|       $desired_sys_fan_speed = max( $sys_temp_to_fan_speed{ $sys_temp }, $desired_sys_fan_speed ); |  | ||||||
|       # print "The fan speed setting for GPU Temp $sys_temp *C is $sys_temp_to_fan_speed{$sys_temp} % duty cycle\n"; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -118,15 +90,15 @@ sub UpdateFanSpeed { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   $cpu_temp_difference = $g_current_cpu_temp - $g_last_set_cpu_temp;   |   $cpu_temp_difference = $g_current_cpu_temp - $g_last_set_cpu_temp;   | ||||||
|   $sys_temp_difference = $g_current_sys_temp - $g_last_set_sys_temp; |   $sys_power_difference = $g_current_sys_power - $g_last_set_sys_power; | ||||||
|  |  | ||||||
|   if( (abs $sys_temp_difference) > $min_temp_change ) { |   if( (abs $sys_power_difference) > $min_power_change ) { | ||||||
|     print "(SYS) Temp change of $sys_temp_difference °C, current $g_current_sys_temp °C, fan speed set to $desired_sys_fan_speed %\n"; |     print "(SYS) Power change of $sys_power_difference W, current $g_current_sys_power W, fan speed set to $desired_sys_fan_speed %\n"; | ||||||
|  |  | ||||||
|     $g_last_set_sys_temp = $g_current_sys_temp; |     $g_last_set_sys_power = $g_current_sys_power; | ||||||
|     $g_current_sys_fan_duty_cycle = $desired_sys_fan_speed; |     $g_current_sys_fan_duty_cycle = $desired_sys_fan_speed; | ||||||
|  |  | ||||||
|     `ipmitool raw 0x30 0x70 0x66 0x01 0x01 $desired_sys_fan_speed`; |     `ipmitool raw 0x30 0x70 0x66 0x01 0x00 $desired_sys_fan_speed`; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if(  (abs $cpu_temp_difference) > $min_temp_change ) { |   if(  (abs $cpu_temp_difference) > $min_temp_change ) { | ||||||
| @@ -135,7 +107,7 @@ sub UpdateFanSpeed { | |||||||
|     $g_last_set_cpu_temp = $g_current_cpu_temp; |     $g_last_set_cpu_temp = $g_current_cpu_temp; | ||||||
|     $g_current_cpu_fan_duty_cycle = $desired_cpu_fan_speed; |     $g_current_cpu_fan_duty_cycle = $desired_cpu_fan_speed; | ||||||
|  |  | ||||||
|     `ipmitool raw 0x30 0x70 0x66 0x01 0x00 $desired_cpu_fan_speed`; |     `ipmitool raw 0x30 0x70 0x66 0x01 0x01 $desired_cpu_fan_speed`; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -144,8 +116,6 @@ print "Setting Fan mode to FULL SPEED.\n"; | |||||||
| `ipmitool raw 0x30 0x45 0x01 0x01`; | `ipmitool raw 0x30 0x45 0x01 0x01`; | ||||||
|  |  | ||||||
| while( 1 ) { | while( 1 ) { | ||||||
|   #print "Calling UpdateFanSpeed()...\n"; |  | ||||||
|   UpdateFanSpeed(); |   UpdateFanSpeed(); | ||||||
|   #print "Update Complete - going to sleep for $seconds_to_sleep seconds...\n"; |  | ||||||
|   sleep $seconds_to_sleep; |   sleep $seconds_to_sleep; | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user