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()这个方法计算的。计算方法见代码注释。
三、运行
