Python 物联网入门指南(四)(1)https://developer.aliyun.com/article/1507227
缩进
注意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 中,可以实现循环内的循环。例如,假设我们需要打印地图的x
和y
坐标。我们可以使用嵌套循环来实现这个:
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
循环。while
循环通常用于执行无限循环中的代码。让我们看一个具体的例子,我们想要打印i
的值从0
到9
:
i=0 while i<10: print("The value of i is ",i) i+=1
在while
循环内,我们每次迭代都会将i
增加1
。i
的值增加如下:
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 可以打印字符串和整数的组合,只要它们作为print
函数的参数呈现,并用逗号分隔。在前面提到的示例中,i,j 的值是
,i
是print
函数的参数。您将在下一章中了解更多关于函数和参数的内容。此功能使得格式化输出字符串以满足我们的需求成为可能。
树莓派的 GPIO
树莓派 Zero 配备了一个 40 针的 GPIO 引脚标头。在这 40 个引脚中,我们可以使用 26 个引脚来读取输入(来自传感器)或控制输出。其他引脚是电源引脚(5V,3.3V和Ground引脚):
树莓派 Zero GPIO 映射(来源:https://www.raspberrypi.org/documentation/usage/gpio-plus-and-raspi2/README.md)
我们可以使用树莓派的 GPIO 最多 26 个引脚来接口设备并控制它们。但是,有一些引脚具有替代功能。
较早的图像显示了树莓派的 GPIO 引脚的映射。圆圈中的数字对应于树莓派处理器上的引脚编号。例如,GPIO 引脚2(底部行左侧的第二个引脚)对应于树莓派处理器上的 GPIO 引脚2,而不是 GPIO 引脚标头上的物理引脚位置。
一开始,尝试理解引脚映射可能会令人困惑。保留 GPIO 引脚手册(可与本章一起下载)以供参考。需要一些时间来适应树莓派 Zero 的 GPIO 引脚映射。
树莓派 Zero 的 GPIO 引脚是 3.3V 兼容的,也就是说,如果将大于 3.3V 的电压应用到引脚上,可能会永久损坏引脚。当设置为高时,引脚被设置为 3.3V,当引脚被设置为低时,电压为 0V。
闪烁灯
让我们讨论一个例子,我们将使用树莓派 Zero 的 GPIO。我们将把 LED 接口到树莓派 Zero,并使其以 1 秒的间隔闪烁开和关。
让我们接线树莓派 Zero 开始:
使用 Fritzing 生成的 Blinky 原理图
在前面的原理图中,GPIO 引脚 2 连接到 LED 的阳极(最长的腿)。LED 的阴极连接到树莓派 Zero 的地引脚。还使用了 330 欧姆的限流电阻来限制电流的流动。
)。Raspbian Jessie操作系统映像带有预安装的库。这是一个非常简单易用的库,对于初学者来说是最好的选择。它支持一套标准设备,帮助我们轻松入门。
例如,为了接口 LED,我们需要从gpiozero
库中导入LED
类:
from gpiozero import LED
我们将在 1 秒的间隔内打开和关闭 LED。为了做到这一点,我们将导入time
库。在 Python 中,我们需要导入一个库来使用它。由于我们将 LED 接口到 GPIO 引脚 2,让我们在我们的代码中提到这一点:
import time led = LED(2)
我们刚刚创建了一个名为led
的变量,并定义我们将在LED
类中使用 GPIO 引脚 2。让我们使用while
循环来打开和关闭 LED,间隔为 1 秒。
gpiozero
库的 LED 类带有名为on()
和off()
的函数,分别将 GPIO 引脚 2 设置为高电平和低电平:
while True: led.on() time.sleep(1) led.off() time.sleep(1)
在 Python 的时间库中,有一个sleep
函数,可以在打开/关闭 LED 之间引入 1 秒的延迟。这在一个无限循环中执行!我们刚刚使用树莓派 Zero 构建了一个实际的例子。
将所有代码放在名为blinky.py
的文件中(可与本书一起下载),从命令行终端运行代码(或者,您也可以使用 IDLE3):
python3 blinky.py
GPIO 控制的应用
现在我们已经实施了我们的第一个示例,让我们讨论一些能够控制 GPIO 的可能应用。我们可以使用树莓派的 GPIO 来控制家中的灯光。我们将使用相同的示例来控制台灯!
有一个名为PowerSwitch Tail II的产品(www.powerswitchtail.com/Pages/default.aspx
),可以将交流家电(如台灯)与树莓派连接起来。PowerSwitch Tail 配有控制引脚(可以接收 3.3V 高电平信号),可用于打开/关闭灯。开关配有必要的电路/保护,可直接与树莓派 Zero 接口:
树莓派 Zero 与 PowerSwitch Tail II 接口
让我们从上一节中使用相同的示例,将 GPIO 引脚 2 连接到 PowerSwitch Tail 的**+in引脚。让我们将树莓派 Zero 的 GPIO 引脚的地线连接到 PowerSwitch Tail 的-in**引脚。PowerSwitch Tail 应连接到交流电源。灯应连接到开关的交流输出。如果我们使用相同的代码并将灯连接到 PowerSwitch Tail,我们应该能够以 1 秒的间隔打开/关闭。
连接到树莓派 Zero 的 PowerSwitch Tail II 使用 LED 闪烁代码进行家电控制只是一个例子。不建议在如此短的时间间隔内打开/关闭台灯。
总结
在本章中,我们回顾了 Python 中的整数、布尔和字符串数据类型,以及算术运算和逻辑运算符。我们还讨论了接受用户输入和循环。我们介绍了树莓派 Zero 的 GPIO,并讨论了 LED 闪烁示例。我们使用相同的示例来控制台灯!
您听说过名为Slack的聊天应用程序吗?您是否尝试过在工作时从笔记本电脑控制家里的台灯?如果这引起了您的兴趣,请在接下来的几章中与我们一起工作。
第十一章:条件语句、函数和列表
在本章中,我们将在前一章学到的基础上进行扩展。您将学习有关条件语句以及如何使用逻辑运算符来检查条件的使用。接下来,您将学习如何在 Python 中编写简单的函数,并讨论如何使用触摸开关(瞬时按键)将输入接口到树莓派的 GPIO 引脚。我们还将讨论使用树莓派 Zero 进行电机控制(这是最终项目的预演),并使用开关输入来控制电机。让我们开始吧!
在本章中,我们将讨论以下主题:
- Python 中的条件语句
- 使用条件输入根据 GPIO 引脚状态采取行动
- 使用条件语句跳出循环
- Python 中的函数
- GPIO 回调函数
- Python 中的电机控制
条件语句
在 Python 中,条件语句用于确定特定条件是否满足,通过测试条件是true
还是false
。条件语句用于确定程序的执行方式。例如,条件语句可以用于确定是否是开灯的时间。语法如下:
if condition_is_true: do_something()
通常使用逻辑运算符来测试条件,并执行缩进块下的任务集。让我们考虑一个例子,check_address_if_statement.py
(可在本章下载)中,程序需要使用yes
或no
问题来验证用户输入:
check_address = input("Is your address correct(yes/no)? ") if check_address == "yes": print("Thanks. Your address has been saved") if check_address == "no": del(address) print("Your address has been deleted. Try again")
在这个例子中,程序期望输入yes
或no
。如果用户提供了输入yes
,条件if check_address == "yes"
为true
,则在屏幕上打印消息Your address has been saved
。
同样,如果用户输入是no
,程序将执行在逻辑测试条件if check_address == "no"
下的缩进代码块,并删除变量address
。
if-else 语句
在前面的例子中,我们使用if
语句测试每个条件。在 Python 中,还有一种名为if-else
语句的替代选项。if-else
语句使得在主条件不为true
时测试替代条件成为可能:
check_address = input("Is your address correct(yes/no)? ") if check_address == "yes": print("Thanks. Your address has been saved") else: del(address) print("Your address has been deleted. Try again")
在这个例子中,如果用户输入是yes
,则在if
下的缩进代码块将被执行。否则,将执行else
下的代码块。
if-elif-else 语句
在前面的例子中,对于除yes
之外的任何用户输入,程序执行else
块下的任何代码。也就是说,如果用户按下回车键而没有提供任何输入,或者提供了no
而不是no
,则if-elif-else
语句的工作如下:
check_address = input("Is your address correct(yes/no)? ") if check_address == "yes": print("Thanks. Your address has been saved") elif check_address == "no": del(address) print("Your address has been deleted. Try again") else: print("Invalid input. Try again")
如果用户输入是yes
,则在if
语句下的缩进代码块将被执行。如果用户输入是no
,则在elif
(else-if)下的缩进代码块将被执行。如果用户输入是其他内容,则程序打印消息:Invalid input. Try again
。
重要的是要注意,代码块的缩进决定了在满足特定条件时需要执行的代码块。我们建议修改条件语句块的缩进,并找出程序执行的结果。这将有助于理解 Python 中缩进的重要性。
到目前为止,我们讨论的三个例子中,可以注意到if
语句不需要由else
语句补充。else
和elif
语句需要有一个前置的if
语句,否则程序执行将导致错误。
跳出循环
条件语句可以用于跳出循环执行(for
循环和while
循环)。当满足特定条件时,可以使用if
语句来跳出循环:
i = 0 while True: print("The value of i is ", i) i += 1 if i > 100: break
在前面的例子中,while
循环在一个无限循环中执行。i
的值递增并打印在屏幕上。当i
的值大于100
时,程序会跳出while
循环,并且i
的值从 1 打印到 100。
条件语句的应用:使用 GPIO 执行任务
在上一章中,我们讨论了将输出接口到树莓派的 GPIO。让我们讨论一个简单的按键按下的例子。通过读取 GPIO 引脚状态来检测按钮按下。我们将使用条件语句来根据 GPIO 引脚状态执行任务。
让我们将一个按钮连接到树莓派的 GPIO。你需要准备一个按钮、上拉电阻和几根跳线。稍后给出的图示展示了如何将按键连接到树莓派 Zero。按键的一个端子连接到树莓派 Zero 的 GPIO 引脚的地线。
按键接口的原理图如下:
树莓派 GPIO 原理图
按键的另一个端子通过 10K 电阻上拉到 3.3V。按键端子和 10K 电阻的交点连接到 GPIO 引脚 2(参考前一章中分享的 BCM GPIO 引脚图)。
将按键接口到树莓派 Zero 的 GPIO - 使用 Fritzing 生成的图像
让我们回顾一下需要查看按钮状态的代码。我们利用循环和条件语句来使用树莓派 Zero 读取按钮输入。
我们将使用在上一章介绍的gpiozero
库。本节的代码示例是GPIO_button_test.py
,可与本章一起下载。
在后面的章节中,我们将讨论面向对象编程(OOP)。现在,让我们简要讨论类的概念。在 Python 中,类是一个包含定义对象的所有属性的蓝图。例如,gpiozero
库的Button
类包含了将按钮接口到树莓派 Zero 的 GPIO 接口所需的所有属性。这些属性包括按钮状态和检查按钮状态所需的函数等。为了接口一个按钮并读取其状态,我们需要使用这个蓝图。创建这个蓝图的副本的过程称为实例化。
让我们开始导入gpiozero
库,并实例化gpiozero
库的Button
类(我们将在后面的章节中讨论 Python 的类、对象及其属性)。按钮接口到 GPIO 引脚 2。我们需要在实例化时传递引脚号作为参数:
from gpiozero import Button #button is interfaced to GPIO 2 button = Button(2)
gpiozero
库的文档可在gpiozero.readthedocs.io/en/v1.2.0/api_input.html
找到。根据文档,Button
类中有一个名为is_pressed
的变量,可以使用条件语句进行测试,以确定按钮是否被按下:
if button.is_pressed: print("Button pressed")
每当按下按钮时,屏幕上会打印出消息Button pressed
。让我们将这段代码片段放在一个无限循环中:
from gpiozero import Button #button is interfaced to GPIO 2 button = Button(2) while True: if button.is_pressed: print("Button pressed")
在无限的while
循环中,程序不断检查按钮是否被按下,并在按钮被按下时打印消息。一旦按钮被释放,它就会回到检查按钮是否被按下的状态。
通过计算按钮按下次数来中断循环
让我们再看一个例子,我们想要计算按钮按下的次数,并在按钮接收到预定数量的按下时中断无限循环:
i = 0 while True: if button.is_pressed: button.wait_for_release() i += 1 print("Button pressed") if i >= 10: break
前面的例子可与本章一起下载,文件名为GPIO_button_loop_break.py
。
在这个例子中,程序检查is_pressed
变量的状态。在接收到按钮按下时,程序可以使用wait_for_release
方法暂停,直到按钮被释放。当按钮被释放时,用于存储按下次数的变量会增加一次。
当按钮接收到 10 次按下时,程序会跳出无限循环。
连接到树莓派 Zero GPIO 引脚 2 的红色瞬时按钮
Python 中的函数
我们简要讨论了 Python 中的函数。函数执行一组预定义的任务。print
是 Python 中函数的一个例子。它可以将一些东西打印到屏幕上。让我们讨论在 Python 中编写我们自己的函数。
可以使用def
关键字在 Python 中声明函数。函数可以定义如下:
def my_func(): print("This is a simple function")
在这个函数my_func
中,print
语句是在一个缩进的代码块下编写的。在函数定义下缩进的任何代码块在代码执行期间调用函数时执行。函数可以被执行为my_func()
。
向函数传递参数:
函数总是用括号定义的。括号用于向函数传递任何必要的参数。参数是执行函数所需的参数。在前面的例子中,没有向函数传递参数。
让我们回顾一个例子,我们向函数传递一个参数:
def add_function(a, b): c = a + b print("The sum of a and b is ", c)
在这个例子中,a
和b
是函数的参数。函数将a
和b
相加,并在屏幕上打印总和。当通过传递参数3
和2
调用函数add_function
时,add_function(3,2)
,其中a
为3
,b
为2
。
因此,执行函数需要参数a
和b
,或者在没有参数的情况下调用函数会导致错误。可以通过为参数设置默认值来避免与缺少参数相关的错误:
def add_function(a=0, b=0): c = a + b print("The sum of a and b is ", c)
前面的函数需要两个参数。如果我们只向这个函数传递一个参数,另一个参数默认为零。例如,add_function(a=3)
,b
默认为0
,或者add_function(b=2)
,a
默认为0
。当在调用函数时未提供参数时,它默认为零(在函数中声明)。
同样,print
函数打印传递的任何变量。如果调用print
函数时没有传递任何参数,则会打印一个空行。
从函数返回值
函数可以执行一组定义的操作,并最终在结束时返回一个值。让我们考虑以下例子:
def square(a): return a**2
在这个例子中,函数返回参数的平方。在 Python 中,return
关键字用于在执行完成后返回请求的值。
函数中变量的作用域
Python 程序中有两种类型的变量:局部变量和全局变量。局部变量是函数内部的变量,即在函数内部声明的变量只能在该函数内部访问。例子如下:
def add_function(): a = 3 b = 2 c = a + b print("The sum of a and b is ", c)
在这个例子中,变量a
和b
是函数add_function
的局部变量。让我们考虑一个全局变量的例子:
a = 3 b = 2 def add_function(): c = a + b print("The sum of a and b is ", c) add_function()
在这种情况下,变量a
和b
在 Python 脚本的主体中声明。它们可以在整个程序中访问。现在,让我们考虑这个例子:
a = 3 def my_function(): a = 5 print("The value of a is ", a) my_function() print("The value of a is ", a)
程序输出为:
The value of a is 5 The value of a is 3
在这种情况下,当调用my_function
时,a
的值为5
,在脚本主体的print
语句中a
的值为3
。在 Python 中,不可能在函数内部显式修改全局变量的值。为了修改全局变量的值,我们需要使用global
关键字:
a = 3 def my_function(): global a a = 5 print("The value of a is ", a) my_function() print("The value of a is ", a)
一般来说,不建议在函数内修改变量,因为这不是一个很安全的修改变量的做法。最佳做法是将变量作为参数传递并返回修改后的值。考虑以下例子:
a = 3 def my_function(a): a = 5 print("The value of a is ", a) return a a = my_function(a) print("The value of a is ", a)
在上述程序中,a
的值为3
。它作为参数传递给my_function
。函数返回5
,保存到a
中。我们能够安全地修改a
的值。
Python 物联网入门指南(四)(3)https://developer.aliyun.com/article/1507229