Python 物联网入门指南(四)(3)

简介: Python 物联网入门指南(四)

Python 物联网入门指南(四)(2)https://developer.aliyun.com/article/1507228

GPIO 回调函数

让我们回顾一下在 GPIO 示例中使用函数的一些用途。函数可以用来处理与树莓派的 GPIO 引脚相关的特定事件。例如,gpiozero库提供了在按钮按下或释放时调用函数的能力:

from gpiozero import Button 
def button_pressed(): 
  print("button pressed")
def button_released(): 
  print("button released")
#button is interfaced to GPIO 2 
button = Button(2) 
button.when_pressed = button_pressed 
button.when_released = button_released
while True: 
  pass

在这个例子中,我们使用库的 GPIO 类的when_pressedwhen_released属性。当按钮被按下时,执行函数button_pressed。同样,当按钮被释放时,执行函数button_released。我们使用while循环来避免退出程序并继续监听按钮事件。使用pass关键字来避免错误,当执行pass关键字时什么也不会发生。

能够为不同事件执行不同函数的能力在家庭自动化等应用中非常有用。例如,可以用来在天黑时打开灯,反之亦然。

Python 中的直流电机控制

在本节中,我们将讨论使用树莓派 Zero 进行电机控制。为什么要讨论电机控制?随着我们在本书中不同主题的进展,我们将最终构建一个移动机器人。因此,我们需要讨论使用 Python 编写代码来控制树莓派上的电机。

为了控制电机,我们需要一个H 桥电机驱动器(讨论 H 桥超出了我们的范围。有几种资源可供 H 桥电机驱动器使用:www.mcmanis.com/chuck/robotics/tutorial/h-bridge/)。有几种专为树莓派设计的电机驱动器套件。在本节中,我们将使用以下套件:www.pololu.com/product/2753

Pololu产品页面还提供了如何连接电机的说明。让我们开始编写一些 Python 代码来操作电机:

from gpiozero import Motor 
from gpiozero import OutputDevice 
import time
motor_1_direction = OutputDevice(13) 
motor_2_direction = OutputDevice(12)
motor = Motor(5, 6)
motor_1_direction.on() 
motor_2_direction.on()
motor.forward()
time.sleep(10)
motor.stop()
motor_1_direction.off() 
motor_2_direction.off()

树莓派基于电机控制

为了控制电机,让我们声明引脚、电机的速度引脚和方向引脚。根据电机驱动器的文档,电机分别由 GPIO 引脚 12、13 和 5、6 控制。

from gpiozero import Motor 
from gpiozero import OutputDevice 
import time 
motor_1_direction = OutputDevice(13) 
motor_2_direction = OutputDevice(12) 
motor = Motor(5, 6)

控制电机就像使用on()方法打开电机,使用forward()方法向前移动电机一样简单:

motor.forward()

同样,通过调用reverse()方法可以改变电机方向。通过以下方式可以停止电机:

motor.stop()

读者的一些迷你项目挑战

以下是一些迷你项目挑战给我们的读者:

  • 在本章中,我们讨论了树莓派的输入接口和电机控制。想象一个项目,我们可以驱动一个移动机器人,该机器人从触须开关读取输入并操作移动机器人。结合限位开关和电机,是否可能构建一个沿墙行驶的机器人?
  • 在本章中,我们讨论了如何控制直流电机。我们如何使用树莓派控制步进电机?
  • 如何使用树莓派 Zero 接口运动传感器来控制家里的灯?

总结

在本章中,我们讨论了条件语句以及条件语句在 Python 中的应用。我们还讨论了 Python 中的函数,将参数传递给函数,从函数返回值以及 Python 程序中变量的作用域。我们讨论了回调函数和 Python 中的电机控制。

第十二章:通信接口

到目前为止,我们已经讨论了 Python 中的循环、条件语句和函数。我们还讨论了与树莓派接口的输出设备和简单的数字输入设备。

在本章中,我们将讨论以下通信接口:

  • UART - 串行端口
  • 串行外围接口
  • I²C 接口

