BMC的风扇控制 (Fan speed control)

BMC的风扇控制算一个蛮重要的功能,那这个功能包含了"TACH"和"PWM"这两个常用讯号怎么解读,还有最常用的控制演算法"PID(closed loop)"和"Stepwise(openloop)",而Error control ,因为每家做法不同,就不会在这边作介绍

##实作代码是来自Facebook的openBMC

Why and how to do fan speed control ?

在服务器中的风扇是非常高速也耗电的,根据统计在数据中心的运维成本上,电费占了7成,并且如果让风扇长期处在全转状态也会有噪音和耗损度的问题。

目前CPU可以达到单一耗电量200W以上,伴随而来的高热也会使个晶片老化速度加快,当然服務器中的SSD, NIC card, E1.S等装置也是有同样的情况,因此我们希望能根据这些高热的元件温度来决定风扇的转速,达到省电和正常运作的效果

风扇控制的做法如下:

  1. Thermal team(热流部门) 通常会提供一个fan table,里面会详细描述风扇要怎么转
  2. BMC (controller) 会透过PWM讯号去设定风扇转速
  3. 风扇也能透过TACH讯号来回传目前的转速

PWM(Pulse-Width Modulation)

PWM是透过平均电压来传递类比讯号,简单来说就是在一个cycle中,高电为占百分之多少,就表示他要传递的值是多少

例如在一个周期中,如果高电位占25%,低电位占75%,这样表示我们要传递的值是25%,风扇就会转25%

那如果今天我们都一直是high (高电位),这样风扇就会全转,因此在线路图的review过程中,都会注意PWM有没有pull high,避免在BMC更新过程或是死掉后,机器过热

那每个周期的时间是多少呢?  PWM的传递频率会定义在风扇的spec中,每一颗风扇的接收频率有可能会不一样

TACH (Tachometer)

我们可以透过Tach来传递风扇的转速,有修过机械方面的课程就会知道,马达会有n个机械原点,传一圈的话会产生n个pulse,一圈会产生几个pulse也是定义在风扇的spec中

假如今天风扇转一圈会产生两个pulse,我们在一秒内收到1000个pulse,这样表示风扇一秒转了500圈,风扇转速是用rpm(一分钟转几圈)表示的,因此500*60 rpm就是我们要求的值

TACH的讯号大概就长得像底下这样,只要统计一秒钟有几个讯号,就能得到风扇的转速

Picture provided by: http://www.angelfire.com/super/ghettoretta/m90/windowswitch.htm
Picture provided by: http://www.angelfire.com/super/ghettoretta/m90/windowswitch.htm

System Control  

在传统控制(Classical Control )理论中,通常会用有没有feedback 来区分open loop control 和 closed loop control,前者通常就是我们常说的stepwise,后者就是工业控制中广泛使用的PID control,他们的示意图如下,接下来会分别介绍这两个算法的的内容

Open loop control  演算法 (Stepwise)

Open loop,会根据input来直接求出output并输出,不会参考feedback或任何的actuating error

通常thermal team会给BMC一个表(fan table),表示Sensor 温度(input)为多少的时候,风扇转速(output)为多少,大概如下

CPU 温度风扇转速
6040
7050
8070
9080
10098

 实作也相对简单,就一个for 回圈就可以了

# Threshold table
class TTable:
    def __init__(self, table, neg_hyst=0.0, pos_hyst=0.0):
        self.table = sorted(
            table, key=lambda in_thr_out: in_thr_out[0], reverse=True)
        self.compare_fsc_value = 0
        self.last_out = None
        self.neghyst = neg_hyst
        self.poshyst = pos_hyst

    def run(self, value, ctx):
        mini = 0

        if value >= self.compare_fsc_value:
            if math.fabs(self.compare_fsc_value - value) <= self.poshyst:
                return self.last_out

        if value <= self.compare_fsc_value:
            if math.fabs(self.compare_fsc_value - value) <= self.neghyst:
                return self.last_out

        for (in_thr, out) in self.table:
            mini = out
            if value >= in_thr:
                self.compare_fsc_value = value
                self.last_out = out
                return out

        self.compare_fsc_value = value
        self.last_out = mini
        return mini

