Python 算术运算、循环和闪烁的灯光详解

现在让我们看一下这一章,在这里我们将复习 Python 中的算术运算和变量。我们还将讨论 Python 中的字符串和接受用户输入。您将了解 Raspberry Pi 的 GPIO 及其特性,并使用 Python 编写代码,使用 Raspberry Pi Zero 的 GPIO 使 LED 闪烁。我们还将讨论控制树莓 Pi 的 GPIO 的实际应用。

在本章中,我们将介绍以下主题:

在本章中,我们将讨论控制 Raspberry Pi 的 GPIO 的示例。我们需要一个试验板、跨接导线、LED 和一些电阻器(330 或 470 欧姆)来讨论这些示例。

我们还需要一些可选的硬件,我们将在本章最后一节讨论这些硬件。

Python 支持执行所有标准算术运算。让我们启动 Python 解释器并了解更多信息:

  • 加法:可以使用+操作数将两个数字相加。结果打印在屏幕上。使用 python 解释器尝试以下示例:
       >>>123+456 
       579
  • 减法:可以使用-操作数将两个数字相加:
       >>>456-123 
       333 
       >>>123-456 
       -333
  • 乘法:两个数字可以相乘,如下所示:
       >>>123*456 
       56088
  • 划分:两个数字可以划分为:
       >>>456/22 
       20.727272727272727 
       >>>456/2.0 
       228.0 
       >>>int(456/228) 
       2
  • 模运算符:在 Python 中,模运算符(%返回除法运算的剩余部分:
       >>>4%2 
       0 
       >>>3%2 
       1
  • 楼层操作符//与模数操作符相反。此运算符返回商的下限,即整数结果,并丢弃分数:
       >>>9//7 
       1 
       >>>7//3 
       2 
       >>>79//25 
       3

在 Python 中,可以对数字执行位级操作。这在解析来自某些传感器的信息时特别有用。例如,某些传感器以特定频率共享其输出。当新数据点可用时,将设置一个特定位,指示数据可用。位运算符可用于在从传感器检索数据点之前检查是否设置了特定位。

如果您对深入研究逐位运算符感兴趣,我们建议您从开始 https://en.wikipedia.org/wiki/Bitwise_operation

考虑其数值 T0 和 T1,其二元等价是分别为 T2 T2 和 AUT T3。让我们来看一看不同的操作符,它对数字的每一个比特执行操作:

  • AND 运算符:AND 运算符用于对两个数字进行 AND 运算。使用 Python 解释器尝试以下操作:
       >>>3&2 
       2

这相当于以下步骤和操作:

   0 1 1 &
   0 1 0
   --------
   0 1 0 (the binary representation of the number 2)
  • OR 运算符:OR 运算符用于对两个数字执行 OR 操作,如下所示:
       >>>3|2 
       3

这相当于以下 OR 操作:

   0 1 1 OR
   0 1 0
   --------
   0 1 1 (the binary representation of the number 3)
  • 非运算符:非运算符翻转数字的位。请参见以下示例:
       >>>~1 
       -2

在前面的示例中,位被翻转,即,1作为00作为1。因此,1的二进制表示为0001,当执行按位 NOT 运算时,结果为1110。解释器将结果返回为-2,因为负数存储为其二的补码1的两个补语是-2

For a better understanding of two's complement and so on, we recommend reading the following articles, https://wiki.python.org/moin/BitwiseOperators and https://en.wikipedia.org/wiki/Two's_complement.

  • 异或运算符:异或运算可以按如下方式执行:
       >>>3^2 
       1
  • 左移位运算符:左移位运算符允许将给定值的位向左移位所需的位数。例如,将数字3位移到左边,就得到了数字6。数字3的二进制表示为0011。将位左移一个位置将得到0110,即数字6
       >>>3<<1 
       6
  • 右移位运算符:右移位运算符允许将给定值的位向右移位所需的位数。启动命令行解释器并亲自尝试。当您将数字6向右移动一个位置时会发生什么情况?

逻辑运算符用于检查不同的条件并相应地执行代码。例如,检测到与 Raspberry Pi 的 GPIO 接口的按钮被按下,从而执行特定任务。让我们讨论一下基本的逻辑运算符:

  • 相等:相等(==运算符用于比较两个值是否相等:
       >>>3==3 
       True 
       >>>3==2 
       False
  • 不相等:不相等(!=运算符比较两个值,如果不相等,则返回True
       >>>3!=2 
       True 
       >>>2!=2 
       False
  • 大于:如果一个值大于另一个值,则此运算符(>)返回True
       >>>3>2 
       True 
       >>>2>3 
       False
  • 小于:此运算符比较两个值,如果一个值小于另一个值,则返回True
       >>>2<3 
       True 
       >>>3<2 
       False
  • 大于或等于(>=):此运算符比较两个值,如果一个值大于或等于另一个值,则返回True
       >>>4>=3 
       True 
       >>>3>=3 
       True 
       >>>2>=3 
       False
  • 小于或等于(<=):此运算符比较两个值,如果一个值小于或等于另一个值,则返回True
       >>>2<=2 
       True 
       >>>2<=3 
       True 
       >>>3<=2 
       False

在 Python 中,变量用于在程序执行期间将结果或值存储在计算机内存中。变量可以轻松访问计算机内存中的特定位置,并可以编写用户可读的代码。

例如,让我们考虑一个人想从办公室或大学里得到新的身份证的情景。该人员将被要求填写一份包含相关信息的申请表,包括姓名、部门和紧急联系信息。表单将具有必需的字段。这将使办公室经理能够在创建新的身份证时参考表格。

类似地,变量通过提供将信息存储在计算机内存中的方法来简化代码开发。如果必须在编写代码时牢记存储内存映射,那么编写代码将非常困难。例如,使用名为 name 的变量比使用像0x3745092这样的特定内存地址更容易。

Python 中有不同类型的数据类型。让我们回顾一下不同的数据类型:

  • 通常,姓名、街道地址等是字母数字字符的组合。在 Python 中,它们存储为字符串。Python 中的字符串表示并存储在变量中,如下所示:
       >>>name = 'John Smith' 
       >>>address = '123 Main Street'
  • Python 中的数字可以存储如下:
       >>>age = 29 
       >>>employee_id = 123456 
       >>>height = 179.5 
       >>>zip_code = 94560
  • Python 还支持存储布尔变量。例如,一个人的器官捐赠者状态可以是TrueFalse
       >>>organ_donor = True
  • 可以同时将值分配给多个变量:
       >>>a = c= 1 
       >>>b = a
  • 变量可以删除如下:
       >>>del(a)

Python 中还有其他数据类型,包括列表、元组和字典。我们将在下一章详细讨论这一点。

现在,我们将讨论一个简单的程序,其中我们要求用户输入两个数字,程序返回两个数字的总和。现在,我们要假装用户总是提供有效的输入。

在 Python 中,可以使用input()函数(提供 Python 程序的用户输入 https://docs.python.org/3/library/functions.html#input

    var = input("Enter the first number: ")

在前面的示例中,我们使用input()函数来查找用户输入的号码。input()函数将提示("Enter the first number: ")作为参数,并返回用户输入。在此示例中,用户输入存储在变量var中。为了增加两个数字,我们利用input()功能要求用户提供两个数字作为输入:

    var1 = input("Enter the first number: ") 
    var2 = input("Enter the second number: ") 
    total = int(var1) + int(var2) 
    print("The sum is %d" % total)

我们正在利用input()功能查找用户对两个数字的输入。在这种情况下,用户号码分别存储在var1var2中。 用户输入是一个字符串。在添加它们之前,我们需要将它们转换为整数。我们可以使用int()函数(将字符串转换为整数 https://docs.python.org/3/library/functions.html#int )。

int()函数将字符串作为参数,并返回转换后的整数。转换后的整数相加并存储在变量total中。上述示例与本章一起作为input_function.py下载。

If the user input is invalid, the int() function will throw an exception indicating that an error has occurred. Hence, we assumed that user inputs are valid in this example. In a later chapter, we will discuss catching exceptions that are caused by invalid inputs.

以下快照显示程序输出:

The input_function.py output

让我们重温上一节讨论的示例。我们将结果打印如下:

    print("The sum is %d" % total)

在 Python 中,可以格式化字符串以显示结果。在前面的示例中,我们使用%d表示它是整数变量的占位符。这允许打印带有整数的字符串。除了向print()函数传递参数的字符串外,还向需要打印的变量传递参数。在前面的示例中,使用%运算符传递变量。也可以传递多个变量:

    print("The sum of %d and %d is %d" % (var1, var2, total))

也可以按如下方式格式化字符串:

    print("The sum of 3 and 2 is {total}".format(total=5))

format()方法允许使用大括号({}作为占位符格式化字符串。在前面的示例中,我们使用total作为占位符,并使用 string 类的 format 方法填充每个占位符。

使用format()方法格式化包含多个变量的字符串。

让我们构建一个控制台/命令行应用程序,从用户那里获取输入并将其打印到屏幕上。让我们创建一个名为input_test.py的新文件(与本章下载一起提供),获取一些用户输入并将其打印在屏幕上:

    name = input("What is your name? ") 
    address = input("What is your address? ") 
    age = input("How old are you? ") 

    print("My name is " + name) 
    print("I am " + age + " years old") 
    print("My address is " + address)

执行程序,看看会发生什么:

The input_test.py output

上述示例与本章一起作为input_test.py下载。

使用字符串格式化技术重复前面的示例。

在前面的示例中,我们结合另一个字符串打印用户输入。例如,我们接受用户输入name并将句子打印为My name is Sai。将一个字符串附加到另一个字符串的过程称为串联

在 Python 中,可以通过在两个字符串之间添加+来连接字符串:

    name = input("What is your name? ") 
    print("My name is " + name)

可以连接两个字符串,但不能连接整数。让我们考虑下面的例子:

    id = 5 
    print("My id is " + id)

它将抛出一个错误,暗示整数和字符串不能组合:

An exception

可以将整数转换为字符串并将其连接到另一个字符串:

    print("My id is " + str(id))

这将产生以下结果:

有时,一项特定的任务必须重复几次。在这种情况下,我们可以使用循环。在 Python 中,有两种类型的循环,即for循环和while循环。让我们用具体的例子来回顾它们。

在 Python 中,for循环用于执行任务n次。for 循环遍历序列的每个元素。此序列可以是字典、列表或任何其他迭代器。例如,让我们讨论一个执行循环的示例:

    for i in range(0, 10): 
       print("Loop execution no: ", i)

在上例中,print语句执行 10 次:

为了执行print任务 10 次,range()功能(https://docs.python.org/2/library/functions.html#range 使用)。range函数为开始值和停止值生成一个数字列表,作为参数传递给函数。在这种情况下,010作为参数传递给range()函数。这将返回一个包含从09的数字的列表。for循环在步骤 1 中遍历每个元素的代码块。range功能还可以按步骤 2 生成数字列表。这是通过将开始值、停止值和步长值作为参数传递给range()函数来实现的:

    for i in range(0, 20, 2): 
       print("Loop execution no: ", i)

本例中,0为起始值,20为停止值,2为阶跃值。这将以两个步骤生成一个包含 10 个数字的列表:

range功能可用于从给定数字开始倒计时。假设我们要从10倒计时到1

    for i in range(10, 0, -1): 
       print("Count down no: ", i)

输出类似于:

range函数的一般语法为range(start, stop, step_count)。它生成从startn-1的数字序列,其中n是停止值。

注意for回路块中的压痕

    for i in range(10, 1, -1): 
       print("Count down no: ", i)

Python 执行for循环语句下的代码块。这是 Python 编程语言的特性之一。只要缩进级别相同,它就会执行for循环下的任何代码:

    for i in range(0,10): 
       #start of block 
       print("Hello") 
       #end of block

缩进有以下两种用途:

  • 它使代码可读
  • 它帮助我们识别循环中要执行的代码块

注意 Python 中的缩进非常重要,因为缩进直接影响代码的执行方式。

在 Python 中,可以在循环中实现循环。例如,我们必须打印地图的xy坐标。我们可以使用嵌套循环来实现这一点:

for x in range(0,3): 
   for y in range(0,3): 
         print(x,y)

预期产出为:

要小心嵌套循环中的代码缩进,因为它可能会引发错误。考虑下面的例子:

for x in range(0,10): 
   for y in range(0,10): 
   print(x,y)

Python 解释器将抛出以下错误:

    SyntaxError: expected an indented block

这在以下屏幕截图中可见:

因此,重要的是要注意 Python 中的缩进(特别是嵌套循环),以成功地执行代码。IDLE 的文本编辑器会在您编写代码时自动缩进代码。这将有助于理解 Python 中的缩进。

while循环用于在满足特定条件之前执行特定任务。while循环通常用于在无限循环中执行代码。让我们看一个具体的例子,我们想将i的值从0打印到9

i=0 
while i<10: 
  print("The value of i is ",i) 
  i+=1

while循环中,我们为每个迭代增加i1i的值按如下方式递增:

i += 1

这相当于i = i+1

本例将执行代码,直到i的值小于 10。也可以在无限循环中执行某些操作:

i=0 
while True: 
  print("The value of i is ",i) 
  i+=1

按键盘上的Ctrl+C可以停止这个无限循环的执行。

也可以有嵌套的while循环:

i=0 
j=0 
while i<10: 
  while j<10: 
    print("The value of i,j is ",i,",",j) 
    i+=1 
    j+=1

for循环类似,while循环也依赖缩进的代码块来执行一段代码。

Python enables printing a combination of strings and integers as long as they are presented as arguments to the print function separated by commas. In the earlier-mentioned example, The value of i,j is, i are arguments to the print function. You will learn more about functions and arguments in the next chapter. This feature enables formatting the output string to suit our needs.

Raspberry Pi Zero 配有 40 针 GPIO 头。在这 40 个引脚中,我们可以使用 26 个引脚读取输入(来自传感器)或控制输出。其他引脚为电源引脚(5V3.3V接地引脚):

Raspberry Pi Zero GPIO mapping (source: https://www.raspberrypi.org/documentation/usage/gpio-plus-and-raspi2/README.md)

我们可以使用多达 26 个 Raspberry Pi 的 GPIO 引脚来连接和控制设备。但是,有些管脚具有替代功能。

前面的图像显示了 Raspberry Pi 的 GPIO 引脚的映射。圆圈中的数字对应于 Raspberry Pi 处理器上的管脚编号。例如,GPIO 引脚2(底部一行左侧的第二个引脚)对应于 Raspberry Pi 处理器上的 GPIO 引脚2,而不是 GPIO 头上的物理引脚位置。

一开始,试图理解 pin 映射可能会让人困惑。保存一份 GPIO pin 讲义(可与本章一起下载),以供参考。要习惯 RespberryPi 零点的 GPIO 引脚映射需要一些时间。

The Raspberry Pi Zero's GPIO pins are 3.3V tolerant, that is, if a voltage greater than 3.3V is applied to the pin, it may permanently damage the pin. When set to high, the pins are set to 3.3V and 0V when the pins are set to low.

让我们讨论一个使用 Raspberry Pi Zero 的 GPIO 的示例。我们将把一个 LED 连接到 RespberryPi 零点,使其以 1 秒的间隔闪烁

让我们连接 RespberryPi 零开始:

Blinky schematic generated using Fritzing

在前面的示意图中,GPIO 引脚 2 连接到 LED 的阳极(最长的支脚)。LED 的阴极连接到 Raspberry Pi Zero 的接地引脚。330 欧姆限流电阻器也用于限制电流。

Breadboard connections to the Raspberry Pi Zero

我们将使用python3-gpiozero图书馆(https://gpiozero.readthedocs.io/en/v1.3.1/Raspbian Jessie操作系统映像附带预安装的库。它使用起来非常简单,是初学者入门的最佳选择。它支持一套标准设备,帮助我们轻松入门。

例如,为了连接 LED,我们需要从gpiozero库中导入LED类:

from gpiozero import LED

我们将以 1 秒的间隔打开和并关闭LED。为此,我们将导入库。在 Python 中,我们需要导入一个库来利用它。由于我们将 LED 连接到 GPIO 引脚 2,因此让我们在代码中提及:

import time 

led = LED(2)

我们刚刚创建了一个名为led的变量,并定义我们将在LED类中使用 GPIO 引脚 2。让我们利用while环路以 1 秒的间隔打开和关闭 LED。

gpiozero库的 LED 类带有名为on()off()的函数,分别将 GPIO 引脚 2 设置为高和低:

while True: 
    led.on() 
    time.sleep(1) 
    led.off() 
    time.sleep(1)

在 Python 的时间库中,有一个sleep函数,允许在打开/关闭 LED 之间引入 1 秒延迟。这是在一个无限循环中执行的!我们刚刚使用 Raspberry Pi Zero 构建了一个实际示例。

将所有代码放在一个名为blinky.py的文件中(可随本书下载),从命令行终端运行代码(或者,您可以使用 IDLE3):

    python3 blinky.py

现在我们已经实现了第一个示例,让我们讨论一些能够控制 GPIO 的可能应用程序。我们可以用树莓 Pi 的 GPIO 来控制家里的灯光。我们将使用相同的示例来控制台灯!

有一款产品名为动力开关尾 IIhttp://www.powerswitchtail.com/Pages/default.aspx ),可将台灯等交流电器连接到树莓 Pi。动力开关尾部带有控制引脚(可接收 3.3V 高信号),可用于打开/关闭灯。该开关配有必要的电路/保护装置,可将其直接连接至 Raspberry Pi Zero:

The Pi Zero interfaced to the PowerSwitch Tail II

让我们以上一节中的相同示例为例,将 GPIO 引脚 2 连接到动力开关尾部的引脚中的+。让我们将覆盆子 Pi Zero 的 GPIO 头的接地引脚连接到动力开关尾部的-在中。电源开关尾部应连接至交流电源。灯应连接至开关的交流输出。如果我们使用相同的代码并将灯连接到电源开关尾部,我们应该能够以 1 秒的间隔打开/关闭。

PowerSwitch Tail II connected to a Raspberry Pi Zero This appliance control using the LED blinking code is just an example. It is not recommended to turn on/off a table lamp at such short intervals. 

在本章中,我们回顾了 Python 中的整数、布尔值和字符串数据类型以及算术运算和逻辑运算符。我们还讨论了接受用户输入和循环。我们介绍了 Raspberry Pi Zero 的 GPIO,并讨论了 LED 闪烁的示例。我们用同样的例子来控制台灯!

您听说过名为Slack的聊天应用程序吗?工作时用笔记本电脑控制家里的台灯怎么样?如果这引起了您的兴趣,请在接下来的几章中与我们合作。

教程来源于Github,感谢apachecn大佬的无私奉献,致敬!

技术教程推荐

Service Mesh实践指南 -〔周晶〕

从0打造音视频直播系统 -〔李超〕

高并发系统设计40问 -〔唐扬〕

现代C++编程实战 -〔吴咏炜〕

说透敏捷 -〔宋宁〕

跟月影学可视化 -〔月影〕

乔新亮的CTO成长复盘 -〔乔新亮〕

零基础学Python(2023版) -〔尹会生〕

程序员职业规划手册 -〔雪梅〕