在写PWM风扇驱动之前:如何透过FG信号,获取风扇转速?

简介: 本文介绍了如何通过PWM风扇的FG信号线获取风扇转速的方法,包括风扇规格的解读、FG信号的公式推导、软件算法的解析,以及在全志H713平台上实现风扇转速获取的驱动代码示例。

一、前言

  • PWM风扇也是日常SOC智能设备开发中常见的外围小设备,而对于驱动工程师而言,主要工作就是实现风扇的控制驱动,除了设定风扇的速度之外,还要获取风扇的转速信息,而PWM风扇就
    是一个可以通过FG信号线反馈转速信息的设备。
  • 本文即基于全志H713平台,介绍一下FG信号线的用法,以及PWM风扇转速获取的算法。

二、风扇规格

2.1 线序

  • 从风扇规格书中,可得知YELLOW黄色线为FB线
  • 根据规定线序,接好线
    在这里插入图片描述

2.2 FG 信号说明

  • 下图就是风扇规格书中的FG信号的说明,可以看到最下方有四个公式
  • 对于新手而言,最开始看到下面公式会有些疑惑,后续我们可以猜猜(推导)下公式的具体含义
    在这里插入图片描述

三、FG公式推导

  • FG 信号是由风扇,根据其转速反馈的一个方波频率信号,从图中可知,风扇转一圈的周期 T=T1+T2+T3+T4
  • 假设方波的频率为 f, 则 f = 1 / T
  • N = R.P.M ,此处的R.P.M代表的是每分钟的转速,例如风扇每分钟转60圈,则N = R.P.M = 60 rpm,所以N就是转速
  • 下面就是一些公式的推导和验证,通过自己推导,就可以 理解最终 N = FG * 30 的含义
• N=R.P.M  电机铭牌中_R.P.M_就是指电机的额定转速,单位是:转/分。
• T = T1+T2+T3+T4, 可知 T 代表周期
• N / 60秒 = 每秒钟 n 转, 即 HZ (用 f 表示) 
• 60秒 / N = 1 / n = 1 / f   = T 周期
• 如按上升沿次数计算,一个周期里面有 2个上升沿,如1秒钟内有 a 个上升沿,a其实就是FG,我们可以通过下面来验证:
  • 则 f = a / 2 =>  T = 2 / a  ==> T = 2 / FG  ==>  FG = 2 / T = 1 / (2T) 
  • 则 频率 f = 1 / T , 转速 N = fx60秒 =  60秒 x  (1/ T) = 60 / ( 2/ FG) = FGx30 , 即 N = FGx30
  • 综上,可得知FG = 1秒内出现的上升沿的次数,即上升沿中断的次数,
  • 之后可通过 N = FG x 30 得出风扇的R.P.M, 每分钟转速

四、软件算法解析

  • 此软件算法已集成在全志公版代码之中,此处仅贴出必要部分做讲解

4.1 HZ 的概念

  • Jiffy是在中声明的内核时间单位。
  • 为了理解Jiffy,需要引入一个新的常量HZ,它是jiffies在1s内递增的次数,每个增量被称为一个Tick。
  • 在全志内核中 #define HZ 1000 ,它代表的含义是1秒内有1000个Tick

4.2 算法

  • 从FG信号的原理,我们如何进行编码呢?
  • 答案是,我们只需要统计1秒内,或者说单位时间内 FG信号的上升沿次数就可以了,也就是利用中断触发的次数来统计,每次有FG的上升沿到来时,就将 nFgCount + 1
  • 比如,设定1个定时器,这个定时器每秒钟触发1次,每次触发,都读取nFgCount ,将其除以2就是频率f
  • 下面,演示的就是这个算法

//(1)FG信号的中断处理函数,每次给自己+1
static irqreturn_t pulse_handler(int irq, void *dev_id)
{
   
   
    struct pwm_fan_ctx *ctx = dev_id;
        //每次FG引脚的中断触发,让pluses + 1
    atomic_inc(&ctx->pulses);

    return IRQ_HANDLED;
}

//(2)定时器的中断处理函数,每次触发,先获取pulse,用完后又将ctx->pulses归零,方便统计单位时间内次数
static void sample_timer(struct timer_list *t)
{
   
   
    struct pwm_fan_ctx *ctx = from_timer(ctx, t, rpm_timer);
    unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start);
    int pulses;

    if (delta) {
   
                   
        pulses = atomic_read(&ctx->pulses);//1秒内发生的脉冲次数
        atomic_sub(pulses, &ctx->pulses);// 归零

                //此处delta的理论值应该是1000ms,但会有些小小误差
                //可见此处,最终计算每分钟转速的公式: RPM=FGx30
        ctx->rpm = (unsigned int)(pulses * 1000 * 60) /
            (ctx->pulses_per_revolution * delta);

        ctx->sample_start = ktime_get();
    }

    mod_timer(&ctx->rpm_timer, jiffies + HZ);//设置+HZ后超时,继续触发sample_timer函数
}


