在第 1 章设置您的开发环境中,我们介绍了 Python 生态系统、虚拟环境和包管理的要点,并设置了用于开发和 GPIO 接口的 Raspberry Pi。在本章中,我们将开始 Python 和 IoT 的旅程。
我们在本章中介绍的内容将奠定基础,并为我们在后面章节中介绍的更高级内容提供工作参考点。我们将学习创建一个带有按钮、电阻器和 LED(或发光二极管)的简单电路,并探索使用 Python 与按钮和 LED 交互的替代方法。然后,我们将继续创建并讨论一个完整的端到端物联网计划,以通过互联网控制 LED,并通过查看扩展该计划的方法来完成本章。
在本章中,我们将介绍以下主题:
- 创建试验板原型电路
- 阅读电子原理图
- 探索在 Python 中闪烁 LED 的两种方法
- 探索在 Python 中集成按钮的两种方法
- 创建您的第一个物联网计划
- 扩展物联网计划
要完成本章和本书中的练习,您需要以下内容:
- Raspberry Pi 4 型号 B.A 1GB 的 RAM 版本足以运行我们的示例。如果您直接使用 Raspberry Pi,而不是安全 Shell(SSH会话;例如,建议增加 RAM 以改善 Raspbian 桌面体验和响应能力。
- 您需要 Raspbian OS Buster(带桌面和推荐软件)。
- 您至少需要 Python 版本 3.5。
这些需求是本书中代码示例的基础。只要 Python 版本为 3.5 或更高版本,就可以合理地期望代码示例在 Raspberry Pi 3 Model B、Raspberry Pi Zero W 或不同版本的 Raspbian OS 上无需修改即可工作。
您可以在 GitHub 存储库中的chapter02文件夹中找到本章的源代码,网址如下:https://github.com/PacktPublishing/Practical-Python-Programming-for-IoT 。
您需要在终端中执行以下命令,以设置虚拟环境并安装本章代码所需的 Python 库:
$ cd chapter02 # Change into this chapter's folder
$ python3 -m venv venv # Create Python Virtual Environment
$ source venv/bin/activate # Activate Python Virtual Environment
(venv) $ pip install pip --upgrade # Upgrade pip
(venv) $ pip install -r requirements.txt # Install dependent packages以下依赖项是从requirements.txt安装的:
- GPIOZero:GPIOZero GPIO 库(https://pypi.org/project/gpiozero
- PiGPIO:PiGPIO 库(https://pypi.org/project/pigpio *** 请求:用于发出 HTTP 请求的高级 Python 库(https://pypi.org/project/requests**
****我们需要一些物理电子元件:
-
1 x 5 毫米红色发光二极管
-
1 x 200Ω电阻器:其色带为红色、黑色、棕色,然后为金或银
-
瞬时按钮(单刀单掷-SPST)
-
试验板
-
公-母和公-公跨接电缆(有时称为杜邦电缆)
You will find a complete parts list cataloging all of the electrical components required for every chapter in the Preface.
当您准备好电子元件后,我们可以继续将它们放在您的试验板上。
在本书中,我们将构建许多电路,我们将使用电子实验板来实现这一点。在最初的几章中,我将介绍许多电路,包括与图 2.7中本节末尾所示类似的试验板布局和图 2.8**中所示的示意图。
当我们通过这本书的学习,并且你们获得了更多的经验来构建实验板电路时,我将停止简单电路的实验板布局;但是,我仍然会为更复杂的电路提供它们,这样您就可以将构建与之进行比较。
Please note that the proceeding circuit examples and discussions are only brief. At this stage of this book, we intend to build a simple electronic circuit that will be the basis for our Python examples in this chapter and Chapter 3, Networking with RESTful APIs and Web Sockets Using Flask, and Chapter 4, Networking with MQTT, Python, and the Mosquitto MQTT Broker. We will discuss the Raspberry Pi and its pin numbering in detail in Chapter 5, Connecting Your Raspberry Pi to the Physical World. Furthermore, we will cover in detail circuits and electronics fundamentals in Chapter 6, Electronics 101 for the Software Engineer , where among other topics we will learn the why behind how the button interacts electrically with your Raspberry Pi and why a 200 Ω resistor accompanies our LEDs.
让我们开始建造我们的第一条赛道。我将一步一步地引导您完成 breadboard 构建,并在使用它们时简要介绍每个组件。我们将首先讨论什么是试验板以及它是如何工作的。
电子试验板如图 2.1所示,是一种原型板,可帮助您快速、轻松地将部件和电线进行电气连接。在本节中,我们将在以下各节中讨论试验板的一般特性,以准备将部件和导线连接在一起:
Figure 2.1 – Breadboard
面包板有许多不同的尺寸,我们的图文并茂的面包板是一个半尺寸的面包板。然而,不管它们的大小,它们的基本布局和电气连接都是相似的,只有一个小的例外,我将在后面提到。
Real breadboards may, or may not, have the row and column numbers markings on them. They have been included in the illustration to assist with the following discussion and explanations.
实验板上的孔是放置电气元件和电线以进行电气连接的地方。这些孔通过以下方式进行电气连接:
-
孔的两个外柱通常称为电源轨。在试验板的两侧有一个正(+)列和一个负(-)列。每列孔都是电气连接的,并在整个试验板长度上运行。因此,该试验板上有四个独立的电源导轨:试验板左侧有一个*+和-导轨,右侧有一个+和-*导轨。
电源导轨通常用于帮助将试验板周围的电源分配给组件。请注意,它们本身不提供电源!他们需要一个电源,如电源或电池连接到他们提供电力。
-
实验板的中心有两排孔,我已经标记为A-E 组和F-J 组。每排孔通过电气连接。例如,孔 A1 至 E1 与孔 F1 至 J1 电气连接。然而,我们清楚地了解到,A1-E1未与 F1-J1 电气连接,因为它们位于单独的气缸组上。
We straddle Integrated Circuits (ICs)—commonly called chips — across the gap between the two banks when we connect them into a breadboard. We will see an example of this in Chapter 10, Movement with Servos, Motors, and Steppers, when we use an IC to control motors.
下面是几个关于孔如何连接的示例,您可以通过这些示例来帮助理解:
- B5 与 C5 电连接(它们共用一行)。
- H25 与 J25 电气连接(它们共享同一行)。
- A2未与 B2 电气连接(它们不共享同一行)。
- E30未与 F30 电气连接(它们位于不同的银行)。
- 左侧电源轨上的第三个+孔(从试验板顶部开始)与左侧电源轨上的最后一个+孔电连接(它们位于同一垂直柱中)。
- 左侧电源轨上的第三个+孔(从试验板顶部开始)与右侧电源轨上的第三个+孔没有电连接(它们位于不同的电源轨上)。
我在本节开头提到,所有的面包板基本上都是一样的,只有一个小的例外。此例外情况与电源导轨有关。一些全尺寸的面包板可能会将其电源导轨分成两个独立的垂直组(因此,从电气上讲,导轨上的垂直孔不会贯穿整个面包板)。电源导轨分开的视觉效果并不总是很明显,因此发现需要逐个实验板进行。我提到这一点只是为了防止您使用全尺寸的试验板,并在使用电源导轨时遇到连接问题。
现在我们已经介绍了面包板,并且我们了解了孔之间是如何相互电关联的,让我们开始将元件和导线插入面包板来创建第一个电路。我们从按钮开始。
我们使用的是一个简单的开/关按钮,也称为单极单掷(SPST瞬时开关。示例如图 2.2: 所示
Figure 2.2 – A push button and schematic symbol
图 2.2左侧为瞬时按钮的照片,右侧为瞬时按钮的示意图符号。我们将看到这个符号,并在下一节讨论这些符号类型出现的示意图。
按钮有多种形状和尺寸;但是,它们的一般操作是相同的。图中左侧的特定按钮称为触觉按钮。它们体积小,非常适合与试验板一起使用。
图 2.3显示了我们需要在试验板上创建的按钮连接。请在执行后续步骤时参考以下内容:
Figure 2.3 – Connecting the push button
下面是如何将按钮连接到你的试验板,并将其连接到你的树莓皮。以下步骤编号与图 2.3中编号的黑色圆圈匹配:
-
如图所示,将按钮放置在试验板上。按钮进入哪一排孔并不重要,但是,图 2.3显示了按钮位于 B10 孔的位置(左上脚)。
-
接下来,将一根跨接导线连接到按钮最上面的支腿所在的同一行(我们的插图使用孔 A10)。将此导线的另一端连接到从 Raspberry Pi 的 GPIO 头的外边缘开始倒数的第八个引脚。该引脚称为 GPIO 23。
You can get header pin labels and breadboard compatible modules to assist you with Raspberry Pi pin connections and identification. Here is a link to a printable version to get you started: https://github.com/splitbrain/rpibplusleaf. We will cover GPIO pins and their numbering in Chapter 5, Connecting Your Raspberry Pi to the Physical World.
- 最后,使用另一根电线(标记为gnd’,我们将按钮的另一侧(B2 孔中的支腿)连接到试验板上的负极电源导轨。我们的插图显示了从 A12 孔到左侧负极(-)电源轨附近孔的gnd’接线。缩写词gnd表示地面。我们将在下一节理解接地连接和符号中更详细地介绍这一术语。
Electrically, an SPST switch can be installed any way around. If your button has four legs (two sets will be electrically connected) and your circuit below does not work when we test it later in the Exploring two ways to integrate a push button in Python section try rotating the button in your breadboard 90 degrees.
现在我们的按钮已就位并接线,我们将下一步定位并连接 LED。
LED 是一种小而明亮的灯,由一个微小的晶体制成,当与之相连时,它会发出一种颜色。
典型 LED 如图 2.4 所示*。*图的左侧显示 LED 的物理表示,而右侧显示 LED 的原理图符号:
Figure 2.4 – LED and schematic symbol
LED 需要以正确的方式连接到电路中,否则,它们将无法工作。如果仔细观察 LED,您会发现 LED 外壳上有一个平面。这一侧的支腿是阴极,它连接到电源的负极或接地侧。阴极支腿也将是 LED 支腿中较短的一个。另一个支路称为阳极,连接到电源的正极侧。如果你检查 LED 符号,你会注意到 LED 的阴极侧有一条线画在三角形的顶端。如果你认为这条线像一个大的负号,它会帮助你记住符号的哪一侧是阴极支腿。
图 2.5我们将要创建的 LED 连接。请参考此图,然后执行以下步骤:
Figure 2.5 – Connecting the LED
下面是如何将 LED 连接到您的试验板,并将其连接到您的树莓 Pi。以下步骤编号与图 2.5中编号的黑色圆圈相匹配:
- 如图所示,将 LED 连接到您的试验板上,注意确保 LED 的安装方式正确。我们的插图显示了孔 E15 中的阴极支腿和孔 E16 中的阳极支腿。
You may need to bend the legs on your LED to get it into position. As you position your LED, make sure the two legs are not touching one another! If they are touching, this will cause what is known as an electrical short, and the LED part of the circuit will not work.
- 接下来,使用一根跨接导线(标记为gnd“),将 LED 的阴极支脚连接到按钮共享的同一个电源轨中。我们已经显示了与连接在 A15 孔中的gnd“导线一端的连接,而导线的另一端连接到左侧负极(-)电源轨上的附近孔。 ** 最后,使用另一根跨接导线(标记为*gnd),将负极(-)电源轨连接到 Raspberry Pi 的 GPIO 头上的第 17th外边缘引脚。该引脚是覆盆子圆周率接口上的接地引脚。
*做得好!这是我们的 LED 连接。接下来,我们添加电阻器,这将完成我们的电路。
电阻器是一种电子元件,用于限制(即抵抗)电流和分压,是一种非常常见的电气元件。
图 2.6所示为一个物理电阻器(左侧)和两个原理图符号(右侧)。图中的示意图符号之间没有实际区别。它们代表不同的文档标准,您会发现原理图的作者会选择并坚持使用一种类型的符号。在本书中,我们将使用之字形符号:
Figure 2.6 – Resistor and schematic symbols
电阻器有多种形状、尺寸和颜色。一般来说,它们的物理形状和大小与其物理特性和性能有关,而外壳的颜色通常无关紧要,至少就其特性而言是如此。然而,电阻器上的色带非常重要,因为它们标识电阻器的值。值得一提的是,小型通用电阻器(我们将使用)使用色带指定其值,而在大功率应用中使用的物理较大电阻器通常在其外壳上打印其电阻值。
电阻器是一种无偏的电气元件,这意味着它们可以安装在任意一种电路中。但是,需要正确选择它们的值,否则电路可能无法按预期工作,或者更糟糕的是,电阻器和/或其他部件(包括树莓 Pi)可能会损坏。
When starting out and learning about circuits, it is highly recommended and safest to always use the intended resistor values that are listed for a circuit. Avoid any temptation to substitute different values when you do not have the correct value on hand as this can result in damage to components and even your Raspberry Pi.
通过本书,我们对电阻器的使用将是务实的。尽管我将解释如何以及为什么我们会在第 6 章、电子 101 中为软件工程师之后使用某些值。如果您对电阻器不熟悉,您可以在进一步阅读部分找到两个链接,从中您可以了解有关电阻器的更多信息,包括如何读取电阻器的值。
图 2.7展示了我们需要创建的电阻器连接。请在执行后续步骤时参考以下内容:
Figure 2.7 – Completed button and LED circuit on the breadboard
下面是如何将电阻器连接到您的试验板。以下步骤编号与图 2.7中编号的黑色圆圈相匹配:
-
将电阻器的一个支脚(不管是哪一个)放入与 LED 阳极支脚共用一行的孔中。该连接如孔 D16 所示。将另一条腿插入一个空行,如 D20 所示(在我们连接下一条电线之前,它将是您的试验板上的一个空行)。
-
使用跨接导线(如图所示,从 A20孔开始),我们将电阻器的另一支脚连接到 Raspberry Pi GPIO 头外缘的第 20th引脚。该引脚称为 GPIO 21。
*做得好!通过最后的连接,我们创建了第一条电路。我们将在本章的其余部分和接下来的两章中使用此基本电路,第 3 章、使用 Flask与 RESTful API 和 Web 套接字进行联网,第 4 章、与 MQTT、Python 和 Mosquitto MQTT 代理进行联网。我们将从第 5 章开始探索将树莓圆周率连接到物理世界的一系列其他电路。
现在,我们已经完成了实验板电路,并了解了元件和导线如何连接到实验板上,我们准备探索一种用于描述电路的图解技术。
在最后一节中,我们按照一系列说明步骤在试验板上构建了第一个电路。在本节中,我们将学习示意图**示意图,这是记录和描述电路的正式方式。这些是电子文本和数据表中的图表。
我们将学习如何阅读一个简单的原理图,以及它如何与我们刚刚创建的实验板布局相关联。了解两者之间的关系,尤其是能够从原理图中创建试验板布局,是您在继续电子和物联网旅程时需要掌握的一项重要技能。
就原理图而言,我们将在本书中看到并使用的电子电路和原理图相对简单。当我们在个案基础上遇到重要概念和组件符号时,我们将讨论它们。在我们的旅程中,没有必要对示意图的细节进行全面详细的解释,这超出了本书的实际范围。但是,我鼓励您通读进一步阅读部分中提到的火花乐趣教程。它提供了一个简单而全面的阅读示意图的概述,并将为您提供一个很好的基本理解这种图表技术及其语义。
让我们先看一个示意图,它表示我们刚刚创建的实验板电路,如图 2.7 所示。我们的语义图如下所示:
Figure 2.8 – Schematic diagram of the breadboard circuit from Figure 2.7
原理图可以用多种方法正确绘制;然而,我特意画了这张图(在本书中适当的时候也会这样做),使其与等效的试验板布局非常相似,以帮助解释和理解。
我们将通过首先解释按钮连接和接线来学习阅读此示意图。
我将试验板布局和示意图(带有一些附加标签)结合在一起,如下所示:
Figure 2.9 – Combined breadboard and schematic diagram, part 1 of 2
下面是如何读取按钮连接。以下步骤编号与图 2.9中编号的黑色圆圈相匹配:
-
从试验板开始,使用标有*导线 1 的导线。*如果我们观察这根电线的两端,我们会看到一端连接到树莓 Pi 上的 GPIO 23,而另一端(在 A10 孔)连接到按钮共享的一行。
-
从示意图上看,该试验板连接通过标记为*导线 1 的线进行了图示。*您会注意到线的一端标有 GPIO23,而另一端则通向按钮符号的一侧。
The color of a wire's casing has no inherent meaning. The color is simply a visual aid to help to distinguish different wires and connections. However, there are some common conventions such as using a red wire for a positive power connection and a black wire for the negative or ground wire
-
接下来,从试验板上按钮的另一侧(A12 孔)开始,注意标记为*gnd'*的导线。该导线将按钮连接到试验板上的外部电源导轨。
-
在第一个电源轨连接的五个孔下面,我们看到第二条地线(标有*gnd】*从试验板引回到 Raspberry Pi 上的 gnd 引脚。
-
电路板接地和接地接线在示意图中被视为标记为接地的线路,该线路从按钮引出,并在一个向下指向的箭头符号处结束,该符号注有接地(记得吗接地和接地通过电气方式连接在试验板上,因此在逻辑上是一根单线】这是接地的符号,你会经常看到这个符号在示意图中反复出现。当我们到达标题为阅读和理解地面符号的部分时,我将有更多关于这个符号的内容。
** 检查示意图中的按钮符号,您会注意到,导线 1和接地线没有连接,而是终止于按钮符号(小圆圈)。这被称为一个常开**连接或者,在我们的具体案例中,一个**常开开关。您可以将常开视为表示线路断开(记住线路代表导线)。现在,如果您想象按下按钮,则按钮接触每个圆圈,并连接蓝色和gnd线,从而形成闭合连接,完成 GPIO 23 和 gnd 之间的电路。我们将在第 6 章、软件工程师电子 101中详细讨论这个想法。*
*当您理解了试验板上的按钮连接如何与示意图的按钮部分相匹配时,我们将继续讨论 LED 和电阻器连接。
从上一节开始,我们学习了如何阅读和理解示意图中的按钮部分,接下来,我们通过介绍 LED 和电阻器连接来完成解释,如下所示:
Figure 2.10 – Combined breadboard and schematic diagram, part 2 of 2
以下是如何读取 LED 和电阻器连接。以下步骤编号与图 2.10中编号的黑色圆圈相匹配:
- 从试验板上标记为导线 2的导线开始。该导线将 Raspberry Pi 上的 GPIO 21 连接到电阻器一端共享的行中(孔 A25)。
- 线 2连接由示意图上标记为线 2的线表示。
- 在试验板上,电阻器的另一端连接到 LED 的阳极支脚(孔 E15)。请记住,LED 的电阻器和阳极支腿是电气连接的,因为它们在试验板的同一排孔中共用同一排孔。
- 我们在原理图中看到电阻器/LED 连接,其中电阻器符号与 LED 符号相交。通过 LED 符号的方向,我们知道电阻连接到图中 LED 的阳极侧。
- 接下来,在试验板上,LED 的另一支脚(孔 E15)-阴极支脚-连接到gnd“导线(孔 A15),然后再连接到外部电源轨,该外部电源轨也由按钮的gnd“导线共享(然后通过接地导线将其连接回 Raspberry Pi 的接地引脚。)
- 最后,在示意图上,从 LED 阴极支腿到 GND 的连接用标记为GND的线表示(按钮使用的同一条线)。
现在我们已经完成了示意图说明。你好吗?我希望你能在图表中找到线索,看看它是如何与我们在实验板上构建的电路相联系的。
我们的最后一步说明了电子学中的一个重要概念,即公共接地。接下来我们将更详细地讨论这个概念。
电路都需要一个共同的电气参考点,我们称之为接地。这就是为什么我们在实验板和原理图上看到按钮和 LED 共用一个连接(作为提示,请参考图 2.10。
对于本书中介绍的简单电路,以及当您的树莓 Pi 的 GPIO 引脚工作时,考虑术语 Ty0 T0。这是因为电源的负侧将是我们共同的电气参考点(是的,GPIO 引脚是一种电源,我们将在第 6 章、电子 101 中为软件工程师进行更多探讨)。
正如前面在阅读按钮示意图连接一节中提到的,在步骤 4中,我们使用箭头符号绘制了接地点。我们的地面符号(由线段组成)是地面符号的一种常见变体。您将在图 2.11中看到另一个变化:
Figure 2.11 – Common schematic diagram ground symbols
所有接地点都是电气连接的,我们可以在原理图中多次重复该符号,以帮助简化示意图。通过使用接地符号来表示公共接地连接,我们无需绘制许多互连线来将所有接地连接连接在一起(对于大型或更复杂的电路,这将变得相当混乱)。
我们的简单电路当然不在大型或复杂的旗帜下,但是,为了说明共同点的概念,我在这里重新绘制了图 2.8中最初显示的示意图,只是这次使用了多个接地符号:
Figure 2.12 – Alternative schematic diagrams of the breadboard circuit in Figure 2.7
虽然我们的备选示意图看起来像两个独立的电路,但它们的电气连接与图 2.8 中的原始示意图完全相同。
现在请花点时间检查图 2.8和图 2.12,看看您是否能够计算出这两个图在电气方面是如何相同的。
我在这里所做的就是断开线路(在图 2.8中标记为gnd,并以不同方向重新绘制按钮子电路和 LED/电阻子电路,并为每个子电路使用单独的接地符号。
如前所述,在本书的这一阶段,我们不会讨论该电路如何或为什么以电子方式工作,或者它如何与 Raspberry Pi 上的 GPIO 引脚进行电子交互。当我们到达第 6 章、软件工程师的电子 101时,我们将通过实践和说明性练习涵盖这些主题以及更多内容。
现在,您已经看到了记录我们的试验板电路的示意图,并了解了它们之间的关系,我们终于准备好深入研究代码并学习两种在 Python 中使 LED 闪烁的方法!
在本节中,我们将研究两个可选的 GPIO 库以及在 Python 中制作 LED 闪存的方法,包括以下内容:
- GPIOZero 库:入门级 GPIO 库
- PiGPIO 库:一个高级 GPIO 库
当我们学习使用这两个库时,我们将看到它们如何以不同的方式处理 GPIO 控制,并发现它们的相对优势和劣势。
在完成本节(以及下一节,探索了在 Python中集成按钮的两种方法)之后,您将探索并比较了两种非常不同的 GPIO 控制方法:高级(使用 GPIOZero)和低级(使用 PiGPIO)-并且在构建电子接口程序时,对何时以及如何在备选方案之间进行选择有很好的入门理解。
让我们通过使用 GPIOZero 使 LED 闪烁来开始我们的实践练习。
现在,我们准备研究使用 GPIOZero 库的第一个闪烁方法。您将在chapter02/led_gpiozero.py文件中找到我们将要介绍的代码。请在继续之前查看此文件。
In the Further reading section, you will find relevant links to the GPIOZero API documentation for the specific features of this library that we use in this section.
我们将从运行示例代码开始。
使用以下命令运行程序,记住您需要处于激活的虚拟环境中(如果您需要更新如何激活 Python 虚拟环境,请参阅第 1 章,设置您的开发环境:
(venv) $ python led_gpiozero.py 如果 LED 连接正确,则应闪烁。
If you receive an error about PiGPIO when you run the program, make sure you have enabled the pigpio daemon as outlined in Chapter 1, Setting Up Your Development Environment. We'll talk more about PiGPIO and the PiGPIO daemon in Chapter 5, Connecting Your Raspberry Pi to the Physical World .
现在,我们已经运行了代码并看到 LED 闪烁,现在是时候查看导致这种情况发生的代码了。
我们将通过查看在 Python 程序中导入的外部库来开始代码探索。它们出现在源文件顶部附近,如下所示:
from gpiozero import Device, LED # (1)
from gpiozero.pins.pigpio import PiGPIOFactory # (2)
from time import sleep 利息进口如下:
- 在第(1)行,我们从 GPIOZero 包导入
Device和LED类。 - 在第(2)行,我们正在导入一个 GPIOZero引脚工厂。这与
Device类一起使用,我们将在下面看到。
接下来,我们将了解如何设置 GPIOZero 引脚工厂实现。
GPIOZero 中使用了一个引脚工厂,指定 GPIOZero 将使用哪个具体的 GPIO 库来执行实际的 GPIO 工作。在本章后面的比较 GPIOZero 和 PiGPIO 示例一节中,我们将在比较 GPIOZero 和 PiGPIO 示例时更详细地讨论引脚工厂:
Device.pin_factory = PiGPIOFactory() # (3) 在第(3)行中,我们告诉 GPIOZero 使用Device和PiGPIOFactory进口的 PiGPIO 作为其引脚工厂。
现在我们已经了解了 Pin 工厂是如何建立的,让我们看看使 LED 闪烁的代码。
在这里,我们看到下面第(4)行的LED类被创建并分配给led变量。LED的参数是物理 LED 连接到的 GPIO 引脚,如图 2.1中的实验板所示:
GPIO_PIN = 21
led = LED(GPIO_PIN) # (4)
led.blink(background=False) # (5)在第(5)行,我们开始 LED 闪烁。blink()的background=False参数是在主线程上运行 LED 所必需的,因此程序不会退出(另一种background=True选项是使用signal.pause(),我们将在下一节中看到一个示例)。
GPIOZero 使得与常见电子元件(如 LED)的接口非常容易。接下来,我们将执行相同的练习,只是这次使用 PiGPIO 库。
现在我们已经了解了如何使用 GPIOZero 库闪烁 LED,让我们看看使用 PiGPIO 库的另一种方法。
我们将要浏览的代码包含在chapter02/led_pigpio.py文件中。如果上一个示例仍在运行,则终止该示例,然后运行led_pigpio.py。LED 应再次闪烁。
In the Further reading section, you will find relevant links to the PiGPIO API documentation for the specific features of this library that we are using in this section.
让我们浏览一下 PiGPIO 版本的 LED 闪烁代码。
从文件顶部开始,我们有源文件的import部分:
import pigpio # (1)
from time import sleep这一次,在第(1)行中,我们只需要导入 PiGPIO 模块。
接下来,我们将了解如何配置 PiGPIO 并在连接到 LED 的 GPIO 引脚上设置 I/O 模式。
让我们看一下配置 PiGPIO 和 LED 的 GPIO 引脚的代码:
GPIO_PIN = 21
pi = pigpio.pi() # (2)
pi.set_mode(GPIO_PIN, pigpio.OUTPUT) # (3)我们在第(2)行创建一个 PiGPIO 实例,并将其分配给pi变量。我们使用此变量从代码中的这一点开始与 PiGPIO 库交互。
在第(3)行,我们将 GPIO 引脚 21 配置为一个输出引脚。将一个 pin 配置为输出意味着我们希望使用该 pin 从 Python 代码控制连接到它的东西。在本例中,我们希望控制 LED。在本章后面,我们将看到一个用于响应按钮按下的输入引脚示例。
现在我们已经导入了所需的库,并配置了 PiGPIO 和 out GPIO 引脚,现在让我们看看如何使 LED 闪烁。
最后,我们让 LED 闪烁:
while True:
pi.write(GPIO_PIN, 1) # 1 = High = On # (4)
sleep(1) # 1 second
pi.write(GPIO_PIN, 0) # 0 = Low = Off # (5)
sleep(1) # 1 second我们使用while环路实现 PiGPIO 的闪烁。当循环执行时,我们正在切换 GPIO 引脚 21——我们的输出引脚开和关(第(4)行和第(5)行),中间有一个短sleep()功能,因此使 LED 看起来闪烁。
接下来,我们将比较我们的两个库以及它们闪烁 LED 的不同方法。
如果您查看 GPIOZero 示例的代码,很明显我们正在使 LED 闪烁-代码中非常明确。但是 PiGPIO 的例子呢?没有提到 LED 或闪烁。事实上,它可以做任何事情-只是我们知道一个 LED 连接到 GPIO 21。
我们的两个闪烁示例揭示了 GPIOZero 和 PiGPIO 的重要方面:
-
GPIOZero是一个更高级的包装库。表面上,它将常见的电子元件(如 LED)抽象为易于使用的类,而在下面,它将实际的接口工作委托给具体的 GPIO 库。
-
PiGPIO是一个较低级别的 GPIO 库,您可以在其中直接使用、控制和访问 GPIO 引脚。
The "zero" in GPIOZero refers to a naming convention for zero boilerplate code libraries where all of the complex internals are abstracted away to make it easier for beginners to get started.
GPIOZero 使用引脚工厂将其委托给外部 GPIO 库。在我们的示例中,我们使用行Device.pin_factory = PiGPIOFactory()委托给 PiGPIO。我们将在第 5 章中再次讨论 GPIOZero 和委派的主题,将您的树莓圆周率与物理世界连接起来。
当我们继续阅读本书时,我们将同时使用 GPIOZero 和 PiGPIO。我们将使用 GPIOZero 在适当的地方简化和压缩代码,同时我们将使用 PiGPIO 来获得更高级的代码示例,并教授核心 GPIO 概念,否则这些概念将被 GPIOZero 抽象掉。
接下来,我们将通过集成按钮继续构建 LED 闪烁示例。
在上一节中,我们探讨了使 LED 闪烁的两种不同方法——一种使用 GPIOZero 库,另一种使用 PiGPIO 库。在本节中,我们将使用 Python 集成图 2.1中电路中的按钮,并了解如何使用 GPIOZero 和 PiGPIO 库集成按钮。
我们将首先通过使用 GPIOZero 库集成的按钮打开和关闭 LED。
我们将要介绍的代码包含在chapter02/button_gpiozero.py文件中。请检查并运行此文件。按下按钮时,LED 应打开和关闭。根据图 2.1中的电路,LED 仍然连接到 GPIO 21,而我们的按钮连接到 GPIO 23。
As mentioned previously in the Creating a breadboard circuit section , if your button has four legs (two sets will be electrically joined) and your circuit does not work, try rotating the button in the breadboard 90 degrees.
让我们浏览一下代码的重要部分,注意我们正在跳过我们已经讨论过的代码部分。
从源文件的顶部开始,您将找到我们导入外部库的代码部分,如下所示:
from gpiozero import Device, LED, Button # (1)
from gpiozero.pins.pigpio import PiGPIOFactory
import signal # (2)对于本例,我们还导入了 GPIOZeroButton类(1)和 Pythonsignal模块(2)。
现在您已经看到我们正在导入Button类,让我们看看当按下按钮时将调用的处理函数。
我们使用回调处理程序来响应pressed()函数中定义的按钮按下:
def pressed():
led.toggle() # (3)
state = 'on' if led.value == 1 else 'off' # (4)
print("Button pressed: LED is " + state) # (5)在第(3)行,每次使用led的toggle()方法调用pressed()时,我们的 LED 都会打开和关闭。在第(4)行,我们查询led的value属性,以确定 LED 是亮起(value == 1)还是熄灭(value == 0),并将其存储在state变量中,我们将其打印到第(5)行的终端。
You can also control the LED with the led.on(), led.off(), and led.blink() methods . You can also directly set the LED on/off state by setting led.value , for example, led.value = 1 will turn the LED on.
让我们继续,看看如何创建和配置Button类实例,并注册pressed()函数,以便在按下物理按钮时调用它。
以下是用于配置按钮的行。在第(6)行中,我们使用的类是Button。在 GPIOZero 中,我们对任何可以打开或关闭的输入设备使用Button类,例如按钮和开关:
button = Button(BUTTON_GPIO_PIN,
pull_up=True, bounce_time=0.1) # (6)
button.when_pressed = pressed # (7)在第(7)行,我们向我们的button实例注册pressed()回调处理程序。
以下是第(6)行Button构造函数的参数含义:
- 第一个参数是按钮的 GPIO 引脚(
BUTTON_GPIO_PIN == 23。 - 第二个参数
pull_up=True启用 GPIO 23 的内部上拉电阻器。上拉电阻和下拉电阻是数字电子学中的一个重要概念。我们现在将跳过这个概念,因为我们将在第 6 章软件工程师电子 101中更详细地介绍上拉和下拉电阻器的重要性和使用。 - 第三个参数
bounce_time=0.1(0.1 秒)用于补偿称为开关或触点弹跳的事件。
反弹是一种电噪声,当物理按钮或开关内的金属触点聚集在一起时会发生。这种噪声的结果被视为数字输入管脚上开关(或高低)状态的快速连续变化。这是不可取的,因为我们希望一次物理按下按钮(或开关的拨动)被视为输入引脚上的一次状态变化。这通常是通过使用去盎司阈值或超时的代码实现的,在我们的例子中,这是我们的树莓 Pi 忽略初始状态变化后的连续 pin 阶段变化的时间量。
*尝试设置bounce_time=0(无去抖动)。您应该发现按钮的行为非常不稳定。然后,使用更高的数字,如bounce_time=5(5 秒),您会发现,在第一次按下按钮后,直到持续时间到期,按钮都没有响应。
When it comes to push buttons, selecting an appropriate debounce threshold is a matter of balancing how rapidly a user needs to press the button (this demands lower thresholds) versus how much bounce is inherent in your button (this demands higher thresholds). About 0.1 seconds is a good suggested starting value.
最后,让我们介绍一种用于防止退出电子接口 Python 程序的常用技术。
在 GPIO 示例和程序中经常会看到使用signal.pause()或等效构造:
signal.pause() # Stops program from exiting. # (8)第(8)行阻止主程序线程到达其自然端,在正常情况下,该自然端是程序终止的地方。
Forgetting to add signal.pause() to the end of a GPIO-interfacing Python program is a common and often confusing mistake when starting out. If your program exits immediately after it's started, try adding signal.pause() at the end of your program as a first step.
我们之前的 LED 闪烁示例不需要signal.pause()。原因如下:
- 我们的 GPIOZero 示例(
chapter02/led_gpiozero.py在 LED 构造函数中使用了background=False。这通过将 LED 的线程保持在前台来防止我们的程序退出。 - 在 PiGPIO 示例(
chapter02/led_pigpio.py中,while循环阻止程序退出。
如果这看起来令人困惑,不要担心!了解如何防止程序不正常地存在,归根结底是经验、实践和理解 Python 和 GPIO 库是如何工作的。
接下来,让我们看看如何使用 PiGPIO 集成按钮。
现在,我们将复制与上一个 GPIOZero 示例相同的功能,通过按下按钮来打开和关闭 LED,只是这次使用 PiGPIO 库。我们 PiGPIO 示例的代码可以在chapter02/button_pigpio.py文件中找到。请现在查看并运行此文件,并确认 LED 响应您的按钮按下。
让我们从按钮的 GPIO 引脚配置开始,分析代码中有趣的部分(再次注意,我们跳过了已经介绍过的代码部分)。
从第(1)行开始,我们将 GPIO 引脚 23(BUTTON_GPIO_PIN == 23配置为输入引脚:
pi.set_mode(BUTTON_GPIO_PIN, pigpio.INPUT) # (1)
pi.set_pull_up_down(BUTTON_GPIO_PIN, pigpio.PUD_UP) # (2)
pi.set_glitch_filter(BUTTON_GPIO_PIN, 10000) # (3)接下来,在第(2)行,我们为引脚 23 启用一个内部上拉电阻器。在 PiGPIO 中,我们使用pi.set_glitch_filter()方法对第(3)行上的按钮进行去抖动。此方法以毫秒为单位获取参数。
注意,在 PiGPIO 中,我们需要将按钮的每个属性(引脚输入模式、上拉电阻器和去抖动)配置为离散方法调用,而在前面的 GPIOZero 示例中,当我们创建 GPIOZero LED 类的实例时,这一切都发生在一行上。
我们的按钮回调处理程序是从第(4)行开始定义的,比以前的 GPIOZero 处理程序更复杂:
def pressed(gpio_pin, level, tick): # (4)
# Get current pin state for LED.
led_state = pi.read(LED_GPIO_PIN) # (5)
if led_state == 1: # (6)
# LED is on, so turn it off.
pi.write(LED_GPIO_PIN, 0) # 0 = Pin Low = Led Off
print("Button pressed: Led is off")
else: # 0
# LED is off, so turn it on.
pi.write(LED_GPIO_PIN, 1) # 1 = Pin High = Led On
print("Button pressed: Led is on")
# Register button handler.
pi.callback(BUTTON_GPIO_PIN, pigpio.FALLING_EDGE, pressed) # (7)注意pressed(gpio_pin, level, tick)的签名。我们以前的 GPIOZero 版本没有参数,而 PiGPIO 有三个必需参数。我们简单的单按钮示例不使用这些参数;但是,为了完整性,它们如下所示:
gpio_pin:这是负责调用回调的 pin 码。在我们的例子中是 23。level:这是 pin 的状态。对我们来说,这将是pigpio.FALLING_EDGE(我们将很快了解原因)。tick:这是自启动以来的微秒数。
在第(5)行,我们将 GPIO 21(我们的 LED)的当前状态读入一个带有led_state = pi.read()的变量。然后,从第(6)行开始,根据 LED 当前是亮起(led_state == 1)还是熄灭(led_state == 0),我们使用pi.write()将 GPIO 21 设置为高或低,以将 LED 切换到其反向开启或关闭状态。
最后,在第(7)行注册回调处理程序。参数值pigpio.FALLING_EDGE表示每当 GPIO 引脚BUTTON_GPIO_PIN(即 23)开始从数字高电平转换为数字低电平时,调用处理程序为pressed()。这比简单地测试引脚是高还是低要明确得多;但是,为了简单起见,考虑下面的级别参数选项来选择 Ty3T.尝试更改参数,然后查看按下按钮时发生的情况:
pigpio.FALLING_EDGE:这是低的(想想朝着低的方向下降。当您按下按钮时,会调用pressed()。pigpio.RAISING_EDGE:这很高(想想将升高到高)。当您松开按钮时,会调用pressed()。pigpio.EITHER_EDGE:可以高也可以低。当您同时按下和释放按钮时,会调用pressed(),这实际上意味着只有当您按下按钮时,LED 才会点亮。
您是否注意到或认为在 PiGPIO 示例的任何阶段,当按下按钮时,即您激活按钮-GPIO 引脚 23 变低(即第(7)行上的pigpio.FALLING_EDGE参数),从而导致pressed()开始调用?从编程的角度来看,这似乎有点背道而驰还是错误?我们将在第 6 章、软件工程师电子 101中重新探讨这个想法并讨论其背后的原因。
就目前而言,GPIO 库和电子产品已经足够了。我们已经了解了如何使用 GPIOZero 和 PiGPIO 库响应按钮按下。特别是,我们看到 GPIOZero 方法与 PiGPIO 方法相比非常简单和直接,后者涉及更多代码和更多配置。这与我们在上一节中发现的结果相同,探索了用 Python闪烁 LED 的两种方法——也就是说,GPIOZero 方法更简单。
一种方法比另一种好吗?这一切的答案都取决于你想要达到的目标,以及你需要对你的电子接口进行多低级别的控制才能达到这个目标。在本书的这一阶段,我只想给大家提供关于 GPIO 库的对比选项,以及我们如何将它们与电子设备接口。当我们在第 5 章将树莓 Pi 连接到物理世界中重温流行的 Python GPIO 库时,我们将再次更详细地讨论这个主题。
让我们继续并创建一个物联网程序,通过互联网控制我们的 LED。
我们将创建一个 Python 程序,与名为dweet.io的服务集成。他们的网站是这样描述这项服务的:“就像社交机器的 Twitter
我们将通过将 URL 粘贴到 web 浏览器中,创建简单的dweets,,这是 dweet.io 相当于tweet,。
我们的程序将通过轮询 dweet.io RESTful API 端点来监视和接收数据。当接收到数据时,将对其进行分析,以找到一条指令,该指令指定我们的 LED 是否应打开或关闭,或使其闪烁。根据此指令,我们的 LED 状态将使用 GPIOZero 库进行更改。在后续标题为理解服务器代码的章节中,我们将讨论从 dweet.io 接收的数据格式。
We're using the free public dweet.io service where all information is publicly accessible, so do not publish any sensitive data. There is a professional service available at dweetpro.io that provides data privacy, security, dweet retention, and other advanced features.
该程序的代码包含在chapter02/dweet_led.py文件中。在继续之前,请通读此文件中的源代码,以全面了解正在发生的事情。
在本节中,我们将运行 Python 服务器程序并与之交互,该程序允许我们通过复制和粘贴链接从 web 浏览器控制 LED。一旦我们使用该程序来控制 LED,我们将在下一节深入研究代码的机制及其工作原理。
以下是要遵循的步骤:
- 运行
chapter02/dweet_led.py程序。您应该看到类似于以下内容的输出:
(venv) $ python dweet_led.py
INFO:main:Created new thing name a8e38712 # (1)
LED Control URLs - Try them in your web browser:
On : https://dweet.io/dweet/for/a8e38712?state=on # (2)
Off : https://dweet.io/dweet/for/a8e38712?state=off
Blink : https://dweet.io/dweet/for/a8e38712?state=blink
INFO:main:LED off
Waiting for dweets. Press Control+C to exit.在第(1)行,程序为我们的东西创建了一个唯一的名称,用于 dweet.io。您会在第(2)行开始的 URL 中注意到这个名称。为您的对象创建的名称将与前面的示例不同。
A thing name in dweet.io is analogous to an @handle on Twitter.
- 将第(2)行起始处的 URL 复制并粘贴到 web 浏览器中(可能是一台计算机,而不是 Raspberry Pi)。短暂延迟后,LED 应根据使用的 URL 改变其状态(打开、关闭或闪烁)。
一旦您确认 LED 可以使用 URL 控制,我们将继续并查看程序。
在本节中,我们将逐步介绍dweet_led.py程序的主要部分,并从导入开始了解其工作原理。
首先,在源代码文件的开头,我们看到 Python 导入:
...truncated...
import requests # (1)我想提请你们注意一个特别的问题。在第(1)行,我们正在导入request模块(这是在本章前面运行pip install -r requirements.txt时安装的)。requests是一个用 Python 进行 HTTP 请求的高级库。我们的程序使用这个模块与 dweet.ioAPI 进行通信,稍后我们将看到。
现在我们了解了我们正在导入并且稍后将使用requests库,让我们介绍一下我们程序中使用的全局变量。
接下来,我们定义几个全局变量。现在,请查看以下评论,以供参考。您将看到在代码中使用它们:
LED_GPIO_PIN = 21 # LED GPIO Pin
THING_NAME_FILE = 'thing_name.txt' # Thing name file
URL = 'https://dweet.io' # Dweet.io service API
last_led_state = None # "on", "off", "blinking"
thing_name = None # Thing name
led = None # GPIOZero LED instance当您阅读主源文件时,遵循这些变量定义,您还会注意到我们使用的是 Python 日志记录系统,而不是print()语句:
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger('main') # Logger for this module
logger.setLevel(logging.INFO) # Debugging for this file. # (2)如果您需要打开程序调试以诊断问题或查看我们的程序与 dweet.io 服务之间交换的原始 JSON 数据,请将第(2)行更改为logger.setLevel(logging.DEBUG)。
接下来,我们将逐步介绍程序中的重要方法,并了解它们的作用。
resolve_thing_name()方法负责为我们的对象加载或创建一个唯一的名称,以便与 dweet.io 一起使用。
使用此方法时,我们的目的是始终重复使用名称,以便在程序重新启动期间,用于控制 LED 的 dweet URL 保持不变:
def resolve_thing_name(thing_file):
"""Get existing, or create a new thing name"""
if os.path.exists(thing_file): # (3)
with open(thing_file, 'r') as file_handle:
name = file_handle.read()
logger.info('Thing name ' + name +
' loaded from ' + thing_file)
return name.strip()
else:
name = str(uuid1())[:8] # (4)
logger.info('Created new thing name ' + name)
with open(thing_file, 'w') as f: # (5)
f.write(name)
return name在第(3)行,如果文件存在,我们加载之前存储在thing_file中的名称;否则,我们使用第(4)行上的 PythonUUID模块方法uuid1()创建一个 8 个字符的唯一标识符,并将其用作对象名称。我们将这个新创建的标识符和名称存储在第(5)行的thing_file中。
接下来,我们将看一看用于检索对对象所做的最后一个 dweet 的函数。
get_lastest_dweet()查询 dweet.io 服务以检索为*物品制作的最新 dweet(如果有)。*下面是我们期望收到的 JSON 响应示例。我们最终感兴趣的是第(1)行的content.state财产:
{
this: "succeeded",
by: "getting",
the: "dweets",
with: [
{
thing: "a8e38712-9886-11e9-a545-68a3c4974cd4",
created: "2019-09-16T05:16:59.676Z",
content: {
state: "on" # (1)
}
}
]
}查看以下代码,我们可以在第(6)行中看到用于查询 dweet.io 服务的资源 URL 的创建。对该 URL 的调用将返回一个类似于前面所示的 JSON。您将在进一步阅读部分找到完整 dweet.io API 参考的链接。
接下来,在第(7)行,requests模块用于发出 HTTP GET 请求以检索最新的 dweet:
def get_lastest_dweet():
"""Get the last dweet made by our thing."""
resource = URL + '/get/latest/dweet/for/' + thing_name # (6)
logger.debug('Getting last dweet from url %s', resource)
r = requests.get(resource) # (7)在下面的第(8)行中,我们检查请求是否在 HTTP 协议级别成功。如果在第(9)行成功,我们将继续解析 JSON 响应,并从第(10)行开始提取并返回content属性:
if r.status_code == 200: # (8)
dweet = r.json() # return a Python dict.
logger.debug('Last dweet for thing was %s', dweet)
dweet_content = None
if dweet['this'] == 'succeeded': # (9)
# Interested in the dweet content property.
dweet_content = dweet['with'][0]['content'] # (10)
return dweet_content
else:
logger.error('Getting last dweet failed
with http status %s', r.status_code)
return {}我们的下一个覆盖方法是poll_dweets_forever(),它将使用get_lastest_dweet()。
poll_dweets_forever()是一个长时间运行的函数,它定期在第(11)行调用我们刚才介绍的get_lastest_dweet()方法。当 dweet 可用时,process_dweet()将在第(12)行处理,我们将很快讨论:
def poll_dweets_forever(delay_secs=2):
"""Poll dweet.io for dweets about our thing."""
while True:
dweet = get_last_dweet() # (11)
if dweet is not None:
process_dweet(dweet) # (12)
sleep(delay_secs) # (13)在继续循环之前,我们在第(13)行上默认延迟 2 秒。实际上,这意味着在使用其中一个 dweeting URL 请求 LED 状态更改和 LED 更改其状态之间将有大约 2 秒的延迟。
At this point in the master source file, you will come across a function named stream_dweets_forever(). This is an alternative and more efficient stream-based method of accessing dweets in real time using HTTP streaming.
The polling-based approach of poll_dweets_forever() was chosen here for discussion for simplicity. It will become clear as you read on where you can switch approaches.
我们的下一站是控制 LED 的方法。
正如我们前面看到的,poll_dweets_forever()(类似于stream_dweets_forever())获取 dweet 时,它从 dweet 的 JSON 解析出content属性。然后传递给process_dweet()进行处理,我们从content属性中提取state子属性:
def process_dweet(dweet):
"""Inspect the dweet and set LED state accordingly"""
global last_led_state
if not 'state' in dweet:
return
led_state = dweet['state'] # (14)
if led_state == last_led_state: # (15)
return; # LED is already in requested state.在第(15)(和(17)行的后续代码块中,我们测试并维护 LED 的最后一个已知状态,如果 LED 已经处于请求状态,则避免与 LED 交互。这将避免 LED 在已经闪烁时重复进入闪烁状态时可能出现的潜在视觉闪烁。
process_dweet()的核心是访问 dweet 的state属性并改变 LED 的状态,该状态从第(16)行开始:
if led_state == 'on': # (16)
led_state = 'on'
led.on()
elif led_state == 'blink':
led_state = 'blink'
led.blink()
else: # Off, including any unhanded state.
led_state = 'off'
led.off()
last_led_state = led_state # (17)
logger.info('LED ' + led_state)在第(16)行之后,我们根据 dweet 设置 LED 状态(记住,led变量是 GPIOZero LED 实例),然后在第(17)行跟踪新状态,如前所述,以便在第(15)行调用process_dweet()时进行后续测试。
由于 GPIOZero 的简单性,我们的 LED 控制代码在代码中只是短暂的出现!
最后,我们将介绍该计划的主要切入点。
在源文件的末尾,我们有以下代码:
# Main entry point
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler) # Capture CTRL + C
print_instructions() # (18)
# Initialize LED from last dweet.
latest_dweet = get_latest_dweet() # (19)
if (latest_dweet):
process_dweet(latest_dweet)
print('Waiting for dweets. Press Control+C to exit.')
#Only use one of the following.
#stream_dweets_forever() # Stream dweets real-time.
poll_dweets_forever() # Get dweets by polling. # (20)在第(8)行,print_instructions()负责将甜美 URL 打印到终端,而在第(19)行,我们看到对get_latest_dweet()的调用。当程序启动时,此调用将 LED 初始化为最后一个 dweeted 状态。最后,在第(20)行,我们开始轮询 dweet.io 服务以访问最新的 dweet。在这里,您可以将 dweet 轮询方法交换为流式方法。
这就完成了我们对dweet_led.py的演练。通过本次讨论,我们现在已经了解了如何利用 dweet.io 服务创建一个简单且功能强大的物联网计划。在我们完成本章之前,我想给你们留下两个额外的源代码文件,你们可以用它们来扩展你们的物联网计划。
chapter02文件夹中的以下两个文件结合了我们所学的概念,补充了本章的内容。由于总体代码和方法与我们已经介绍的类似,我们将不详细介绍代码:
dweet_button.py提供了一个实现,展示了如何使用按钮通过 dweet.io 服务创建 dweet。这将允许您通过按下按钮更改 LED 状态。pigpio_led_class.py提供了一个代码级示例,说明像 PiGPIO 这样的低级库如何与像 GPIOZero 这样的高级库相关联。
我们将从讨论dweet_button.py开始。
dweet_button.py中的此程序将 GPIOZero 按钮示例与 dweet.io 集成。在本章的前面,在标题为运行和测试 Python 服务器的部分中,我们将 URL 复制并粘贴到 web 浏览器中,以控制我们的 LED。
当您运行dweet_button.py时,每次按下按钮,该程序都会在 dweet.io URL 中循环以更改 LED 的状态。要配置此程序,请使用您正在使用的dweet_led.py名称查找并更新以下行:
thing_name = '**** ADD YOUR THING NAME HERE ****'请记住,您还需要在终端中运行dweet_led.py程序,否则,LED 将不会响应您的按钮按下。
接下来,我们将看到如何使用 PiGPIO 和 Python 类模拟 GPIOZero。
在pigpio_led_class.py文件中,我们有一个 Python 类,它是对 PiGPIO 示例的重新设计,将其包装为一个模仿 GPIOZeroLED类的类。它演示了 GPIOZero 如何抽象出较低级别的 GPIO 复杂性的基本原理。这个重新设计的类可以作为本章中 GPIOZeroLED示例的替代品,如下所示。更多信息请参见pigpio_led_class.py中的标题注释:
""" chapter02/dweet_led.py """
...
# from gpiozero import LED # Comment out import
from pigpio_led_class import PiGPIOLED as LED # Add new import我希望您会发现这两个奖励文件很有趣,并且通过将 PiGPIO LED 作为一个类示例进行研究,您可以更好地了解高级 GPIOZero 库和低级 PiGPIO 库是如何相互关联的。
在你的旅程的这个阶段,如果你对pigpio_led_class.py发生了什么有点不清楚,不要担心。我只想简单地列出一个 GPIO 库交互的简单示例,供您在端到端应用程序的上下文中思考,因为这将作为您继续阅读时的参考点。我们将在第 5 章、将树莓 Pi 连接到物理世界中更详细地介绍 GPIOPZero 和 PiGPIO 库(以及其他库),此外,我们还将在中介绍更高级的概念,如电子接口程序中的线程(类似于pigpio_led_class.py中的线程使用)第 12 章、高级物联网编程概念——线程、异步 IO 和事件循环。
通过本章,您刚刚使用 Raspberry Pi 和 Python 创建了一个真正的功能性物联网应用程序。我们看到了在 Python 中使用 GPIOZero 和 PiGPIO 库闪烁 LED 和读取按键的两种可选方法。我们还比较了这些库的使用情况,发现 GPIOZero 采用了比低级别 PiGPIO 库更高级、更抽象的编码和 GPIO 控制方法。我们还使用在线 dweet.io 服务将 LED 连接到互联网。通过使用简单的 URL,我们可以通过在 web 浏览器中访问 URL 来打开、关闭和闪烁 LED。
当您继续阅读本书后续章节时,我们将在本章中学习到的关于 GPIO 接口、电子电路和通过互联网控制电路的核心知识的基础上继续深入学习。我们将学习在本章中介绍的基础上构建应用程序的替代方法,并发现与 GPIO 控制和电子接口相关的核心原则。有了这些深入的知识,您将能够在完成本书时创建更强大、更宏大的物联网解决方案!
在第 3 章中,使用 Flask与 RESTful API 和 Web 套接字联网,我们将研究流行的 Flask microservices 框架,我们将创建两个基于 Python 的 Web 服务器和附带的网页,通过本地网络或 internet 控制 LED。
下面是一个问题列表,供您测试有关本章材料的知识。您可以在本书的评估部分找到答案:
- 您没有正确的电阻值。你能用另一个放在周围的电阻值来代替吗?
- GPIOZero 包是一个 GPIO 库。这就是你所需要的一切吗?
- 您是否应该尽可能始终使用内置 Python 包进行联网?
- 正确或错误:n LED 是无偏的,这意味着它可以以任何方式插入电路,并且仍然工作。
- 您正在构建一个物联网应用程序,该应用程序与其他现有网络设备交互,并且超时。有什么问题吗?
- 什么 Python 模块和函数可以用来阻止程序退出?
我们使用 dweet.io 服务将 LED 连接到互联网,并调用其 RESTful API,这些 API 记录在以下位置:
- Dweet.io API 文档:https://dweet.io
您可能希望简单地熟悉 GPIOZero 库,了解它的功能。它有大量的例子。以下是到目前为止我们已经介绍过的 API 文档相关部分的几个有用链接:
- GPIOZero 主页:https://gpiozero.readthedocs.io
- 输出设备(LED):https://gpiozero.readthedocs.io/en/stable/api_output.html
- 输入设备(按钮):https://gpiozero.readthedocs.io/en/stable/api_input.html
关于 PiGPIO,以下是其 API 文档的相关部分。您会注意到 PiGPIO 是一个更高级的 GPIO 库,其文档较少冗长。
- PiGPIO Python 主页:http://abyz.me.uk/rpi/pigpio/python.html
read()方法:http://abyz.me.uk/rpi/pigpio/python.html#readwrite()方法:http://abyz.me.uk/rpi/pigpio/python.html#writecallback()方法:http://abyz.me.uk/rpi/pigpio/python.html#callbackset_glitch_filter():https://abyz.me.uk/rpi/pigpio/python.html#set_glitch_filter
电阻器是一种非常常见的电子元件。以下资源概述了电阻器以及如何读取其色带以确定其电阻值(欧姆):
- 电阻器概述:https://www.electronics-tutorials.ws/resistor/res_1.html
- 阅读色带:https://www.electronics-tutorials.ws/resistor/res_2.html
以下 Spark Fun 教程提供了阅读 s 化学图的精彩介绍:
- 如何阅读原理图:https://learn.sparkfun.com/tutorials/how-to-read-a-schematic/all********











