Python 物联网入门指南(六)(1)https://developer.aliyun.com/article/1507314
通过 I2C 进行接口
到目前为止,一切都很好。电子电路可能非常有趣,虽然它们看起来非常复杂,但我们经常发现工作非常简单。在前一节中,我们一次只接口一个传感器。我们可以继续接口多个传感器,但我们受到现有 GPIO 数量的限制。我们还看到一些传感器,如超声波传感器可能使用多个 GPIO 引脚进行工作。这进一步减少了我们可以与微控制器接口的传感器数量。一旦我们转向更复杂的电路,我们还会意识到布线可能会变得非常混乱,如果出现问题,找出问题所在将变得非常繁琐。
现在,我们在设计机器人系统时面临的一个更大的问题是时间的问题——系统中的所有工作都必顶同步。目前大多数系统都是顺序的,即一个单元的输出成为另一个单元的输入:
现在,为了完成任务,当需要时,处理单元 1必须将输入传递给处理单元 2,处理单元 3也是如此。如果数据的时间不完美,那么处理单元 2要么会一直等待处理单元 1的输入,要么更糟糕的是,处理单元 1会在处理单元 2不需要数据的时候发送数据。在这种情况下,数据将丢失,过程将出现一些错误。
因此,为了解决这个问题,当时的计算机科学家发明了一种脉冲系统。时钟脉冲是一个非常简单的方波,具有 50%的占空比(回想一下脉冲宽度调制(PWM))。电路被设计为在时钟脉冲的上升沿或下降沿执行一次操作。由于这种同步,电路的每个部分都知道何时工作。时钟脉冲的样子如下:
现在,回到问题上,我们有两个问题:
- 机器人连接的设备/传感器存在物理限制
- 如何使传感器和互连电路的时间协调工作
为了解决这些问题,我们使用了一个非常常用的协议,称为 I2C,代表着互联集成电路。当我们需要在相同的 GPIO 上连接多个设备时,比如只有一组 GPIO 引脚可以连接多个传感器时,这个协议非常有用。这是由于为每个硬件分配了唯一的地址。该地址用于识别传感器,然后相应地与其通信。现在,要实现 I2C 协议,我们需要两条线路;这些线路如下:
- 数据
- 时钟
正如你可能已经猜到的那样,时钟线用于向连接的设备发送时钟脉冲,数据是数据流动的总线。
现在,整个 I2C 架构是基于主从配置工作的,其中主设备始终为从设备生成时钟信号,从设备必须不断寻找主设备发送的时钟脉冲和数据包。让我们看看是如何完成的。
如前所述,有两条线路:数据线称为串行数据(SDA),时钟线称为串行时钟(SCL)。从现在开始,我们将使用 SCL 和 SDA 这些术语:
让我们看看图中显示的主要要点:
- 起始条件:为了开始通信,创建一个起始条件,表示通信即将发生。主设备通过在 SCL 之前保持 SDA 线低来表示这个条件。这表示所有从设备都准备好进行通信。
- 地址帧:一旦通信开始,主设备发送需要通信的设备的地址。这是一个 7 位地址。在每个时钟脉冲中,一个位被发送,因此需要七个时钟脉冲来发送 7 位地址。在这 7 位地址之后是读/写位。这表明设备是否在这个操作中想要写入,还是想要读取一些数据。因此,总地址帧是 8 位,需要八个时钟脉冲来发送。在这八个脉冲之后,在第九个时钟脉冲期间,主设备等待来自设备的确认。当 SDA 线被被寻址的从设备拉低时,从设备发送这个确认。通过这种策略,主设备知道它发送的地址已经被接收,并且从设备现在准备好进行通信。如果没有发送确认,那么由主设备决定接下来该做什么。
- 数据帧:一旦确认被发送,根据是读操作还是写操作,数据要么由主设备写入从设备,要么在读操作中,数据由从设备发送到主设备。这个数据帧的长度可以是任意的。
- 停止帧:一旦数据传输完成,主设备发出停止条件,表示通信必须停止。当 SDA 线在 SCL 线从低电平变为高电平后,此条件被执行。
这基本上就是 I2C 通信的工作原理。对于每个设备,我们有一个 7 位地址,因此我们可以在单个总线上连接多达 128 个设备。这是很多设备。几乎可以忽略物理限制用完的可能性。现在让我们继续看看如何通过这种协议连接传感器。通常,不需要为 I2C 进行核心编程,因为这很冗长和繁琐。这就是开源的魔力所在。全球有很多开发人员正在研究这些传感器,其中大多数人足够慷慨,制作了一个库并分享给大家以便编程。这些库可以在线获取,其中大多数库都处理了通信的复杂过程。
现在是我们接口第一个 I2C 设备的时候了,这是一个模拟到数字转换器。你一定会想为什么我们首先使用这个转换器。回想一下我们开始理解 GPIO 引脚的时候。这些神奇的引脚可以用作输入和输出;你可能还记得这些引脚可以是开或关状态——这些都是数字引脚,不仅在输出时,也在输入时。但是有大量的传感器是通过模拟通信工作的。由于树莓派的数字架构,直接接口这些传感器是困难的。因此,我们使用模拟到数字转换器(ADC),这个转换器将传感器的模拟值转换为树莓派可以理解的数字位。
我们将连接一个 LDR,电阻将根据光线的多少改变电阻值。因此,电压将取决于光线照射在 LDR 上的多少。
现在让我们看看如何实际操作。拿起你的树莓派,让我们开始吧。首先,我们需要在树莓派上启用 I2C;按照这里列出的步骤进行操作:
- 打开终端(Ctrl + Shift + T)
- 输入
sudo raspi-config
- 选择接口选项:
- 然后转到高级选项:
- 然后选择 I2C 以启用它。然后选择是:
现在安装adafruit
库以接口 ADC1115:
- 打开终端并复制以下命令:
sudo apt-get install build-essential python-dev python-smbus python-pip
这个命令将库和依赖项下载到树莓派上
- 现在输入以下内容:
sudo pip install adafruit-ads1x15
这个命令将库和依赖项安装到树莓派上。
现在软件已经设置好了,让我们准备好硬件。按照下图将树莓派连接到 ADS1115:
准备好后,继续在 Pi 上上传这段代码:
import time import Adafruit_ADS1x15 import RPi.GPIO as GPIO LED =14 GPIO.setmode(GPIO.BCM) GPIO.setup(LED,GPIO.OUT) adc = Adafruit_ADS1x15.ADS1115() GAIN = 1 channel=0 adc.start_adc(channel, gain=GAIN) while True: value = adc.get_last_result() print(str(value)) time.sleep(0.1) if value >= 100: GPIO.output(LED,1) else : GPIO.output(LED,0) adc.stop_adc()
请注意,有时这段代码可能不起作用,如果是这样,请尝试调整阈值的值:
if value >= 100:
你可能已经注意到,每当 LDR 面向光源时,LED 也会亮起,而当它远离光线时,LED 会熄灭。
现在你已经接口了一个 I2C 设备。让我们了解这段代码实际上是如何工作的:
import Adafruit_ADS1x15
上一行代码导入了Adafruit_ADS1x15
库,以便我们在程序中使用它的所有函数。
adc = Adafruit_ADS1x15.ADS1115()
上一行代码创建了库Adafruit_ADS1x115
的实例。.ADS1115()
是创建实例adc
的函数。明白了吗?让我用英语解释一下。
现在,我们可以简单地写adc
而不是一直写Adafruit_ADS1x15
,来调用库函数。此外,你可以使用任何单词代替adc
;它可以是你猫的名字或你邻居的名字,它仍然可以工作:
GAIN = 1
这是传感将进行的值。1
表示传感将在整个范围内进行。对于我们的 ADC 来说,范围是从 0V 到+/-4.096V 的电压范围。现在改变增益会导致传感范围的改变。也就是说,如果我们将增益值更改为2
,那么传感范围将是原始范围的一半,即 0 到+/-2.048 伏。
现在你可能会问电压范围是多少,为什么我们要改变增益?
原因很简单。有不同类型的模拟传感器。它们的输出电压范围各不相同。有些传感器的输出范围是 0.5 伏到 4 伏,其他的可以是 0.1 伏到 0.98 伏。现在,如果我们将增益设置为1
,那么所有这些传感器都可以轻松接口。因为它们都在 0 到 4.098 伏的感应范围内。然而,由于它是一个 16 位 ADC,因此 ADC 可以提供的离散值的总数将在 2¹⁶或 65,536 个读数之间。因此,在增益为1
时,ADC 可以检测到的最小电压变化为:4.096 / 65536 = 0.000062。
但是,如果增益增加到4
,那么传感范围将减少到仅为0
到+/-1.0245。因此,这将能够处理 0.1 伏到 0.98 伏之间的输出范围。但现在让我们看看它可以检测到的最小电压变化:1.0245 / 65536 = 0.00001563。
现在你可以看到可以检测到的最小电压非常低。这对于与传感器的兼容性是一件好事。
现在,你可以决定你想要什么增益值。LDR 在 5V 上工作,因此最好使用整个增益读数为1
:
channel=0
当你仔细观察 ADC 硬件时,你会注意到有各种引脚,包括A0、A1、A2和A4。这是一个四通道 ADC——它可以将四个模拟输入转换为数字数据。由于我们只使用一个数据流,我们将让 Pi 知道它连接在哪个引脚上。通过下面的代码,我们告诉 Pi 开始转换数据的过程:
adc.start_adc(channel, gain=GAIN)
在下一行中,我们指示 ADC 停止转换,代码到此结束。
adc.stop_adc()
摘要
本章主要讲述了如何将传感器与 GPIO 进行接口,以便传感器可以检索数据。
第十九章:制作园丁机器人
好了,朋友们,你已经了解了一些输入和输出的基础知识;现在是时候制作一些我们可以交出一些日常责任的东西了。这个机器人可能看起来并不像一个机器人,但相信我,它会让你的生活更轻松。最重要的是,你花园中的大部分植物都会因为你的制作而祝福你。
我们将涵盖以下主题:
- 与电磁阀一起工作
- 制作机器人
- 使它更智能
- 使它真正智能
与电磁阀一起工作
我们要做的是一个自动系统,它会在植物需要时给它们浇水。所以从技术上讲,一旦它建立起来,你就不用担心给你的绿色生物浇水了。无论你是在家里、在办公室还是度假,它都会不管任何情况下继续工作。
现在,你一定在想它是如何给植物浇水的,所以让我告诉你,对于这个世界上的每个问题,都存在一个解决方案。在我们的情况下,这个解决方案被称为电磁阀。它的基本作用是切换液体的流动。市场上有各种各样的电磁阀;一些识别特征如下:
- 尺寸:它们有各种尺寸,如半英寸、四分之三英寸、1 英寸等。这基本上将决定电磁阀的流量。
- 介质:无论是液体、气体、蒸汽等。
- 正常状态:
- 通常打开:这个阀门在关闭状态下会允许液体流动——当阀门没有供电时
- 通常关闭:这个阀门在关闭状态下会阻止液体流动——当阀门没有供电时
- 方式数量:一个简单的阀门会有一个进口和一个出口。所以,当它打开时,它会允许液体从进口流向出口。然而,还可以有其他类型的阀门,比如三通阀,可能有两个出口和一个进口。它会调节液体的流动方向。
阀门的一些具体细节也可能会有所不同,但目前我们只需要知道这些。关于电磁阀要注意的一点是,这些阀门可以打开或关闭。无法实现这些阀门之间的任何状态或通过这些阀门控制流动。为此,我们可以使用伺服阀或电动阀。但目前我们不需要。
在本章中,我们将使用一个半英寸的水/液体阀,它通常是关闭的。当你仔细看这个阀时,你会发现它在 12 伏特下运行,电流消耗接近 1 安培。这对树莓派来说是很大的电流。树莓派每个引脚可以提供的电流上限约为 50 毫安。所以如果我们把这个阀接到树莓派上,它肯定不会工作。
我们现在该怎么办?这个问题的答案是继电器。继电器的基本工作是重新布置电路。基本上,它是一个电子控制开关。继电器的基本工作是打开和关闭具有比控制单元提供的更高电流/电压消耗的设备。这是一个相当简单的设备,正如你在图中所看到的。有两个电路。一个是蓝色的,是低电压和低电流电路。这个电路正在给线圈供电。另一个电路是红色和黑色的。这个电路是高电压、高电流电路。
在初始阶段,正如你所看到的,高电压高电流电路不完整,烤箱不会工作:
现在,在这第二个图中,你可以看到蓝色电路连接到 5V 电源,线圈被激活。每当线圈被激活,它就形成一个电磁铁,吸引高功率电路的金属片,使电路完整,从而给烤箱供电:
这就是电磁阀的工作原理。线圈的消耗几乎只有几毫安,因此通过微控制器驱动线圈非常容易。这反过来使得最终电路之间产生接触。
市场上有各种类型的继电器;一些识别特征如下:
- 最大输出电压:它可以处理的最大电压
- 最大输出电流:它可以承受的连接到它的任何输出设备的最大电流
- 信号电压:它需要开关组件的电压
- 正常条件:
- 正常关闭:这将不允许任何电流流动,直到接收到信号为止
- 正常开启:它将允许电流流动,直到接收到信号为止
现在,回到我们的园艺机器人,连接到它的电磁阀将在 1 安培和 12V 上工作,因此任何可以提供等于或大于 1 安培和 12V 的继电器都可以工作。
通常,市场上可用的继电器是 120V 和 12 安培直流。要记住的一件重要事情是交流电压和直流电压和电流将有两个单独的等级。由于我们的电磁阀将在 12V 下工作,我们只考虑直流的上限。
制作机器人
现在,让我们开始制作机器人。首先,您需要从水龙头到电磁阀的水管连接,从电磁阀到洒水器的连接。您还需要进行以下连接:
现在让我们开始编程。在这个机器人中,我们将接口一个土壤湿度传感器。该传感器的工作是确定土壤中的水量。通过确定这一点,我们可以了解花园是否需要水。这个土壤湿度传感器是一个模拟传感器,因此我们将使用 ADC 将模拟读数转换为树莓派可理解的数字值。所以让我们开始吧:
import time import RPi.GPIO as GPIO import Adafruit_ADS1x15 water_valve_pin = 23 moisture_percentage = 20 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(water_valve_pin, GPIO.OUT) adc = Adafruit_ADS1x15.ADS1115() channel = 0 GAIN = 1 while True: adc.start_adc(channel, gain=GAIN) moisture_value = adc.get_last_result() moisture_value= int(moisture_value/327) print moisture_value if moisture_value < moisture_percentage: GPIO.output(water_valve_pin, GPIO.HIGH) time.sleep(5) else: GPIO.output(water_valve_pin, GPIO.LOW)
在运行此代码之前,让我们先了解它实际上在做什么:
moisture_percentage = 20
moisture_percentage = 20
是一个阈值百分比;如果土壤中的湿度水平低于 20%,那么您的花园就需要水。这是您的机器人将继续寻找的条件;一旦满足这个条件,就可以采取适当的行动。这个百分比也可以根据您花园的需要更改为30
、40
或其他任何值:
moisture_value = int(moisture_value/327)
ADC 是一个 16 位设备——有 16 个二进制数字可以表示一个值。因此,该值可以在0
和2¹⁵
之间,换句话说,可以在0
和32768
之间。现在,很简单的数学,对于每个百分比的湿度,ADC 将给出以下读数:32768/100
,或327.68
。因此,要找出土壤中的湿度百分比,我们需要将 ADC 给出的实际值除以327.68
。
其余的代码非常简单,一旦您阅读它,您就不会很难理解。
使其更智能
祝贺您制作了您的第一个机器人!但您是否注意到了一个问题?我们制作的机器人一直在寻找湿度值,一旦注意到湿度值偏低,它就会突然泵水,并确保土壤的湿度始终高于 20%。然而,这是不必要的。一般来说,我们每天浇水一两次。如果我们浇水更多,那对植物可能不利。
因此,让我们继续使它稍微更智能化,并且只在特定时间土壤湿度低时给植物浇水。这一次,我们不需要对硬件进行任何更改;我们只需要微调代码。
让我们继续上传以下代码,然后看看到底发生了什么:
from time import sleep from datetime import datetime import RPi.GPIO as GPIO import Adafruit_ADS1x15 water_valve_pin = 23 moisture_percentage = 20 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(water_valve_pin, GPIO.OUT) adc = Adafruit_ADS1x15.ADS1115() GAIN = 1 def check_moisture(): adc.start_adc(0,gain= GAIN) moisture_value = adc.get_last_result() moisture_value = int(moisture_value/327) if moisture_value < moisture_level: GPIO.output(water_valve_pin, GPIO.HIGH) sleep(5) GPIO.output(water_valve_pin, GPIO.LOW) else: GPIO.output(water_valve_pin, GPIO.LOW) while True: H = datetime.now().strftime('%H') M = datetime.now().strftime('%M') if H == ‘07’ and M <= ‘10’: check_moisture() if H == ‘17’ and M <= ‘01’: check_moisture()
这段代码可能对您来说有点陌生,但相信我,它就是这么简单。让我们一步一步地看看发生了什么:
from datetime import datetime
这行代码是从日期时间库中导入日期时间实例。这是 Python 中默认的一个库。我们只需要调用它。它的作用是在我们的代码中轻松确定时间。
def check_moisture():
有时我们必须一遍又一遍地做一些事情。这些代码集可以是几行重复的代码,也可以是多页的代码。因此,重写那些代码毫无意义。我们可以创建一个函数。在这个函数中,我们可以定义每次调用时会发生什么。在这行代码中,我们创建了一个名为check_moisture()
的函数;现在,每当程序中调用这个函数时,将执行一系列活动。将要执行的一系列活动由用户定义。因此,每当我们写def
时,就意味着我们正在定义一个函数;然后,我们写出需要定义的函数的名称。
完成后,然后我们在缩进中写的任何内容都将在调用函数时执行。请记住,每当我们调用或定义一个函数时,函数名称的末尾都有一个开放和关闭的()
括号表示:
moisture_value = adc.get_last_result()
adc.get_last_result()
是adc
的一个函数。它的功能是简单地从之前定义的引脚(引脚号为0
)获取结果,并将读数存储到变量moisture_value
中。因此,在moisture_value
之后将是 ADC 引脚号0
的读数,或者换句话说,是湿度传感器的读数。
H = datetime.now().strftime('%H')
代码datetime
是.now()
的一个实例和方法。这个函数的作用是更新时间。现在,datetime.now()
已经更新了日期和时间的所有参数,包括小时、分钟、秒,甚至日期。我们可以选择是否要全部或者日期和时间的任何特定部分。目前,我们想要将小时的值放入变量H
中,因此我们使用了.strftime('%H')
方法。strftime
代表时间的字符串格式。因此,它输出的任何值都是以字符串格式。('%H')
表示它只会给我们小时的值。同样,我们也可以使用('%M')
和('%S)
来获取分钟的时间。我们还可以使用以下语法获取日期、月份和年份的值:
- 获取日期:
('%d')
- 获取月份:
('%m')
- 获取年份:
('%Y')
if H == ‘07’ and M <= ‘10’:
在前面的条件中,我们正在检查时间是否为 7 点;此外,我们还在检查时间是否小于或等于 10 分钟。因此,只有当时间为 7 小时并且在 0 到 10 分钟之间时,此代码段才会运行if
语句中的语句。
特别要注意的一点是,我们在两个条件之间使用了and
,因此只有在两个语句都绝对为真时才会运行其中的代码。我们还可以在其中使用一些其他语句,比如or
,在这种情况下,如果其中一个语句为真,它将运行代码。
如果我们在这个if
语句中用or
替换and
,那么它将在每个小时的 0 到 10 分钟内运行代码,并且将在上午 7:00 到 7:59 之间的整个时间内连续运行代码:
check_moisture()
正如你可能记得的,之前我们定义了一个名为check_moisture()
的函数。在定义该函数时,我们还定义了每次调用该函数时将发生的一系列活动。
现在是调用该函数的时候了。一旦程序到达代码的末尾,它将执行之前在函数中定义的一系列活动。
所以我们就是这样。现在,一旦你运行这段代码,它将等待程序中定义的时间。一旦达到特定的时间,它将检查湿度。如果湿度低于设定值,它将开始给植物浇水,直到湿度超过阈值为止。
真正智能化
了不起的工作!我们已经开始自己建造比我们更聪明的东西。但现在我们想要更进一步,让它比我们更聪明——这就是机器人存在的意义。不仅仅是做我们做的事情,而是以更好的方式做所有这些。
那么,我们能做些什么改进呢?在寒冷的冬天,我们不需要太多的水,但在夏天,我们需要比冬天喝的水多得多。植物也是一样的情况。
在冬天,它们需要的水量要少得多。此外,土壤中的水蒸发速度也较慢。因此,在这两种情况下,我们需要向花园供应不同数量的水。问题是,我们该如何做到呢?
首先,要知道外面是热还是冷,我们需要一个传感器。我们将使用一个名为 DHT11 的传感器。这是一个便宜但坚固的传感器,可以给我们提供温度和湿度的读数。最好的部分是,它的价格非常便宜,大约 2 美元。
它有四个引脚。但是,如果你认为它将适用于 I2C 协议,那么你就错了。它有自己的数据传输方法。拥有一个单一的协议来处理所有传感器是很好的,但通常你也会发现有各种传感器或设备使用不同或全新的协议。DHT11 就是这样的传感器。在这种情况下,我们可以选择要么理解整个通信方法,要么简单地从制造商那里获取库并随时使用。目前我们将选择后者。
现在让我们看看 DHT11 的引脚是什么样子的:
你可以看到这里只有一个信号引脚,它将完成所有数字通信。有两个电源引脚,其中一个引脚没有使用。也就是说,这个引脚没有明显的用途。它可能只是用于焊接或将来使用。这个传感器使用 5V 电源,只需要几毫安,因此我们可以通过树莓派来为其供电。现在,对于数据通信,我们将把信号引脚连接到 GPIO 引脚号4
。
在我们开始编写代码之前,让我们先安装 DHT11 和树莓派之间的通信库。我们之前已经在 ADS1115 的库中做过这个,但在这个库中有一些小技巧需要我们注意。所以让我们开始吧。
首先,我们需要确保你的树莓派操作系统是最新的。所以将树莓派连接到互联网,打开树莓派的命令提示符,输入以下命令:
sudo apt-get update
这个命令将自动更新你的树莓派的 raspbian 操作系统。然后继续输入这个命令:
sudo apt-get install build-essential python-dev python-openssl
在这个命令中,我们正在安装以下软件包:
build-essential
python-dev
python-openssl
你一定在想为什么我们要安装所有这些。好吧,长话短说,这些是我们即将安装的 DHT11 通信库的依赖项。如果这些软件包没有安装在树莓派上,我们将无法使用该库。
最后,我们必须安装库;这是一个通用库,其中还包括与 DHT11 传感器通信的功能。这应该足以满足我们的简单通信需求。以下是安装它的命令:
sudo python setup.py install
好了,我们准备好了。我们的系统已经准备好与 DHT11 进行通信。让我们首先看看我们到目前为止所做的是否按我们想要的方式工作。为了做到这一点,按照以下方式连接 DHT11;你可以将其他组件如电磁阀和土壤湿度传感器连接好。它们不应该干扰。现在在树莓派上上传以下代码:
from time import sleep from datetime import datetime import RPi.GPIO as GPIO import Adafruit_DHT sensor = 11 pin = 4 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) while True: humidity, temperature = Adafruit_DHT.read_retry(sensor, pin) print("Temperature: " +temperature+ "C") print("Humidity: " +humidity+ "%") time.sleep(2)
一旦你上传了这段代码,你将在屏幕上看到传感器的读数。这段代码只是简单地为你提供传感器的原始读数。这段代码非常简单,你会理解其中的一切,除了一些代码行,其中包括:
import Adafruit_DHT
在代码的这一行中,我们在代码中导入了Adafruit_DHT
库。这是与 DHT11 传感器通信的相同库。
sensor = 11
DHT 有不同的版本,如 DHT11、DHT22 等。我们需要告诉程序我们使用的是哪种传感器。因此,我们已经为变量传感器分配了一个值。稍后,你将看到我们将如何使用它:
pin = 4
在这一行中,我们将值 4 赋给一个名为pin
的变量。这个变量将用于告诉程序我们已经连接了 DHT11 的树莓派引脚。
humidity, temperature = Adafruit_DHT.read_retry(sensor, pin)
在这一行中,我们使用了Adafruit
库的一个方法,名为Adafruit_DHT.read_retry()
。现在,它的作用是读取 DHT 传感器,并将传感器的读数给变量humidity
和temperature
。需要注意的一点是,DHT11 每 2 秒更新一次读数。因此,你将在每 2 秒后收到更新的读数。
一旦这段代码完成,我们就可以确信传感器正在按我们想要的方式工作。最后,是时候将所有传感器整合在一起,制作一个完全智能的机器人了。由于电磁阀、湿度传感器和温度传感器已经连接好,我们所需要做的就是将代码上传到树莓派上,然后看魔法发生。
from time import sleep from datetime import datetime import RPi.GPIO as GPIO import Adafruit_ADS1x15 import Adafruit_DHT water_valve_pin = 23 sensor = 11 pin = 4 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(water_valve_pin, GPIO.OUT) Channel =0 GAIN = 1 adc = Adafruit_ADS1x15.ADS1115() def check_moisture(m): adc.start_adc(channel, gain=GAIN) moisture_value = adc.get_last_result() moisture_value = int(moisture_value/327) print moisture_value if moisture_value < m: GPIO.output(water_valve_pin, GPIO.HIGH) sleep(5) GPIO.output(water_valve_pin, GPIO.LOW) else: GPIO.output(water_valve_pin, GPIO.LOW) while True: humidity, temperature = Adafruit_DHT.read_retry(sensor, pin) H = datetime.now().strftime(‘%H’) M = datetime.now().strftime(‘%M’) if H == ‘07’ and M <= ‘10’: if temperature < 15: check_moisture(20) elif temperature >= 15 and temperature < 28: check_moisture(30) elif temperature >= 28: check_moisture(40) if H == ‘17’ and M <= ‘10’: if temperature < 15: check_moisture(20) elif temperature >= 15 and temperature < 28: check_moisture(30) elif temperature >= 28: check_moisture(40)
代码很长,对吧?看起来是这样,但是一旦你逐行编写它,你肯定会明白,它可能比我们迄今为止编写的所有代码都长,但它一点也不复杂。你可能已经理解了大部分程序,但是让我解释一下我们在这里使用的一些新东西:
def check_moisture(m): adc.start_adc(channel, gain = GAIN) moisture_value = adc.get_last_result() moisture_value = int(moisture_value / 327) print moisture_value if moisture_value < m: GPIO.output(water_valve_pin, GPIO.HIGH) sleep(5) GPIO.output(water_valve_pin, GPIO.LOW) else : GPIO.output(water_valve_pin, GPIO.LOW)
在这一行中,我们定义了一个名为check_moisture()
的函数。以前,如果你还记得,当我们制作check_moisture
函数时,我们基本上是在检查湿度值是否大于或小于 20%。如果我们需要检查 30%、40%和 50%的湿度怎么办?我们会为此制作一个单独的函数吗?
显然不是!我们所做的是向函数传递一个参数,参数基本上是放在函数括号内的变量。现在我们可以为这个变量分配值,例如check_moisture(30)
-现在在执行该函数时m
的值将为 30。然后,如果再次调用check_moisture(40)
,那么m
的值将为 40。
现在,你可以看到我们在整个函数中比较m
的值。
if moisture_value < m:
if 语句将检查调用函数时分配的m
的值。这使我们的工作变得非常简单。
让我们看看程序的其余部分在做什么:
if temperature < 15: check_moisture(20)
每当达到所需的时间,它将继续检查温度。如果温度低于 15 度,它将调用函数check_moisture
并将参数值设为 20。因此,如果湿度低于 20%,则会给花园浇水。
elif temperature >= 15 and temperature < 28: check_moisture(30)
elif
或else if
语句在if
语句之后使用。通俗地说,这意味着如果前面的if
语句不成立,它将检查这个if
语句。因此,在前一行中,它将检查温度是否在 15 到 28 摄氏度之间。如果是,它将检查土壤的湿度。在这一行中,函数的参数是 30。因此,它将检查湿度是否低于 30。如果是,它将给花园供水。
elif temperature >= 28: check_moisture(40)
同样,在这行代码中,我们正在检查温度,如果温度等于或超过28
摄氏度,那么它将把值40
作为参数传递给函数check_moisture
。因此,这次它将检查湿度是否达到或超过28
。
正如您所看到的,现在系统将检查环境温度,并根据此调节植物所需的水量。最好的部分是它是一致的,并将提供植物所需的正确水量。
本章中提到的数值仅为假设值。我强烈建议根据您所在地区和您花园中种植的植物来调整数值,以便系统发挥最佳效果。
总结
在本章中,我们涵盖了一些主题,如电磁阀集成和土壤湿度传感器,以构建一个可以自动给您的后院花园浇水的机器人。接下来,我们将介绍电机的基础知识。
第二十章:电机基础
好了!我们已经制作了一个照顾你花园的机器人,我希望它运行良好。现在是时候把事情提升到另一个水平了。
我们一直认为机器人就像 WALL-E 一样,四处移动并为我们做事。好吧,朋友,现在这个梦想并不遥远。事实上,在这一章中,我们将继续前进并制作一个。让我们看看如何做到。
我们将涵盖以下主题:
- 基础知识
- 让它滚动
- 改变速度
Python 物联网入门指南(六)(3)https://developer.aliyun.com/article/1507317