PID  algorithm

PID分别是proportional(比例) , integral(积分) and derivative(微分) 三个单字的缩写所组成的

我们在做风扇控制的时候,会希望我们的电脑上元件的温度维持在几度,以下会以CPU温度为例子。假设今天我们希望CPU温度维持在60度左右,那60就是set-point (S),而CPU目前温度就是process value (P),那S和P之间的差值就是error value (E) ,他们之间的关系就是E=S-P

PID演算法就是拿求得的E分别做比例运算,积分和微分,如下图所示,算出来的结果会输出PWM去控制风扇

那我们现在来分别聊聊PID这三个算法

Proportional(比例)

比例控制就是依据当前温度来决定风扇转速,将求得的E乘上一个Kp常数

P_{out}=K_p\cdot(S-P)

因为当E 最大,表示P离S很远,风扇的转速需要变化大一点,举例来说

Set-point: 60, Kp = -2

case 1 : CPU 温度 70度 → E=60-70 = -10

case 2 : CPU 温度 90度 → E=60-70 = -30

从两个case当中,我们可以发现当 | E | 越大,风扇需要的转速变化也要很大,所以风扇转速分别就是20 (=-2*-10) 和60 (=-30*-2)

class PID:
    def __init__(self, setpoint, kp=0.0, ki=0.0, kd=0.0, neg_hyst=0.0, pos_hyst=0.0):
        self.last_error = 0
        self.I = 0
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.minval = setpoint - neg_hyst
        self.maxval = setpoint + pos_hyst
        self.last_out = None

    def run(self, value, ctx):
        dt = ctx["dt"]
        # don't accumulate into I term below min hysteresis
        if value < self.minval:
            self.I = 0
            self.last_out = None
        # calculate PID values above max hysteresis
        if value > self.maxval:
            error = self.maxval - value
            self.I = self.I + error * dt
            D = (error - self.last_error) / dt
            out = self.kp * error + self.ki * self.I + self.kd * D
            self.last_out = out
            self.last_error = error
            return out
        # use most recently calc'd PWM value
        return self.last_out

Integral(积分) 

积分控制是根据历史经验来决定风扇转速,将从刚开机到现在的Error value全部相加起来,在乘上Ki

I_{out}=K_i\cdot\sum_{k=0}^tE_k

E0~Ei相加的值越大表示目前的历史经验告诉我们风扇变化要大一点,而相加的值是不会为无限大的,因为E值是有正有负

但I 有个问题 就是overshoot ,在CPU温度已经达到set-point的时候,风扇却仍没减少风量,造成CPU温度持续下降,原因是因为sum(E)仍未趋近于0,这个问题是存在于PID演算法的,大部分的程式码会在这个问题上做work around

底下蓝色的字就是对overshoot所做的workaround

class PID:
    def __init__(self, setpoint, kp=0.0, ki=0.0, kd=0.0, neg_hyst=0.0, pos_hyst=0.0):
        self.last_error = 0
        self.I = 0
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.minval = setpoint - neg_hyst
        self.maxval = setpoint + pos_hyst
        self.last_out = None

    def run(self, value, ctx):
        dt = ctx["dt"]
        # don't accumulate into I term below min hysteresis
        if value < self.minval:
            self.I = 0
            self.last_out = None

        # calculate PID values above max hysteresis
        if value > self.maxval:
            error = self.maxval - value
            self.I = self.I + error * dt
            D = (error - self.last_error) / dt
            out = self.kp * error + self.ki * self.I + self.kd * D
            self.last_out = out
            self.last_error = error
            return out
        # use most recently calc'd PWM value
        return self.last_out

Derivative(微分) 

来到最后的微分,D就是求Error value的变化量,以最近一两次的误差变化量来决定风扇转速

D_{out}=K_d\cdot\frac{E_t-E_{t-n}}{n}

