上一回,我们学习了霍尔传感器的原理和简易使用方法。这次我们将试着用这霍尔传感器制作可在自行车等中使用的简易速度计。
此次的电子工程配方
完成为止的大致时间标准:60分钟
必要零件
- Arduino主体(Arduino UNO R3 或者 Arduino UNO SMD Rev3)
http://www.ameya360.com/product/960218 - 罗姆传感器评估套件
http://www.rohm.com.cn/sensor-shield-support - 3位7段LED(LB-303MK)
- 8位移位寄存器(SN74HC595N)
- 电阻器(220Ω) ×3
目 录
- 考虑简易速度计的规格
- 7段LED的复习~移位寄存器的使用方法
- 简易速度计的程序
- 总结
1.考虑简易速度计的规格
首先,我们应考虑速度计的规格。以安装在自行车上为例来考虑时,是在前轮或后轮的轮胎框架上安装霍尔传感器,在轮胎侧安装磁铁。其原理是,当轮胎旋转时,磁铁接近霍尔传感器时会检测到转动1圈。此时,请一边观察Arduino的串行监视器一边对磁铁与霍尔传感器的距离进行调整。接着,Arduino与传感器评估套件主体可安装在自行车的车把附近,以便在确认7段LED所显示的速度的同时进行骑行。
大致的功能设想应该就是这样。

图1 速度计的规格
2.7段LED的复习~移位寄存器的使用方法
这次,我们使用7段LED来进行速度显示。关于7段LED的使用方法,这次作为更简单的使用方法,使用移位寄存器来进行7段LED的显示。
移位寄存器是什么?
简单来说,移位寄存器就是可以增加Arduino的引脚个数的IC芯片。例如在第8回的7段LED显示电路中,要使7段LED的各LED都发光,需要在Arduino侧分别使用相应的引脚。这时,剩下的数字引脚较少,只有0、1、9、10、12,需要进行其他扩展时,就会在开发方面缚手缚脚。这种情况下,就轮到移位寄存器出场了。

图2 第8回的7段LED的显示电路
此次使用的是名为SN74HC595N的8位移位寄存器。说到8位,请简单将其视为可进行8路输出。

照片1 8位移位寄存器(SN74HC595N)
移位寄存器的原理
根据数据表确认使用方法。

图3 SN74HC595N的引脚说明
其原理是使用Arduino时,从Arduino对带红色的SER、RCLK、SRCLK引脚发送特定的信号后,会从QA~QH发送与信号对应的输出。详细的数据流程原理是,将要对QA~QH输出的信号从Arduino对SER引脚在8位中的第1位(通过MSB/LSB更改)输入数据(HIGH or LOW),对SRCLK引脚发送HIGH信号并移动至8位中的第2位~在这一流程对全部8位重复输入数据完成的阶段,将RCLK设为HIGH后,从QA~QH输出数据。
这一流程要通过Arduino的程序安装并进行控制非常麻烦,因此Arduino中备有名为shiftOut()的函数。通过使用该函数,可以轻松使用移位寄存器。
shiftOut(dataPin, clockPin, bitOrder, value)
- dataPin – SER信号引脚
- clockPin – SRLK信号引脚
- bitOrder – 指定是"MSBFIRST"(从最高位发送)还是"LSBFIRST"(从最低位发送)
- value – 要发送的数据
让我们利用移位寄存器,从Arduino发送使7段LED的各LED都显示的"01000111"等数据,在7段LED上显示任意的数字。具体操作如图4所示,将移位寄存器的QA~QH的输出引脚与7段LED的a~g、D.P一一对应连接,非常简单易懂。value为"01000111"这样的数据时,会从移位寄存器对7段LED实际发送"0-QH / 1-QG / 0-QF /0-QE,0-QD,1-QC,1-QB,1-QA"的数据,7段LED则据此进行显示。

图4 移位寄存器与7段LED的连接方法
实际的电路如下所示。7段LED的配线始终会变多这一点稍稍难以理解,但可以理解的是Arduino中使用的引脚数在变少。

图5 移位寄存器与7段LED的电路