//(3)最后,来看一下这个风扇设备的Probe过程,其中绑定了中断和中断处理函数,初始化了计时器
static int pwm_fan_probe(struct platform_device *pdev)
{
   
       
        …… 略 ……
    //从DTS中解析中断 FG信号线的中断,interrupts 
    ctx->irq = platform_get_irq_optional(pdev, 0);
    if (ctx->irq == -EPROBE_DEFER)
        return ctx->irq;
        …… 略 ……
        timer_setup(&ctx->rpm_timer, sample_timer, 0);//初始化定时器和定时函数
        …… 略 ……

    of_property_read_u32(dev->of_node, "pulses-per-revolution", &ppr);
    ctx->pulses_per_revolution = ppr;//获取一个周期有几个pulses,PWM风扇一般为2个,具体见规格书
    if (!ctx->pulses_per_revolution) {
   
   
        dev_err(dev, "pulses-per-revolution can't be zero.\n");
        return -EINVAL;
    }

    if (ctx->irq > 0) {
   
   
        ret = devm_request_irq(dev, ctx->irq, pulse_handler, 0,
                       pdev->name, ctx);//绑定FG中断响应函数
        if (ret) {
   
   
            dev_err(dev, "Failed to request interrupt: %d\n", ret);
            return ret;
        }
        ctx->sample_start = ktime_get();//初始化开始时间
        mod_timer(&ctx->rpm_timer, jiffies + HZ);//定时器开始计时,+HZ 后响应定时中断
    }
        …… 略 ……

        //此处,将fan注册为 cooling device, 并提供了查询和设置当前风扇转速等级的函数,供Thermal使用
       ctx->pwm_fan_state = ctx->pwm_fan_max_state;
    if (IS_ENABLED(CONFIG_THERMAL)) {
   
   
        cdev = devm_thermal_of_cooling_device_register(dev,
            dev->of_node, "pwm-fan", ctx, &pwm_fan_cooling_ops);
        if (IS_ERR(cdev)) {
   
   
            ret = PTR_ERR(cdev);
            dev_err(dev,
                "Failed to register pwm-fan as cooling device: %d\n",
                ret);
            return ret;
        }
        ctx->cdev = cdev;
        thermal_cdev_update(cdev);
    }
}

五、篇尾

谢谢关注~

相关文章
交流电路理论:峰值、平均值和RMS值的计算公式
除了频率和周期之外,AC 波形的一个关键属性是振幅,它表示交变波形的最大值,或者更广为人知的是峰值。
13547 1
交流电路理论:峰值、平均值和RMS值的计算公式
|
Web App开发 关系型数据库 RDS
电源缓启动(软起动)原理分享
该文讨论了电源的缓启动(软起动)技术,主要是为了解决热插拔时的电源振荡和冲击电流问题。缓启动电路有两个主要功能:防抖动延时上电和控制输入电流上升斜率。文章提到了电压斜率型缓启动电路,通过MOS管和相关电阻、电容元件实现延迟和电流控制。电路设计中,MOS管的栅极电压和漏源电流的变化决定了电流上升斜率,从而限制热插拔时的冲击。
1046 0
|
IDE Linux 测试技术
Rockchip系列之深度分析CAN接口系列(1)
Rockchip系列之深度分析CAN接口系列(1)
913 2
|
缓存 移动开发 JavaScript
PCIe 参考时钟架构 (Refclk Architecture)
PCIe 参考时钟架构 (Refclk Architecture)
7216 0
PCIe 参考时钟架构 (Refclk Architecture)
23【办公软件】WPS2019打开时报错:安装Office自定义项,安装期间出错
左下角【开始】按钮,点击【运行】,在对话框输入【regedit】打开注册表
2760 0
|
存储 并行计算 Linux
国产之路:复旦微FMQL调试笔记1:PS网口
FPGA,全程现场可编程门阵列,是指一切通过软件手段更改、配置器件内部连接结构和逻辑单元,完成既定设计功能的数字集成电路。换个简单通俗的介绍方式,就好比一个全能的运动员,FPGA就是这么神奇的可以通过设定而实现各种复杂的功能电路。
2756 0
国产之路:复旦微FMQL调试笔记1:PS网口
|
6月前
|
存储 安全 开发工具
如何安全删除GitHub中的敏感文件?git-filter-repo操作全解析
当敏感文件误传至GitHub时,需使用`git-filter-repo`彻底删除文件及历史记录。本文详解操作步骤与注意事项,如备份、强制推送、团队协作处理,并建议搭配高安全性云服务,防止数据泄露,保障代码仓库安全。
477 1
|
编解码 算法
掌握PWM:STM32F103实现PWM控制直流电机小风扇
PWM,即脉冲宽度调制(Pulse Width Modulation),是一种广泛应用于电子和电机控制领域的信号编码方法。PWM的核心思想是通过改变数字信号的脉冲宽度来模拟模拟信号的幅度变化,从而达到控制输出功率的目的。
2605 0
|
人工智能 Java 程序员
一文彻底搞明白电路图和原理图
本文介绍电路图的基本构成、作用及类型,帮助理解电路原理和实际应用。元件符号、连线、节点和注释说明是电路图的核心要素,通过原理图、方框图、装配图和印板图,可以清晰展示电路结构和工作原理。君志所向,一往无前!
7640 0
|
移动开发 C语言
C语言:&&和&、||和|有什么区别
在C语言中,&&和||是逻辑运算符,分别表示逻辑与(AND)和逻辑或(OR),它们用于连接两个布尔表达式,只有当两边都为真时&&返回真,||在至少一边为真时返回真;&和|是位运算符,对应地进行位级的与、或操作,它们对操作数的二进制位进行逐位处理。&&和||具有短路特性,而&和|没有。
15305 1