Article Index


So I came up with the following, which may or may not be worth a hill of beans.

#!/bin/bash

# AMD processors do not report a physical temperature. Can we generate
# something reasonable for our conky?

#******************************************************************************
# ***** From lm-sensors wiki at their website: ********************************
#******************************************************************************

# coretemp returns unrealistic values
#
# The temperature value returned by the coretemp driver isn't absolute. It's a
# thermal margin from the critical limit, and the greater the margin, the worse
# the accuracy. It isn't really returning degrees Celsius. At high temperatures,
# the (small) thermal margin is almost expressed in degrees Celsius, but at low
# temperature, the (high) thermal margin is no longer expressed in actual
# degrees Celsius.
#
# So, if the temperature value reported by coretemp is unrealistically low, all
# it means is that you are far away from the critical limit so your systems are
# running totally fine and cool and you don't have to worry at all.
# Unfortunately, there is no way to improve the readings, this is a hardware
# limitation.
#
# Additionally, the critical limit value may be wrong on come CPU models. We
# may be able to address this problem over time, but again it's not really a
# problem in the first place. All that really matters is how far the
# measurement is from that limit. If the difference is above 40 pseudo degrees
# Celsius (again these are not real degrees Celsius!) then you're safe.
#******************************************************************************


#******************************************************************************
# ***** From the k10temp module documantation: ********************************
#******************************************************************************

# There is one temperature measurement value, available as temp1_input in
# sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree.
# Please note that it is defined as a relative value; to quote the AMD manual:
#
# Tctl is the processor temperature control value, used by the platform to
# control cooling systems. Tctl is a non-physical temperature on an
# arbitrary scale measured in degrees. It does _not_ represent an actual
# physical temperature like die or case temperature. Instead, it specifies
# the processor temperature relative to the point at which the system must
# supply the maximum cooling for the processor's specified maximum case
# temperature and maximum thermal power dissipation.
#
# The maximum value for Tctl is available in the file temp1_max.
#
# If the BIOS has enabled hardware temperature control, the threshold at
# which the processor will throttle itself to avoid damage is available in
# temp1_crit and temp1_crit_hyst.
#******************************************************************************

# For those of you following along, I'm going to make a few of very stupid
# and very wrong assumptions to see if I can get a more reasonable and workable
# CPU temp reading at a glance:
#
# 1. Since this reading is supposed to drive cooling, assume that means
# how fast the fan runs
# 2. Assume the relationship to the fan speed is linear.
# 3. Assume that at max fan speed, the k10temp is roughly the same as the
# physical temp

# IF YOU USE THIS AND BREAK YOUR SYSTEM, IT'S ON YOU!

# Here are some basic values I'm assuming from observing my own system --
# an FX-8350 cooled by a monster Noctua HSF.
# These will take a bit of observation for another system.
idle_correction=20
no_correction=0
min_fanspeed=500
max_fanspeed=1200
speed_span=$(( ($max_fanspeed - $min_fanspeed) ))

# Get the CPU temp and HSF fan speed from sensors. This may take some fiddling
# depending on your motherboard.
cpu_temp=$(sensors k10temp-pci-00c3 | grep 'temp1' | awk -F'.' '{print $1}'| awk -F'+' '{print $2}')
fanspeed=$(sensors it8728-isa-0228 | grep 'fan1' | awk '{print $2}' | cut -c1-4)

# If fanspeed<=500, factor = 1, so correction = idle_correction
# If fanspeed>=1200, factor = 0, so correction = 0
# Otherwise, calculate correction

if [ $fanspeed -le $min_fanspeed ]
     then
     # At idle, add the idle correction
     final_temp=$(( ($cpu_temp + $idle_correction) ))
     echo $final_temp
elif [ $fanspeed -ge $max_fanspeed ]
    then
     # At max fan speed, assume k10temp approaches physical temp
     final_temp=$cpu_temp
     echo $final_temp
else
     # Interpolate a correction based on fan speed
     fan_diff=$(( ($max_fanspeed - $fanspeed) ))
     # A little trick here, since integer division returning values less than
     # 1 gives 0.
     correction_factor=$(( (($fan_diff) * 100 )/ ($speed_span) ))
     correction=$(( ($idle_correction * $correction_factor) ))

     # And now we need a useful integer.
     correction=$(( ($correction / 100) ))

     # Calculate the corrected temperature
     final_temp=$(( ($cpu_temp + $correction) ))
     echo $final_temp
fi