照片2 7段LED与移位寄存器(照片中的配线稍有改变)
下述程序是将移位寄存器的8位数据从1到128全部发送的测试程序。实际运行后,可以确认7段LED的对应部分依次发光。
程序 – 移位寄存器的测试程序
//移位寄存器用 #define SCK_PIN 13 #define RCK_PIN 10 #define SI_PIN 11 #define DP1 2 #define DP2 3 #define DP3 4 void setup(){ pinMode(SCK_PIN, OUTPUT); pinMode(RCK_PIN, OUTPUT); pinMode(SI_PIN, OUTPUT); pinMode(DP1, OUTPUT); pinMode(DP2, OUTPUT); pinMode(DP3, OUTPUT); } void loop() { digitalWrite(DP1, HIGH); //第1位不显示 digitalWrite(DP2, HIGH); //第2位不显示 digitalWrite(DP3, LOW); //显示第3位 //按顺序发送移位寄存器的8位信号(1、0的2种模式数据8位 =>; 2的8次方 = 128) for(int i = 0; i < 128; i++){ SEGMENT_OUT(i); } } void SEGMENT_OUT(int num){ digitalWrite(RCK_PIN, LOW); shiftOut(SI_PIN, SCK_PIN, MSBFIRST, num); digitalWrite(RCK_PIN, HIGH); delay(20); }
3.基于霍尔传感器的简易速度计的程序
在了解移位寄存器的使用方法和复习7段LED之后,我们开始实际设计速度计的程序。具体的程序流程是以按一定间隔(此次为1秒钟)获取的转速为基础,计算时速的程序。假设为每转1圈前进0.5m时,1秒钟检测到2次时为0.5m×2次 = 前进1m。将其换算为1小时即可求出时速。
程序的关键在于,对7段LED就像之前也操作过的那样,通过在短时间内切换显示第1~3位来实现3位显示,和获取millis()函数处理时机的时间,按一定时间计算速度并在7段LED上显示的原理。
程序 – 简易速度计的程序
#include <BD7411.h> long _beforetime = 0; //传感器用 int _hallout_pin = 0; // use D0 pin int _cnt = 0; bool _flg = false; unsigned long _starttime = 0; BD7411 bd7411; //移位寄存器用 #define SCK_PIN 13 #define RCK_PIN 10 #define SI_PIN 11 //位数控制用 #define DP1 2 #define DP2 3 #define DP3 4 // float _meter = 1; //每转1圈的距离数 float _speedVal = 0; //7段LED的数字排列 const int digits[10] = { 0b00111111, // 0 0b00000110, // 1 0b01011011, // 2 0b01001111, // 3 0b01100110, // 4 0b01101101, // 5 0b01111101, // 6 0b00100111, // 7 0b01111111, // 8 0b01101111, // 9 }; void setup(){ Serial.begin(9600); while (!Serial); bd7411.init(_hallout_pin); pinMode(SCK_PIN, OUTPUT); pinMode(RCK_PIN, OUTPUT); pinMode(SI_PIN, OUTPUT); pinMode(DP1, OUTPUT); pinMode(DP2, OUTPUT); pinMode(DP3, OUTPUT); _beforetime = millis(); } void loop() { int hallout; hallout = bd7411.readoutpin(); if (hallout == 0 && _flg == false) { if(_starttime == 0){ _starttime = millis(); } Serial.print("BD7411G Magnet field Detect! - "); _flg = true; _cnt++; Serial.print(hallout); Serial.print("-"); Serial.println(_cnt); } else{ _flg = false; } //超过从上一次闪烁开始的经过时间(1秒)后刷新速度 if (millis() - _beforetime > 1000) { _beforetime = millis(); //计算速度并在7段LED上显示 float sp = _meter * _cnt * 60*60 / 1000; //速度=距离(_meter*_cnt)÷时间(60秒×60分)/1000(为了做成仪表单位) _speedVal = sp * 10; Serial.print("SPEED:"); Serial.println(_speedVal); _cnt = 0; } SEGMENT_OUT((int)_speedVal); delay(1); } void SEGMENT_OUT(int num){ for(int i = 0; i < 3; i++){ int disp_num = 0; int dots = 0; //第1位的处理 if(i==0){ disp_num = NumParse(num,1); digitalWrite(DP1, LOW); digitalWrite(DP2, HIGH); digitalWrite(DP3, HIGH); } //第2位的处理 else if(i==1){ dots = 0b10000000; disp_num = NumParse(num,2); digitalWrite(DP2, LOW); digitalWrite(DP1, HIGH); digitalWrite(DP3, HIGH); } //第3位的处理 else if(i==2){ disp_num = NumParse(num,3); digitalWrite(DP3, LOW); digitalWrite(DP1, HIGH); digitalWrite(DP2, HIGH); } digitalWrite(RCK_PIN, LOW); shiftOut(SI_PIN, SCK_PIN, MSBFIRST, digits[disp_num]+dots); digitalWrite(RCK_PIN, HIGH); delay(3); } } //将3位逐一分解的函数 int NumParse(int Number,int s){ int val[3]; val[0] = (Number % 10); Number /= 10; // 取出第1位 val[1] = (Number % 10); Number /= 10; // 取出第2位 val[2] = (Number % 10); Number /= 10; // 取出第3位 return val[s-1]; }
可以看出接近或远离磁铁后,速度会随之刷新。
装到自行车上试试
准备完成后,将其实际装上自行车。此次,将以100日元均价购买的强力磁铁安装在自行车的后轮上(轮胎的框架是金属的,因此直接吸住磁铁)并固定,以使磁铁与传感器接近。磁铁与传感器的距离需要稍稍调整,因此用遮蔽胶带固定传感器。
传感器固定完成后,实际转动轮胎以测试传感器有无反应。快速旋转时,确认到显示的数值发生变化!
基于霍尔传感器的简易速度计的总结
此次,我们使用霍尔传感器制作了简易速度计。使用传感器评估套件时,或不使用时,随着制作设备的经验增加,发现Arduino的引脚数太少的情况会越来越多。这时,通过使用移位寄存器等方法,可以制作扩展性更强的设备。下次,将继续介绍传感器评估套件中的其他传感器!