Node.js中的树莓派GPIO引脚入门
这是SitePoint的物联网周!必威西盟体育网页登录整个星期我们都在发表文章,重点是互联网和物理世界的交集,所以继续查看物联网的标签获取最新信息。
物联网现在正风靡一时。在物理计算领域,我们有很多想法可以付诸实践,很容易就会陷入为我们生活的世界编程的想法中!一旦你有了树莓派和面包板,下一步是什么?
在本文中,我们将探索如何使用Node.js访问树莓派上的GPIO引脚。使用GPIO引脚,可以直接对硬件编程。JavaScript api使之无缝衔接。这些api是对常见技术的抽象,可以从任何地方获得。Node.js解释器运行在一个单独的进程中,这打开了以可测试的方式编写代码的方法。最让我兴奋的是,你可以像其他JavaScript程序一样,在你的计算机上编写单元测试、点击断点和检查代码。
让我们开始吧。
什么是GPIO?
GPIO代表通用输入/输出.它们是树莓派侧面黄色视频输出插座旁边的引脚。下面是它们的样子。
把它们想象成你通过圆周率与外部世界连接的方式。这使您能够编写不在计算机屏幕上运行的程序。每个引脚就像一个开关,你可以打开或关闭。您可以从物理世界接收输入,也可以发送输出。基本的电路板有26个引脚,其中9个是电源或接地引脚。接地引脚位于电流流经的每个电路的末端。最新的树莓派板子多了一组14根引脚。
如果您对GPIO引脚的更多细节感兴趣,这张在线图表让您了解每个大头针的用途。有无数的输入/输出和接地引脚。这些引脚是物理计算的基础。根据你的目标,你可以使用你需要的数量。
模拟的fs
!
我知道你在想什么,到底是怎么回事fs
我为什么要在乎?在类unix操作系统中,a设备文件是一个看起来像文件的驱动程序。用外行的术语来说,设备驱动程序就是一个文件!你猜怎么着?GPIO api是读取或写入设备文件的包装器。文件系统api是您可能已经熟悉的概念。如果你从未在Node.js中使用过文件,我建议你浏览一下fs
模块和文件系统.fs
是“文件系统”的简写,使您能够读取或写入普通的旧文件。这里没什么特别的,我们所做的就是writeFile ()
例如,让GPIO处理其余的。诀窍在于知道在哪个文件上写什么。
有一个方便的小npm包叫做mock-fs这将帮助我们进行单元测试。使用这个库,可以在文件系统上虚构任何文件,并在内存中模拟它。如此激进的是,我们只处理文件,这是我们所需要做的。在类unix系统中,GPIO的行为与任何其他普通的旧文件一样。这让我们可以自由地处理这个解决方案。
问题的关键mock-fs
图书馆是模拟({})
函数。它只接受一个JavaScript对象参数。在这个参数中,你可以想象任何你想要的文件。这里的美妙之处在于,所有这些都在内存中运行,因此您可以疯狂地进行单元测试。解释器运行在单个进程中,这意味着可以重写fs
模块。JavaScript是一种动态语言,因此我们可以自由地模拟当前进程可用的任何模块。
一旦在GPIO接口上编写了良好的单元测试,它就更有意义了。我喜欢的是你可以得到自动化的测试覆盖和一个很好的干净的解决方案。单元测试提高了代码的可读性,因为它清楚地显示了API的用途。
所以让我们动手吧。
单元测试
所以让我们用“out”打开一个大头针并测试一下:
它(“用out打开大头针”,函数(完成){模拟({' / sys /类/ gpio / gpio23 /方向”:”});gpio.开放(16,“出”,函数(){常量方向=fs.readFileSync(' / sys /类/ gpio / gpio23 /方向”).toString();应该(方向).平等的(“出”);完成();});});
该测试的实现应该将物理引脚16映射到GPIO中的BCM引脚23。BCM编号是内核将在设备驱动程序中看到的Broadcom引脚编号。的GPIO设备驱动程序让您大致了解设备文件的位置。如图所示,要打开一个大头针,请将字符串“out”写入/方向
.这告诉GPIO我们期望写入这个引脚。完成后,检查文件是否具有所需的内容。模拟
来自于mock-fs
图书馆,fs
是Node.js中的标准文件系统。内核告诉我们路径在哪里——3.18版本。X及以上为/ sys /类/ gpio
.
要写到板上的引脚并测试这一点,可以这样做:
它(“写入高值的pin”,函数(完成){模拟({' / sys /类/ gpio / gpio23 /价值”:' 0 '});gpio.写(16,5,函数(){常量价值=fs.readFileSync(' / sys /类/ gpio / gpio23 /价值”).toString();应该(价值).平等的(' 1 ');完成();});});
两者之间有相似之处gpio.open ()
而且gpio.write ()
.使用write,它会写入到/值
文件。为了进行完整性检查,我编写了一个极高的值5,但是我们希望在测试中只得到1。GPIO只接收高或低的值,就像二进制一样。
我从pi-gpio.这个库可以很好地概述每个大头针的位置。您还可以在内核上查找设备文件。不管怎样,我的目标是让你很好地掌握基础知识,这样你就可以有一个清晰的画面。
让我们有点疯狂,在我的单元测试中击中一个断点怎么样?我使用WebStorm来做这件事,同样,使用任何你觉得舒服的东西:
对于健全的编程,关键在于缩短发现bug所需的反馈循环。单元测试是收紧循环并获得即时反馈的好方法。
为了简单起见,我正在写入一个引脚。GPIO的其余部分以同样的方式总结。打开一个大头针,告诉它你想用它做什么。读或写一个大头针,无论你需要做什么。底层api是设备文件,因此您可以选择如何编程每个引脚。
眨眼演示
为了充实每个单元测试,让我们看看一些常见的变量:
varsysFsPath=' / sys /类/ gpio / gpio ';varpinMapping={“16”:23};
上面,我已经在GPIO中定义了引脚映射和到设备驱动程序的路径。下面的代码查看打开并写入引脚的代码:
函数开放(pinNumber,方向,回调){常量路径=sysFsPath+pinMapping[pinNumber]+' /方向';fs.writeFile(路径,方向,(回调||无操作));}函数写(pinNumber,价值,回调){常量路径=sysFsPath+pinMapping[pinNumber]+‘/值’;价值=!!价值?' 1 ':' 0 ';fs.writeFile(路径,价值,“use utf8”,回调);}函数无操作(){}
如所示,所做的就是writeFile ()
到一个设备文件。的无操作
在没有回调的情况下是一个虚拟回调。有了这个实现细节,我就可以通过测试,并确信这将正常工作。的价值
在写入时确保将其设置为高或低(' 0 '
或' 1 '
)。
在最后,使用上面所示api的一个工作的blinker演示:
gpio.开放(16,“出”,函数(){var在=0;var信号灯=setInterval(函数(){gpio.写(16,在,函数(){在=(在+1)%2;控制台.日志(' on = '+在);});},1000);setTimeout(函数(){clearInterval(信号灯);},12000);});
的setInterval ()
每秒钟调用一次,在回调中,我告诉它用模量切换引脚。的信号灯
有区间,setTimeout ()
12秒后用这个清除。回调setTimeOut ()
完成工作,结束程序。
要运行示例代码,输入:
sudonpm开始
(需要管理员权限才能访问Raspberry Pi上的GPIO)
我希望GPIO在这个演示中看起来更直观。它期望一个有方向的开引脚。然后,写入一个引脚,让GPIO处理其余的细节。
结论
测试驱动的方法非常适合物联网。在物联网领域,你的想象力是极限。树莓派可以部署在世界上的任何地方——有了物理计算,你不会想把硬件运送到世界的另一边去调试代码。有了测试驱动的方法,就有了工作解决方案的即时反馈和保证。你的工作效率更高,并且可以收紧反馈回路。
我喜欢GPIO api的地方在于,可以将它简化为一个包装器fs
模块。这使您可以完全自由地编写干净和可测试的代码。
其余的示例演示都在上面GitHub.