IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Windows 10 IoT开发:HC-04超声波传感器测距(树莓派3)

    汪宇杰发表于 2016-04-02 10:31:43
    love 0

    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.3K欧,一个10K欧。为什么要这样呢,是因为根据电压分配定律,如上图所示,4.3K和10K电阻的组合可以得到3.4V的输出。这对GPIO来说是可以接受的。如果你有别的值的电阻可以让输出正好3.3V也是可以的。我在淘宝买的常用电阻包没有办法配出正好3.3V,所以只能用4.3K和10K的组合。

    然后,传感器和树莓派的连接也可以看上面这张图来连。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()这个方法计算的。计算方法见代码注释。



沪ICP备19023445号-2号
友情链接