Script to Read I2C Data From Supermicro PSU

I have a Supermicro Chassis that has the I2C/SMBus connector for the power supply. Unfortunately, the motherboard I am using doesn’t have LOM, so I can’t grab PSU data using the normal methods, and the PMBus support seems to not be working either. Fortunately, the PSU exposes an I2C device which exposes temperature and fan speed. These values might not be correct for every PSU – I had to use a combination of spec sheets for similar PSUs and some reverse engineering to get these values.

#!/bin/bash

address=$1

function getValue () {
        local rawVal=$(i2cget -y 0 $address $1 | cut -c3- | tr a-f A-F)
        local decVal=$(echo "obase=10; ibase=16; $rawVal" | bc -l)
        echo $decVal
}

TEMPERATURE=$(getValue 0x09)
FAN1RAW=$(getValue 0x0a)
FAN2RAW=$(getValue 0x0b)
DCSTATUS=$(getValue 0x0c)
ALARMTEMP=$(getValue 0x0d)
FAN1MIN=$(getValue 0x0e)
FAN2MIN=$(getValue 0x0f)

FAN1=$(echo $FAN1RAW '* 60 / 2 / .262' | bc)
FAN2=$(echo $FAN2RAW '* 60 / 2 / .262' | bc)

echo Temperature: $TEMPERATURE
echo Temp Max: $ALARMTEMP
echo Fan1 RPM: $FAN1
echo Fan2 RPM: $FAN2
echo Fan1 Raw: $FAN1RAW
echo Fan2 Raw: $FAN2RAW
echo Fan1 Min: $FAN1MIN
echo Fan2 Min: $FAN2MIN
echo DC Status Raw: $DCSTATUS


Example:

# ./psu.sh 0x38
Temperature: 33
Temp Max: 75
Fan1 RPM: 4122
Fan2 RPM: 5038
Fan1 Raw: 36
Fan2 Raw: 44
Fan1 Min: 0
Fan2 Min: 35
DC Status Raw: 1

The single argument is the i2c address of the PSU you want to read from. They seem to usually be in the 0x30-0x3f or 0x70-0x7e range. Systems with redundant power supplies will have two separate addresses. In addition, you may need to edit it if your system has multiple i2c buses (change i2cget -y 0 to i2cget -y 1 for example).

Disclaimer: reading/writing random i2c devices can hang your system or cause other issues.

Leave a Reply