我们将使用不同的传感器/电子元件来演示在 Python 中编写这些接口的代码。我们留给您选择一个您喜欢的组件来探索这些通信接口。

UART - 串行端口

通用异步收发器UART),即串行端口,是一种通信接口,数据以位的形式从传感器串行传输到主机计算机。使用串行端口是最古老的通信协议之一。它用于数据记录,微控制器从传感器收集数据并通过串行端口传输数据。还有一些传感器以串行通信的形式响应传入的命令传输数据。

我们不会深入讨论串行端口通信的理论(网络上有大量理论可供参考,网址为en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter)。我们将讨论使用串行端口与树莓派接口不同的传感器。

树莓派 Zero 的 UART 端口

通常,UART 端口由接收器(Rx)和发送器(Tx)引脚组成,用于接收和发送数据。树莓派的 GPIO 引脚带有 UART 端口。 GPIO 引脚 14(Tx引脚)和 15(Rx引脚)用作树莓派的 UART 端口:

GPIO 引脚 14 和 15 是 UART 引脚(图片来源:https://www.rs-online.com/designspark/introducing-the-raspberry-pi-b-plus

设置树莓派 Zero 串行端口

为了使用串行端口与传感器通信,串行端口登录/控制台需要被禁用。在Raspbian操作系统镜像中,默认情况下启用此功能,因为它可以方便调试。

串行端口登录可以通过raspi-config禁用:

  1. 启动终端并运行此命令:
sudo raspi-config
  1. raspi-config的主菜单中选择高级选项:

从 raspi-config 菜单中选择高级选项

  1. 从下拉菜单中选择 A8 串行选项:

从下拉菜单中选择 A8 串行

  1. 禁用串行登录:

禁用串行登录

  1. 完成配置并在最后重新启动:

保存配置并重新启动

示例 1 - 将二氧化碳传感器与树莓派连接

我们将使用 K30 二氧化碳传感器(其文档可在此处找到,co2meters.com/Documentation/Datasheets/DS30-01%20-%20K30.pdf)。它的范围是 0-10,000 ppm,传感器通过串行端口以响应来自树莓派的特定命令提供二氧化碳浓度读数。

以下图显示了树莓派和 K30 二氧化碳传感器之间的连接:

与树莓派连接的 K30 二氧化碳传感器

传感器的接收器(Rx)引脚连接到树莓派 Zero 的发送器(Tx-GPIO 14(UART_TXD))引脚(前图中的黄色线)。传感器的发送器(Tx)引脚连接到树莓派 Zero 的接收器(Rx-GPIO 15(UART_RXD))引脚(前图中的绿色线)。

为了给传感器供电,传感器的 G+引脚(前图中的红线)连接到树莓派 Zero 的5V引脚。传感器的 G0 引脚连接到树莓派 Zero 的GND引脚(前图中的黑线)。

通常,串行端口通信是通过指定波特率、帧中的位数、停止位和流控来初始化的。

用于串行端口通信的 Python 代码

我们将使用pySerial库(pyserial.readthedocs.io/en/latest/shortintro.html#opening-serial-ports)来接口二氧化碳传感器:

  1. 根据传感器的文档,可以通过以波特率 9600、无奇偶校验、8 位和 1 个停止位初始化串行端口来读取传感器输出。 GPIO 串行端口为ttyAMA0。与传感器进行接口的第一步是初始化串行端口通信:
import serial 
       ser = serial.Serial("/dev/ttyAMA0")
  1. 根据传感器文档(co2meters.com/Documentation/Other/SenseAirCommGuide.zip),传感器对二氧化碳浓度的以下命令做出响应:

从传感器数据表中借用的读取二氧化碳浓度的命令

  1. 命令可以如下传输到传感器:
ser.write(bytearray([0xFE, 0x44, 0x00, 0x08, 0x02, 0x9F, 0x25]))
  1. 传感器以 7 个字节的响应做出响应,可以如下读取:
resp = ser.read(7)
  1. 传感器的响应格式如下:

二氧化碳传感器响应

  1. 根据数据表,传感器数据大小为 2 个字节。每个字节可用于存储 0 和 255 的值。两个字节可用于存储高达 65,535 的值(255 * 255)。二氧化碳浓度可以根据消息计算如下:
high = resp[3] 
       low = resp[4] 
       co2 = (high*256) + low
  1. 把它全部放在一起:
import serial 
       import time 
       import array 
       ser = serial.Serial("/dev/ttyAMA0") 
       print("Serial Connected!") 
       ser.flushInput() 
       time.sleep(1) 
       while True: 
           ser.write(bytearray([0xFE, 0x44, 0x00, 0x08,
           0x02, 0x9F, 0x25])) 
           # wait for sensor to respond 
           time.sleep(.01) 
           resp = ser.read(7) 
           high = resp[3] 
           low = resp[4] 
           co2 = (high*256) + low 
           print() 
           print() 
           print("Co2 = " + str(co2)) 
           time.sleep(1)
  1. 将代码保存到文件并尝试执行它。

I2C 通信

I²C(Inter-Integrated Circuit)通信是一种串行通信类型,允许将多个传感器接口到计算机。 I²C 通信由时钟和数据线两根线组成。树莓派 Zero 的 I²C 通信的时钟和数据引脚分别为GPIO 3SCL)和GPIO 2SDA)。为了在同一总线上与多个传感器通信,通常通过 I²C 协议通信的传感器/执行器通常通过它们的 7 位地址进行寻址。可以有两个或更多树莓派板与同一 I²C 总线上的同一传感器进行通信。这使得可以在树莓派周围构建传感器网络。

