HC-04是树莓派上用的比较广泛的超声波传感器,可以用来测量设备和物体之间的距离。可惜网上的资料很少有针对Windows 10的,几乎都是Python和C在Linux上的例子。
hackster.io上有一篇用HC-04做雷达的例子,但是设计的部件太多了,对单纯学习HC-04传感器的使用来说这个例子比较复杂。搜了一圈,英文资料最好的是这篇:http://www.guruumeditation.net/en/digital-io-with-windows-10-iot-raspberry-pi-2-and-the-ultrasonic-ranging-module-hc-sr04/ 国内中文资料介绍Windows 10上HC-04传感器的文章似乎还没有,所以就简单总结一下步骤。
一、物理连接
对于没有多少物理和电子知识基础的人(比如我)来说,第一步连线是比较难的。很多文章都一笔带过说“这很简单,没啥好说的”,尼玛。。。
其实要解决的问题是这样的:HC-04需要接入5V电源才能工作,它的响应输出是ECHO,这个要接到树莓派的GPIO端口上使用,但是ECHO的输出是5V,GPIO只能接受3.3V左右的输入,5V会烧掉树莓派,所以必须加电阻来爆一下,至于怎么加,我总结了一个最直观的示意图,如下:
简单来说,你需要2个电阻,一个4.7K欧,一个10K欧。为什么要这样呢,是因为根据电压分配定律,如上图所示,4.7K和10K电阻的组合可以得到3.4V的输出。这对GPIO来说是可以接受的。如果你有别的值的电阻可以让输出正好3.3V也是可以的。我在淘宝买的常用电阻包没有办法配出正好3.3V,所以只能用4.7K和10K的组合。(上图的4.3K R1标错了)
然后,传感器和树莓派的连接也可以看上面这张图来连。VCC接树莓派的5V输出,TRIG接GPIO 23,ECHO通过一个4.3K电阻之后接GPIO 24,GND接Ground。
二、代码
爆代码就可以用一个现成的类,这是国外的 http://www.guruumeditation.net/en/digital-io-with-windows-10-iot-raspberry-pi-2-and-the-ultrasonic-ranging-module-hc-sr04/ 这篇文章里抄过来的。(稍微改进过)
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Windows.Devices.Gpio; namespace HC04 { public class HC04UltrasonicDistanceSensor { private GpioPin Pin_Trig, Pin_Echo; public double? Distance { get; } /// <summary> /// Available Gpio Pins. Refer: https://ms-iot.github.io/content/en-US/win10/samples/PinMappingsRPi2.htm /// </summary> public enum AvailableGpioPin : int { /// <summary> /// Raspberry Pi 2 - Header Pin Number : 29 /// </summary> GpioPin_5 = 5, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 31 /// </summary> GpioPin_6 = 6, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 32 /// </summary> GpioPin_12 = 12, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 33 /// </summary> GpioPin_13 = 13, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 36 /// </summary> GpioPin_16 = 16, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 12 /// </summary> GpioPin_18 = 18, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 15 /// </summary> GpioPin_22 = 22, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 16 /// </summary> GpioPin_23 = 23, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 18 /// </summary> GpioPin_24 = 24, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 22 /// </summary> GpioPin_25 = 25, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 37 /// </summary> GpioPin_26 = 26, /// <summary> /// Raspberry Pi 2 - Header Pin Number : 13 /// </summary> GpioPin_27 = 27 } public HC04UltrasonicDistanceSensor(AvailableGpioPin trigPin, AvailableGpioPin echoPin) { var gpio = GpioController.GetDefault(); Pin_Trig = gpio.OpenPin((int)trigPin); Pin_Trig.SetDriveMode(GpioPinDriveMode.Output); Pin_Trig.Write(GpioPinValue.Low); Pin_Echo = gpio.OpenPin((int)echoPin); Pin_Echo.SetDriveMode(GpioPinDriveMode.Input); } public double GetDistance() { var mre = new ManualResetEventSlim(false); //Send a 10µs pulse to start the measurement Pin_Trig.Write(GpioPinValue.High); mre.Wait(TimeSpan.FromMilliseconds(0.01)); Pin_Trig.Write(GpioPinValue.Low); var time = PulseIn(Pin_Echo, GpioPinValue.High, 500); // multiply by speed of sound in milliseconds (34000) divided by 2 (cause pulse make rountrip) var distance = time * 17000; return distance; } private double PulseIn(GpioPin pin, GpioPinValue value, ushort timeout) { var sw = new Stopwatch(); var swTimeout = new Stopwatch(); swTimeout.Start(); // Wait for pulse while (pin.Read() != value) { if (swTimeout.ElapsedMilliseconds > timeout) return 3.5; } sw.Start(); // Wait for pulse end while (pin.Read() == value) { if (swTimeout.ElapsedMilliseconds > timeout) return 3.4; } sw.Stop(); return sw.Elapsed.TotalSeconds; } } }
使用方法如下:
public sealed partial class MainPage : Page { public HC04UltrasonicDistanceSensor Hc04UltrasonicDistanceSensor { get; set; } private DispatcherTimer _timer; public MainPage() { this.InitializeComponent(); Hc04UltrasonicDistanceSensor = new HC04UltrasonicDistanceSensor( HC04UltrasonicDistanceSensor.AvailableGpioPin.GpioPin_23, HC04UltrasonicDistanceSensor.AvailableGpioPin.GpioPin_24); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); _timer = new DispatcherTimer(); _timer.Tick += (sender, o) => { var distance = Hc04UltrasonicDistanceSensor.GetDistance(); var s = $"Distance : {distance} cm"; TxtDistance.Text = s; Debug.WriteLine(s); }; _timer.Interval = TimeSpan.FromSeconds(1); _timer.Start(); } }
简单解释一下:
MainPage里的timer是用来定时每一秒取一次HC-04传感器返回的距离的,这个值可以自己改。这个距离是public double GetDistance()这个方法计算的。计算方法见代码注释。
三、运行