把这次的error和上次的error做相减在除上时间差,就是D值了

代码大概如下: 

class PID:
    def __init__(self, setpoint, kp=0.0, ki=0.0, kd=0.0, neg_hyst=0.0, pos_hyst=0.0):
        self.last_error = 0
        self.I = 0
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.minval = setpoint - neg_hyst
        self.maxval = setpoint + pos_hyst
        self.last_out = None

    def run(self, value, ctx):
        dt = ctx["dt"]
        # don't accumulate into I term below min hysteresis
        if value < self.minval:
            self.I = 0
            self.last_out = None
        # calculate PID values above max hysteresis
        if value > self.maxval:
            error = self.maxval - value
            self.I = self.I + error * dt
            D = (error - self.last_error) / dt
            out = self.kp * error + self.ki * self.I + self.kd * D
            self.last_out = out
            self.last_error = error
            return out
        # use most recently calc'd PWM value
        return self.last_out

风扇控制会用到的概念大概就这些 :)
剩下的部分因为各家做法都不一样,所以就先不讨论

  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Aspeed 2400BMC是一种集成式基板管理控制器(BMC),它旨在为数据中心和云计算环境中的服务器提供远程管理和监控功能。 Aspeed 2400BMC通过提供中央管理和监视来增强服务器的可靠性和可管理性,同时减少维护成本和停机时间。 这种基板管理控制器采用ARM Cortex A9架构,集成了256MB DDR3 / DDR3L内存和128MB闪存存储器,能够提供高性能的远程管理功能。在远程监视和控制方面,Aspeed 2400BMC支持多个远程访问协议,例如IPMI 2.0,Web BMC,SNMP和SSH。这些协议可以确保管理员可以轻松管理、监视和控制服务器,而无需直接与物理服务器进行交互。 此外,Aspeed 2400BMC还具有各种安全功能,例如SSL / TLS加密、AES加密和RSA签名,以确保服务器连接和数据安全。因此,Aspeed 2400BMC是一种非常有用的工具,可以帮助IT管理员在数据中心和云计算环境中更好地管理和监视服务器。 ### 回答2: Aspeed2400BMC是一个嵌入式系统开发板,它的核心是Aspeed AST2400芯片。BMC是指基板管理控制器,它是一种独立的微控制器,用于监控处理器和其他硬件组件。Aspeed2400BMC通常集成在服务器主板中,可以通过网络远程连接到服务器,进行远程管理和维护,例如重置服务器、监控系统健康状况、诊断硬件故障等。Aspeed2400BMC支持多种操作系统和虚拟化解决方案,如Linux、Windows、VMware等。此外,它还具有对高级远程协议(如Redfish、IPMI)的支持,可以实现远程控制和管理,提高系统可靠性和稳定性。因此,Aspeed2400BMC对于企业级和数据中心行业来说具有重要意义,可以提升服务器的运行效率和安全性。 ### 回答3: Aspeed2400BMC是一种基于ARM Cortex-A9处理器的远程管理芯片(BMC)。BMC服务器或网络设备中的一种硬件组件,它可以通过网络控制和监测设备,提供内置监测和管理功能。Aspeed2400BMC芯片能够提供类似于操作系统的环境和API,这些API可以让服务器管理者通过命令行或者Web界面来监测和管理服务器,包括远程访问、远程控制、远程升级等一系列操作。此外,Aspeed2400BMC还具有低功耗、可扩展性和安全性等特点。 Aspeed2400BMC芯片也可以增加服务器的安全性,提供监测和管理功能。它能够控制服务器开机、关机、重启、监测服务器的功耗、温度、风扇转速等硬件信息,并且可以监测服务器的操作系统及其各种组件的状态,通过提供详细的报告和警告通知,及时处理服务器的异常状况,提高服务器可用性。 总之,Aspeed2400BMC是一种功能强大、安全可靠的芯片,可提供广泛的远程管理功能,帮助服务器管理员实现更高效的管理和监测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值