I²C 通信线是开漏线路;因此,它们使用电阻上拉,如下图所示:

I²C 设置

让我们通过一个示例来回顾一下 I²C 通信。

示例 2 - PiGlow

PiGlow是树莓派的一个附加硬件,由 18 个 LED 与SN3218芯片接口。该芯片允许通过 I²C 接口控制 LED。芯片的 7 位地址为0x54

为了接口附加硬件,SCL引脚连接到GPIO 3SDA引脚连接到GPIO 2;地线引脚和电源引脚分别连接到附加硬件的对应引脚。

PiGlow 附带了一个抽象 I²C 通信的库:github.com/pimoroni/piglow

尽管该库是对 I²C 接口的封装,但我们建议阅读代码以了解操作 LED 的内部机制:

PiGlow 叠放在 Raspberry Pi 上

安装库

PiGlow 库可以通过从命令行终端运行以下命令来安装:

curl get.pimoroni.com/piglow | bash

示例

安装完成后,切换到示例文件夹(/home/pi/Pimoroni/piglow)并运行其中一个示例:

python3 bar.py

它应该运行闪烁灯效果,如下图所示:

PiGlow 上的闪烁灯

同样,还有库可以使用 I²C 通信与实时时钟、LCD 显示器等进行通信。如果你有兴趣编写自己的接口,提供 I²C 通信与传感器/输出设备的细节,请查看本书附带网站上的一些示例。

示例 3 - 用于树莓派的 Sensorian 附加硬件

Sensorian是为树莓派设计的附加硬件。这个附加硬件配备了不同类型的传感器,包括光传感器、气压计、加速度计、LCD 显示器接口、闪存存储器、电容触摸传感器和实时时钟。

这个附加硬件上的传感器足以学习本章讨论的所有通信接口的使用方法:

堆叠在树莓派 Zero 上的 Sensorian 硬件

在本节中,我们将讨论一个示例,我们将使用 I²C 接口通过树莓派 Zero 测量环境光水平。附加硬件板上的传感器是APDS-9300传感器(www.avagotech.com/docs/AV02-1077EN)。

用于光传感器的 I2C 驱动程序

传感器硬件的驱动程序可从 GitHub 存储库中获取(github.com/sensorian/sensorian-firmware.git)。让我们从命令行终端克隆存储库:

