第12课 霍尔模块、外部中断与millis()计时

我是潘,曾经是个工程师。这是为 Ardui.Co 制作的 “Arduino 公开课” 系列的入门教程。第5.1课介绍了温控风扇,这次我们要通过中断函数并使用霍尔传感器测量风扇速转。有任何疑问请在评论区提出,我会逐一回答。

霍尔传感器是一种磁感应元件,只要有磁场(磁铁、金属物体、电感)接近,就会产生相应的电平信号。霍尔传感器应用很广,电机/车轮测速、电流测量、运动与接近检测等。汽车、航天、工业制造等领域都是不可或缺的元件。

常见的霍尔传感器模块分为两种,一种是线性模块,根据磁感应强度输出相应的模拟量(电压),另一种是开关型模块,磁感应达到一定强度,输出一个脉冲信号。另外,线性模块也可以采用数字通信,只不过中间加入了 ADC 模块,主要用在需要高精度、高稳定性的测量场合。

这是最常见的霍尔传感器模块,采用A3144E霍尔传感器原件,同时提供了模拟和数字信号输出。测速原理是,在转盘上设置磁感应点,每次磁场穿过传感器时,输出一个脉冲信号:

图片来源:wikipedia

传感器的接线很简单,除了两根电源线,将 Vin 接入 Arduino 的 D3(3号数字端口)即可,如果出现传输信号不稳定的情况,可以接一只 5K 上拉电阻。

在风扇转盘的边缘贴上1颗小磁铁,然后将传感器固定在上方,记录每秒圈数乘以60,即可换算出 rpm (每分钟转速)。

速度是距离/次数与时间的比值,因此程序要设计两个变量,一个计时,另一个计数

计时用到 millis(),该函数的作用是记录系统累计运行时间,返回毫秒(值类型为 unsigned long),最长纪录为50天,超时后返回0秒。如果要更精确,可以用micro()返回微秒。

millis() 返回的是累计时间,但我们要测量输出的是每一秒内的旋转次数,怎么处理呢?其实,只要设置一个临时变量,标记下一秒的时间点,当 millis() 到达这个时间点后,输出 milli() 至 millis() + 1000ms 之间的触发次数即可。

同时,我们采用外部中断函数计数。当传感器被磁铁触发,程序中断,执行计数函数,记录一次。

使用 digitalPinToInterrupt(interruptPin) 原因是提高程序的兼容性,只要修改interruptPin 即可在不同 Arduino 版本上映射对应的中断端口号。

特别注意的是,触发外部中断函数的模式,必须是 RISING 或者 FALLING。如果是CHANGE,传感器每一次触发都会产生“高 – 低”、“高 – 低”两个信号,也就是说函数会被触发两次;如果是LOW,磁铁穿过传感器的过程中,外部中断函数会被连续触发,这个时间内 count() 会多次计数;

上面程序使用未来的时间点 millis() + 1000ms 来控制中断,但还有一种算法,就是当前时间去比较过去的时间,将时间范围控制在1000ms以内。

两个程序效果是完全一样的,但从理解上,一个是用未来时间点来规定测量时间,一个是用过去时间点。

大部分 PC 散热风扇内置了霍尔传感器,我们用示波器测量第3个引脚:

每 10~12 ms 出现一个波谷,转速约为 900~1000rpm,与刚才测量的结果有一些出入。(请思考为什么?答案会在评论区介绍)

降低刷新速度或者增加触发点,都能提高测量的分辨率。比如,对于转速特别低的设备,每秒不到1圈,我们将刷新率降到5秒,分辨率就能提高至  60rpm / 5  = 12rpm。也可以增加 n 个磁感应点,每次触发低电平信号,则记录 1/n 圈,分辨率也相应提高到1/n 。

现在,我们通过外部传感器产生中断请求,然后来计数。那么,是否可以由内部计时,定时来触发中断?答案是肯定的,上面两个程序就使用了内部中断的一种——程序定时器,它们以 millis() 计时,然后在规定的时间点上输出结果。

但是,millis() 计时是十分不精准的,因为,虽然程序中断也是内部中断的一种,但是在各种中断的优先级别中,跟普通程序没有任何区别,外部中断会打断 millis() 的计时。尽管外部中断的时间非常短,但其执行时间不会被记入millis()。

后面将深入介绍 Arduino 的内部中断和硬件定时器的使用。

5 thoughts on “第12课 霍尔模块、外部中断与millis()计时

  1. YODIAN

    版主,想用红外线感应器去感应风扇的转速和转动次数,红外线感应器数量是10个,请问程式部分要怎么写?

    Reply
    1. panft Post author

      为什么要用10个红外感应?一个就可以。风扇5页面切割红外线计数5,将计数除以5即可。如果为了准确计数,用10个传感器,最简单的是每次测量求中位数,但不够精确。具体的算法很多,可以参考一下各种滤波算法。当你知道用什么滤波算法时,代码实现就很简单,无非就是加减乘除、求积分极限之类。

      Reply
  2. YODIAN

    arduino uno板,要同时测量多个风扇会使用多个红外线感应,版主上面的是测量单一,所以想知道多个的写法运算

    Reply
    1. panft Post author

      不一定要用中断,只要触发一个高/低电平,然后在一段时间内计数。

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *