上回老周在说准备工作的时候,提到过树莓派用金属盒散热的事情。有朋友会说,加了金属盒子接线不方便,就算用了“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 接口。

启动系统后,你可以进入以下目录:

  1. cd /sys/class/gpio

然后执行 ls 命令,你会看到目录下有两个文件:

1、export:向这个文件写入 GPIO 口的编号,就可以打开相关接口;

2、unexport:向这个文件写入 GPIO 口的编号,关闭对应的接口。

你如果看到这两个文件,就可以试验一下了。不过在试之前,你还要做这件事:

  1. 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”。

  1. cd /sys/class/gpio
  2. 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。

  1. echo out > direction

向 value 写入“1”,输出高电平,发射激光,开始逗猫。

  1. echo 1 > value

逗久了猫也觉得不好玩了,你手也累了,这时向 value 写入“0”,输出低电平,关闭激光发射。

  1. 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 库的引用。

  1. dotnet add package system.device.gpio

在VS2019 中,你也可以用非常熟悉的 Nuget 包管理器来添加,操作方法省略,老周相信你会用的了。

在代码中引入 System.Device.Gpio 命名空间,然后就可以欢畅地撸代码了。

  1. using System;
  2. using static System.Threading.Thread;
  3. using static System.Console;
  4. using System.Device.Gpio;
  5.  
  6. namespace testA
  7. {
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. int pin = 17;
  13. GpioController gpio = new GpioController();
  14. // 打开接口
  15. gpio.OpenPin(pin);
  16. // 设置通信方向
  17. gpio.SetPinMode(pin, PinMode.Output);
  18. gpio.Write(pin, PinValue.Low); //先置低电平
  19. // 也可以这样写
  20. //gpio.Write(pin, 0);
  21.  
  22. // 发送信号
  23. int x = 20;
  24. while (x-- > 0)
  25. {
  26. WriteLine("打开激光头");
  27. gpio.Write(pin, 1);
  28. Sleep(1000);
  29. WriteLine("关闭激光头");
  30. gpio.Write(pin, 0);
  31. Sleep(1000);
  32. }
  33.  
  34. // 关闭接口
  35. gpio.ClosePin(pin);
  36. gpio.Dispose();
  37. // 退出
  38. WriteLine("3166");
  39. }
  40. }
  41. }

变量 pin 的值是17,前面接线的时候接的是 GPIO 17 引脚。

下一步就是发布代码,发布到本地目录就行。
  1. 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 包)。

  1. 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。

  1. sudo mkdir /usr/local/dotnet

这个地方要加上 sudo ,不然权限不够。/usr/local 这个目录很适合,它就是让我们安装自己需要的第三方软件用的。

4、解压刚刚下载的压缩包,放到 /usr/local/dotnet 目录下面。

  1. 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 文件中加入以下内容。

  1. # /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
  2. # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
  3.  
  4. if [ "`id -u`" -eq 0 ]; then
  5. PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  6. else
  7. PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
  8. fi
  9.  
  10. # .NET 的运行路径
  11. if [ -d /usr/local/dotnet ]; then
  12. PATH=$PATH:/usr/local/dotnet
  13. fi
  14.  
  15. export PATH
  16. ……

位置是在 PATH 环境变量导出之前,将 dotnet 运行时的路径追加上去。即在 export 命令之前。保存并退出就OK了。

设置 PATH 变量放在 /etc/profile 中比放在 bash 的资源文件中好一些。放在bash资源中需要你登录终端时才执行,而且只在当前会话期间可用。放在 /etc/profile 中就成了“全局”了,只要顺利登入系统都有效。

在任意路径下执行 dotnet --info,如果有以下输出,那就成功了。

好了,现在可以把我们已经发布的程序上传到树莓派了。Win 10 自带 scp 命令,不需要安装传输工具。

在树莓派上 cd 到 pi 用户目录下(如果你改了用户名,可能是其他名字,可以用“~”代替)。

  1. cd ~

创建一个新目录,叫 app

  1. mkdir app

回到 Windows  上,打开命令提示符窗口,cd 到程序发布的目录。

  1. cd C:\Users\<用户名>\...\testA\bin\release\net5.0\linux-arm\publish

执行 scp 命令上传文件。

  1. scp ** pi@192.168.200.15:/home/pi/app

其中,**(用一个星号也可以,通配符)表示把发布目录下的所有文件上传到树莓派;冒号后面是树莓派上的路径,把文件放到前面创建的 app 目录下面,注意要用绝对路径,不能用“~”。

用终端登入树莓派,cd 到app下,能看到刚上传的文件。

无比紧张的时刻来临,执行我们写好的程序。

  1. dotnet testA.dll

如果没有出其他问题的话,你会看到激光头一开一关(其间暂停1秒)。

示例的源代码可以点这里下载:拼命点这里

这个 System.device.gpio 库还封装了 i2c、SPI 等常见的硬件通信方式,后续文章中老周还会介绍。