git clone https://github.com/sensorian/sensorian-firmware.git 

让我们使用驱动程序(位于 ~/sensorian-firmware/Drivers_Python/APDS-9300文件夹中)从传感器的两个 ADC 通道读取值:

import time 
import APDS9300 as LuxSens 
import sys 
AmbientLight = LuxSens.APDS9300() 
while True: 
   time.sleep(1) 
   channel1 = AmbientLight.readChannel(1)                       
   channel2 = AmbientLight.readChannel(0) 
   Lux = AmbientLight.getLuxLevel(channel1,channel2) 
   print("Lux output: %d." % Lux)

有了两个通道的 ADC 值,驱动程序可以使用以下公式(从传感器数据表中检索)计算环境光值:

使用 ADC 值计算的环境光水平

这个计算是由属性getLuxLevel执行的。在正常照明条件下,环境光水平(以勒克斯为单位)约为2。当我们用手掌遮住光传感器时,测得的输出为0。这个传感器可以用来测量环境光,并相应地调整房间照明。

挑战

我们讨论了使用光传感器测量环境光水平。我们如何利用光输出(环境光水平)来控制房间照明?

SPI 接口

还有一种名为串行外围接口SPI)的串行通信接口。必须通过raspi-config启用此接口(这类似于在本章前面启用串行端口接口)。使用 SPI 接口类似于 I²C 接口和串行端口。

通常,SPI 接口由时钟线、数据输入、数据输出和从机选择SS)线组成。与 I²C 通信不同(在那里我们可以连接多个主机),在同一总线上可以有一个主机(树莓派 Zero),但可以有多个从机。SS引脚用于选择树莓派 Zero 正在读取/写入数据的特定传感器,当同一总线上连接了多个传感器时。

示例 4 - 写入外部存储器芯片

让我们查看一个示例,我们将通过 SPI 接口向 Sensorian 附加硬件上的闪存存储器写入数据。SPI 接口和存储器芯片的驱动程序可从同一 GitHub 存储库中获取。

由于我们已经下载了驱动程序,让我们查看一下驱动程序中提供的示例:

import sys 
import time   
import S25FL204K as Memory

让我们初始化并将消息hello写入存储器:

Flash_memory = Memory.S25FL204K() 
Flash_memory.writeStatusRegister(0x00) 
message = "hello" 
flash_memory.writeArray(0x000000,list(message), message.len())

现在,让我们尝试读取刚刚写入外部存储器的数据:

data = flash_memory.readArray(0x000000, message.len()) 
print("Data Read from memory: ") 
print(''.join(data))

本章提供了代码示例,可通过下载获得(memory_test.py)。

我们成功地演示了使用 SPI 读/写外部存储器芯片。

向读者提出挑战

在这里的图中,有一个 LED 灯带(www.adafruit.com/product/306)与树莓派附加硬件的 SPI 接口相连,使用了 Adafruit Cobbler(www.adafruit.com/product/914)。我们提供了一个线索,说明如何将 LED 灯带与树莓派 Zero 相连。我们希望看到您能否自己找到将 LED 灯带与树莓派 Zero 相连的解决方案。请参考本书网站获取答案。

LED 灯带与树莓派 Zero 的 Adafruit Cobbler 接口

总结

在本章中,我们讨论了树莓派 Zero 上可用的不同通信接口。这些接口包括 I²C、SPI 和 UART。我们将在我们的最终项目中使用这些接口。我们使用了二氧化碳传感器、LED 驱动器和传感器平台来讨论这些接口。在下一章中,我们将讨论面向对象编程及其独特的优势。我们将通过一个例子讨论面向对象编程的必要性。面向对象编程在您需要编写自己的驱动程序来控制机器人的组件或编写传感器的接口库的情况下尤其有帮助。

第十三章:Python 中的数据类型和面向对象编程

