标签:position 基于 scheme rgs 新建 通过 private change set
GPIO 是 General Purpose Input Output 的缩写,即“通用输入输出”。 Raspberry Pi 有两行 GPIO 引脚, Raspberry Pi 通过这两行引脚进行一些硬件上的扩展,与传感器进行交互等等。
Raspberry Pi B+/2B/3B/3B+/Zero 引脚图
简单的讲,每一个 GPIO 引脚都有两种模式:输出模式(OUTPUT)和输入模式(INPUT)。输出模式类似于一个电源,Raspberry Pi 可以控制这个电源是否向外供电,比如打开外部的 LED 小灯,当然最有用的还是向外部设备发送信号。输入模式相当于电源的阴极,还是以 LED 小灯为例,只不过这次 LED 小灯的阳极接着外部电源,一个电路只有产生电压差时才会有电流,因此要想让小灯亮需要让电流流入 Raspberry Pi 中。和输出模式相反,输入模式是接收外部设备发来的信号。
GPIO 通常采用标准逻辑电平,即高电平和低电平,用二进制 0 和 1 表示。在这两值中间还有阈值电平,即高电平和低电平之间的界限。 Arduino 会将 -0.5 ~ 1.5 V 读取为低电平,3 ~ 5.5 V 读取为高电平, Raspberry Pi 未查到相关资料。GPIO 还可用于中断请求,即设置 GPIO 为输入模式,值达到相应的要求时进行中断。
此处默认各位是面向对象的程序员,具有一定的 C# 基础,这里只介绍本人认为常用的方法,介绍将以代码注释的形式体现。
GPIO 操作主要依赖于两个类: GpioController 、 GpioPin 。这两个类位于 System.Devices.Gpio 名称空间下。
// GpioController 即 GPIO 控制器
// GPIO 引脚依靠 GpioController 初始化
public class GpioController : IDisposable
{
// 构造函数
/* PinNumberingScheme 即引脚编号方案,是一个枚举类型,包含 Board 和 Gpio 两个值。
* 可以看上方的 Raspberry Pi 引脚图,以 GPIO 17 为例,如果实例化时选 Gpio ,那么打开引脚时需要填写 17。
* 如果实例化时选 Board ,那么打开引脚时需要填写右侧灰色方框内的值,即 11 。
*/
public GpioController(PinNumberingScheme numbering = PinNumberingScheme.Gpio);
// 第二个构造函数中的 GpioDriver 应该是用于扩展的,一般还是用 Raspberry Pi 默认的 GPIO 驱动。
public GpioController(GpioDriver driver, PinNumberingScheme numbering = PinNumberingScheme.Gpio);
// 属性
// 获取已打开的所有 GPIO 引脚
public IEnumerable<GpioPin> OpenPins { get; }
// 方法
// 打开 GPIO 引脚,pinNumber 需要填写和 PinNumberingScheme 相对应的值。
public GpioPin OpenPin(int pinNumber);
// 关闭 GPIO 引脚
public void ClosePin(int pinNumber);
public void ClosePin(GpioPin pin);
// 判断某个引脚是否打开
// 注意:引脚连续打开会抛出异常
public bool IsPinOpen(int pinNumber);
}
// GpioPin 表示单个的引脚实体
// 需要通过 GpioController.OpenPin() 获取
public class GpioPin : IDisposable
{
// 属性
// 一个去抖时间,即在此时间间隔引脚电平变化,不触发 ValueChanged 事件
public TimeSpan DebounceTimeout { get; set; }
// 事件
// 引脚电平变化时触发
public event EventHandler<PinValueChangedEventArgs> ValueChanged;
// 方法
// 读取当前引脚电平
public PinValue Read();
// 向引脚写入指定电平
public void Write(PinValue value);
}
示例地址:https://github.com/ZhangGaoxing/dotnet-core-iot-demo/tree/master/src/PIR
人体红外传感器是基于周围区域的红外热来检测运动的,也称被动红外传感器(Passive Infra-Red, PIR)。
这里使用的是 HC-SR501 。当传感器检测到人体时,LED 小灯亮,当传感器未检测到人体时,LED 小灯灭。
HC-SR501
名称 | 数量 |
---|---|
HC-SR501 | x1 |
LED 小灯 | x1 |
220 Ω 电阻 | x1 |
杜邦线 | 若干 |
HC-SR501
LED
新建类 HCSR501,替换如下代码(此处略有精简,只为必要的代码,不包含自定义事件,详细可查看提供的示例):
public class HCSR501 : IDisposable
{
private GpioPin sensor;
private readonly int pinOut;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="pin">OUT Pin</param>
public HCSR501(int pin)
{
pinOut = pin;
}
/// <summary>
/// 初始化
/// </summary>
public void Initialize()
{
// 实例化 GpioController
GpioController controller = new GpioController(PinNumberingScheme.Gpio);
// 打开引脚,设置模式为输入模式
sensor = controller.OpenPin(pinOut, PinMode.Input);
}
/// <summary>
/// 读取
/// </summary>
/// <returns>是否检测到人体</returns>
public bool Read()
{
// 当电平为高时,认为检测到人体
if (sensor.Read() == PinValue.High)
{
return true;
}
else
{
return false;
}
}
}
在 Program.cs 中,将主函数代码替换如下:
static void Main(string[] args)
{
// get the GPIO controller
// 获取 GPIO 控制器
GpioController controller = new GpioController(PinNumberingScheme.Gpio);
// open PIN 27 for led
// 为 led 打开引脚 27
GpioPin led = controller.OpenPin(27, PinMode.Output);
// initialize PIR sensor
// 初始化传感器
HCSR501 sensor = new HCSR501(17);
sensor.Initialize();
// loop
// 循环
while (true)
{
if (sensor.Read() == true)
{
// turn the led on when the sensor detected infrared heat
// 当传感器检测到热量时打开 led
led.Write(PinValue.High);
Console.WriteLine("Detected! Turn the LED on.");
}
else
{
// turn the led off when the sensor undetected infrared heat
// 当传感器未检测到热量时关闭 led
led.Write(PinValue.Low);
Console.WriteLine("Undetected! Turn the LED off.");
}
// wait for a second
// 等待 1s
Thread.Sleep(1000);
}
}
发布、拷贝、更改权限、运行
如何改进?
剔除主函数循环,尝试在自定义事件中进行检测,即 GpioPin 的 ValueChanged 事件。
备注
下一篇文章将谈谈 IIC 总线的使用。
张高兴的 .NET Core IoT 入门指南:(二)GPIO 的使用
标签:position 基于 scheme rgs 新建 通过 private change set
原文地址:https://www.cnblogs.com/zhanggaoxing/p/10327917.html