【.NET 与树莓派】使用 GPIO 库
上回老周在说准备工作的时候,提到过树莓派用金属盒散热的事情。有朋友会说,加了金属盒子接线不方便,就算用了“T”形板,毕竟是把导线延长了的。其实扩展板就是把原有的引脚引出(类似于延长),有的引出后使用并联电路来“复制”出几套接口。所以你买一块插孔多的面包板,自己也可以并联出许多扩展接口来,何况树莓派好一点的扩展板也比较贵。
如果你不运行桌面,不看岛国片,只是执行命令和运行代码,完全不用散热措施。老周直接用裸板试验过,只是运行程序的话,温度平均在 40 度上下,受室温影响不是很大,夏天的时候会高2度。这个温度问题不大,挂不了。70 度以上才要考虑散热。
最简单的散热方案是贴散热片,不过你不要贴歪了,想撕下来再贴一次好像不那么容易,弄不好可能会把芯片扯坏。曾经还听说有人把处理器扯下来的,不知道是真是假。另外,加个小风扇的方式应该挺好,有点噪音也没关系的(不要像轰炸机就行)。
好,现在说正题。我们知道,树莓派有许多 GPIO 引脚,通用方式是发出,或者接收电平信号。信号就是两种——高电平 or 低电平。我们可以简单地认为,高电平是 3.3 V 电压,低电平是 0V 电压,更深层的电路原理你可以不理会,不影响你编程。
为什么是高电平和低电平两个信号呢?嗯,问得真TM地好。你想一下啊,计算机只认识两个数字,哪两个呢?0 和 1,你给计算机下命令时,其实只要 0 和 1 组合就行。1 开灯,0 关灯;1 向左转,0 向右转;0 翻墙,1 撞墙;0 引爆火药,1 引爆自己……
哟西,这么一来,两个电平就可以对应两个二进制数字:高电平—— 1,低电平—— 0,完事。
有了两个明确的值,还需要明确方向。树莓派自身把电平拉高或者拉低,以此来告诉连接的电子模块要干什么活,这是发送信号;当一个触摸开关被你的娇美的小手触碰后,模块把电平拉高(高电平状态),告诉树莓派有人按了按钮,这时候树莓派的接口就是接收状态,然后树莓派可以控制另一个设备去做其他事情(比如,冲马桶)。
由于树莓派带有 Linux 操作系统,所以,GPIO 接口的操作方法很多,可以直接调用相关的 lib,也可以用一些封装好的库。不过,系统集成了一种简单的操作方法,类似于文件的方式,你只需要读写对应的路径就能控制 IO 接口。
启动系统后,你可以进入以下目录:
cd /sys/class/gpio
然后执行 ls 命令,你会看到目录下有两个文件:
1、export:向这个文件写入 GPIO 口的编号,就可以打开相关接口;
2、unexport:向这个文件写入 GPIO 口的编号,关闭对应的接口。
你如果看到这两个文件,就可以试验一下了。不过在试之前,你还要做这件事:
sudo raspi-config
sudo 是为了防止权限不够,raspi-config,是树莓派系统专用的配置程序,在命令模式下也是图形化操作的。
选第3项,接口选项,回车。
用上下箭头键移到最下面的 P8,回车。
用 Tab 键选中 Yes,默认会选中,然后回车确认,收工。按 Esc 可以退出配置程序(或者选 Finish)。
Remote GPIO 选项必须打开的,不然你连接的电子模块是没有反应的。
接下来,老周用这个激光模块来做演示。
这个模块上面有一个激光头,跟我们小时候在路边买的装钮扣电池的差不多,发出的激光比小时候买的玩具还差。那这个模块有什么鸟用。其实这个模块真没什么鸟用,不过用来学习演示挺不错,现实用途可以拿来逗猫,不过注意不要让猫碰到单片机。
这个模块有三个引脚,PCB板上只标注了两侧的引脚。
为了提升拍照效果,我在下面垫了一张厕纸。最左边的引脚旁标注了“-”,意思是接电源负极,即接树莓派上的 GND 引脚。树莓派有八个 GND 引脚,你可以随便接;最右边的引脚标注了“S”,表示这是信号脚,接树莓派的 GPIO 脚,这个有很多了,当然了,最好选默认没有分配功能的 GPIO 接口。比如下图中画了蓝线的。
左右两边的引脚都知道用处了,所以,中间那个引脚就是接电源正极的,可以接树莓派的 5V,上面的图上你也看到了,树莓派两个 5V 脚都放在了一起(第2、4脚)。
下面开始接线,由于树莓派没有在板子印有引脚符号(无丝印),所以在接线时要小心,不要接错。
信号线老周选用了 GPIO 17,在树莓派上是 11 号引脚,也就是左边一排,往下顺数第六个脚。
接好线之后,我们回到终端,还记得前面提到的那两个文件吗?先用 cd 命令定位到 /sys/class/gpio 目录,然后向 export 文件输入文本“17”。
cd /sys/class/gpio
echo 17 > export
然后用 ls 列出一下 gpio 下的子项,你是不是发现多了个子目录?叫 gpio17。
这说明 GPIO 的第17口已经准备就绪,可以通信了。
注意一下,这里的 GPIO 编号不是树莓派板子上的顺序,而是BCM编号,刚刚接线时接的是左排的第六脚,可以上 pinout.xyz 查看,这个脚的编号是17。
然后,cd gpio17,进入这个目录,看看里面有什么。
这里面有两个文件我们需要用到的。
1、direction:配置 GPIO 口的通信方向。向其中写入“in”为输入,写入“out”为输出。
2、value:GPIO 口输出的值,0 为低电平,1 为高电平。
激光头模块是收到高电平时发射激光的,所以这里要把通信方向设为 out。
echo out > direction
向 value 写入“1”,输出高电平,发射激光,开始逗猫。
echo 1 > value
逗久了猫也觉得不好玩了,你手也累了,这时向 value 写入“0”,输出低电平,关闭激光发射。
echo 0 > value
最后,向 /sys/class/gpio/unexport 写入GPIO口编号 17,就可以关闭这个接口了。这时候,gpio17 子目录就不见了。
有了上面的试验,我们可以开始使用微软封装的 GPIO 库了。
这个 Nuget 库叫 System.Device.Gpio,它已经封装好了GPIO操作常用的类型。
1、对于Windows平台,用的是 UWP 的库;
2、对于类 Unix 平台,封装了以下几种版本:
1) LibGpio;
2)SysFsDriver,这个就是上面举例用的方式,以文件方式操作 /sys/class/gpio 路径下的文件。
3)Raspberry Pi 专版。
另外,还有 HummingBoard 版本。
我们在使用时,其实并不需要去思考使用哪个平台的类型,在实例化 GpioController 类的时候,会自动选用合适的类型。
使用以下命令,在.NET项目中添加 System.Device.gpio 库的引用。
dotnet add package system.device.gpio
在VS2019 中,你也可以用非常熟悉的 Nuget 包管理器来添加,操作方法省略,老周相信你会用的了。
在代码中引入 System.Device.Gpio 命名空间,然后就可以欢畅地撸代码了。
using System;
using static System.Threading.Thread;
using static System.Console;
using System.Device.Gpio; namespace testA
{
class Program
{
static void Main(string[] args)
{
int pin = 17;
GpioController gpio = new GpioController();
// 打开接口
gpio.OpenPin(pin);
// 设置通信方向
gpio.SetPinMode(pin, PinMode.Output);
gpio.Write(pin, PinValue.Low); //先置低电平
// 也可以这样写
//gpio.Write(pin, 0); // 发送信号
int x = 20;
while (x-- > 0)
{
WriteLine("打开激光头");
gpio.Write(pin, 1);
Sleep(1000);
WriteLine("关闭激光头");
gpio.Write(pin, 0);
Sleep(1000);
} // 关闭接口
gpio.ClosePin(pin);
gpio.Dispose();
// 退出
WriteLine("3166");
}
}
}
变量 pin 的值是17,前面接线的时候接的是 GPIO 17 引脚。
dotnet publish -r linux-arm -c release --no-self-contained
-r linux-arm,就是指定目标的运行时为 arm (32)的 Linux 系统。
-c 指定生成方案,有 Debug 和 Release,这个老周就不多解释了,.NET 程序习惯模式。
--no-self-contained 表示不包含运行时库,因为老周已在树莓派的系统上装了 dotnet 运行时;如果你不想在上面安装运行时,可以去掉 --on-self-contained 选项,这样默认会包含运行时库。上传到树莓派上面,执行 chmod u+x xxxx 提升权限,然后就可以直接运行了。
要在树莓派上安装.NET 运行时也很简单。
1、执行 cd /tmp 转到临时目录。
2、下载时可以选择 .NET runtime,或 ASP.NET Core Runtime。后者包含运行Web应用的库。使用 wget 下载压缩包(选择 arm32 的 Linux 包)。
wget https://download.visualstudio.microsoft.com/download/pr/7aa18d1a-1c9a-4571-9668-3d76b5cda367/41a75d18282fa815c548be4dbc9dd55f/aspnetcore-runtime-5.0.2-linux-arm.tar.gz
3、在 /usr/local 目录下创建一个目录,叫 dotnet。
sudo mkdir /usr/local/dotnet
这个地方要加上 sudo ,不然权限不够。/usr/local 这个目录很适合,它就是让我们安装自己需要的第三方软件用的。
4、解压刚刚下载的压缩包,放到 /usr/local/dotnet 目录下面。
sudo tar -zxf aspnetcore-runtime-5.0.2-linux-arm.tar.gz -C /usr/local/dotnet
-z 参数表示使用 gz 算法,-x 表示解压,-f 表示要解压的文件,三个参数合起来就是 -zxf。注意 -C 参数是大写的,表示工作目录,也就是你要解压到哪个目录,此处解压到 /usr/local/dotnet 目录下。
5、在 /etc/profile 文件中加入以下内容。
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...). if [ "`id -u`" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi # .NET 的运行路径
if [ -d /usr/local/dotnet ]; then
PATH=$PATH:/usr/local/dotnet
fi export PATH
……
位置是在 PATH 环境变量导出之前,将 dotnet 运行时的路径追加上去。即在 export 命令之前。保存并退出就OK了。
设置 PATH 变量放在 /etc/profile 中比放在 bash 的资源文件中好一些。放在bash资源中需要你登录终端时才执行,而且只在当前会话期间可用。放在 /etc/profile 中就成了“全局”了,只要顺利登入系统都有效。
在任意路径下执行 dotnet --info,如果有以下输出,那就成功了。
好了,现在可以把我们已经发布的程序上传到树莓派了。Win 10 自带 scp 命令,不需要安装传输工具。
在树莓派上 cd 到 pi 用户目录下(如果你改了用户名,可能是其他名字,可以用“~”代替)。
cd ~
创建一个新目录,叫 app
mkdir app
回到 Windows 上,打开命令提示符窗口,cd 到程序发布的目录。
cd C:\Users\<用户名>\...\testA\bin\release\net5.0\linux-arm\publish
执行 scp 命令上传文件。
scp ** pi@192.168.200.15:/home/pi/app
其中,**(用一个星号也可以,通配符)表示把发布目录下的所有文件上传到树莓派;冒号后面是树莓派上的路径,把文件放到前面创建的 app 目录下面,注意要用绝对路径,不能用“~”。
用终端登入树莓派,cd 到app下,能看到刚上传的文件。
无比紧张的时刻来临,执行我们写好的程序。
dotnet testA.dll
如果没有出其他问题的话,你会看到激光头一开一关(其间暂停1秒)。
示例的源代码可以点这里下载:拼命点这里
这个 System.device.gpio 库还封装了 i2c、SPI 等常见的硬件通信方式,后续文章中老周还会介绍。
【.NET 与树莓派】使用 GPIO 库的更多相关文章
- 树莓派高级GPIO库,wiringpi2 for python使用笔记(三)GPIO操作
GPIO库的核心功能,当然就是操作GPIO了,GPIO就是"通用输入/输出"接口,比如点亮一个LED.继电器等,或者通过iic spi 1-wire等协议,读取.写入数据,这都是G ...
- 树莓派高级GPIO库,wiringpi2 for python使用笔记(一)安装
网上的教程,一般Python用RPi.GPIO来控制树莓派的GPIO,而C/C++一般用wringpi库来操作GPIO,RPi.GPIO过于简单,很多高级功能不支持,比如i2c/SPI库等,也缺乏高精 ...
- 树莓派高级GPIO库,wiringpi2 for python使用笔记(四)实战DHT11解码
DHT11是一款有已校准数字信号输出的温湿度传感器. 精度湿度+-5%RH, 温度+-2℃,量程湿度20-90%RH, 温度0~50℃. 我买的封装好的模块,上边自带了上拉电阻,直接查到树莓派上即可灰 ...
- 树莓派高级GPIO库,wiringpi2 for python使用笔记(五)i2c读取测试
wiringpi2显然也把i2c驱动带给了Python,手头上正巧有一个DS3231的模块,上边带了一个DS3231 RTC(实时时钟),与一片24C32,两个芯片均为iic总线设备,与树莓派接线如下 ...
- 树莓派高级GPIO库,wiringpi2 for python使用笔记(二)高精度计时、延时函数
学过单片机的同学应该清楚,我们在编写传感器驱动时,需要用到高精度的定时器.延时等功能,wiringpi提供了一组函数来实现这些功能,这些函数分别是: micros() #返回当前的微秒数,这个数在调用 ...
- 树莓派的GPIO编程
作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载. 树莓派除了提供常见的网口和USB接口 ,还提供了一组GPIO(General Purpose Input/ ...
- 逗比学树莓派之GPIO
wiringPi适合那些具有C语言基础,在接触树莓派之前已经接触过单片机或者嵌入式开发的人群.wiringPi的API函数和arduino很相似,这也使得它广受欢迎.作者给出了大量的说明 ...
- 树莓派 - RPi.GPIO
RPi.GPIO是通过Python/C API实现的,C代码操作底层寄存器, python通过Python/C API调用这些C接口. 这是关于RPi.GPIO项目的介绍. 其中提到了有python ...
- 树莓派控制GPIO(Python)
如果你的raspi没有安装python那么先 sudo apt-get update sudo apt-get install python-dev 例如想要控制35管脚的亮灭: 先建一个文本 ...
随机推荐
- P4085 [USACO17DEC]Haybale Feast
我又开始水了,感觉又是一道虚假的蓝题 题意 非常好理解,自己看吧 题解 可以比较轻易的发现,如果对于一段满足和大于等于 \(m\) 的区间和其满足和大于等于 \(m\) 的子区间来说,选择子区间肯定是 ...
- springcloud gateway解决跨域问题
/** * 跨域允许 */ @Configuration public class CorsConfig { @Bean public WebFilter corsFilter() { return ...
- Python之Windows服务
1.首先要安装pywin32-220.win-amd64-py2.7.exe 2. SvcDoRun:服务启动的时候会执行的方法 SvcStop:服务停止的时候会执行的方法 # coding=utf- ...
- CSS知识点记录
1.浏览器style中显示的样式 这里面的样式,是行内样式或者是使用js添加的样式
- Jmeter之登录接口参数化实战
为了纪念我走过的坑(为什么有些简单的问题就是绊住我了,还是不够细啊) Jmeter之接口登录参数化实战 因为想要在登录时使用不同的数据进行测试,所以我选择了将数据进行参数化.因为涉及到新建一个接口的功 ...
- 01-flask-helloWorld
代码 from flask import Flask # 创建Flask对象 app = Flask(__name__) # 定义路由 @app.route('/') def index(): # 函 ...
- 面试 16-01.MVVM
16-01.MVVM #前言 MVVM的常见问题: 如何理解MVVM 如何实现MVVM 是否解读过Vue的源码 题目: 说一下使用 jQuery 和使用框架的区别 说一下对 MVVM 的理解 vue ...
- react第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制)
第五单元(事件系统-原生事件-react中的合成事件-详解事件的冒泡和捕获机制) 课程目标 深入理解和掌握事件的冒泡及捕获机制 理解react中的合成事件的本质 在react组件中合理的使用原生事件 ...
- Eureka 集群Demo
由于自己遇到了一些eureka集群疑问,就自己搭了一个集群demo进行测试.测试中通过两个eureka相互注册形成集群,两个服务提供者向eureka中注册服务,两个服务消费者通过feign进行服务调用 ...
- Python基础编程——数据类型
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 在程序设计和编程中,会涉及到各种各样的数据类型,而不同的数据类型变量之间可以进行的运算是不同的.在p ...