在本章中,我们将讨论 Python 中的数据类型和面向对象编程OOP)。我们将讨论 Python 中的列表、字典、元组和集合等数据类型。我们还将讨论 OOP,它的必要性以及如何在树莓派基于项目中编写面向对象的代码(例如,使用 OOP 来控制家用电器)。我们将讨论在树莓派 Zero 项目中使用 OOP。

列表

在 Python 中,列表是一种数据类型(其文档在此处可用,docs.python.org/3.4/tutorial/datastructures.html#),可用于按顺序存储元素。

本章讨论的主题如果不在实践中使用很难理解。任何使用此符号表示的示例:>>>都可以使用 Python 解释器进行测试。

列表可以包含字符串、对象(在本章中详细讨论)或数字等。例如,以下是列表的示例:

>>> sequence = [1, 2, 3, 4, 5, 6]
 >>> example_list = ['apple', 'orange', 1.0, 2.0, 3]

在前面的一系列示例中,sequence列表包含介于16之间的数字,而example_list列表包含字符串、整数和浮点数的组合。列表用方括号([])表示。项目可以用逗号分隔添加到列表中:

>>> type(sequence)
 <class 'list'>

由于列表是有序元素的序列,可以通过使用for循环遍历列表元素来获取列表的元素,如下所示:

for item in sequence: 
    print("The number is ", item)

输出如下:

The number is  1
 The number is  2
 The number is  3
 The number is  4
 The number is  5
 The number is  6

由于 Python 的循环可以遍历一系列元素,它会获取每个元素并将其赋值给item。然后将该项打印到控制台上。

可以在列表上执行的操作

在 Python 中,可以使用dir()方法检索数据类型的属性。例如,可以检索sequence列表的可用属性如下:

>>> dir(sequence)
 ['__add__', '__class__', '__contains__', '__delattr__',
    '__delitem__', '__dir__', '__doc__', '__eq__',
    '__format__', '__ge__', '__getattribute__', '__getitem__',
    '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', 
    '__iter__', '__le__', '__len__', '__lt__', '__mul__',
    '__ne__', '__new__', '__reduce__', '__reduce_ex__',
    '__repr__', '__reversed__', '__rmul__', '__setattr__', 
    '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 
    'append', 'clear', 'copy', 'count', 'extend', 'index',
    'insert', 'pop', 'remove', 'reverse', 'sort']

这些属性使得可以在列表上执行不同的操作。让我们详细讨论每个属性。

向列表添加元素:

可以使用append()方法添加元素:

>>> sequence.append(7)
 >>> sequence
 [1, 2, 3, 4, 5, 6, 7]

从列表中删除元素:

remove()方法找到元素的第一个实例(传递一个参数)并将其从列表中删除。让我们考虑以下示例:

  • 示例 1
>>> sequence = [1, 1, 2, 3, 4, 7, 5, 6, 7]
 >>> sequence.remove(7)
 >>> sequence
 [1, 1, 2, 3, 4, 5, 6, 7]
  • 示例 2
>>> sequence.remove(1)
 >>> sequence
 [1, 2, 3, 4, 5, 6, 7]
  • 示例 3
>>> sequence.remove(1)
 >>> sequence
 [2, 3, 4, 5, 6, 7]

检索元素的索引

index()方法返回列表中元素的位置:

>>> index_list = [1, 2, 3, 4, 5, 6, 7]
 >>> index_list.index(5)
 4

在这个例子中,该方法返回元素5的索引。由于 Python 使用从 0 开始的索引,因此元素5的索引为4

random_list = [2, 2, 4, 5, 5, 5, 6, 7, 7, 8]
 >>> random_list.index(5)
 3

在这个例子中,该方法返回元素的第一个实例的位置。元素5位于第三个位置。

Python 物联网入门指南(四)(4)https://developer.aliyun.com/article/1507230

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
2月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
2月前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
本文将引导读者了解如何使用Python进行数据分析,从安装必要的库到执行基础的数据操作和可视化。通过本文的学习,你将能够开始自己的数据分析之旅,并掌握如何利用Python来揭示数据背后的故事。
|
1天前
|
开发者 Python
Python入门:8.Python中的函数
### 引言 在编写程序时,函数是一种强大的工具。它们可以将代码逻辑模块化,减少重复代码的编写,并提高程序的可读性和可维护性。无论是初学者还是资深开发者,深入理解函数的使用和设计都是编写高质量代码的基础。本文将从基础概念开始,逐步讲解 Python 中的函数及其高级特性。
Python入门:8.Python中的函数
|
1天前
|
存储 索引 Python
Python入门:6.深入解析Python中的序列
在 Python 中,**序列**是一种有序的数据结构,广泛应用于数据存储、操作和处理。序列的一个显著特点是支持通过**索引**访问数据。常见的序列类型包括字符串(`str`)、列表(`list`)和元组(`tuple`)。这些序列各有特点,既可以存储简单的字符,也可以存储复杂的对象。 为了帮助初学者掌握 Python 中的序列操作,本文将围绕**字符串**、**列表**和**元组**这三种序列类型,详细介绍其定义、常用方法和具体示例。
Python入门:6.深入解析Python中的序列
|
1天前
|
程序员 UED Python
Python入门:3.Python的输入和输出格式化
在 Python 编程中,输入与输出是程序与用户交互的核心部分。而输出格式化更是对程序表达能力的极大增强,可以让结果以清晰、美观且易读的方式呈现给用户。本文将深入探讨 Python 的输入与输出操作,特别是如何使用格式化方法来提升代码质量和可读性。
Python入门:3.Python的输入和输出格式化
|
1天前
|
机器学习/深度学习 人工智能 算法框架/工具
Python入门:1.Python介绍
Python是一种功能强大、易于学习和运行的解释型高级语言。由**Guido van Rossum**于1991年创建,Python以其简洁、易读和十分工程化的设计而带来了庞大的用户群体和丰富的应用场景。这个语言在全球范围内都被认为是**创新和效率的重要工具**。
Python入门:1.Python介绍
|
1天前
|
缓存 算法 数据处理
Python入门:9.递归函数和高阶函数
在 Python 编程中,函数是核心组成部分之一。递归函数和高阶函数是 Python 中两个非常重要的特性。递归函数帮助我们以更直观的方式处理重复性问题,而高阶函数通过函数作为参数或返回值,为代码增添了极大的灵活性和优雅性。无论是实现复杂的算法还是处理数据流,这些工具都在开发者的工具箱中扮演着重要角色。本文将从概念入手,逐步带你掌握递归函数、匿名函数(lambda)以及高阶函数的核心要领和应用技巧。
Python入门:9.递归函数和高阶函数
|
1天前
|
存储 SQL 索引
Python入门:7.Pythond的内置容器
Python 提供了强大的内置容器(container)类型,用于存储和操作数据。容器是 Python 数据结构的核心部分,理解它们对于写出高效、可读的代码至关重要。在这篇博客中,我们将详细介绍 Python 的五种主要内置容器:字符串(str)、列表(list)、元组(tuple)、字典(dict)和集合(set)。
Python入门:7.Pythond的内置容器
|
1天前
|
存储 Linux iOS开发
Python入门:2.注释与变量的全面解析
在学习Python编程的过程中,注释和变量是必须掌握的两个基础概念。注释帮助我们理解代码的意图,而变量则是用于存储和操作数据的核心工具。熟练掌握这两者,不仅能提高代码的可读性和维护性,还能为后续学习复杂编程概念打下坚实的基础。
Python入门:2.注释与变量的全面解析
|
1月前
|
物联网 Python
请问:如何使用python对物联网平台上设备的属性进行更改?
为验证项目可行性,本实验利用阿里云物联网平台创建设备并定义电流、电压两个整型属性。通过Python与平台交互,实现对设备属性的控制,确保后续项目的顺利进行。此过程涵盖设备连接、数据传输及属性调控等功能。

热门文章

最新文章

推荐镜像

更多