【.NET 与树莓派】使用 GPIO 库的更多相关文章

  1. 树莓派高级GPIO库,wiringpi2 for python使用笔记(三)GPIO操作

    GPIO库的核心功能,当然就是操作GPIO了,GPIO就是"通用输入/输出"接口,比如点亮一个LED.继电器等,或者通过iic spi 1-wire等协议,读取.写入数据,这都是G ...

  2. 树莓派高级GPIO库,wiringpi2 for python使用笔记(一)安装

    网上的教程,一般Python用RPi.GPIO来控制树莓派的GPIO,而C/C++一般用wringpi库来操作GPIO,RPi.GPIO过于简单,很多高级功能不支持,比如i2c/SPI库等,也缺乏高精 ...

  3. 树莓派高级GPIO库,wiringpi2 for python使用笔记(四)实战DHT11解码

    DHT11是一款有已校准数字信号输出的温湿度传感器. 精度湿度+-5%RH, 温度+-2℃,量程湿度20-90%RH, 温度0~50℃. 我买的封装好的模块,上边自带了上拉电阻,直接查到树莓派上即可灰 ...

  4. 树莓派高级GPIO库,wiringpi2 for python使用笔记(五)i2c读取测试

    wiringpi2显然也把i2c驱动带给了Python,手头上正巧有一个DS3231的模块,上边带了一个DS3231 RTC(实时时钟),与一片24C32,两个芯片均为iic总线设备,与树莓派接线如下 ...

  5. 树莓派高级GPIO库,wiringpi2 for python使用笔记(二)高精度计时、延时函数

    学过单片机的同学应该清楚,我们在编写传感器驱动时,需要用到高精度的定时器.延时等功能,wiringpi提供了一组函数来实现这些功能,这些函数分别是: micros() #返回当前的微秒数,这个数在调用 ...

  6. 树莓派的GPIO编程

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载. 树莓派除了提供常见的网口和USB接口 ,还提供了一组GPIO(General Purpose Input/ ...

  7. 逗比学树莓派之GPIO

           wiringPi适合那些具有C语言基础,在接触树莓派之前已经接触过单片机或者嵌入式开发的人群.wiringPi的API函数和arduino很相似,这也使得它广受欢迎.作者给出了大量的说明 ...

  8. 树莓派 - RPi.GPIO

    RPi.GPIO是通过Python/C API实现的,C代码操作底层寄存器, python通过Python/C API调用这些C接口. 这是关于RPi.GPIO项目的介绍. 其中提到了有python ...

  9. 树莓派控制GPIO(Python)

    如果你的raspi没有安装python那么先   sudo apt-get update sudo apt-get install python-dev   例如想要控制35管脚的亮灭: 先建一个文本 ...

随机推荐

  1. C++ 消失的析构函数 —— virtual 实现的动态析构

    在C++类的结构中可以使用类方法创建内存,使用类的析构函数去施放内存,但有这么一种情况会导致:即使在析构函数中释放了内存,但由于析构函数没有被调用而导致内存泄漏,如下代码. 1 #include &l ...

  2. C++异常之四 异常类型的生命周期

    异常类型的生命周期 1. throw 基本类型: int.float.char 这三种类型的抛出和函数的返回传值类似,为参数拷贝的值传递. 1 int test_1(int num) throw (i ...

  3. Vue3源码解析(computed-计算属性)

    作者:秦志英 前言 上一篇文章中我们分析了Vue3响应式的整个流程,本篇文章我们将分析Vue3中的computed计算属性是如何实现的. 在Vue2中我们已经对计算属性了解的很清楚了,在Vue3中提供 ...

  4. JavaSE18-字节缓冲流&字符流

    1.字节缓冲流 1.1 字节缓冲流构造方法 字节缓冲流介绍 BufferOutputStream:该类实现缓冲输出流. 通过设置这样的输出流,应用程序可以向底层输出流写 入字节,而不必为写入的每个字节 ...

  5. [日常摸鱼]bzoj1444 [JSOI2009]有趣的游戏——AC自动机+矩阵

    今天学校跳蚤市场摆摊聚众吸毒打call,东西卖了一百多好开心_(:з」∠)_ (然后大家中午就去吃了一顿好的x) 下午听演讲然后现在来填坑orz(其实是昨晚的坑) 题目:bzoj1444 先用字符串构 ...

  6. [BUUCTF] MISC-九连环

    0x01 知识点 伪加密 steghide提取信息 0x02 伪加密的判断 首先,在winhex分析,发现有4个zip文件的文件头和2个文件尾,有完整文件头尾那么可以直接修改后缀为zip解压, 查看一 ...

  7. CentOS 8 部署 ASP.NET Core 3.1 应用程序 kestrel+Nginx IIS+kestrel

    vs2019发布到IIS  下载文档https://files.cnblogs.com/files/netlock/%E4%BD%BF%E7%94%A8VS2019%E5%8F%91%E5%B8%83 ...

  8. 用git上传项目到GitHub或者码云全过程

    用git上传项目到GitHub或者码云全过程 1. 会生成一个隐藏文件夹".git".这是一个不可删文件,因为暂存区和历史区还有一些其他的信息都在这里,删掉就不是一个完整的仓库了 ...

  9. 认识ollydbg

    四个区域:汇编区:虚拟地址,机器码,汇编指令,注释: 寄存器区:寄存器,数据: 数据区, 栈. 这是上面按钮的作用 热键: Ctrl+F2 - 重启程序. Alt+F2 - 关闭被调试程序. F3 - ...

  10. 【mysql】- Expalin篇

    简介 id:在一个大的查询语句中每个 SELECT 关键字都对应一个唯一的id 与查询优化器有关,假如被优化过,那么可能是上下两个的id都是一样的 select_type:SELECT 关键字对应的那 ...