MicroPython物联网进阶教程(三)

原文:MicroPython for the Internet of Things

协议:CC BY-NC-SA 4.0

六、低级硬件支持

对于所有支持的通用 Python 语言和许多内置函数,MicroPython 固件在最基本的功能上是相同的。然而,MicroPython 固件中的一些库在不同的主板上有一些细微的差别。在某些情况下,可用的库或类比其他的多,或者类的组织方式不同,但大多数都以某种形式实现了相同的核心库。在较低级别的硬件抽象层,情况就不一样了。这仅仅是因为一个主板供应商可能实现不同的硬件。在某些情况下,该板具有其它板上不存在的特性。例如,WiPy 有 WiFi 和蓝牙,而 Pyboard 两者都没有。

在这一章中,我们将看几个 MicroPython 中低级硬件支持的例子。我们将了解特定于主板的库以及一些低级别的专用库,如蓝牙、SPI、I2C 等库。我们还将看到一些简短的代码示例来说明特定于主板的库的功能。其中一些将是简短的代码片段,而不是您可以自己实现的实际项目。

但是,有几个是完整的项目,您可能想探索一下,但是大多数都没有深入的解释,只是作为例子,而不是详细的演练。此外,请记住,它们可能需要特定的分线板和 MicroPython 板以及其他附件来实现。同样,这些只是为了演示的目的。我们将在后面的章节中看到更完整的、循序渐进的例子,包括如何组装硬件。

为了保持简洁,我们将探索 Pyboard 和 WiPy 上不同的板专用库。其他电路板可能会有进一步的不同,但您需要查看供应商文档,以了解它们之间的差异。本章将为你提供发现这些差异的洞察力。我们还将重温使用分线板来演示前几章中讨论的一些库和硬件协议和技术。

让我们先来看一下 Pyboard 和 WiPy 的板专用库。

特定于主板的库

我们已经看到 Pyboard 和 WiPy 的机器库中存在差异。但是还有其他的不同:特定于每块板的库,因此只能用于同一块板的另一块板上。这些包括具有用于低级硬件的函数和类的库、特定于电路板的函数和常数等。

第一次使用新的 MicroPython 板时,您应该记住的一件事是,硬件级别的固件很可能与您使用的上一个 MicroPython 板不同。当您查看 BBC micro:bit、Circuit Playground、ESP8266 等板的固件端口时,情况尤其如此。

Tip

请务必查阅您的主板文档,以获得主板专用库的完整功能、用途和更多示例。

Pyboard

特定于 Pyboard 的库是独一无二的,因为它们包含对特定于供应商的皮肤的支持。正如我们在第三章中了解到的,Pyboard 有几种皮肤可供使用。幸运的是,固件中的 Pyboard 特定类直接支持所有的皮肤。这包括音频皮肤、LCD 等。

还有一些特定于 Pyboard 本身的库,如pyb库,它支持一些特定于电路板的功能,包括时间、电源、中断等。我们还将简单地浏览一下这个库,然后看看 LCD 皮肤的一个库:lcd160cr类。

下面几节将更详细地介绍这些库,并包括一些常见的功能示例。有关每个库的内容和功能的完整详细信息,请参见指定的文档。

标准型

pyb库是 Pyboard 相关函数和类的总括库。如果您正在寻找与 Pyboard 或其任何板载硬件相关的函数或库,这个库是您应该首先寻找的地方。下面列出了可用的函数组和类。

  • 时间:与时间相关的函数,以毫秒或微秒为单位延迟,并计算事件发生后的毫秒或微秒数(保存的变量)
  • 重置:允许您打开调试、启动引导加载程序模式或重置主板的功能
  • 中断:启用或禁用中断
  • 电源:使主板进入睡眠或深度睡眠模式并改变性能特征的功能(轻踩)
  • 杂项:信息、控制 UART、USB 和安装块设备的各种功能
  • 现在让我们看几个简短的例子。前两个展示了复位函数的例子,后两个是杂项函数,最后一个展示了如何使用其中一个类与板上的硬件进行交互。

    您可以使用pyb.hard_reset()功能执行硬复位,如下所示。如果您在 REPL 控制台中输入此语句,板将以与您按下重置按钮相同的方式重置。如果您需要从严重错误或硬件故障中中止,这可能很方便。

    MicroPython v1.9.1-154-g4d55d880 on 2017-07-11; PYBv1.1 with STM32F405RG
    Type "help()" for more information.
    >>> import pyb
    >>> pyb.hard_reset()
    
    

    Note

    hard_reset()功能可能会导致您的电脑抱怨 SD 卡在没有停止文件系统的情况下被弹出,因此请谨慎使用该功能。

    pyb.bootloader()功能将板卡置于引导加载模式。回想一下第三章中的,要安装固件,必须先关闭主板电源,安装跳线,然后打开主板电源,才能加载固件。通过此功能,您可以从 REPL 控制台执行此操作。也就是说,如果你能拿到 REPL 控制台的话。如果您的主板损坏或固件损坏,您仍然可以执行跳线过程,将主板置于引导加载程序模式以加载新固件。

    pyb.info()函数被用作信息转储。它打印出大量关于电路板的底层信息,包括硬件地址等等。除非您正在编写低级驱动程序或类似的东西,否则大多数都没有用,但是您可以将 True 传递给该函数,并以 GC 内存布局转储的形式获得更多信息,如下面的摘录所示。如果您对这些数据感到好奇,请参阅在线参考手册中的 Pyboard 硬件规格部分或forum.micropython.org论坛。

    >>> pyb.info(True)
    ...
    LFS free: 52224 bytes
    GC memory layout; from 20003e40:
    00000: h=hhhhhBShh==Sh=hhhh==h==Bh=hBh=hBhThShh=h==hh=BhhhBhBh=hh=hBh=h
    00400: =hTh==Shhhh==B........h=....................................h===
    00800: ====h===========================================================
    00c00: ==============..................................................
           (92 lines all free)
    18000: ............................
    
    

    pyb.main(filename)函数是最有用的函数之一。它设置 boot.py 完成后运行的主脚本的文件名。您可以将该功能与几个可选的main.py代码模块结合使用。如果您想实现一些自动启动和运行的项目,这可能是一个有用的工具。您可以使用这个函数告诉 Pyboard 从一个替代文件开始,而不是手动进入boot.py并改变它。这样,你就可以有“配置文件”来改变董事会的行为。酷。只需用有效的代码模块路径和名称(作为字符串)调用函数。在您更改之前,此设置一直有效。

    Note

    您应该只从boot.py内部调用该函数。

    pyb库也为支持的硬件主机提供了低级硬件类。注意,我们在机器库中看到了 WiPy 的一组类似的类。在 Pyboard 上,它们在pyb库中。表 6-1 显示了可用硬件类别的列表。如您所见,它支持 led、LCD(我们将在后面的章节中看到)、GPIO 引脚等等。记住类名是区分大小写的。

    表 6-1。

    Pyboard Low-Level Hardware Classes (pyb library)

    | 班级 | 描述 | | — | — | | 加速的 | 加速度计控制 | | 物理输出核心 | 模数转换 | | 能 | 控制器局域网通信总线 | | 数(字)-模(拟)转换器 | 数模转换 | | 灭绝 | 将 I/O 引脚配置为外部事件中断 | | I2C | 双线串行协议 | | 液晶显示 | LCD 触摸传感器 pyskin 的 LCD 控制 | | 发光二极管 | 发光二极管物体 | | 别针 | 控制 I/O 引脚 | | 皮纳夫 | 引脚替代功能 | | 雷达跟踪中心(Radar Tracking Centre 的缩写) | 实时时钟 | | 伺服系统 | 三线业余伺服驱动器 | | 精力 | 主机驱动的串行协议 | | 转换 | 切换对象 | | 计时器 | 控制内部定时器 | | 时间通道 | 为计时器设置通道 | | 通用非同步收发传输器(Universal Asynchronous Receiver/Transmitter) | 双工串行通信总线 | | USB_HID | USB 人机接口设备(HID) | | USB_VCP | USB 虚拟通信端口 |

    现在,让我们来看看其中的一个。我们将使用加速度计对电路板进行简单测试。也就是说,我们将编写一些代码,您可以使用这些代码来运行和检测 Pyboard 何时在三个方向上发生了物理移动。下面显示了可用于Accel类的方法。

  • Accel.filtered_xyz():获取一个过滤后的 x、y 和 z 值的三元组
  • Accel.tilt():获取倾斜寄存器
  • Accel.x():获取 x 轴数值
  • Accel.y():获取 y 轴值
  • Accel.z():获取 z 轴值
  • 加速度计是一种用于测量速度随时间变化的设备:换句话说,就是物体移动的方式和速度。虽然 Pyboard 上的加速度计不是一种能够超精细检测微小运动的精密仪器,但您可以使用它来检测电路板何时移动,甚至是有限程度的移动方向(移动轴)。因此,如果您想知道项目何时因安全原因移动,或者想检测或更改基于方向的行为,可以将加速度计集成到项目中。有很多很酷的方式可以使用加速度计!

    现在,让我们看一些代码!下面显示了如何使用加速度计获得 X、Y 和 Z 轴的原始值。值的范围从-32 到 32。只要稍加观察,我们就可以推断出哪些值表示棋盘在每个方向上移动了多远。尝试下面的代码,轻轻地拿起棋盘,通过向不同的方向旋转,在三维空间内移动它。慢慢地做,然后稍微快一点,注意数值是如何变化的。然后,将板放回原来的位置并观察。您可以按CTRL-C停止循环。

    import pyb
    from pyb import Accel
    acc = Accel()
    print("Press CTRL-C to stop.")
    while True:
        pyb.delay(500)    # Short delay before sampling
        print("X = {0:03} Y = {1:03} Z = {2:03}".format(acc.x(), acc.y(), acc.z()))
    
    

    Use Soft Reset to Refresh Import

    如果您像我一样,喜欢在 PC 上编写 MicroPython 代码并在那里进行测试,然后将其移动到板上进行更多的开发和测试,那么您可能会感到困惑,因为每次您复制想要包含和测试的代码模块或库的新版本时,都必须重置板。当连接到 REPL 控制台时,您可以使用CTRL+D键进行软复位,而不是关闭电路板电源或进行硬复位。这将执行软重启,允许您再次运行导入。事实上,您必须再次发出import——它刚刚重启了!最好的部分是,你将不必重新连接你的董事会或 REPL 控制台!试试看。

    下面显示了在 REPL 控制台中运行时的输出摘录。

    X = 002 Y = 000 Z = 021
    X = 000 Y = -01 Z = 023
    X = 005 Y = 020 Z = 000
    X = -05 Y = 016 Z = -11
    X = -11 Y = -13 Z = 014
    X = 022 Y = -04 Z = -05
    X = -03 Y = 019 Z = 012
    ...
    
    

    如果你喜欢挑战,你可以试着写一个脚本来使用加速度计检测电路板何时被颠倒。提示:在实验和编写代码时观察 X、Y 和 Z 的原始值,以寻找特定的范围。

    Caution

    在 Pyboard 上,加速度计使用 I2C(1),因此您不能同时使用加速度计和 I2C(1)。I2C 必须使用不同的引脚才能同时使用加速度计和 I2C 设备。

    这些例子只是这个库中可用内容的一小部分。如果您正在使用 Pyboard,您应该首先查看这个库,以满足您所有的低级硬件和特定于电路板的控制需求。我们将在后面的章节中看到一些可用类的例子以及它们的用法。

    Tip

    参见 http://docs.micropython.org/en/latest/pyboard/library/pyb.html 获取 pyb 库中可用函数和类的完整列表。

    液晶显示器 160cr

    Pyboard 的制造商制作了一个有趣的皮肤,到目前为止,在提供 MicroPython 板的供应商中是独一无二的。这种皮肤称为 lcd160cr 因此,LCD 是一个触摸感应 LCD 屏幕,您可以直接将其连接到 Pyboard,为您提供一个非常漂亮的触摸屏,您可以用它来制作一个现代化的用户界面。想想看——你可以制作一个 MicroPython 手表,天气传感器,或者任何需要用户界面的东西。

    Pyboard 固件中内置的库(名为lcd160cr)允许你感知屏幕被触摸的时间(和位置),你可以发送文本或绘制形状。这意味着,只要稍加想象,您就可以构建简单的图形用户界面。非常好。

    LCD 可以安装在两个位置之一,称为位置 X 和 y。然后在构造函数中使用这些值。图 6-1 显示了在 X 和 Y 位置(从左到右显示)连接 LCD 和 Pyboard 的位置。

    A447395_1_En_6_Fig1_HTML.jpg

    图 6-1。

    Positions for Mounting the LCD (Pyboard)

    位置差异指的是液晶屏在主板上的方向。在 X 位置,LCD 安装在 X 范围的 GPIO 引脚上,在 Y 位置,它安装在 Y 范围的 GPIO 引脚上。请注意,在 Y 位置,LCD 必须旋转 180 度,如图所示。

    现在,让我们来看一个使用 LCD 的例子。在这个例子中,我们将创建一个简单的用户界面来检测屏幕四角的触摸。为了让它更有趣,我们还会在每次触摸时打开不同的 LED。这将给你一个视觉反馈,告诉你已经触摸了屏幕。

    这个例子是本书中较长的例子之一,但不难理解。让我们从代码的高级演练开始。

    我们应该做的第一件事是编写import语句,这样我们就可以检测代码何时在 Pyboard(或另一个板)上运行。如果它不是 Pyboard,我们应该中止,因为其他板没有我们需要的库(lcd160cr)。如果您在自己的代码中采用这种技术,您可以避免奇怪的导入异常和其他可能不清楚程序失败原因的问题。另外,这是很好的编程。下面显示了用于检测所需库是否存在的代码,以及如何在其中一个库无法导入时退出程序。

    # First, make sure this is running on a Pyboard
    try:
        import pyb
    except ImportError:
        print("ERROR: not on a Pyboard!")
        sys.exit(-1)
    
    # Next, make sure the LCD skin library in the firmware
    
    try:
        import lcd160cr
    except ImportError:
        print("ERROR: LCD160CR library missing!")
        sys.exit(-1)
    
    

    接下来,我们将编写一个函数来打开 LED。这是一个如何编写可重用代码的例子。也就是说,我们不想重复的重复同样的代码。在这种情况下,我们可以按颜色打开特定的 LED。为了帮助我们做到这一点,我们可以编写一个函数来检索基于颜色的 LED(1 =红色,2 =绿色,等等)。).下面显示了 helper 函数。

    def led_color(num):
        if num == 1: return "red"
        elif num == 2: return "green"
        elif num == 3: return "orange"
        else: return "blue"
    
    

    以下显示了打开 LED 的可重复使用的功能。如您所见,我们首先关闭旧的 LED,然后打开新的(选定的)LED。

    def turn_on_led(num, led_last):
        # turn last LED off
        led = pyb.LED(led_last)
        led.off()
        led = pyb.LED(num)
        led.on()
        sys.stdout.write("Turning off ")
        sys.stdout.write(led_color(led_last))
        sys.stdout.write(" - Turning on ")
        sys.stdout.write(led_color(num))
        sys.stdout.write("\n")
    
    

    接下来,我们可以编写代码来读取 LCD 上被触摸的位置,并根据触摸发生的位置,打开该角的 LED。我们将用红色表示左上角,绿色表示右上角,橙色表示右下角,蓝色表示右下角。

    由于pyb.LED()用数字指代发光二极管,因此使用数字来简化代码。精明的读者可能会发现一种通过枚举甚至使用常量来改进代码的方法。如果你看到这些潜在的改进,请随意把这些改进作为练习。清单 6-1 展示了这个例子的完整代码。

    # MicroPython for the IOT - Chapter 6
    # Example module for the LCD skin on a Pyboard
    #
    # Note: The LCD is positioned in the "X" position.
    #
    import sys
    
    # First, make sure this is running on a Pyboard
    try:
        import pyb
    except ImportError:
        print("ERROR: not on a Pyboard!")
        sys.exit(-1)
    
    # Next, make sure the LCD skin library in the firmware
    try:
        import lcd160cr
    except ImportError:
        print("ERROR: LCD160CR library missing!")
        sys.exit(-1)
    
    # Return color of LED
    def led_color(num):
        if num == 1: return "red"
        elif num == 2: return "green"
        elif num == 3: return "orange"
        else: return "blue"
    
    # Use a method to turn off last LED and the next one on
    def turn_on_led(num, led_last):
        # turn last LED off
        led = pyb.LED(led_last)
        led.off()
        led = pyb.LED(num)
        led.on()
        sys.stdout.write("Turning off ")
        sys.stdout.write(led_color(led_last))
        sys.stdout.write(" - Turning on ")
        sys.stdout.write(led_color(num))
        sys.stdout.write("\n")
    
    # Setup the LCD in the "X" position
    lcd = lcd160cr.LCD160CR('X')
    
    for j in range(1, 4):   # Turn off all of the LEDs
        led = pyb.LED(j)    # Get the LED
        led.off()           # Turn the LED off
    
    # Now, let's play a game. Let's change the LEDs to
    # different colors depending on where the user touches
    # the screen.
    print("Welcome to the touch screen demo!")
    print("Touch the screen in the corners to change the LED lit.")
    print("Touch the center to exit.")
    center = False
    last_led = 1
    while not center:
        pyb.delay(50)
        if lcd.is_touched:
            touch = lcd.get_touch()
            if (touch[0] == 0):
                continue
            # Upper-left corner
            if ((touch[1] <= 60) and (touch[2] <= 60)):
                turn_on_led(1, last_led)
                last_led = 1
            # Upper-right corner
            elif ((touch[1] >= 100) and (touch[2] <= 60)):
                turn_on_led(2, last_led)
                last_led = 2
            # Lower-right corner
            elif ((touch[1] >= 100) and (touch[2] >= 100)):
                turn_on_led(3, last_led)
                last_led = 3
            # Lower-left corner
            elif ((touch[1] <= 60) and (touch[2] >= 100)):
                turn_on_led(4, last_led)
                last_led = 4
            # Center
            elif ((touch[1] > 60) and (touch[1] < 100) and (touch[2] > 60) and (touch[2] < 100)):
                led = pyb.LED(last_led)
                led.off()
                center = True
    
    print("Thanks for playing!")
    sys.exit(0)
    
    Listing 6-1.Using the Pyboard LCD (lcd160cr)
    
    

    如果你有液晶显示器,继续尝试这个例子。一旦你这样做,你应该看到发光二极管灯,因为你触摸每个角落,你会看到在你的 REPL 控制台输出如下。

    >>> import pyboard_lcd
    Welcome to the touch screen demo!
    Touch the screen in the corners to change the LED lit.
    Touch the center to exit.
    Turning off red - Turning on green
    Turning off green - Turning on red
    Turning off red - Turning on red
    Turning off red - Turning on orange
    Turning off orange - Turning on green
    Turning off green - Turning on green
    Turning off green - Turning on orange
    Turning off orange - Turning on blue
    Turning off blue - Turning on red
    Thanks for playing!
    
    

    Tip

    液晶屏上有一层薄薄的保护膜。您需要删除它,并使用手写笔或类似的软指针来测试脚本。如果你的手指很大,触摸指定的小区域可能会有一些困难。

    如果你决定自己尝试这个例子,你会发现它给了你一些实现一个有趣的目标的满足感。如果你喜欢这个例子,并且想为你自己的项目得到一个 LCD,请到 MicroPython 商店订购一个( https://store.micropython.org/store/#/products/LCD160CRv1_0H )。你会发现你可以买一个有标题或没有。如果你决定购买漂亮的(可选)铝制外壳,你可以选择不带外壳的,这需要安装不同的、有角度的头部(你必须自己订购和焊接)。但是,您可以使用带有标题的 LCD,如下例所示。

    Tip

    参见 http://micropython.org/resources/LCD160CRv10-refmanual.pdf 了解 lcd160cr 的参考手册,其中包括使用皮肤的低级规范。

    WiPy

    特定于 WiPy 的库是独一无二的,因为它们支持完整的 Pycom 板,包括扩展板、PySense 和 PyTrack shields。

    还有一些特定于 Pyboard 本身的库,以pycom库的形式出现,其中包括支持更改心跳 LED,包括更改颜色。AES库包含一个保护数据的有趣特性——AES 加密。我们将更详细地探索这个库。此外,回想一下,WiPy 固件包含 I2C、SPI 等底层硬件。与 Pyboard 相反,py board 在pyb库中有这些。

    下面几节将更详细地介绍这些库,包括一些常见的功能示例。有关每个库的内容和功能的完整详细信息,请参见指定的文档。

    派克姆

    pycom库具有控制 Pycom 设备特定功能的功能,例如心跳 RGB LED。事实上,您可以改变 LED 的颜色,打开或关闭它,并获得 LED 的当前状态。虽然这看起来非常初级,但您可以使用心跳 LED 来传达状态信息。例如,您可以更改颜色来指示不同的操作(或状态),如从传感器读取、保存数据、传达错误等。

    让我们看一个使用心跳 LED 设置状态的简短示例。请注意,LED 颜色由代表红、绿、蓝(RGB)的 24 位值定义,其中红色由最高的 8 位表示,绿色接下来是 8 位,蓝色是最低的 8 位。我们通常用十六进制表示这些值。 1 比如亮白色是 0xFFFFFF,0xFFFF00 是黄色,0x00FFFF 是海绿色。

    在本例中,我们将使用一组辅助函数和一个测试循环来处理心跳 LED。注意,要打开(使用)心跳 LED,必须先用heartbeat(False)关闭心跳内部功能。清单 6-2 展示了使用心跳 LED 显示状态的示例代码。

    # MicroPython for the IOT - Chapter 6
    # Example for working with the hearbeat LED as a
    # status/state indicator
    #
    import utime
    
    # First, make sure this is running on a Pyboard
    try:
        import pycom
    except ImportError:
        print("ERROR: not on a WiPy (or Pycom) board!")
        sys.exit(-1)
    
    # State/status enumeration
    _STATES = {
        'ERROR'   : 0xFF0000, # Bright red
        'READING' : 0x00FF00, # Green
        'WRITING' : 0x0000FF, # Blue
        'OK'      : 0xFF33FF, # Pinkish
    }
    
    # Clear the state (return to normal operation)
    def clear_status():
        pycom.heartbeat(True)
    
    # Show state/status with the heatbeat LED
    def show_status(state):
        pycom.heartbeat(False)
        pycom.rgbled(state)
    
    # Now, demonstrate the state changes
    for state in _STATES.keys():
        show_status(_STATES[state])
        utime.sleep(3)
    
    # Return heartbeat to normal
    clear_status()
    
    Listing 6-2.Using the Heartbeat LED for Status/State (WiPy)
    
    

    如果您运行这段代码,您会注意到 LED 会呈现一些非常明亮的颜色。所以,不要直接盯着领导!你可以尝试使用一些更微妙的颜色值来降低亮度。

    Tip

    参见在线计算器 http://www.rapidtables.com/web/color/RGB_Color.htm 确定所需颜色。

    俄歇电子能谱

    WiPy 有一个名为crypto的特殊库,它有支持 AES(高级加密标准)的AES库,AES 是由 NIST 标准化的对称分组密码。虽然您可能不需要这个特性,但是对于我们这些关心保护敏感数据的人来说,这可能是一个值得考虑的漂亮特性。

    例如,您可能希望通过互联网将数据传输到另一个系统。如果您没有用加密来保护数据,那么如果数据以某种方式被利用,解密数据并不太困难。如果您加密数据(并保护密钥!),你可以让人们更难看到数据。

    Note

    加密是一项高级功能,大多数初学者不会使用。因此,这一节很简短。如果你想了解更多关于这个库的信息,请看 https://docs.pycom.io/chapter/firmwareapi/pycom/aes.html

    AES 库提供了几个常量来控制加密模式和两个函数:一个用来加密,另一个用来解密。您需要提供一个密钥,用于由常量AES.MODE_ECB定义的最简单加密形式的加密算法,该常量表示电子代码簿。其他表单可能需要附加参数。

    有一个警告。您加密的数据必须是 16 字节块的倍数。注意我们是如何使用空格使字符串变成 16 字节的。因此,如果您要加密从传感器或网络上的其他节点创建或读取的数据,需要确保使用 16 字节倍数的块进行加密。

    让我们看一个例子。在本例中,我们将创建一个包含加密数据的文件,以展示如何保护您的数据,以便保存或发送到另一个节点(计算机)。然后,我们将打开文件并读取解密数据,这样我们就可以展示如何解密加密数据。我们将使用字符串使它更容易,但你也可以加密二进制数据。清单 6-3 显示了使用 AES 加密保护数据的示例代码。

    # MicroPython for the IOT - Chapter 6
    # Simple example for working with encrypting data
    #
    import sys
    
    # First, make sure this is running on a WiPy (pycom)
    try:
        import pycom
        from crypto import AES
    except ImportError:
        print("ERROR: not on a WiPy (or Pycom) board!")
        sys.exit(-1)
    
    # Setup encryption using simple, basic encryption
    # NOTICE: you normally would protect this key!
    my_key = b'monkeybreadyummy' # 128 bit (16 bytes) key
    cipher = AES(my_key, AES.MODE_ECB)
    
    # Create the file and encrypt the data
    new_file = open("secret_log.txt", "w")    # use "write" mode
    new_file.write(cipher.encrypt("1,apples,2.5   \n"))   # write some data
    new_file.write(cipher.encrypt("2,oranges,1    \n"))   # write some data
    new_file.write(cipher.encrypt("3,peaches,3    \n"))   # write some data
    new_file.write(cipher.encrypt("4,grapes,21    \n"))   # write some data
    new_file.close()  # close the file
    
    # Step 2: Open the file and read data
    old_file = open("secret_log.txt", "r")  # use "read" mode
    # Use a loop to read all rows in the file
    for row in old_file.readlines():
        data = cipher.decrypt(row).decode('ascii')
        columns = data.strip("\n").split(",") # split row by commas
        print(" : ".join(columns))  # print the row with colon separator
    
    old_file.close()
    
    Listing 6-3.Using Encryption to Protect Data (WiPy)
    
    

    代码很简单,你应该没有问题。但是,请注意,我们结合了 write 方法和 encrypt 调用,使事情变得更简短。如果你愿意,你可以用两个语句加上一个中间变量。

    当这个程序运行时,它会在 WiPy 的闪存驱动器上创建一个名为 secret_log.txt 的文件。如果我们用十六进制转储实用程序检查这个文件,我们可以看到它确实被加密了(我们无法读取数据,因为它被打乱了)。下面显示了文件在十六进制转储中的样子。

    $ hexdump -C secret_log.txt
    00000000  c1 02 97 87 74 28 4f 4e  de 83 8d 8d 49 4a f8 93  |....t(ON....IJ..|
    00000010  c9 e7 f8 00 f3 ba e2 f8  7c 6e ca 41 13 0c 09 35  |........|n.A...5|
    00000020  a6 83 f6 fc 2c de ba eb  f6 3a af fe c0 b5 c6 ee  |....,....:......|
    00000030  7a 3b 3a 36 90 da dc 36  3d 61 7e 31 75 a3 ca 96  |z;:6...6=a∼1u...|
    00000040
    
    

    该代码还打印出从文件中读取的字符串,以确认其工作正常。如果您通过 REPL 控制台运行该程序,您应该会看到以下输出。

    >>> import wipy_encryption
    1 : apples : 2.5
    2 : oranges : 1
    3 : peaches : 3
    4 : grapes : 21
    
    

    既然我们已经看到了几个板专用库的例子,让我们来看看几个直接使用硬件特性的例子。我们在前面的例子中已经看到了一些,但是没有详细解释。下面几节将深入探讨一些使用 Pyboard 和 WiPy 的更常见的低级硬件访问。

    低级示例

    使用底层硬件(有些人会说是“硬件”或“设备”)是使用 MicroPython 的所有动作和焦点(以及相对难度)发生的地方。MicroPython 和分线板供应商在让事情变得更容易方面做得非常出色,但是在解释方面还有改进的空间。

    也就是说,当提供使用低级硬件的例子时,在线文档有点简洁。部分原因是这些例子通常需要额外的特定硬件。例如,要使用 I2C 接口,您需要一个支持 I2C 的分线板。因此,在线示例仅提供了最基本的示例和解释。

    然而,这并不意味着缺少底层硬件的其他文档。事实上,该文档提供了您可以使用的所有类和函数的极好概述。接下来的挑战是利用这个概述并应用它来解决你的编程需求,这也是本书的目的之一!

    除了可能存在的车载传感器或其他组件,如 led、RTC、按钮等。大多数低级通信将通过 I2C、单线、模拟或数字引脚,甚至 SPI 接口。I2C 和 SPI 接口是您在使用硬件时可能会遇到最大困难的接口。这是因为您使用的每个设备(分线板)都需要一个非常具体的协议。也就是说,该设备可能需要特殊的序列来触发该设备的不同于其他分支板的传感器或特征。因此,使用 I2C 或 SPI(以及其他一些)类型的设备可能是一个挑战,要弄清楚究竟如何与它们“交谈”。

    司机和图书馆来救援!

    幸运的是,有一小部分人正在制作帮助我们使用这些设备的类和函数集,但是人数在不断增加。这些称为库或更常见的驱动程序,以一个或多个代码模块的形式出现,您可以下载、复制到您的主板,并将功能导入到您的程序中。驱动程序的开发者已经为你做了所有繁重的工作,让你很容易使用这个设备。

    因此,对于大多数刚开始使用 MicroPython 的人来说,他们希望使用某些传感器、设备、分线板等。,您应该将您计划使用的内容限制在那些您可以找到与之一起工作的驱动程序的范围内。那么,如何为你的设备找到一个驱动程序呢?有几个地方可以看看。

    首先,您应该查看 MicroPython 上的论坛和文档。在这种情况下,不要只局限于那些迎合你的选择的论坛。相反,看看他们所有人!很有可能,您可以找到一个只需稍加修改就能适应的库。除了下载并复制到板上,大多数都可以轻松使用。下面列出了在寻找驱动程序时应该经常访问的论坛和文档。

  • MicroPython 论坛: https://forum.micropython.org/
  • MicroPython 文档: https://docs.micropython.org/en/latest/pyboard/
  • Pycom (WiPy)论坛: https://forum.pycom.io/
  • Pycom (WiPy)文件: https://docs.pycom.io/
  • BBC 微:bit MicroPython 论坛: https://forum.micropython.org/viewtopic.php?t=1042
  • BBC micro:bit MicroPython 文档: https://microbit-micropython.readthedocs.io/en/latest/
  • MicroPython Wiki(外部文档): http://wiki.micropython.org/Home
  • 阿达果学习: https://learn.adafruit.com/
  • 注意最后一项。如果您搜索 MicroPython,您会发现许多精彩的(完整的)教程,包括越来越多的硬件主题。

    第二,使用你最喜欢的互联网搜索引擎,搜索硬件的例子。在搜索中使用硬件设备的名称和“MicroPython”。如果设备是新的,你可能找不到任何搜索条件。一定要探索其他搜索词。

    一旦你找到了司机,乐趣就开始了!您应该下载驱动程序,并将其复制到您的主板上进行测试。请务必遵循驱动程序附带的示例,以避免以意外的方式使用驱动程序。

    这让我想起了在决定是否使用这个驱动程序时应该考虑的一件重要事情。如果驱动程序有很好的文档记录,并且有例子,特别是如果例子包括您的主板,您应该可以放心使用它。但是,如果驱动程序根本没有文档,或者没有或只有很少的示例代码,就不要使用它!很有可能它是半生不熟的、陈旧的、正在进行的工作,或者只是糟糕的编码。不是所有分享的人都能很好的分享和交流。

    让我们看两个低级的例子:使用实时时钟和通过中断回调。我们将从实时时钟(RTC)开始。这些只是可用的一小部分样本,代表了你在本书和大多数小型 IOT 项目中需要用到的最常见的东西。

    实时时钟(RTC)

    大多数电路板都有实时时钟(RTC)。RTC 是一种特殊的计时电路(有时是集成电路或芯片)。这是因为大多数处理器(微控制器、微处理器等。)与保持处理器以某一速度(例如,Mhz)运行的晶体或时钟芯片同步操作。遗憾的是,这通常不容易划分为一个时间变量(值)。RTC 是用来记录时间的,这样我们就可以用时间来记录事件。

    要使用 RTC,我们首先用当前的日期和时间初始化起始值(就像设置一个新的桌面时钟一样),我们可以随时读取当前的日期和时间。然而,当板断电时,没有备用电池的 RTC 将丢失其值。因此,我们必须在每次启动电路板时设置它。幸运的是,互联网上有一个时间服务,我们可以用它来获取当前的日期和时间。它被称为网络时间协议(NTP)。 2

    让我们看一个如何使用这个服务的例子。我们将在 WiPy 上创建一个程序,将评估板连接到我们的本地 WiFi,WiFi 已连接到互联网。一旦连接上,我们将使用 NTP 来设置当前时间,然后执行一个测试来查看当前的日期和时间。我们应该在运行代码时看到确切的日期和时间!清单 6-4 展示了完整的例子。

    # MicroPython for the IOT - Chapter 6
    # Example module for using the ntptime server to set the datetime
    # Note: only works on WiPy!
    
    from network import WLAN
    from machine import RTC
    import machine
    import sys
    import utime
    
    wlan = WLAN(mode=WLAN.STA)
    
    def connect():
        wifi_networks = wlan.scan()
        for wifi in wifi_networks:
            if wifi.ssid == "YOUR_SSID":
                wlan.connect(wifi.ssid, auth=(wifi.sec, "YOUR_SSID_PASSWORD"), timeout=5000)
                while not wlan.isconnected():
                    machine.idle() # save power while waiting
                print("Connected!")
                return True
        if not wlan.isconnected():
            print("ERROR: Cannot connect! Exiting...")
            return False
    
    if not connect():
        sys.exit(-1)
    
    # Now, setup the RTC with the NTP service.
    rtc = RTC()
    print("Time before sync:", rtc.now())
    rtc.ntp_sync("pool.ntp.org")
    while not rtc.synced():
        utime.sleep(1)
        print("waiting for NTP server...")
    print("Time after sync:", rtc.now())
    
    Listing 6-4.Using an NTP Time Server to set the RTC (WiPy)
    
    

    这些代码的大部分应该是熟悉的,因为我们在前一章已经看到了 WiFi 连接。在这个例子中,我们将代码放在一个方法中,使它更容易使用。 3 但是,RTC()类的用法是新的。注意,一旦建立了网络连接,我们需要做的就是调用ntp_sync()方法,以 NTP 服务的名义传递。是的,它内置在图书馆里!酷。之后,我们只需要等到 RTC 与 NTP 同步,就可以开始了。

    Note

    Pyboard 在机器库中提供了RTC()类,但它与 WiPy 固件中的略有不同。您可以修改这个示例,作为在 Pyboard 上使用的练习。

    当您在 WiPy 上运行它时,您将看到如下输出。注意,我们打印时间值——这是开始时间——然后在 RTC 与 NTP 同步后再次打印时间。

    >>> import wipy_ntp
    Connected!
    Time before sync: (1970, 1, 1, 0, 0, 36, 560190, None)
    waiting for NTP server...
    waiting for NTP server...
    waiting for NTP server...
    Time after sync: (2017, 7, 13, 16, 19, 51, 402976, None)
    
    

    这个例子非常有帮助,在某些情况下,在读取数据以进行后续分析时是必须的。知道数据何时保存或传感器何时被读取通常是至关重要的。您可能希望将此代码标记为以后在您的 IOT 项目中使用。

    Note

    我们可以使用具有板载时钟的专用 RTC 模块,以便在离线操作或板断电期间保持时钟同步。我们将在第八章中看到如何做到这一点。

    现在,让我们来看看回调,这是一种可以用来处理硬件中断的编程机制。

    回收

    如果你想执行一些代码来响应传感器或用户输入,你会怎么做?利用我们到目前为止所学的知识,我们可以编写一个循环程序来轮询传感器或用户可操作的设备(如按钮),并在被触发时执行代码。这种轮询技术是可行的,但是有一种更好的结构叫做回调。

    回调是我们定义的函数,当某个事件发生时,它与固件相关联来执行。如果硬件抽象允许使用回调,我们就可以使用它。好在 Pyboard 固件(pyb.Switch)中的 Switch 类就有这样的机制。我们也可以用同样的方式使用硬件中断。然而,硬件中断是一个高级话题。让我们使用Switch类来使事情变得更简单。

    回调的使用允许我们继续执行代码来完成诸如读取传感器、显示数据等工作。,当事件(中断)发生时,MicroPython 将执行回调函数,然后返回执行我们的代码。这是通过将回调函数绑定到中断上来实现的。开关类有一个为按钮按压定义的中断。也就是说,当按钮被按下时,回调被触发(执行)。

    使用开关回调有一些注意事项。首先,switch 回调函数不能带参数,因此您不能定义回调函数并向它传递任何数据。事实上,回调函数不允许创建数据。例如,您不能创建字典、元组等。,在函数内部。虽然回调函数可以访问全局变量,但如果使用状态变量,它们可能会引发异常。最后,您可以关闭(断开)回拨。例如,您可以用switch.callback(none)断开交换机的回拨。

    现在,让我们看一个例子。在本例中,我们希望创建一个回调函数来循环显示板上的 led。每按一次按钮,另一个 LED 就会亮起,直到我们循环所有的 LED,然后重新开始。这意味着我们需要保存最后点亮的 LED 或 LED 的状态。为此,我们可以使用一个具有局部变量的类,我们可以在回调函数中访问这个局部变量。

    设置回调很容易。我们只是调用开关的回调函数,并传入函数名。我们通过类的构造函数来实现这一点。也就是说,当我们创建一个类的新实例时,我们传入pyb.Switch对象,然后调用该对象上的回调函数,传入类函数的名称。

    让我们看看代码,你会看到这是如何工作的。清单 6-5 显示了 Pyboard 回调示例的完整代码。

    # MicroPython for the IOT - Chapter 6
    # Simple example for working with interrupts using a class
    # to store state.
    #
    import sys
    
    # First, make sure this is running on a Pyboard
    try:
        import pyb
    except ImportError:
        print("ERROR: not on a Pyboard!")
        sys.exit(-1)
    
    # Initiate the switch class
    switch = pyb.Switch()
    
    class Cycle_LED(object):
        # Constructor
        def __init__(self, sw):
            self.cur_led = 0
            sw.callback(self.do_switch_press)
    
        # Switch callback function
        def do_switch_press(self):#
            # Turn off the last led unless this is the first time through the cycle
            if self.cur_led > 0:
                pyb.LED(self.cur_led).off()
            if self.cur_led < 4:
                self.cur_led = self.cur_led + 1
            else:
                self.cur_led = 1
            # Turn on the next led
            pyb.LED(self.cur_led).on()
    
    # Initiate the Cycle_LED class and setup the callback
    cycle = Cycle_LED(switch)
    
    # Now, simulate doing something else
    print("Testing the switch callback. Press CTRL-C to quit.")
    while True:
        sys.stdout.write(".")  # Print something to show we're still in the loop
        pyb.delay(1000)        # Wait a second...
    
    Listing 6-5.Callback Example (Pyboard)
    
    

    注意我们创建的类,以及它如何为交换机设置回调函数。还要注意我们是如何实例化 switch 实例中传递的类的。之后,我们设置了一个简单的循环来打印出点,直到用 CTRL-C 停止程序。这演示了即使按钮被按下,程序仍继续运行。

    如果您正在使用 Pyboard,请对这个示例进行测试。正如您将看到的,使用回调是非常强大的。

    Tip

    如果你想学习如何编写自己的中断处理程序,请参见 https://docs.micropython.org/en/latest/pyboard/reference/isr_rules.html

    Communication Via Bluetooth Low Energy (BLE)

    WiPy 的另一个有趣的特性是它带有蓝牙低能耗(BLE ),固件支持它作为一个网络类。虽然您可以通过 UART(串行通信)将 ble 模块与其他电路板一起使用,但要了解更高级、更完整的示例,请参见 https://github.com/dmazzella/uble ,WiPy 的 BLE 功能使您可以创建读/写服务,用于传输小数据包:例如,对传感器进行采样并通过 BLE 发送数据。

    可悲的是,固件中的蓝牙支持仍然非常新,对于那些刚刚接触 MicroPython(和 BLE)的人来说还不够完整。因此,对于一本入门书来说,它太超前了。事实上,文档目前非常简洁,示例很难理解。随着越来越多的人使用它并找到创造性的方法来应用它,随着新功能和现有功能的增加,您可能会看到文档得到增强。查看 Pycom 在线文档,了解蓝牙支持(https ://docs.pycom.io/chapter/firmwareapi/pycom/network/bluetooth/).)的更新

    现在,让我们看看如何使用 I2C 和 SPI 协议与分线板通信。

    使用分线板

    我们在第三章简要介绍了分线板,其中我们看到了一个使用 Arduino 屏蔽将 Pyboard 连接到无线网络的有趣示例。这只是分线板的一个例子。您还可以找到承载传感器和其他设备的分线板,从而简化您的 IOT 项目。使用这些分线板的诀窍是找到正确的、有效的驱动程序。

    回想一下,使用分线板有两种方法:找到您可以使用的驱动程序,或者构建您自己的驱动程序。对于不熟悉 MicroPython 和 I2C 或 SPI 的人,不建议构建自己的驱动程序。花时间去寻找一个你能使用(或适应)的驱动程序比自己写一个要容易得多。这是因为您必须能够获得、阅读和理解分线板如何通信(理解其协议)。根据支持的传感器或设备,每个板的通信方式会有所不同。也就是说,BMP180 传感器的驱动程序与 BME280 传感器的驱动程序看起来或工作起来不一样。在查找和使用驱动程序时,您必须非常具体。

    搜索一个驱动程序可能是一项单调乏味的工作,这需要一些耐心,并且可能需要在论坛上使用不同的搜索词进行多次搜索,例如“micropython BME280”一旦你找到一个驱动程序,你可以通过查看包含的例子快速判断它是否是一个可行的选择。如前所述,如果没有例子或者例子与你在本书或在线文档中看到的不相似,就不要使用它。

    Tip

    要查找驱动程序,请访问 https://forum.micropython.org/viewforum.php?f=14 并搜索您的主板。例如,如果你有一个 BME280 分线板,用它作为搜索词。使用“供应商 XYZ 型号#40113”这样的精确术语可能过于具体。首先尝试使用传感器/设备的通用名称。

    让我们来看两个分线板示例:一个使用 I2C 协议,另一个使用 SPI 协议。

    Online Examples

    如果你想在你的 IOT 项目中使用一个分组讨论板,一定要花些时间不仅在论坛上,也看看各种博客和教程,比如那些在hackaday.comlearn.sparkfun.comlearn.adafruit.com上的。最好的博客和教程不仅解释了如何编写代码,还解释了分组讨论板的作用和使用方法。这些网上参考资料很少,但这三个网站的都是最好的。另外,也可以看看一些关于这个话题的视频。其中一些值得一看——尤其是如果它们来自 Adafruit 或 Sparkfun 的好人们。 4

    内部集成电路(I2C)

    I2C 协议可能是你在分组讨论板上看到的最常见的协议。我们在前面的章节中遇到过这个术语几次,因此我们只知道它是一个通信协议。I2C 是一种快速数字协议,使用两条线(加上电源和地)从电路(或设备)读取数据。该协议旨在允许多个设备(从设备)与一个主设备(MicroPython 板)一起使用。因此,每个 I2C 分线板都有自己的地址或标识,您将在驱动程序中使用这些地址或标识来连接设备并与之通信。

    让我们看一个如何使用 I2C 分线板的例子。在这个例子中,我们想要使用 Adafruit ( https://www.adafruit.com/product/1334 )的 RGB 传感器来读取对象的颜色。是的,你可以让你的 MicroPython 板看到彩色!我们将使用这个分线板和 WiPy。

    如果您没有或不想购买 Adafruit RGB 传感器分线板(虽然不贵),也不用担心。此示例作为使用 I2C 分线板的教程提供。我们将在本书后面的一个示例项目中使用另一个 I2C 分线板。图 6-2 显示了 Adafruit RGB 传感器。

    A447395_1_En_6_Fig2_HTML.jpg

    图 6-2。

    Adafruit RGB Sensor (courtesy of adafruit.com)

    配线分线板也非常容易,因为我们只需要电源、接地、SCL 和 SDA 连接。SCL 是时钟信号,SDA 是数据信号。这些引脚在您的 MicroPython 板上(或在文档中)以及分线板上有标签。当您连接分线板时,请确保电源要求匹配。也就是说,一些分线板可以采用 5V,但许多限于 3 或 3.3V。如果您有任何疑问,请查看供应商的网站。

    我们只需要连接 3V、地、SDA、SCL 和 LED 引脚。LED 引脚用于打开分线板上的明亮 LED,以表示可以读取了。我们将让它保持 10 秒钟,以便有时间读取颜色值,然后显示它。然后,我们将再等待 5 秒钟来读取下一个读数。

    要连接电线,您可以使用五根公母跳线插入 WiPy(或扩展板)和分线板。图 6-3 显示了您需要进行的连接。请注意,电线被插入标有“GXX”而不是“PinXX”的引脚中在使用电路板时,这可能会引起混淆。最好参考引脚排列图,以确保使用正确的引脚。在这种情况下,我们需要 P9 和 P10 用于 I2C 连接,我们将使用 P8 用于 LED。

    A447395_1_En_6_Fig3_HTML.jpg

    图 6-3。

    Wiring the RBG Sensor (WiPy) Tip

    参见 https://docs.pycom.io/chapter/datasheets/development/wipy2.html 了解 WiPy 板的引脚排列,参见 https://docs.pycom.io/chapter/datasheets/boards/expansion.html 了解扩展板的引脚排列。请注意,扩展板“镜像”WiPy,但其标签完全不同。

    一旦连接好硬件,就把它放在一边。我们需要下载驱动程序并将其复制到主板上,然后才能进行进一步的实验。你可以在 https://github.com/adafruit/micropython-adafruit-tcs34725 找到司机。这是一个完全工作的,经过测试的驱动程序,演示了使用 I2C 分线板是多么容易。不要担心库的内部。我所指的代码如下所示。请注意,默认地址是 0x29,但由于地址是一个参数,如果同一 RGB 传感器在不同的地址有另一个分线板,您可以覆盖它。这意味着您可以使用多个相同的驱动程序。

    class TCS34725:
        def __init__(self, i2c, address=0x29):
    
            self.i2c = i2c
            self.address = address
            self._active = False
            self.integration_time(2.4)
            sensor_id = self.sensor_id()
            if sensor_id not in (0x44, 0x10):
    raise RuntimeError("wrong sensor id 0x{:x}".format(sensor_id))
    ...
    
    

    要下载驱动程序,首先导航到 https://github.com/adafruit/micropython-adafruit-tcs34725 and,然后单击下载按钮,再单击下载 Zip 按钮。文件下载完成后,解压。在生成的文件夹中,您应该会找到名为tcs34725.py的文件。这是驱动程序代码模块。准备好后,我们将使用 FTP 将其复制到我们的 WiPy,如下所示。请确保首先连接到您的 WiPy Wi-Fi 网络,并在与文件相同的目录中打开一个终端。

    $ ftp 192.168.4.1
    Connected to 192.168.4.1.
    220 Micropython FTP Server
    Name (192.168.4.1:cbell): micro
    Password:
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> cd flash
    ftp> put tcs34725.py
    local: tcs34725.py remote: tcs34725.py
    227 (192,168,4,1,7,232)
    100% |***********************************|  5222      23.05 MiB/s    00:00 ETA
    5222 bytes sent in 00:00 (6.57 KiB/s)
    ftp> quit
    
    

    既然驱动程序已经复制到我们的板上,我们就可以写代码了。在本例中,我们将建立到分线板的 I2C 连接,并运行一个循环来从传感器读取值。听起来很简单,但是有一点技巧。我们将放弃对代码的冗长讨论,而是提供一些关键方面,让您自己阅读代码,看看它是如何工作的。

    关键组件是设置 I2C、传感器、用于控制 LED 的引脚以及从传感器读取数据。通过将引脚设为高电平(开)或低电平(关),可以打开和关闭板上的 LED。首先,I2C 电码如下。这里,我们初始化一个对象,然后调用init()函数将总线设置为主机模式。scan()功能打印出总线上的设备。如果你看到一个空的设置显示,你的 I2C 接线是不正确的。请检查并再次尝试该代码。注意,完成导入后,您可以手动运行这段代码。

    i2c = I2C(0, I2C.MASTER)             # create and init as a master
    i2c.init(I2C.MASTER, baudrate=20000) # init as a master
    i2c.scan()
    
    

    接下来是传感器本身。司机使这变得容易。我们需要做的就是传递 I2C 构造函数,如图所示。

    # Setup the sensor
    sensor = tcs34725.TCS34725(i2c)
    
    

    设置 LED 引脚也很容易。我们需要做的就是调用Pin()类构造函数,传入引脚名称(P8)并将其设置为输出模式,如下所示。

    # Setup the LED pin
    led_pin = Pin("P8", Pin.OUT)
    led_pin.value(0)
    
    

    最后,我们用传入 True 的sensor.read()函数从传感器读取数据,它告诉驱动程序返回 RGBC 值。然后我们会按顺序把这些打印出来。清单 6-6 显示了完整的代码。花一些时间通读它,这样你就能理解它是如何工作的。

    # MicroPython for the IOT - Chapter 6
    # Example of using the I2C interface via a driver
    # for the Adafruit RGB Sensor tcs34725
    #
    # Requires library:
    # https://github.com/adafruit/micropython-adafruit-tcs34725
    #
    from machine import I2C, Pin
    import sys
    import tcs34725
    import utime
    
    # Method to read sensor and display results
    def read_sensor(rgb_sense, led):
        sys.stdout.write("Place object in front of sensor now...")
        led.value(1)                # Turn on the LED
        utime.sleep(5)              # Wait 5 seconds
        data = rgb_sense.read(True) # Get the RGBC values
        print("color detected: {")
        print("    Red: {0:03}".format(data[0]))
        print("  Green: {0:03}".format(data[1]))
        print("   Blue: {0:03}".format(data[2]))
        print("  Clear: {0:03}".format(data[3]))
        print("}")
        led.value(0)
    
    # Setup the I2C - easy, yes?
    i2c = I2C(0, I2C.MASTER)             # create and init as a master
    i2c.init(I2C.MASTER, baudrate=20000) # init as a master
    i2c.scan()
    
    # Setup the sensor
    sensor = tcs34725.TCS34725(i2c)
    
    # Setup the LED pin
    led_pin = Pin("P8", Pin.OUT)
    led_pin.value(0)
    
    print("Reading Colors every 10 seconds. When LED is on, place object in front of sensor.")
    print("Press CTRL-C to quit. (wait for it)")
    while True:
        utime.sleep(10)               # Sleep for 10 seconds
        read_sensor(sensor, led_pin)  # Read sensor and display values
    
    Listing 6-6.Using the Adafruit RGB Sensor (WiPy)
    
    

    一旦你有了代码,你可以把它复制到你的主板上,就像我们用 ftp 工具复制驱动程序一样,如下所示。

    $ ftp 192.168.4.1
    Connected to 192.168.4.1.
    220 Micropython FTP Server
    Name (192.168.4.1:cbell): micro
    Password:
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp> cd flash
    ftp> put wipy_RGB.py
    local: wipy_RGB.py remote: wipy_RGB.py
    227 (192,168,4,1,7,232)
    100% |***********************************|  1202        4.51 MiB/s    00:00 ETA
    1202 bytes sent in 00:00 (2.17 KiB/s)
    ftp> quit
    
    

    剩下的工作就是运行示例并测试它。清单 6-7 展示了如何在 WiPy 上运行这个例子以及一个输出示例。如果您在 WiPy 上运行此示例,您可以将任何想要的对象放在传感器前面,它将读取颜色,并将其作为表示 RGB 值加上透明值的元组返回,如图所示。

    >>> import wipy_RGB
    Reading Colors every 10 seconds. When LED is on, place object in front of sensor.
    Press CTRL-C to quit. (wait for it)
    Place object in front of sensor now...color detected: {
        Red: 057
      Green: 034
       Blue: 032
      Clear: 123
    }
    Place object in front of sensor now...color detected: {
        Red: 054
      Green: 069
       Blue: 064
      Clear: 195
    }
    Place object in front of sensor now...color detected: {
        Red: 012
      Green: 013
       Blue: 011
      Clear: 036
    }
    ...
    Listing 6-7.Output from using the Adafruit RGB Sensor (WiPy)
    
    

    如果你想再做一次练习,你可以从传感器获取这些值,并将它们映射到一个 RGB LED。是的,你可以这样做!来吧,试试看。见 https://github.com/JanBednarik/micropython-ws2812 获取灵感。在您阅读了 SPI 的下一部分之后,再着手解决这个问题。

    Tip

    关于 I2C 的深入讨论见 https://learn.sparkfun.com/tutorials/i2c

    串行外设接口(SPI)

    串行外设接口(SPI)设计用于在两个器件之间通过专用线路双向发送和接收数据。也就是说,它使用两条数据线、一个时钟和一个从机选择引脚。因此,它需要六个连接进行双向通信,或者只需要五个连接进行读写。一些 SPI 器件可能需要第七个引脚,称为复位线。

    让我们看一个如何使用 SPI 分线板的例子。本例中,我们希望使用 Adafruit 热电偶放大器 MAX31855 分线板( https://www.adafruit.com/product/269 )和一个 K 型热电偶传感器( https://www.adafruit.com/product/270 )来读取高温。我们将使用这个分线板和一个 Pyboard。

    如果您没有或不想购买 Adafruit 热电偶放大器 MAX31855 分线板(虽然不贵),也不用担心。此示例作为使用 SPI 分线板的教程提供。我们将在本书后面的一个示例项目中使用另一个 I2C 分线板。图 6-4 显示了 Adafruit 的 Adafruit 热电偶放大器和 H 型传感器。

    A447395_1_En_6_Fig4_HTML.jpg

    图 6-4。

    Adafruit Thermocouple Breakout Board and Type-K Sensor (courtesy of adafruit.com)

    该传感器可用于通过接近或触摸来测量高温。该传感器可以以 0.25 度的增量读取-200°C 至+1350°C 范围内的温度输出。这种传感器的一个可能用途是读取 3D 打印机上喷嘴的温度或任何类似的高热输出。应该注意的是,分线板是未组装的,因此您需要焊接接头和接线柱。

    现在,让我们看看如何将分线板连接到我们的 Pyboard。我们将只使用五根电线,因为我们只从分线板上的传感器读取数据。这需要连接到电源(地(GND)、主输入(MOSI)、时钟(CLK)和从选择(SS)。图 6-5 显示了连接。

    A447395_1_En_6_Fig5_HTML.jpg

    图 6-5。

    Wiring the Adafruit Thermocouple Module (Pyboard)

    表 6-2 中显示了 Pyboard 上使用的正确引脚。你可以在 https://docs.micropython.org/en/latest/pyboard/pyboard/quickref.html 找到的 Pyboard 引脚上找到这些引脚。参见图 6-5 进行确认。

    表 6-2。

    Connecting the Thermocouple Breakout Board (Pyboard )

    | Pyboard | Pyboard 上的位置 | 分线板 | | — | — | — | | 车辆识别号码 | 最右上引脚 | 3V0 | | 地线 | 在右侧,从上往下数第三个销 | 地线 | | Y5 | 在电路板的左侧,从顶部数第五个引脚 | CS(从机选择) | | Y6 | 在电路板的左侧,从顶部数第六个引脚 | 时钟信号 | | Y7 | 在电路板的左侧,从顶部数第七个引脚 | D0 |

    现在,让我们看看代码!在这个例子中,我们不打算使用驱动程序;相反,我们将了解如何使用 SPI 直接从分线板读取数据。为此,我们首先设置 SPI 接口的对象实例,然后选择一个引脚用于从机选择(也称为芯片或代码选择)。从那里,我们需要做的就是读取数据并解释它。我们将循环读取传感器,并编写一个函数来转换数据。

    这是棘手的部分。这个例子向您展示了驱动程序作者必须做些什么来使设备的使用更容易。在这种情况下,我们必须从分线板中读取数据并对其进行解释。我们可以只读取原始数据,但这没有任何意义,因为它是二进制形式的。因此,我们可以从 Adafruit 借用一些代码来读取原始数据并理解它。

    该函数名为normalize_data(),它执行一些位移和算术运算,将原始数据转换为摄氏度值。这些信息来自分线板的数据手册,但是 Adafruit 的友好人员让我们很容易就知道了。

    设置 SPI 类很容易。我们使用 SPI 选项中传递的类构造函数来初始化 SPI 对象。这对于 Pyboard 是唯一的,可以是值 1-使用 X 位置,或值 2-使用 Y 位置。请注意,在上面的连接中,我们使用 Y 引脚,因此我们将使用值 2 作为第一个参数。其他参数告诉 SPI 类设置为主机,设置波特率、极性和相位(可在数据手册中找到)。接下来,我们只需选择用于读取数据的引脚,然后将引脚设为高电平。下面显示了激活 SPI 接口所需的代码。

    spi = SPI(2, SPI.MASTER, baudrate=5000000, polarity=0, phase=0)
    cs = machine.Pin("Y5", machine.Pin.OUT)
    cs.high()
    
    

    现在,让我们看看完整的代码。清单 6-8 显示了使用 Adafruit 热电偶放大器分线板的完整代码。

    # MicroPython for the IOT - Chapter 6
    # Simple example for working with the SPI interface
    # using the Adafruit Thermocouple Amplifier. See
    # https://www.adafruit.com/product/269.
    #
    # Note: this only runs on the Pyboard
    #
    import machine
    import ubinascii
    
    # First, make sure this is running on a Pyboard
    try:
        import pyb
        from pyb import SPI
    except ImportError:
        print("ERROR: not on a Pyboard!")
        sys.exit(-1)
    
    # Create a method to normalize the data into degrees Celsius
    def normalize_data(data):
        temp = data[0] << 8 | data[1]
        if temp & 0x0001:
            return float('NaN')
        temp >>= 2
        if temp & 0x2000:
            temp -= 16384
        return (temp * 0.25)
    
    # Setup the SPI interfaceon the "Y" interface
    spi = SPI(2, SPI.MASTER, baudrate=5000000, polarity=0, phase=0)
    cs = machine.Pin("Y5", machine.Pin.OUT)
    cs.high()
    
    # read from the chip
    print("Reading temperature every second.")
    print("Press CTRL-C to stop.")
    while True:
        pyb.delay(1000)
        cs.low()
        print("Temperature is {0} Celsius.".format(normalize_data(spi.recv(4))))
        cs.high()
    
    Listing 6-8.The Adafruit Thermocouple Module Example (Pyboard)
    
    

    此时,您可以连接硬件并接通 Pyboard 的电源。然后,您可以将该文件复制到您的 Pyboard 并执行它,如下所示。

    >>> import pyboard_SPI
    Reading temperature every second.
    Press CTRL-C to stop.
    Temperature is 32.0 Celsius.
    Temperature is 31.75 Celsius.
    Temperature is 32.0 Celsius.
    Temperature is 32.5 Celsius.
    Temperature is 33.5 Celsius.
    Temperature is 34.0 Celsius.
    Temperature is 34.25 Celsius.
    Temperature is 34.5 Celsius.
    Temperature is 34.5 Celsius.
    ...
    
    

    运行该示例后,您应该会看到它产生以摄氏度为单位的值。如果您看到 0.00,您可能没有正确连接 SPI 接口。对照上图检查您的接线。如果您看到数值,但当您将热电偶暴露在高温下时,数值下降,您需要反转导线。确保先关闭主板电源,以免损坏传感器、分线板或您的 Pyboard!

    如果你想用 WiPy 运行这个例子,你可以!只需修改代码,使用 WiPy SPI 类及其初始化序列,如 https://docs.pycom.io/chapter/firmwareapi/pycom/machine/SPI.html 所示。您还必须对 includes 做一些修改,但是这对于示例项目章节来说是一个很好的实践。

    Tip

    参见 https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi 对 SPI 的深入讨论。

    摘要

    通过固件访问底层硬件是使用 MicroPython 的真正优雅之处,在某些情况下也是复杂性的开始。鉴于可用的主板不同,固件中的低级支持也不同也就不足为奇了。因此,在规划 MicroPython IOT 项目时,我们必须考虑我们想要做什么,以及我们的主板(和固件)是否支持它。我们还需要知道我们想要连接到什么分线板和设备,以及是否有我们可以用来访问它们的驱动程序或其他库。在这种情况下,大多数带 I2C 或 SPI 接口的分线板都需要某种形式的驱动器。

    在本章中,我们探讨了固件中的一些低级支持以及对 Pyboard 和 WiPy 的专门支持。正如我们所发现的,这是代码变得非常专门化的地方。正如我们所看到的,有时需要选择不同的库来导入,但是有时类、函数、甚至如何使用函数在不同的板上是不同的。

    我们在这一章中也看到了很多代码——比之前的任何一章都多。本章中的例子旨在让你看到事情是如何完成的,而不是你自己去实现的项目(尽管我们欢迎并鼓励你这样做)。在后面的章节中,我们将会看到更多更详细的实践项目。

    在下一章中,我们将以电子学的简短教程的形式进行一次简短的探讨。如果你以前从未接触过电子学,下一章将为你提供完成本书中的项目所需的信息,并让你为一个令人兴奋的新爱好做好准备——构建 MicroPython IOT 项目!

    Footnotes 1

    https://en.wikipedia.org/wiki/Hexadecimal

    2

    https://en.wikipedia.org/wiki/Network_Time_Protocol

    3

    每当你发现自己在为常用代码编写函数时,是时候考虑将它添加到你最喜欢的函数库中,以使这些代码对你所有的程序都可用,正如我们在第五章中所讨论的。

    4

    不,我与这两者都没有关系——我只是一个忠实的粉丝和常客。看看他们!

    5

    但是如果你好奇的话,请随意。如果您这样做了,您将会看到一段有趣的代码,它展示了 I2C 设备的寻址能力。

    七、初学者电子学

    如果你刚接触硬件,对电子产品很少或没有经验,你可能会好奇如何完成本书中的项目。幸运的是,本书中的项目将指导您如何使用 MicroPython 板将各种电子器件连接在一起。也就是说,您可以在没有额外技能或经验的情况下完成项目。

    然而,如果你想知道组件是做什么的,除了“把这一端插在这里”之外,你还需要更多的信息如果出了问题,尤其如此。此外,如果你想自己创建项目,你需要足够了解组件如何工作以成功完成你的项目——无论是完成本书中的例子还是在互联网上找到的例子。

    幸运的是,你不需要正式的培训,甚至不需要理论上的大学学位,就能学会如何与电子打交道。你可以在业余爱好者的水平上学习很多关于使用电子学的知识,而不用花费几个月或几年的时间去研究。为了确保哪怕是最基本的成功,你需要知道的不仅仅是如何简单地将组件组装在一起。

    本章不是试图提供一个全面的电子学教程,这需要几卷,而是为那些想使用 IOT 项目中常见的电子元件类型的人提供一个电子学概述。我包括一些基础知识的概述、常见组件的描述以及对传感器的介绍。如果你是电子学新手,这一章会给你额外的帮助,帮助你理解本书项目中使用的元件。

    如果您有电子爱好者或发烧友级别的经验,或者有电子方面的经验或正式培训,您可能希望浏览本章或阅读您希望复习的主题部分。

    让我们先来看看电子学的基础知识。再说一次,这绝不是一个涵盖所有知识的教程,但它将带您了解项目在如何连接和使用组件方面的意义。

    基础知识

    本节简要概述了使用电子设备时需要用到的一些最常用的工具和技术。正如您将看到的,您只需要最基本的工具,技能或技术并不难学习。然而,在我们进入这些之前,让我们看看你在 IOT 项目中需要用到的一些工具。

    工具

    构建 IOT 项目所需的绝大多数工具都是普通的手工工具(螺丝刀、小扳手、钳子等)。).对于较大的项目或创建外壳,您可能需要额外的工具,例如电动工具,但是我将只关注那些用于构建项目的工具。以下是我推荐给你的入门工具列表。

  • 面包板
  • 试验板电线(也称为跳线)
  • 静电放电安全镊子
  • 帮助手或印刷电路板(PCB)固定器
  • 万用表
  • 尖嘴钳
  • 螺丝刀–各种尺寸(微型、小型)
  • 焊料
  • 烙铁
  • 焊料去除器(焊料吸盘)
  • 工具箱、卷轴或储存箱
  • 剥线钳
  • 然而,如果你想买一套完整的电子工具,比如来自 spark fun(sparkfun.com/categories/47)或 Adafruit(Adafruit . com/categories/83)的工具,那就错不了。你经常可以在各大品牌电子商店和家装中心找到电子套件。如果你足够幸运,住在一家电器店附近,你可以找到几乎所有制造的电子工具。大多数电子工具包都有你需要的所有手工工具。有些甚至带有万用表,但更多时候你必须单独购买。

    列表中的大多数工具不需要任何解释,只是说你应该在预算允许的情况下购买最好的工具。以下段落描述了一些用于特殊任务的工具,例如剥线、焊接以及测量电压和电流。

    万用表

    万用表是构建 IOT 解决方案时需要的工具之一。你还需要它来对你的电路进行几乎所有的电气维修。有许多不同的万用表,价格从便宜的基本单位;到复杂、功能丰富、价格昂贵的设备。对于大多数 IOT 项目,包括大多数 IOT 工具包,一个基本单位是你所需要的。然而,如果你计划建立一个以上的 IOT 解决方案或想要组装自己的电子产品,你可能要多投资一点,在一个更复杂的万用表。图 7-1 左边是一个基本的数字万用表(成本约 10 美元),右边是 BK Precision 的专业万用表。

    A447395_1_En_7_Fig1_HTML.jpg

    图 7-1。

    Digital multimeters

    请注意,更好的血糖仪具有更精细的设置和更多功能。同样,你可能不需要超过基本单位。你至少需要测量电压、电流和电阻。无论你买哪个电表,确保它有测量交流和 DC 电压、连续性测试(有声音警报)和检查电阻的模式。我将在后面的章节中解释如何使用万用表。

    Tip

    大多数万用表,包括便宜的万用表,都有一个小说明书,告诉你如何测量电压、电阻和其他功能。

    烙铁

    本书中的任何项目都不需要烙铁,因为我们将使用试验板来布置和连接组件。然而,如果你计划建立一个简单的 IOT 解决方案,你需要将电线焊接在一起,或者可能需要几个连接器,从电子商店如 Radio Shack 购买一个基本的烙铁就可以了。另一方面,如果你打算自己组装电子产品,你可能要考虑买一个好的专业烙铁,比如 Hakko。专业型号包括允许您设置魔杖温度的功能,有更广泛的提示可用,并且往往持续更长时间。图 7-2 显示了 Radio Shack 的一个常用入门级。图 7-3 显示的是专业型号的 Hakko 烙铁。

    Tip

    为获得最佳结果,选择含铅量在 37%-40%范围内的低焊料。如果您使用专业烙铁,请调整温度以匹配焊料的熔点(列在标签上)。

    A447395_1_En_7_Fig2_HTML.jpg

    图 7-2。

    Entry-level soldering iron Do I Need to Learn to Solder?

    如果你不知道如何焊接,或者已经有一段时间没有使用烙铁了,你可以看看 Brian Jepson、Tyler Moskowite 和 Gregory Hayes 所著的《学习焊接》( O’Reilly Media,2012)或者谷歌的焊接视频。或者你也可以从 Maker Shed ( makershed.com/products/make-getting-started-kit-soldering)购买入门焊接套件,它配有烙铁、剪线钳、供应品等等——学习焊接所需的一切。

    A447395_1_En_7_Fig3_HTML.jpg

    图 7-3。

    Professional soldering iron

    剥线器

    剥线钳有几种类型。事实上,可能有一打或更多的设计。但是有两种:一种是当你从电线上拉下来的时候,它只能夹住并切断绝缘层;以及抓持、切割和移除绝缘体的那些。第一种类型更常见,经过一些练习后,对于大多数小工作(比如修理断了的电线)来说就很好了;但是第二种类型的工作量更大,比如用裸线(没有预制连接器)连接电子设备,速度更快。可以想象,第一种要便宜得多。图 7-4 显示了两种类型的剥线钳。两者都是不错的选择。

    A447395_1_En_7_Fig4_HTML.jpg

    图 7-4。

    Wire strippers

    援助之手

    还有一个你可能想要得到的工具,特别是如果你需要做任何焊接的话:它被称为帮助之手或第三手工具。大多数都有一对鳄鱼夹,用来在焊接时夹住电线、印刷电路板或元件。图 7-5 显示了一个简单的帮助工具的例子。

    A447395_1_En_7_Fig5_HTML.jpg

    图 7-5。

    Helping hands tool

    现在让我们来看看在使用高级 IOT 项目时可能需要的一些技能。

    ESD is the Enemy

    您应该注意确保您的身体、工作区和项目接地,以避免静电放电(ESD)。ESD 会永久损坏您的电子设备。避免这种情况的最佳方法是使用接地带,环绕在手腕上,并连接到防静电垫上,就像uline.com/BL_7403/Anti-Static-Table-Mats中的这些。

    让我们来看看如何使用一个你在学习电子学时可能会用得最多的工具——万用表。

    使用万用表

    IOT 项目所需的电气技能各不相同,从在试验板上插上电线(正如我们迄今为止在项目中看到的那样),到需要将元件焊接在一起或焊接到印刷电路板(PCB)上。不管你是否需要焊接电子元件,你都需要能够使用基本的万用表来测量电阻和检查电压和电流。

    对于任何电子爱好者来说,万用表都是非常有用和必不可少的工具,对于任何有价值的发烧友来说,这是绝对需要的。典型的万用表有一个数字显示器【2】(通常是 LCD 或类似的数字显示器)、一个刻度盘和两个或多个用于插入带有探针端的测试引线的接线柱或端口。大多数万用表都有低电流端口(你最常用的)和大电流端口。测试引线使用红色表示正极,黑色表示负极(接地)。接地端口是插入黑色测试引线的地方,通常标有破折号或 COM。您使用的其他端口将取决于您正在测试的内容。

    表盘上有一点需要注意,那就是有很多设置(有些值是重复的)或者那些看起来很相似的设置。例如,您会看到一组欧姆值(有时称为标度),一组或两组安培值,以及一组或两组伏特值。带有 V 形实线和虚线的一组电压值适用于 DC,而带有 V 形波浪线的范围适用于交流。安培范围以同样的方式标记。图 7-6 显示了一个万用表表盘的特写,上面标有我提到的几组数值。

    A447395_1_En_7_Fig6_HTML.jpg

    图 7-6。

    Multimeter Dial (typical) Tip

    不使用时,一定要将万用表拨盘转到 off 或某个电压范围,如果它有单独的 off 按钮的话。

    用万用表可以做很多事情。你可以检查电压,测量电阻,甚至检查连续性。大多数基本的万用表将完成这些功能。然而,有些万用表有更多的功能,如测试电容,测试交流和 DC。

    让我们看看如何使用万用表来完成 IOT 项目中最常见的任务:测试连续性、测量 DC 电路中的电压、测量电阻和测量电流。

    测试连续性

    我们测试连续性,以确定是否有带电粒子流动的路径:也就是说,我们的电线和组件连接正确。例如,您可能想要检查以确保导线已正确接合。

    为了测试连续性,将万用表刻度盘转到标有声音符号、铃或有箭头穿过的三角形的位置。将黑色测试引线插入 COM 端口,将红色测试引线插入标有 Hz VΩ或类似标志的端口。现在,您可以一起触摸测试引线的探针端,以听到声音或嘟嘟声。有些万用表没有声音,但可能显示“1”或类似的数字来表示连续性。查看您的手册,了解您的万用表是如何指示连续性的。图 7-7 显示了如何设置万用表来检查连续性,包括插入测试引线的端口。

    请注意,在照片中,我只是将探针接触在一起,以演示如何检查连续性。我喜欢这样做,只是为了确保我的万用表是打开的,并且设置正确。 3

    A447395_1_En_7_Fig7_HTML.jpg

    图 7-7。

    Settings for checking continuity

    连续性测试的另一个出色用途是在诊断或发现电缆接线方式时。例如,您可以使用连续性测试来发现电缆两端连接的是哪一个连接器(有时称为电线分类或旧电话时代的振铃)。

    测量电压

    我们的 IOT 项目使用 DC。为了测量电路中的电压,我们将使用万用表上的 DC 量程。注意,DC 山脉有几个站点。这是一个音阶选择。选择与您想要测试的电压范围最接近的刻度。例如,对于我们的 IOT 项目,我们通常会测量 3.3-12V,因此我们在表盘上选择 20。接下来,将黑色测试引线插入 COM 端口,将红色测试引线插入标有 Hz VΩ的端口。

    现在我们需要一些东西来衡量!拿起你家里的任何一个电池,用黑色探针接触负极,用红色探针接触正极。您应该会看到显示屏上出现一个接近电池范围的值。例如,如果我们使用 1.5V 的电池,我们应该看到接近 1.5V。如果电池耗尽,它可能不会正好是 1.5-1.6V。现在你知道如何测试电池的新鲜度了吧!图 7-8 显示了如何测量电池电压。

    A447395_1_En_7_Fig8_HTML.jpg

    图 7-8。

    Measuring voltage of a battery

    注意读数显示 1.50,这是该 AA 电池的正确电压。如果我把探针颠倒过来——红色的是负极,黑色的是正极,显示屏上的读数应该是-1.50。这是可以的,因为它表明电流的流动方向与探头的方向相反。

    Note

    如果在 DC 电路中测量电压时使用了错误的探针,大多数万用表会将电压显示为负数。用你的电池试试。不会伤到万用表(或者电池)!

    我们可以在项目中使用这种技术来测量电压。注意将探针放在适当的位置,尽量不要用一个探针头一次接触多个元件而造成交叉或短路。

    测量电流

    电流以安培数(毫安-毫安)来衡量。因此,我们将使用标有 A 的直线和虚线的范围(不是波浪线,那是 AC)。我们串联测量电流。也就是说,我们必须将万用表放在电路中。这可能有点棘手,因为我们必须中断电流,并将电表放在线路上。

    如果你熟悉如何使用试验板,你可以跟着做这个实验。然而,如果你没有使用过试验板,你可能想通读这个实验,然后在你读完这一章后再返回。在本实验中,我们将使用试验板电源、LED 和电阻。我们将连接电路,这样我们将使用万用表来完成电路。图 7-9 显示了如何使用万用表在线设置电路。

    A447395_1_En_7_Fig9_HTML.jpg

    图 7-9。

    Measuring current

    在接通试验板电源之前,将黑色测试引线插入 COM 端口,将其他测试引线插入标有 mA 的端口。有些万用表用同一个端口测量电压和电流。将万用表的旋钮转到 200 毫安的设定值。然后接通试验板电源,将引线接触到指示的位置。注意只触摸试验板电源上的 VCC 引脚。一旦电路通电,您应该会在万用表上看到一个值。图 7-10 显示了如何使用万用表测量电路中的电流

    A447395_1_En_7_Fig10_HTML.jpg

    图 7-10。

    Measuring current

    测量电流还有一个棘手的问题。如果您试图测量大于端口最大值的电流(例如,照片中的仪表在一个端口上的最大值为 20mA)。如果超过这个值,比如说 5A,我可能会烧断万用表的保险丝。这是不可取的,但至少有一个保险丝,我们可以更换,如果我们犯了错误,选择了错误的端口。

    测量电阻

    电阻以欧姆(ω)为单位测量。我们用来在电路中引入电阻的最常见的元件是电阻器。我们可以用万用表通过电阻测试电荷的电阻。要测试电阻,选择最接近电阻额定值的欧姆表。例如,我要测试一个电阻,我认为它大约为 200 欧姆,但由于我不确定,我将选择 2k 设置。

    接下来,将黑色测试引线插入 COM 端口,将红色测试引线插入标有 HzVΩ的端口。现在,将一个探针接触电阻器的一侧,另一个探针接触另一侧。无论选择哪一侧,电阻都可以双向工作。注意读数。仪表将读取以下三个值之一:0.00、1 或实际电阻值。

    这种情况下,电表读数为 0.219,意味着该电阻的阻值为 220ω。回想一下,我使用 2k 标度,这意味着 1k 的电阻读数为 1.0。由于该值是一个小数,我可以将小数点向左移动,得到一个整数。

    如果万用表显示另一个值,如 0 或 1,这表明标度是错误的,你应该尝试更高的标度。这不是问题。只是说明你需要选择更大的尺度。另一方面,如果显示器显示 0 或较小的数字,则需要选择较低的刻度。当我在一个未知的元件或电路中测试电阻时,我喜欢按下旋钮。

    图 7-11 显示了一个测量电阻器电阻的例子。注意显示屏上显示的是 219。我正在测试一个额定 220 欧姆的电阻。之所以是 219 而不是 220,是因为我使用的电阻额定值为 220 +/- 5%。因此,该电阻器的可接受范围是 209-231 欧姆。

    A447395_1_En_7_Fig11_HTML.jpg

    图 7-11。

    Measuring resistance of a resistor

    现在我们知道了如何测试一个电阻来发现它的额定值。正如我们将看到的,电阻体周围的环是我们了解其额定值的主要方式,但如果我们不确定,有人在上面涂了漆(嘿,这种情况时有发生),或者我们懒得去查,我们总是可以测试它。

    现在,让我们来讨论使用电子设备时必须理解的最基本概念——为您的项目供电!

    为您的电子设备供电

    4 简单地定义为电荷的流动,当使用时为我们的电子设备提供电力——从普通的灯泡或吊扇到我们的高清电视或我们的新平板电脑。无论你是用电池还是电源给你的电子设备供电,你都是在启动一个电子以特定模式流动的电路。你将使用两种形式的权力。你的家用交流电供电,你的电子设备用直流电供电。

    术语交流电(AC)用于描述以特定速率(或周期)周期性改变方向的带电粒子流,使电压与电流反向。因此,交流系统被设计成在特定的周期和电压范围内工作。通常,交流系统比直流系统使用更高的电压。

    术语直流电(DC)用于描述不改变方向的带电粒子的流动,因此总是以特定的“方向”流动大多数电子系统由 DC 电压供电,通常比交流系统的电压低。例如,IOT 项目通常在 3.3-24V 范围内的较低直流(DC)电压下运行。

    Tip

    有关交流电流和 DC 电流及其差异的更多信息,请参见 https://learn.sparkfun.com/tutorials/alternating-current-ac-vs-direct-current-dc

    由于 DC 是单向流动的,在 DC 上工作的元件有一个正的和一个负的“面”,电流从正流向负。这些面的方向——一个是正极,一个是负极——叫做极性。有些元件,如电阻,可以在任何一个“方向”上工作,但你应该始终确保按照极性连接你的元件。大多数部件都有明确的标记,但那些没有标记的部件却有着众所周知的排列方式。例如,LED 的正极(侧面)是两条腿中较长的一条(称为阳极,而负极或较短的腿称为阴极)。

    尽管电压较低,但我们不能认为它们完全无害或安全。电子设备接线错误(极性颠倒)或短路(将正极和负极连接在一起)会损坏您的电子设备,在某些情况下会导致过热,在极端情况下,会导致电子设备着火。

    Caution

    不要认为在 3.3 或 5.5 伏电压下工作是“安全的”即使少量电压连接不当也可能导致潜在的灾难性后果。不要认为低 DC 电压是无害的。

    几年前,我就知道这种情况有多真实。我在换烟雾探测器的电池。我把旧电池拿出来,放在口袋里。我忘了在同一个口袋里还有一把小铅笔刀。其中一个电池在刀上短路,在大约十分钟内,电池加热到惊人的温度。它不足以燃烧,但如果我没有注意到这样的东西,它可能会很糟糕。

    这是个可怕的想法,不是吗?把它当作一个告诫和警告;即使是低压项目,我们也不应放松安全操作实践。

    最后,DC 组件通常针对特定的电压范围进行额定。回想一下我们对各种低成本计算板和 GPIO 接头的讨论,一些板的工作电压为 5V,而另一些板的工作电压为 3.3V(或更低)。幸运的是,我们有几种方法可以调整在不同电压下工作的元件——通过使用其他元件!

    Note

    我有意让关于权力的讨论保持简单。电流——甚至 DC——远不止我在这里描述的那样。一旦你理解了这些基础知识,你就能使用本书及更多书中的项目。

    电子元件

    除了学习如何使用万用表和可能的学习焊接,你还需要知道一些关于电子元件可用于建立你的项目。在这一节中,我将按名称的字母顺序提供一个简短的列表和一些常见组件的描述,您将在构建 IOT 解决方案时遇到这些组件。我还介绍了分线板和逻辑电路,它们是用一组组件构建的小电路,提供一种功能或解决一个问题。例如,您可以获得用于 USB 主机连接、以太网模块、逻辑移位器、实时时钟等的分线板。

    纽扣

    按钮(有时称为瞬时按钮)是一种按下时产生连接的机制。更具体地说,按钮在被按下时将两个或多个电极连接在一起。按钮的一个常见(也许是过度使用的)例子是家庭门铃。当按下时,它完成一个电路,触发钟声、铃声、音调或音乐播放。有些老式门铃在按下按钮时会继续响。

    在 IOT 项目中,我们将使用按钮来触发事件、开始和停止动作以及类似的操作。按钮是开关的一种简单形式,但与开关不同的是,您必须持续按下按钮才能进行电气连接。大多数按钮至少有两个脚(或引脚),当按钮被按下时,这两个脚连接在一起。一些具有成对连接的两个以上的腿,并且其中一些可以允许多个连接。图 7-12 显示了几个按钮。

    A447395_1_En_7_Fig12_HTML.jpg

    图 7-12。

    Momentary buttons

    瞬时按钮有一种特殊的变体,称为闩锁瞬时按钮。这个版本使用一个缺口或棘爪来保持电极连接,直到它再次被推动。如果你在音响或汽车上看到一个按钮一直按下,直到再次按下,这很可能是一个瞬时锁定按钮。

    有各种各样的按钮,包括可以用于试验板的按钮(引脚间距允许其插入试验板),可以安装在面板上的按钮,或者焊接到印刷电路板上的按钮。

    电容器

    电容器是用来储存电荷的。当电流流过电容器时,它会积累电荷,并在电流断开后放电。这样,它就像一个电池,但不像电池,电容器充电和放电非常快。我们使用电容来存储各种电流,包括阻挡电流、降低电源和音频电路中的噪声等。图 7-13 显示了几个电容。

    A447395_1_En_7_Fig13_HTML.jpg

    图 7-13。

    Capacitors

    电容器有几种类型,但在为 IOT 项目构建电源时,我们最常遇到的是电容器。大多数电容有两个极化的引脚。即一个是正的,一个是负的。确保在电路中以正确的极性连接电容器。

    二极管

    二极管被设计成只允许电流单向流动。大多数都标有指向一条线的箭头,指示流向。在交流-DC 转换器(将交流转换为 DC 电压的设备)中,二极管通常用作整流器,与其他元件一起使用,以抑制电压尖峰,或保护元件免受反向电压的影响。它们通常用于防止电流流入设备。

    大多数二极管的形状像一个小圆柱体,它们通常是黑色的,有银色的字迹,有两条腿。它们看起来有点像电阻器。我们在电源中使用一种称为齐纳二极管的特殊变体来帮助调节电压。图 7-14 显示了几个齐纳二极管。

    A447395_1_En_7_Fig14_HTML.jpg

    图 7-14。

    Diodes

    融合

    保险丝旨在保护设备(整个电路)免受超过元件安全工作电流的影响。保险丝直列放置在正极上。当过大的电流流过保险丝时,内部零件会触发电流中断。

    一些保险丝内部使用一种特殊的导线,该导线会熔化或断开(从而使其无用,但可以保护您的设备),而其他保险丝使用一种类似开关的机制(其中许多是可复位的)。当这种情况发生时,我们说保险丝“烧断”或“跳闸”保险丝的额定电流安培数表示保险丝在不跳闸的情况下允许流动的最大安培数。

    保险丝有许多形状和种类,可以用交流或 DC 电压工作。我们要用的是一次性的。图 7-15 显示了两个保险丝的示例:左边是汽车式刀片保险丝,右边是玻璃筒保险丝。

    A447395_1_En_7_Fig15_HTML.jpg

    图 7-15。

    Fuses

    如果你熟悉家中装有断路器的配电板,它们就是可复位保险丝。所以,下一次当其中一个“咔嚓”一声,灯灭了,你可以说,“嘿,保险丝断了!”更好的是,现在你知道为什么了——你已经超过了断路器的最大额定值。

    这可能在你不小心让红外线加热器开着的情况下是没问题的,当你弄掉烤面包和启动微波炉时(这种情况会发生),但是如果你经常在没有任何负载的情况下跳闸断路器,你应该叫电工来检查电路。

    发光二极管

    正如我们在第三章中了解到的,LED 有两个引脚,较长的引脚为正极,较短的引脚为负极。发光二极管也有一个平边,表示负支路。它们有各种尺寸,小到 3 毫米,大到 10 毫米。图 7-16 显示了一些较小的发光二极管的例子。

    A447395_1_En_7_Fig16_HTML.jpg

    图 7-16。

    Light emitting diodes

    回想一下,我们还需要使用一个带 LED 的电阻。我们需要这一点来帮助减少电路的流量,以降低流经 LED 的电流。led 可以在较低的电流下使用(它们会比正常情况下稍微暗一点),但不应该在较高的电流下使用。

    为了确定我们需要多大的电阻,我们需要了解 LED 的几个方面。该数据可从制造商处获得,制造商以数据表的形式提供数据,或者在商业包装产品的情况下,在包装上列出数据。我们需要的数据包括最大电压、电源电压(LED 的电压)和 LED 的额定电流。

    例如,如果我有一个像我们在上一章中使用的 LED,在这种情况下,一个 5 毫米的红色 LED,我们在 Adafruit 的网站(adafruit.com/products/297)上发现,该 LED 的工作电流为 1.8-2.2 伏和 20 毫安。假设我们希望使用 5V 电源电压。然后我们可以将这些值代入公式 5 :

    R = (Vcc-Vf)/I
    
    

    使用更具描述性的变量名称,我们得到如下结果。

    Resistor = (Volts_supply - Volts_forward) / Desired_current
    
    

    把我们的数据代入,我们得到这个结果。注意,我们有 mA,所以我们必须使用正确的十进制值(除以 1000)。在这种情况下,它是 0.020,我们将在中间选择一个电压。

    Resistor = (5 - 2.0) / 0.020
             = 3.0 / 0.020
             = 150
    
    

    因此,我们需要一个 150 欧姆的电阻。酷毙了。有时该公式会产生与任何现有电阻都不匹配的值。在这种情况下,选择一个最接近的值,但稍微大一点。记住,我们想要限制,因此宁可多限制也不要少限制。例如,如果你发现你需要一个 95 欧姆的电阻,你可以用一个 100 欧姆的,这比用一个 90 欧姆的更安全。

    Tip

    当公式产生一个没有可用电阻的值时,总是偏向限制性更强的电阻。

    此外,如果您串联或并联使用 led,公式会有所不同。参见 https://learn.adafruit.com/all-about-leds 了解更多关于在项目中使用 led 以及计算 led 使用的电阻大小的信息。

    继电器

    继电器是一种有趣的元件,可以帮助我们用低压电路控制高压。例如,假设您想要控制一个由 MicroPython 板提供 12V 电源的设备,而 MicroPython 板只能产生最大 3V 的电压。继电器可以与 3V 电路一起使用,以打开(或中继)来自较高电源的电源。在本例中,我们将使用 MicroPython 板输出来触发继电器接通 12V 电源。因此,继电器是开关的一种形式。图 7-17 显示了典型的继电器以及引脚的排列方式。

    A447395_1_En_7_Fig17_HTML.jpg

    图 7-17。

    Relay

    继电器可以采取多种不同的形式,通常具有略微不同的接线选项,例如连接电源电压的位置和连接触发电压的位置,以及初始状态是打开(无流量)还是关闭(有流量)以及如何控制电压的行为。一些继电器安装在印刷电路板上,带有明显标记的端子,用于改变其开关特性和所有插件的位置。如果您想在项目中使用继电器,请务必查看数据表,以确保根据其配置正确接线。

    你也可以使用继电器让你的 DC 电路像 Adafruit ( https://www.adafruit.com/product/2935 )的那些开关交流电器。

    电阻器

    电阻器是电子学的标准构件之一。它的作用是阻止电流并降低电压(转化为热量)。它的影响被称为电阻,用欧姆来衡量。电阻可用于降低其它元件的电压,限制频率响应,或保护敏感元件免受过压影响。图 7-18 显示了几个电阻。

    A447395_1_En_7_Fig18_HTML.jpg

    图 7-18。

    Resistors

    当电阻用于上拉电压(通过将一端连接到正电压)或下拉电压(通过将一端连接到地)(电阻是双向的)时,它消除了电压在不确定状态下浮动的可能性。因此,上拉电阻确保稳定状态为正电压,下拉电阻确保稳定状态为零电压(地)。

    转换

    开关设计用于控制两个或多个引脚之间的电流。开关有各种形状、尺寸和包装。一些被设计为简单的开/关,而另一些可以用来改变从一组引脚到另一组引脚的电流。像按钮一样,开关有多种安装选择,从 PCB(也称为通孔)到面板安装,以便安装在外壳中。图 7-19 显示了各种开关。

    A447395_1_En_7_Fig19_HTML.jpg

    图 7-19。

    Various switches

    只有一个电极(腿或边)的开关称为单极开关。能够将电流从一组电极转移到另一组电极的开关叫做双极开关。每极只有一个次级连接的开关称为单投开关。从一组极点断开并连接到另一组极点同时保持公共输入的开关称为双掷开关。这些通常被组合并形成如下的开关类型(或种类)。

  • SPST:单刀单掷
  • DPST:双刀单掷
  • SPDT:单刀双掷
  • DPDT:双刀双掷
  • 3PDT:三杆双掷
  • 您可能会遇到其他变体。我喜欢这样保持笔直;如果我有刚开/关的情况,我想要一个单掷开关。多少极取决于我想同时接通或断开多少根电线或电路。对于双掷开关,当我有“A”条件和“B”条件时,我使用这些开关,当 B 断开时,我希望 A 接通,反之亦然。当我需要“A”、“B”和“off”时,我有时会使用多个投掷开关,其中我使用中间位置(投掷)作为 off。你可以非常有创意地使用开关!

    晶体管

    晶体管(双极晶体管)被设计成在一个周期内开关电流或放大电流的波动。有趣的是,用来放大电流的晶体管取代了真空管。如果你是一个音响发烧友,你可能知道很多关于真空管。当电阻器在开关模式下工作时,其行为类似于继电器,但其“关”位置仍允许少量电流流动。晶体管用于音频设备、信号处理和开关电源。图 7-20 显示了两种晶体管。

    A447395_1_En_7_Fig20_HTML.jpg

    图 7-20。

    Transistors

    晶体管有各种各样的种类、封装和额定值,适合不同的解决方案。

    稳压器

    电压调节器(线性电压调节器)被设计成保持电流恒定。当我们需要调节或降低来自电源的电流时,电压调节器经常出现在电子设备中。例如,我们想为一个电路提供 5V 电压,但只有 9V 电源。电压调节器(大致)通过吸收电流并通过散热器耗散多余的电流来实现这一点。因此,电压调节器有三个分支:正电流输入、负电流和正电流输出。它们的典型形状如图 7-21 所示,但也存在其他种类。

    A447395_1_En_7_Fig21_HTML.jpg

    图 7-21。

    Voltage regulators

    延伸出电压调节器的板上的小孔是安装散热器的地方。电压调节器通常被编号以匹配其额定值。例如,LM7805 产生 5V,而 LM7833 产生 3.3V。

    图 7-22 显示了一个使用电压调节器向试验板上的 3.3V 电路供电的示例。该电路设计有电容来帮助平滑或调节电源。请注意,电容的额定值为 uF,即微法。

    A447395_1_En_7_Fig22_HTML.jpg

    图 7-22。

    Power supply circuit on a breadboard with voltage regulator

    分线板和电路

    分线板是我们 IOT 解决方案的模块化构建模块。它们通常将几个组件组合在一起,形成一种功能,如测量温度、读取 GPS 数据、通过蜂窝服务进行通信等。图 7-23 显示了两个分线板。左边是 adafruit 模数转换器(adafruit.com/products/1083),右边是 Adafruit 气压传感器转接板( https://www.adafruit.com/product/1603 )。

    A447395_1_En_7_Fig23_HTML.jpg

    图 7-23。

    Breakout boards

    无论何时设计电路或 IOT 解决方案,都应该考虑尽可能使用分线板,因为它们可以简化元件的使用。以大气压力传感器为例。Adafruit 设计了这种板,因此我们使用它所需要做的就是连接电源,并通过其 I2C 总线将其连接到我们的 IOT 设备。I2C 总线是一种快速数字协议,它使用两条线(加上电源和地)从电路(或设备)读取数据。

    因此,没有必要担心如何将传感器连接到其他组件来使用它-只需像任何 I2C 设备一样连接它并开始读取数据!我们将在本书后面的项目中使用几个分线板。

    使用试验板构建电路

    如果你一直跟随书中的项目,你已经遇到了一个制作非常简单电路的试验板。回想一下第三章,试验板是我们用来插入元件形成电路的工具。从技术上讲,我们使用的是无焊试验板。焊料试验板具有相同的布局,只是在 PCB 上只有通孔焊点。

    Why are they Called Breadboards?

    在微电子和分立元件广泛用于实验的辉煌时代,当我们想要制作电路原型时,有些人会使用一块钉有钉子的木头(有时是网格图案),通过在钉子上缠绕电线来连接(称为“线路”)。一些人使用厨房里的试验板来制作绕线原型。这个名字一直沿用至今。

    试验板允许我们为电路或简单的临时电路创建原型,而不必花费时间(和成本)来制作印刷电路板。原型制作是通过构建和测试您的想法来试验电路的过程。事实上,一旦我们让电路正常工作,就可以利用试验板布局来帮助我们设计 PCB。图 7-24 显示了几个试验板。

    A447395_1_En_7_Fig24_HTML.jpg

    图 7-24。

    Assorted breadboards

    回想一下,大多数试验板(有几个品种)都有一个中心凹槽(称为峡谷)或沿着板中心的印刷线。这表示垂直于通道延伸的端子排未连接。也就是说,一侧的端子排没有连接到另一侧。这允许我们插入封装为两排引脚的集成电路(IC)或芯片。因此,我们可以将 IC 插入试验板,在试验板的每一侧都有一组引脚。我们在下面的例子中看到了这一点。

    大多数试验板还有一组或多组电源轨,它们平行于沟道连接在一起。如果有两个集合,则这两个集合不会连接在一起。电源轨可能有一条彩色参考线,但这仅用于参考;你可以把其中一个变成积极的,另一个变成消极的。最后,一些试验板对端子排进行编号。这些仅供参考,没有其他意义。然而,它们可以方便地在你的工程笔记本上做笔记。图 7-25 显示了试验板的命名以及端子板和电源轨是如何连接在一起的。

    Note

    电源轨组没有连接在一起。如果你想在试验板的两侧都有电源,你必须使用跳线来连接它们。

    A447395_1_En_7_Fig25_HTML.jpg

    图 7-25。

    Breadboard layout Fritzing: A Breadboarding Software Application

    这本书里的面包板图是用一个叫 Fritzing ( http://fritzing.org/home/ )的程序制作的。这个开源应用允许你在试验板上创建一个电路的数字表示。使用起来相当方便。如果你发现自己想设计一个原型电路,使用 Fritzing 可以帮助你节省大量的试验和错误。另外,Fritzing 允许您在电子原理图或 PCB 布局视图中看到相同的电路。我建议下载并试用这个应用。

    有时需要将电路与代码分开测试。例如,如果我们想确保所有设备都正确连接在一起,我们可以使用试验板电源为电路供电。这样,如果出现严重问题,我们就不会冒损坏 IOT 设备的风险。大多数试验板电源都建立在一个小 PCB 上,带有一个用于壁式电源的桶形插孔,两组用于插入试验板上电源轨的引脚,一个关闭开关(非常方便),有些可以产生不同的电压。图 7-26 展示了我最喜欢的 Sparkfun ( sparkfun.com/products/13157)的试验板电源之一。

    A447395_1_En_7_Fig26_HTML.jpg

    图 7-26。

    Breadboard power supply

    如果我们的电路需要比单个试验板更多的空间,您可以通过简单地跳过电源轨并继续电路来使用多个试验板。为了方便起见,一些试验板可以使用侧面的小块和插槽进行连接。最后,大多数试验板还带有背胶,您可以用它来安装在板上或外壳或类似的工作空间内。如果你决定使用背胶,要预先警告他们不能轻易拆开-他们会很好地保持不动。

    现在我们对试验板的工作原理有了更多的了解,让我们来讨论一下我们的 IOT 解决方案中用来收集数据的组件:传感器。

    什么是传感器?

    传感器是一种测量物理世界现象的装置。这些现象可以是你看到的东西,像光、气体、水蒸气等等。它们也可以是你感觉到的东西,像温度、电、水、风等等。人类的感觉就像传感器一样,让我们能够体验周围的世界。然而,有些东西你的传感器看不到或感觉不到,比如辐射、无线电波、电压和安培数。在测量这些现象时,传感器的工作是以电压表示或数字的形式传达测量结果。

    传感器有多种形式。它们通常是为单一用途设计的低成本设备,处理能力有限。大多数简单的传感器都是分立元件;甚至那些具有更复杂部件的设备也可以被视为单独的组件。传感器可以是模拟的,也可以是数字的,通常只用于测量一种东西。但是越来越多的传感器模块被设计用来测量一系列相关的现象,例如来自 spark fun Electronics(www.sparkfun.com/products/10586)的 USB 天气板。

    以下部分探讨传感器如何测量数据、如何存储数据,以及一些常见传感器的示例。

    传感器如何测量

    传感器是基于其化学和机械结构的独特属性产生电压的电子设备。一些人对传感器的常见误解之一是,它们不会操纵它们被设计来测量的现象(改变事件或数据)。相反,传感器对一些物理变量进行采样,并将其转换为成比例的电信号(电压、电流、数字信号等)。

    例如,湿度传感器测量空气中水(湿气)的浓度。湿度传感器对这些现象做出反应,并产生一个电压,微控制器或类似设备可以读取该电压,并使用该电压来计算秤的数值。一种基本的低成本湿度传感器是可从大多数电子商店( https://www.adafruit.com/product/385 )买到的 DHT-22。图 7-27 显示了一个典型的 DHT-22 传感器。

    A447395_1_En_7_Fig27_HTML.jpg

    图 7-27。

    DHT-22 Humidity Sensor

    DHT-22 设计用于测量温度和湿度。它在输出端(数据引脚)产生一个数字信号。虽然使用简单,但它有点慢,应该用于以合理的慢速度跟踪数据(不超过每 3 或 4 秒一次)。

    当该传感器产生数据时,数据以一系列高(解释为 1)和低(解释为 0)电压的形式传输,微控制器可以读取并使用这些电压来形成一个值。在这种情况下,微控制器从传感器读取长度为 40 位(40 个高或低电压脉冲)的值,即 5 个字节,并将其放入程序变量中。前两个字节是湿度值,后两个字节是温度值,第五个字节是校验和值,以确保读数准确。幸运的是,所有这些艰苦的工作都以专门为 DHT-22 和类似传感器设计的库的形式为您完成了。

    DHT-22 产生一个数字值。不是所有的传感器都这样做;一些产生电压范围。这些被称为模拟传感器。让我们花一点时间来理解它们的区别。这将成为您规划和构建传感器节点的重要信息。

    模拟传感器

    模拟传感器是产生电压范围的装置,通常在 0 到 5 伏之间。需要一个模数转换电路将电压转换成数字。但事情并没有那么简单(是吗?).模拟传感器的工作原理类似于电阻,当连接到 GPIO 引脚时,通常需要另一个电阻来“上拉”或“下拉”电压,以避免被称为浮动的杂散电压变化。这是因为流过电阻的电压在时间和幅度上都是连续的。

    因此,即使传感器不产生值或测量值,仍有电压流过传感器,可能导致虚假读数。您的项目需要明确区分关(零电压)和开(正电压)。上拉和下拉电阻确保您拥有这两种状态之一。模数转换器负责从传感器读取电压,并将其转换为可被解读为数据的值。

    采样时(从传感器读取值时),电压读数必须解释为给定传感器指定范围内的值。请记住,比方说,一个模拟传感器输出的 2 伏电压可能与另一个模拟传感器输出的 2 伏电压不是一回事。每个传感器的数据手册都向您展示了如何解释这些值。

    如您所见,使用模拟传感器比使用 DHT-22 数字传感器要复杂得多。稍加练习,您会发现,一旦了解如何将模拟传感器连接到微控制器,以及如何在传感器校准工作的范围内解释其电压,大多数模拟传感器都不难使用。

    数字传感器

    像 DHT-22 这样的数字传感器被设计成使用串行传输产生一串比特(一次一个比特)。然而,一些数字传感器通过并行传输产生数据(一次一个或多个字节 6 )。如前所述,这些位表示为电压,其中高电压(比如 5 伏)或开是 1,低电压(0 甚至-5 伏)或关是 0。这些开和关值序列称为离散值,因为传感器以脉冲形式产生一个或另一个值,即开或关。

    与模拟信号相比,数字传感器的采样频率更高,因为它们生成数据的速度更快,而且不需要额外的电路来读取数值(例如 A/D 转换器以及将数值转换为刻度的逻辑或软件)。因此,数字传感器通常比模拟传感器更精确和可靠。但是,数字传感器的精度与其用于采样数据的位数成正比。

    数字传感器最常见的形式是按钮或开关。什么,按钮是传感器?为什么,是的,这是一个传感器。考虑一下安装在家庭安全系统窗户上的传感器。这是一个简单的开关,当窗户关闭时关闭,当窗户打开时打开。当开关连接到电路中时,当车窗关闭且开关闭合时,电流是恒定且不间断的(使用上拉电阻测量正电压),但当车窗和开关打开时,电流中断(测量零电压)。这是最基本的开关传感器。

    大多数数字传感器都是由几个元件组成的小电路,用于产生数字数据。与模拟传感器不同,读取它们的数据很容易,因为这些值无需转换就可以直接使用(除了转换到其他刻度或测量单位)。有些人可能认为这比使用模拟传感器更困难,但这取决于你的观点。电子爱好者会认为使用模拟传感器更容易,而程序员会认为数字传感器更容易使用。

    现在,让我们看看一些可用的传感器及其测量的现象类型。

    传感器的例子

    观察某物的 IOT 解决方案可能使用至少一个传感器和一种方法来读取和解释数据。你可能在想各种各样有用的东西,你可以在家里或办公室,甚至在你的院子里或周围测量。你可能想测量新日光浴室的温度变化,检测邮递员何时将最新的通知扔进你的邮箱,或者记录你的狗使用狗门的次数。我希望到现在为止,当你想象你能测量什么的时候,你能看到这些只是冰山一角。

    有哪些类型的传感器可用?以下部分描述了一些比较流行的传感器及其测量内容。我还提供了一些关于如何在 IOT 项目中使用传感器的提示。然而,这只是不断增长的可用传感器阵列中的一部分。细读 Mouser Electronics ( www.mouser.com )、spark fun Electronics(www.sparkfun.com)和 Adafruit Industries ( www.adafruit.com )等在线电子产品供应商的目录,会发现更多的例子。

    我还包括一些传感器类型的流行例子的照片。

    加速计

    这些传感器测量传感器或它所连接的任何东西的运动或移动。它们被设计用来感应几个轴上的运动(速度、倾斜度、振动等等)。一些包括回转仪特征。大多数是数字传感器。Wii 双截棍(或 WiiChuck)包含一个复杂的加速度计,用于跟踪运动。啊哈:现在你知道 Wii 附带的那些有趣的小东西的秘密了吧!如果您的 IOT 项目涉及运动中的物体,并且对该运动的观察提供了有用的信息,您可能需要添加加速度计。

    音频传感器

    也许这是显而易见的,但麦克风是用来测量声音的。大多数是模拟的,但一些更好的安全和监控传感器具有数字版本,用于传输数据的更高压缩。家庭安全、儿童监控、捉鬼或听觉健康等 IOT 项目都可以从集成音频传感器中受益。

    条形码阅读器

    这些传感器被设计用来读取条形码。最常见的是,条形码阅读器生成代表条形码的数字等价物的数字数据。这种传感器通常用在库存跟踪系统中,以在工厂或运输过程中跟踪设备。它们数量众多,而且许多价格经济实惠,使您能够将它们整合到自己的项目中。如果您的 IOT 项目需要从对象中捕获数据,您可能需要考虑条形码。

    例如,如果您希望感应停车场用户何时进入或离开无人值守的停车场,您可以在门口放置一个条形码读取器,读取您设计并分发给用户的条形码。当汽车停在大门前时,条形码阅读器可以读取条形码,记录入口,并升起大门。如果你曾经在大城市生活过,在受控的办公大楼工作过,或者是通勤学生,你可能会遇到这样的停车解决方案。

    生物传感器

    读取指纹、虹膜或掌纹的传感器包含一个用于识别模式的特殊传感器。鉴于指纹和掌纹等图案的独特性,它们是安全访问系统的优秀组件。大多数生物传感器产生一组代表指纹或掌纹的数字数据。需要更高安全级别的 IOT 项目可能希望包括生物传感器来帮助识别系统的用户。

    电容式传感器

    脉搏传感器是电容传感器的一种特殊应用,设计用于测量您的脉搏率,通常使用指尖作为感测部位。称为脉搏血氧仪(一些医疗专业人员称为 pulse-ox)的特殊设备通过电容传感器测量脉搏率,并通过光传感器确定血液中的含氧量。

    如果你拥有现代电子设备,你可能会遇到触敏按钮,它们使用特殊的电容传感器来检测触摸和压力。如果你的 IOT 项目需要测量任何类型的运动,或对触摸做出反应,电容传感器可以帮助提供一个未来的非触觉界面。最新 MacBook Pro 上的 Touch Bar 就是这种解决方案的一个例子。

    图 7-28 展示了两个你可以从 Adafruit 买到的触摸感应模块的例子。在这种情况下,我们看到用于瞬时开关( www.adafruit.com/products/1374 )和拨动开关( www.adafruit.com/products/1375 )的分线板。

    A447395_1_En_7_Fig28_HTML.jpg

    图 7-28。

    Touch Capacitive Sensor Breakout Boards

    硬币传感器

    这是最不寻常的传感器之一。这些装置 7 就像典型自动售货机上的投币口。像它们的商业等价物一样,它们可以被校准以感应何时插入一定大小的硬币。虽然不像商业单位那样复杂,可以区分真假硬币,硬币传感器可以用来为您的项目添加一个新的维度。对于父母来说,一个伟大而实用的 IOT 项目将是一个投币式 WiFi 站,孩子们可以在那里购买自己的上网时间。这不仅能让他们避免过度使用互联网,还能帮助他们学会如何安排自己的零花钱。现在,这应该可以防止孩子们在互联网上花太多时间!

    电流传感器

    这些设计用于测量电压和电流。有些是为测量变化而设计的,而有些是为了测量负载。IOT 的项目集成电路或需要监测电流将需要一个电流传感器。这些可能是一些更深奥的项目,但您可以使用这些传感器来监控现有解决方案的行为,而无需修改它们。

    例如,如果您想采用传感器来观察制造机器,您可以添加传感器来监控各种组件的电流。也就是说,您可以记录电压何时施加到电机、致动器,甚至警告灯,以确定设备何时(或多少)被激活。然而,作为一个业余爱好者,你更可能有兴趣建立自己的万用表或类似的工具。

    弯曲/力传感器

    电阻传感器测量一块材料的弯曲或压力对传感器的影响。弯曲传感器可能有助于测量扭转效应或测量手指运动(就像任天堂的电动手套一样)。当传感器弯曲时,传感器电阻增加。例如,如果您想创建一个 IOT 解决方案来实时报告您的钓鱼体验,您可能希望在您的鱼竿上使用一个 flex 传感器来报告您每次投掷或击中鱼饵的情况。

    气体传感器

    有很多种气体传感器。有些测量潜在有害气体,如液化石油气和甲烷以及其他气体,如氢气、氧气等。其他气体传感器与光传感器相结合来感测空气中的烟雾或污染物。下次当你从烟雾探测器中听到那种警告性的、通常令人讨厌的低电量警告声 8 时,想想那个设备包含了什么。为什么,这是一个传感器节点!如果您的 IOT 项目需要观察或检测任何形式的气体,特别是如果它涉及到对某些气体或其水平的反应,您将需要使用适当的气体传感器。

    光传感器

    测量光强或缺光的传感器是特殊类型的电阻:光敏电阻(ldr),有时也称为光敏电阻或光电池。因此,它们本质上是模拟的。

    如果你有一台 Mac 笔记本电脑,当你的发光键盘在弱光下自动打开时,你很可能已经看到了光敏电阻的作用。特殊形式的光传感器可以检测其他光谱,如红外线(如旧的电视遥控器)。例如,如果您希望您的 IOT 项目自动调整其显示器的亮度,光传感器就是您需要的组件。

    A447395_1_En_7_Fig29_HTML.jpg

    图 7-29。

    Mini Photocell

    下面显示了光传感器的两个例子。图 7-29 显示了一个典型的微型光电池( www.sparkfun.com/products/9088 ),图 7-30 显示了一个颜色传感器( www.adafruit.com/products/1334 )。

    A447395_1_En_7_Fig30_HTML.jpg

    图 7-30。

    Color Sensor Breakout Board

    液体流量传感器

    这些传感器类似于阀门,内嵌在管道系统中。他们测量液体通过时的流量。基本的流量传感器使用旋转轮和磁铁来产生霍尔效应(快速开/关序列,其频率等于通过的水量)。如果你的 IOT 项目涉及任何形式的液体,如花园池塘或灌溉系统,了解水的流动可能有助于学习或观察某些东西。

    液位传感器

    一种特殊的电阻固态器件可以用来测量水体的相对高度。一个例子是当水位高时产生低电阻,当水位低时产生高电阻。像液体流量传感器一样,液位传感器通常用于相同的解决方案中。图 7-31 显示了一个典型的液位传感器,当水位上升时,浮子关闭开关。

    A447395_1_En_7_Fig31_HTML.jpg

    图 7-31。

    Water-Level Sensor

    位置传感器

    现代智能手机有 GPS 传感器来感应位置,当然 GPS 设备使用 GPS 技术来帮助你导航。幸运的是,GPS 传感器以低成本的形式提供,使您能够将位置检测添加到您的项目中。GPS 传感器生成经度和纬度形式的数字数据,大多数还可以感知海拔高度。如果你的 IOT 项目需要报告它的位置,GPS 传感器可以给你非常准确的读数。然而,像大多数传感器一样,GPS 传感器可能有一定程度的不准确性。根据你需要定位的距离,你可能需要多花一点钱买一个更精确的 GPS 传感器。

    磁条阅读器

    这些传感器从磁条(像信用卡上的磁条)读取数据,并返回数字形式的字母数字数据(实际的字符串)。包含安全组件的 IOT 项目可能希望使用磁条读取器来帮助识别用户。当与密码和生物传感器结合使用时,安全性可以大大提高。也就是说,某人必须知道某样东西(密码或 pin),拥有某样东西(带有磁条的安全卡,磁条上有关键短语、数字、用户 id 等编码)。),并在获得访问权限之前被验证为某人(指纹)。

    磁力计

    这些传感器通过磁场强度来测量方向。指南针是一种用来寻找磁北的传感器。一些磁力计提供多个轴,以便更好地检测磁场。这是另一个你可能不会经常遇到的传感器,但是如果你的 IOT 项目需要测量来自电机或大气现象的磁场,你可能想看看磁力计。

    湿度传感器

    湿度传感器测量物质(如土壤)或空气中的湿度。它们通常以电压读数的形式发送数据,低值表示水分较少。您经常会在大气项目甚至工厂监控解决方案中发现湿度传感器。图 7-32 显示了一个典型的土壤湿度传感器()。请注意,尖头是传感器插入土壤的部分。

    A447395_1_En_7_Fig32_HTML.jpg

    图 7-32。

    Soil Moisture Sensor

    接近传感器

    接近传感器通常被认为是距离传感器,它使用红外线或声波来检测物体的距离、运动或距离。受低成本机器人套件的欢迎,视差超声波传感器通过感应发送脉冲和接收脉冲之间的时间量(回声),使用声波来测量距离。对于近似的距离测量, 9 把时间转换成距离是一个简单的数学问题。如果您正在构建一个检测移动或接近的 IOT 项目,如运动感应相机,您可能需要使用接近传感器。

    下图显示了两种类型的接近传感器。图 7-33 展示了一个流行的被动红外传感器(PIR)运动传感器( www.sparkfun.com/products/13285 )。

    A447395_1_En_7_Fig33_HTML.jpg

    图 7-33。

    PIR Motion Sensor

    图 7-34 展示了一个超声波传感器( www.sparkfun.com/products/13959 ),用在从机器人到无人机的很多项目中。

    A447395_1_En_7_Fig34_HTML.jpg

    图 7-34。

    Ultrasonic Proximity Sensor

    辐射传感器

    更重要的传感器是那些探测辐射的传感器。这也可能是电磁辐射(也有传感器),但盖革计数器使用辐射传感器来检测有害的电离。事实上,使用一个传感器和一个 Arduino(以及一些电子元件)来建造你自己的盖革计数器是可能的。作为业余爱好者,你可能不会遇到这种传感器。然而,有几个工具包可以用来构建你自己的盖革计数器,比如 Adafruit ( www.adafruit.com/products/483 )的那些。

    RFID 传感器

    射频识别使用无源设备(有时称为 RFID 标签)通过电磁感应使用射频来传输数据。例如,RFID 标签可以是信用卡大小的塑料卡、标签或类似的包含特殊天线的东西,通常以线圈、细线或箔层的形式调谐到特定频率。

    当标签被放置在阅读器附近时,阅读器发射无线电信号;标签可以使用电磁能量以无线电信号的形式传输嵌入在天线中的非易失性消息,该无线电信号然后被转换成字母数字串。 10 RFID 传感器是安防系统的另一个好选择。如果你有宠物,你可能想拜访你的兽医询问 RFID 传感器作为隐藏的主人识别标签。如果你知道频率,你甚至可以用它来帮助检测你的宠物何时通过宠物门。图 7-35 显示了一个 RFID 阅读器(传感器),您可以使用它通过 USB ( www.sparkfun.com/products/9963 )读取 RFID 标签。

    A447395_1_En_7_Fig35_HTML.jpg

    图 7-35。

    RFID Reader

    速度传感器

    像流量传感器一样,许多自行车上的简单速度传感器使用磁铁和簧片开关来产生霍尔效应。频率结合车轮的周长可以用来计算速度,以及随着时间的推移,行驶的距离。如果您的 IOT 解决方案需要读取运动,您可以使用磁开关和磁铁来检测旋转。例如,自行车速度计通常使用磁铁和磁性开关来检测转数、车轮周长和动作频率,以计算速度。

    开关和按钮

    这些是最基本的数字传感器,用于检测某个东西是被设置(开)还是被重置(关)。尽管如此,你可以使用开关和按钮来建立一个用户界面,用于控制其他设备,甚至是打开它!

    倾斜开关

    这些传感器可以检测设备何时向某个方向倾斜。虽然非常简单,但它们对于低成本运动检测传感器非常有用。它们是数字的,本质上是开关。如果您的 IOT 解决方案需要检测设备何时倾斜,您可以使用倾斜传感器在特定倾斜角度触发。例如,一些现代摩托车使用倾斜传感器来打开转向灯——前照灯倾斜,以改善夜间转弯时的视野。

    触摸传感器

    形成小键盘、键盘、定点设备等的触敏膜是一种有趣的传感器形式。你可以使用像这样的触摸感应设备来收集人类的数据。触摸传感器可以帮助您为您的 IOT 项目构建一个用户界面,该界面可以以低调的形式呈现,或者节省控制台、项目箱等的空间。

    视频传感器

    如前所述,有可能获得非常小的视频传感器,这些传感器使用摄像机和电路来捕捉图像并将其作为数字数据传输。如果要将视频元素整合到 IOT 项目(如安全解决方案)中,可以添加摄像机或视频传感器来捕捉视觉组件,以帮助提供事件测量之外的信息。也就是说,你可以查看一张照片,了解更多信息,而不仅仅是移动或靠近设备的东西。例如,您可以构建一个 IOT 项目,该项目可以检测运动,并在某个物体足够接近或者运动速度超过某个阈值时拍摄照片。 11

    天气传感器

    温度、气压、降雨量、湿度、风速等传感器都属于天气传感器。大多数生成数字数据,并可以结合起来创建全面的环境解决方案。图 7-36 显示了 BMP280 压力和温度传感器( www.adafruit.com/products/2651 )的通用转接板。

    A447395_1_En_7_Fig36_HTML.jpg

    图 7-36。

    BMP280 Pressure and Temperature Sensor

    有了这个和其他易于使用的传感器,就有可能用大约十几个廉价的传感器、你的 MicroPython 板和一点解释和组合数据的程序来建立你自己的气象站。事实上,我们将在第十章中讨论这个问题!

    提示–如果您想查看更多传感器,您可以从 Adafruit ( www.adafruit.com/category/35 )或 Sparkfun ( www.sparkfun.com/categories/23 )购买任意数量的传感器。

    I Want to Learn More!

    如果你发现你需要或想要学习比我在这一章中介绍的更多的关于电子学的知识,或者你想要学习更多的关于你在一个更高级的 IOT 项目中需要的电子学知识,你可能想要考虑在一所社区大学上一门课程或者尝试一门自定进度的电子学课程。

    我发现的最好的自定进度课程之一包括查尔斯·普拉特的一套电子书籍。我发现这些书写得非常好,为许多人打开了学习电子学的大门,而不必花数年时间学习乏味的(但同样重要的)电子学理论和数学。最重要的是,它们不是以沉闷的教科书式的事实-事实-事实-问题的节奏写成的。它们是由一位世界著名的专家撰写的,这位专家具有以易于阅读和理解的风格呈现材料的天赋。我向任何想学习更多电子知识的人推荐以下书籍。

  • 制作:电子,第二版(奥赖利,2015),查尔斯·普拉特
  • 制造商:更多电子公司(奥赖利,2014 年),查尔斯·普拉特
  • 电子元件百科全书第 1 卷(O’Reilly,2012),查尔斯·普拉特
  • 电子元件百科全书第 2 卷(O’Reilly,2014),查尔斯·普拉特
  • 电子元件百科全书第 3 卷(O’Reilly,2016),查尔斯·普拉特
  • 他的百科全书系列的第三卷包括对传感器的深入研究:高级 IOT 项目的必备。

    maker shed(makershed.com/collections/electronics)出售配套套件,其中包含完成《制作:电子》和《制作:更多电子书籍》中的实验所需的所有部件。这些书和工具包一起构成了一个极好的自定进度的学习体验。

    摘要

    学习如何把使用电子产品作为一种爱好或者创造一个 IOT 解决方案并不需要终生学习或者改变职业。事实上,学习如何使用电子设备是体验 IOT 乐趣的一部分!我遇到过许多自学电子的人,虽然大多数人承认正式学习对于掌握这个主题是必不可少的,但你可以自学很多东西——足以熟练使用 IOT 项目中常见的基本电子元件。

    本章介绍了电子元件的基础知识,包括试验板、常见元件和示例电路的使用。这一点和一些如何使用万用表的关键知识将会让你在精通电子学的道路上走得很远。我们还了解了 IOT 解决方案的关键组件之一——传感器。我们发现了它们通信的两种方式(数字和模拟)以及一些可用的传感器类型。

    在下一章,我们将深入我们的第一个电子项目——相当于“你好,世界!”硬件项目。我们将看到如何将我们的 MicroPython 板连接到几个组件,并编写一个 Python 程序来控制它们。酷!

    Footnotes 1

    但是,正规的训练是没有替代品的!如果你想在本章的教程之外探索电子学,你可以考虑正式的培训,甚至是一个自定进度的课程,如侧栏“我想了解更多!”

    2

    旧的万用表有一个模拟仪表。如果你想要一点老学校的感觉,你仍然可以找到他们。

    3

    是的,有点强迫症。检查,再检查,再检查。

    4

    https://learn.sparkfun.com/tutorials/what-is-electricity

    5

    欧姆定律的变体( https://en.wikipedia.org/wiki/Ohm's_law )。

    6

    这取决于并行缓冲区的宽度。8 位缓冲区一次可以传输 1 个字节,16 位缓冲区一次可以传输 2 个字节,依此类推。

    7

    www.sparkfun.com/products/11719

    8

    我相信越多越好的理论,在家里有很多探测器,这很好,但是当电池耗尽时,我永远也不会知道哪个探测器在响!当它们只发出一两声哔哔声,然后就无声无息了,这就变得令人沮丧。幸运的是,我已经用最新的 10 年电池变体替换了几乎所有的电池。不再有野鹅追逐!

    9

    精度可能取决于环境变量,如海拔、温度等。

    10

    http://en.wikipedia.org/wiki/Radio-frequency_identification

    11

    你有没有想过,如果你能抓拍到一张正在你的花园里吃东西的动物的照片,那该有多好?用一个接近传感器和一个红外线照相机建造你自己的动物照相机!

    八、项目一:MicroPython 风格的你好世界

    这是本书最有趣的部分——从事 MicroPython 项目!正是在这一点上,我们已经学会了如何用 MicroPython 编写代码,现在对硬件甚至如何使用分立电子器件和分线板有了更多的了解。

    本章介绍了如何构建 MicroPython 项目。因此,我们还需要学习一些东西,包括在我们的 MicroPython 板上安装和运行项目的技术和程序。这一章将介绍那些使你的 MicroPython 项目成功所需要的东西。因此,这一章有点长,即使你不打算实现这个项目,也应该被认为是必读的。

    为了帮助实现这些目标并使事情变得简单一点(因为这是您的第一个真正的 MicroPython 项目),我们将放弃将这个项目连接到互联网,这样我们可以使这个项目更容易实现。后面的章节会有更少的介绍性信息,并且会更多地关注项目,因为随着我们的进展,它们会变得更加复杂。

    正如您将看到的,所有项目章节的格式都是相同的:首先是项目概述,然后是所需组件的列表以及如何组装硬件。一旦我们掌握了如何连接硬件,我们就可以看到如何连接一切,并开始编写代码。每章都以如何执行项目结束,并附有一个项目运行的例子和美化项目的建议。

    如果你现在想知道你需要哪种板来完成这些项目,不要担心,因为我们将在本章中看到如何在 WiPy 和 Pyboard 上实现这个项目,以及不同之处的演示。

    那么,让我们开始我们的第一个 MicroPython 项目吧!

    概观

    在这一章中,我们将设计并构建一个 MicroPython 时钟。我们将同时使用 SPI 和 I2C 分线板。我们将使用小型有机发光二极管(有机发光二极管) 1 显示器,该显示器使用 SPI 接口和基于硬件的实时时钟(RTC),该时钟使用 DS1307 芯片和电池在项目关闭时记录时间。我们将使用基于硬件的 RTC,并在小型有机发光二极管显示器上显示当前日期和时间,而不是简单地连接到互联网上的网络时间协议(NTP)服务器。这不仅使项目变得更小,还演示了如何为可能没有连接到互联网的项目使用 RTC。

    虽然 Pyboard 具有 RTC 电路,您可以连接外部电池,以便在电路板关闭时保持 RTC 供电(参见 http://docs.micropython.org/en/latest/pyboard/pyboard/quickref.html 的 VBAT 引脚参考),但大多数片上系统(SOC)板,如 WiPy 和其他基于 Espressif 的板,不支持此功能。因此,我们将使用外部 RTC,以便您可以在其他板上使用该项目。

    正如您将看到的,需要相当多的布线,并且理解硬件功能是编写代码的必要条件,这就是为什么我们在前几章花时间讨论固件和各种低级硬件控制。你需要这些技能和知识来完成这个项目。

    虽然一个时钟可能听起来很简单,但这个项目将引导您完成组装硬件和编写代码所需的所有步骤。正如您将看到的,除了硬件布局和引脚数之外,WiPy 和 Pyboard 之间还有一些明显的差异。事实上,我们将看到在我们如何为每一个写代码方面有一些不同。

    此外,该项目很小而且很简单,因此我们可以专注于过程,然后我们可以将其应用于更高级的项目。事实上,我们会看到,即使是一个相对简单的项目也可能有意想不到的难度。但是不要担心,因为这一章记录了你完成这个项目需要做的所有事情。

    这个项目的来源很多。以下链接包括本项目使用的背景数据。学习如何应用来自这些网站的知识不是一件容易解释或学习的事情;然而,通过查看这些资源(如果你愿意的话),它应该可以帮助你理解如何研究和计划你自己的项目。

  • 项目创意和驱动因素来源: http://micropython-urtc.readthedocs.io/en/latest/examples.html
  • 有机发光二极管显示信息: https://learn.adafruit.com/monochrome-oled-breakouts/wiring-128x32-spi-oled-display
  • 有机发光二极管显示驱动: https://github.com/adafruit/micropython-adafruit-ssd1306
  • RTC 驱动文档: https://github.com/adafruit/Adafruit-uRTC/tree/master/docs
  • RTC 驱动: https://github.com/adafruit/Adafruit-uRTC
  • 注意使用的网站。一个好的实践是从 Adafruit 和 MicroPython 学习、blobs 和论坛开始。然后检查驱动程序。也就是说,先做研究,找到所有你能找到的参考资料。如果你从 Adafruit 或 Sparkfun 上找到了不错的教程,你可以把它们下载到你的平板电脑上,或者打印出来供以后阅读。更重要的是,在开始使用硬件或编写代码之前,花时间阅读参考资料,以便尽可能多的理解。通过了解一些简单的事情,如如何将电路板连接到设备以及如何使用驱动程序,您可以节省大量时间。 3

    Which Driver Do I Use?

    您可能会遇到这样的情况:您为您想要使用的硬件找到了多个驱动程序。事实上,我为有机发光二极管展示会找到了三个司机。它们之间的差异是微妙的,看起来至少有一个是为特定平台编写的。

    其实上面列出的是最好用的一个。尽管如此,它需要做一些小的改动才能与 WiPy 和 Pyboard 一起使用。我将向您展示这些变化,正如您将看到的,它们并不难发现和修复(例如,当 MicroPython 抛出异常时,它将向您显示问题的根源)。

    如果您遇到类似的情况——有多个驱动程序可供选择,您可能希望尝试每个驱动程序,直到找到最适合您的硬件和项目的驱动程序。有时,在这种情况下,这是真的,一个驱动程序可能不可行,或者另一个可能缺乏您需要的功能。例如,我发现的一个驱动程序不支持文本,所以它不能用于这个项目,另一个需要进行重大修改才能用于 Pyboard。诀窍是找到修改量最少但效果最好的驱动程序。

    现在让我们看看这个项目需要哪些组件,然后我们将看看如何将所有组件连接在一起。

    必需的组件

    表 8-1 列出了你需要的部件。您可以从 Adafruit ( adafruit.com)、Sparkfun ( sparkfun.com)或任何出售电子元件的电子商店单独购买元件。如果您想购买这些组件,可以链接到供应商。当列出同一对象的多行时,您可以选择其中一行——您不需要两个都要。此外,您可能会找到销售这些组件的其他供应商。你应该货比三家,找到最好的交易。显示的成本是估计值,不包括任何运输成本。

    表 8-1。

    Required Components

    | 成分 | 数量 | 描述 | 费用 | 链接 | | — | — | — | — | — | | MicroPython 板 | one | 带标题的 Pyboard v1.1 版 | $45-50 | [`https://www.adafruit.com/product/2390`](https://www.adafruit.com/product/2390)[`https://www.adafruit.com/product/3499`](https://www.adafruit.com/product/3499) | | [`https://www.sparkfun.com/products/14413`](https://www.sparkfun.com/products/14413) | | [`https://store.micropython.org/store`](https://store.micropython.org/store) | | WiPy | $25 | [`https://www.adafruit.com/product/3338`](https://www.adafruit.com/product/3338) | | [`https://www.pycom.io/product/wipy/`](https://www.pycom.io/product/wipy/) | | 有机发光二极管显示器 | one | 基于 ssd1306 的 SPI 显示器 | $18 | [`https://www.adafruit.com/product/661`](https://www.adafruit.com/product/661) | | RTC 分线板 | one | 带备用电池的 RTC 模块 | $15 | [`https://www.sparkfun.com/products/12708`](https://www.sparkfun.com/products/12708) | | 试验板 | one | 原型板,半尺寸 | $5 | [`https://www.sparkfun.com/products/12002`](https://www.sparkfun.com/products/12002) | | 跳线 | Twelve | M/M 跳线,6”(成本是一套 10 根跳线) | $4 | [`https://www.sparkfun.com/products/8431`](https://www.sparkfun.com/products/8431) | | 力量 | one | 从电脑获取电源的 USB 电缆 |   | 使用您的备件 | | one | USB 5V 电源和电缆 |   | 使用您的备件 | | 纽扣电池 | one | 参见 RTC 分线板数据表 | $3-5 | 常见的 |

    请注意,在源代码中,最后两项是“使用您的备件”。这是指我们大多数人手头都有这些东西,而且在某些情况下还很丰富。例如,如果你买了一块 MicroPython 板,如果你还没有电缆,你也需要买一根。此外,随着 USB 充电设备的激增,很难想象任何拥有一台以上智能设备的人没有额外的 USB 充电器或电源。

    如果您选择使用 WiPy,建议您也从 Adafruit ( https://www.adafruit.com/product/3344 )或 Pycom ( https://www.pycom.io/product/wipy-expansion-board/ ).)购买扩展板

    本项目中使用的有机发光二极管分线板是 Adafruit 的一个小模块。它有一个很小但很亮的显示屏,可以安装在试验板上。分辨率为 128 像素宽,32 像素高。有机发光二极管分线板没有安装接头,但如果你知道如何焊接(现在可能是练习的好时机)或者你可以让朋友帮助你,它们很容易添加。图 8-1 显示了 Adafruit 有机发光二极管 SPI 分线板。

    A447395_1_En_8_Fig1_HTML.jpg

    图 8-1。

    Monochrome 128×32 SPI OLED Graphic Display (courtesy of adafruit.com)

    有几种有机发光二极管分线板可用,只要它们具有 SPI 接口并使用 ssd1306 控制器芯片(说明会告诉你这一点),就可以使用备用有机发光二极管显示器。我们之所以需要在控制器芯片上使用一个,是因为驱动程序是为该控制器编写的。其他控制器芯片将需要不同的驱动器。

    本项目中使用的 RTC 分线板是 Adafruit 的 DS1307 分线板。该板也没有安装接头(但包括接头),也没有配备电池,因此您必须购买 CR1220 纽扣电池。如果你不想去商店的话,Adafruit 也有这些东西。图 8-2 显示了 RTC 分线板。

    A447395_1_En_8_Fig2_HTML.jpg

    图 8-2。

    DS1307 Real-Time Clock Assembled Breakout Board (courtesy of adafrui.com)

    有几种 DS1307 RTC 时钟可用。事实上,Sparkfun 有一个,或者您可以自己创建一个!参见侧栏“构建您自己的 RTC 模块”了解更多细节。幸运的是,我们将使用的库支持带有 DS1307、DS3231 或 PCF8523 RTC 芯片的分线板。

    Tip

    小型分立元件,如 led、电阻等。,甚至跳线和试验板都可以在第二章提到的套件中找到——Adafruit Parts Pal(https://www.adafruit.com/product/2975)或者 Sparkfun 初学者配件套件( https://www.sparkfun.com/products/13973 )。我推荐其中一套。

    现在,让我们看看如何将组件连接在一起。

    安装硬件

    这个项目有很多联系。有机发光二极管需要 7 个,RTC 需要 4 个,电源和接地需要一些额外的跳线。为了让事情更简单,我们将计划事情应该如何连接。我们将使用试验板来安装分线板,使连接更容易。更具体地说,我们将了解每个元件需要什么样的连接,以及它们需要在哪里连接到我们的电路板,将它们写下来以保持事情的连续性。做少量的家庭作业会为你节省时间(并且不会有一点点的挫败感)。

    在这一节和下一节中,我们将看到如何为 WiPy 和 Pyboard 实现这个项目。在硬件的情况下,分线板侧的连接都是相同的,但是每个板的管脚号不同。表中显示了两种板,左边显示了带有 pin 标签的 MicroPython 板,右边显示了带有 pin 标签的分线板。我们将使用公/公跳线通过试验板进行这些连接。

    正如您将看到的,像这样绘制连接使得检查连接变得容易。这个表和一个接线图是你将在本书和互联网或其他地方的其他示例项目中看到的工具。因此,学习如何阅读地图和接线图是一项让你的项目成功的技能。

    表 8-2 显示了本项目所需的连接。注意“导线颜色”列。使用此列记录跨接导线的颜色,以帮助管理连接。使用什么颜色的电线并不重要,但是为每个连接使用不同的颜色有助于管理您将要连接的许多电线。如果您记下每个连接使用的是哪种颜色的电线,还可以更容易地检查您的连接。传统上,我们至少用黑色代表地(负极),红色代表电源(正极)。

    表 8-2。

    Connections for the MicroPython Clock (WiPy and Pyboard)

    | MicroPython 板 | 分线板 | 电线颜色 | | — | — | — | | WiPy | Pyboard | 板 | 个人识别码 |   | | — | — | — | — | — | | P9 | X9 | 雷达跟踪中心(Radar Tracking Centre 的缩写) | 圣地亚哥 |   | | P8 | X10 | 雷达跟踪中心(Radar Tracking Centre 的缩写) | 国家药品监督管理局 |   | | 5V | V+ | 雷达跟踪中心(Radar Tracking Centre 的缩写) | 5V |   | | 地线 | 地线 | 雷达跟踪中心(Radar Tracking Centre 的缩写) | 地线 |   | | P6 | Y3 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 英特尔的快速储存技术 |   | | 孕烯醇酮 | Y4 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 跟单信用证 |   | | P7 | Y5 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 特许测量员 |   | | P10 | Y6 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 时钟信号 |   | | P11 | Y8 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 数据 |   | | 3V3 | 3V3 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 车辆识别号码 |   | | 地线 | 地线 | 有机发光二极管(Organic Light Emitting Diode 的缩写) | 地线 |   |

    哇,联系真多啊!让我们来复习一些元件接线的技巧。将元件连接到电路板的最佳方式是使用试验板。正如我们在第七章中看到的,试验板允许我们插入组件,并使用跳线进行连接。这简化了项目的布线,并允许您在需要腾出更多空间时移动物品。试验板也有助于布线电源和接地连接,因为试验板的两侧都有电源轨,我们可以将其用作公共连接。也就是说,用一根跳线将电源和接地连接到试验板,用另一根跳线连接到分线板。

    插入组件时,务必确保针脚与中央通道平行安装。回想一下,试验板的引脚以垂直于中央通道的方式成行布线。这允许您对元件(或电路板上的引脚)进行多个连接。

    Caution

    项目通电时,切勿插拔跳线。

    最后,务必确保您的项目布线时仔细检查所有连接,尤其是电源、接地和用于信号的任何引脚(将设置为“高”或“开”),如用于 SPI 接口的引脚。最重要的是,当项目(或您的板)通电时,切勿插拔跳线。这很可能会损坏您的主板或组件。 4

    首先,拿出你的试验板,插上元件;然后,使用不同颜色的跳线,将所有需要的电线插入试验板,并在图表中注明您使用的颜色。当您开始将跳线的另一端插入 MicroPython 板时,这将对您有很大帮助。

    在这个项目中,我将有机发光二极管安装在一个半尺寸试验板的左侧,就在中央通道的下方,RTC 模块安装在右侧,也在通道的下方。请注意,这些板使用不同的电源连接。有机发光二极管板使用 3.3V,RTC 板使用 5V。打开项目电源之前,请务必检查组件的电源要求。再三检查你的连接。

    现在,让我们看看如何连接 WiPy 和 Pyboard,如图所示。

    WiPy

    WiPy 的布线最好将扩展板上的 USB 连接器朝向左侧。这将允许您读取电路板上的引脚数,即使在电线插入电路板之后。然而,这只是一个建议。只要电线连接正确,方向并不重要。图 8-3 显示了 WiPy、有机发光二极管和 RTC 分线板的接线图。

    A447395_1_En_8_Fig3_HTML.jpg

    图 8-3。

    Wiring the Clock Project (WiPy)

    Pyboard

    Pyboard 的布线最好将 USB 连接器朝向左侧。这将允许您读取电路板上的引脚数,即使在电线插入电路板之后。图 8-4 显示了 Pyboard、有机发光二极管和 RTC 分线板的接线图。

    A447395_1_En_8_Fig4_HTML.jpg

    图 8-4。

    Wiring the Clock Project (Pyboard) Caution

    总是再三检查你的连接,尤其是所有的电源和接地连接。请务必检查电源连接,以确保正确的电源(3V 或 5V)正确连接到组件。连接错误的电压会损坏部件。

    如果您选择了不同于图中所示的 RTC 板,请务必根据需要调整连接。例如,Sparkfun DS1307 分线板的引脚顺序不同,所以不要只看这张图,尤其是在使用替代组件的情况下!

    同样,在给主板通电之前,请务必仔细检查您的连接。现在,我们来谈谈我们需要编写的代码。暂时不要启动您的主板——在我们准备好测试该项目之前,还需要进行大量的讨论。

    写代码

    现在是时候为我们的项目编写代码了。由于我们正在使用几个新组件,我将依次介绍每个组件的代码。代码并不太复杂,但可能不像以前项目中的一些代码那样清晰。让我们先来看看这个项目的设计。

    设计

    一旦你整理好硬件以及如何将元件连接到你的电路板上,就该开始设计代码了。 5 幸运的是,这个项目足够小,可以让设计变得简单。简而言之,我们希望在有机发光二极管上每秒显示一次时间。因此,代码的“工作”是从 RTC 读取日期和时间,然后在有机发光二极管上显示出来。下面列出的步骤总结了如何为这个项目或任何项目设计和实现代码。

    1. 库:我们需要为 RTC 和有机发光二极管选择和导入库
    2. 设置:我们需要为 I2C 和 SPI 设置接口
    3. 初始化:我们需要为库中的类初始化对象实例
    4. 功能:我们将需要一个新的功能,让我们的项目启动和启动运行
    5. Main:修改我们的 MicroPython 板上的 main.py 文件来运行我们的代码

    这五个元素是我们将在本书的所有项目中使用的,事实上,它是所有 MicroPython 项目都要遵循的一个好模式。新的功能步骤是我们还没有看到的新步骤。简而言之,我们将代码的操作部分包装在一个单独的函数中,以便在启动时从main.py文件中调用。当我们执行和测试这个项目时,我们将会看到更多关于它的内容。

    现在我们知道了项目代码将如何实现,让我们回顾一下所需的库。

    所需的库

    回想一下之前我们需要两个驱动程序:一个用于有机发光二极管显示,另一个用于 RTC。有机发光二极管显示器的驱动程序可在 https://github.com/adafruit/micropython-adafruit-ssd1306 找到,RTC 的驱动程序可在 https://github.com/adafruit/Adafruit-uRTC 找到。

    现在就下载这两个驱动程序吧。您应该能够访问这些站点,单击克隆或下载链接,然后单击下载 Zip 按钮将文件下载到您的 PC。然后,打开下载文件的位置并解压缩。您应该找到以下文件。将这些内容复制到您电脑上的某个位置。我们复制它们是因为我们需要修改它们,如果我们犯了错误或者事情不顺利,复制它们可以让我们回到原来的样子。

  • ssd1306.py:有机发光二极管显示驱动
  • urtc.py:RTC 驱动
  • 我们必须修改一个库有两个主要原因;在这种情况下,我们看到了两者的例子。首先,Adafruit 驱动程序针对的目标平台存在差异。更具体地说,它是为不同的 MicroPython 板编写的,但是我们可以很容易地根据我们的需要对它进行修改。第二,主板上的固件之间存在差异。这将需要更改驱动程序代码,以使用与特定 MicroPython 板相关的正确的类和函数。

    同样,不要担心,因为对库的更改很小。但是,这是一个很常见的现象,你应该习惯于做这样的小改动——尤其是如果你使用的是 WiPy 或 Pyboard 之外的板!

    使用驱动程序时,还有一个需要考虑的问题。您应该查看驱动程序文档以了解任何限制。例如,驱动程序可能需要较新版本的固件。在某些情况下,可能还需要旧版本的固件(但这种情况很少见)。如果您的驱动程序与您的主板不兼容,而文档声称它可以与您的主板兼容,请在文档中检查您的固件版本是否有任何不兼容之处。

    在接下来的章节中,我们将会看到在 WiPy 和 Pyboard 上使用驱动程序所需的一般变化。

    更改 WiPy 的ssd1306.py

    有机发光二极管驱动程序需要对 WiPy 固件进行少量的修改。WiPy 上的引脚类没有high()low()功能。取而代之的是,WiPy 固件使用一个函数value(),我们将它作为参数传递,1 表示高,0 表示低。幸运的是,对于那些知道如何读取差异文件(diff 命令 6 的输出)的人来说,只需将所有出现的.high()更改为.value(1)并将.low()更改为.value(0).,差异文件如清单 8-1 所示。

    --- ./Pyboard/ssd1306.py        2016-10-30 14:06:02.000000000 -0400
    +++ ./WiPy/ssd1306.py           2017-07-20 21:39:31.000000000 -0400
    @@ -146,23 +146,23 @@
    
         def write_cmd(self, cmd):
             self.spi.init(baudrate=self.rate, polarity=0, phase=0)
    -        self.cs.high()
    -        self.dc.low()
    -        self.cs.low()
    +        self.cs.value(1)
    +        self.dc.value(0)
    +        self.cs.value(0)
             self.spi.write(bytearray([cmd]))
    -        self.cs.high()
    +        self.cs.value(1)
    
         def write_framebuf(self):
             self.spi.init(baudrate=self.rate, polarity=0, phase=0)
    -        self.cs.high()
    -        self.dc.high()
    -        self.cs.low()
    +        self.cs.value(1)
    +        self.dc.value(1)
    +        self.cs.value(0)
             self.spi.write(self.buffer)
    -        self.cs.high()
    +        self.cs.value(1)
    
         def poweron(self):
    -        self.res.high()
    +        self.res.value(1)
             time.sleep_ms(1)
    -        self.res.low()
    +        self.res.value(0)
             time.sleep_ms(10)
    -        self.res.high()
    +        self.res.value(1)
    
    Listing 8-1.Changes for the ssd1306.py code module for the WiPy (difference file)
    
    

    What’s a Difference File?

    差异文件是diff命令的输出。它逐行显示同一文件的两个版本之间的变化或差异。在统一差异文件中,以减号开头的行是要删除的行,而以加号开头的行是要添加的行。文件中没有序言(符号)的行被用作定位更改的上下文(以及一个特殊的头)。差异文件可与patch命令一起使用,将更改应用于文件。因此,差异文件有时被称为“补丁”或“差异”文件。

    对 Pyboard 的uRTC. py进行更改

    RTC 驱动程序将无法在 Pyboard 上正确运行(但在 WiPy 上无需更改即可正常运行)。所需的更改是由于 I2C 类的功能不同。驱动程序使用以下方法来读取和写入数据。

    i2c.readfrom_mem(address, register, num_to_read)
    i2c.writeto_mem(address, register, buffer)
    
    

    但是,Pyboard 固件有不同的函数名,参数顺序也不同,如下所示。请注意,read 函数的参数顺序是不同的。

    i2c.mem_read(num_read, address, register)
    i2c.mem_write(buffer, address, register)
    
    

    因此,我们需要改变库中的所有读写功能,以匹配我们的板的固件。你所需要做的就是打开文件并进行修改——只需要重命名函数并重新排列 read 函数的参数。清单 8-2 显示了您需要做出的更改。

    --- ./Pyboard/urtc.py    2017-07-20 19:20:38.000000000 -0400
    +++ ./WiPy/urtc.py    2017-04-21 16:52:32.000000000 -0400
    @@ -40,8 +40,8 @@
    
         def _register(self, register, buffer=None):
             if buffer is None:
    -            return self.i2c.mem_read(1, self.address, register)[0]
    -        self.i2c.mem_write(buffer, self.address, register)
    +            return self.i2c.readfrom_mem(self.address, register, 1)[0]
    +        self.i2c.writeto_mem(self.address, register, buffer)
    
         def _flag(self, register, mask, value=None):
             data = self._register(register)
    @@ -56,8 +56,8 @@
    
         def datetime(self, datetime=None):
             if datetime is None:
    -            buffer = self.i2c.mem_read(7, self.address,
    -                                           self._DATETIME_REGISTER)
    +            buffer = self.i2c.readfrom_mem(self.address,
    +                                           self._DATETIME_REGISTER, 7)
                 if self._SWAP_DAY_WEEKDAY:
                     day = buffer[3]
                     weekday = buffer[4]
    @@ -128,8 +128,8 @@
    
         def alarm_time(self, datetime=None, alarm=0):
             if datetime is None:
    -            buffer = self.i2c.mem_read(3, self.address,
    -                                           self._ALARM_REGISTERS[alarm])
    +            buffer = self.i2c.readfrom_mem(self.address,
    +                                           self._ALARM_REGISTERS[alarm], 3)
                 day = None
                 weekday = None
                 second = None
    @@ -145,8 +145,8 @@
                         if not buffer[1] & 0x80 else None)
                 if alarm == 0:
                     # handle seconds
    -                buffer = self.i2c.mem_read(1,
    -                    self.address, self._ALARM_REGISTERS[alarm] - 1)
    +                buffer = self.i2c.readfrom_mem(
    +                    self.address, self._ALARM_REGISTERS[alarm] - 1, 1)
                     second = (_bcd2bin(buffer[0] & 0x7f)
                               if not buffer[0] & 0x80 else None)
                 return datetime_tuple(
    @@ -219,8 +219,8 @@
    
         def alarm_time(self, datetime=None):
             if datetime is None:
    -            buffer = self.i2c.mem_read(4, self.address,
    -                                           self._ALARM_REGISTER)
    +            buffer = self.i2c.readfrom_mem(self.address,
    +                                           self._ALARM_REGISTER, 4)
                 return datetime_tuple(
                     weekday=_bcd2bin(buffer[3] &
                                      0x7f) if not buffer[3] & 0x80 else None,
    
    Listing 8-2.Changes for the urtc.py code module for the Pyboard (difference file)
    
    

    幸运的是,没有那么多你需要做的改变,所以做这些改变很容易也很快。如果你知道如何应用补丁的差异文件, 7 你可以这样做,所有的变化都会为你做。提示:您需要使用 patch 命令。否则,只需打开文件并手动进行更改。只需找到所有标有减号(-)的行,并更改它们以匹配带加号(+)的行。如果你复制粘贴,别忘了去掉加号。

    更改 Pyboard 的ssd1306.py

    有机发光二极管驱动程序也不能在 Pyboard 上正确运行。所需的改变是由于我们在 RTC 驱动中看到的 I2C 类函数的相同差异。您可能想知道,如果我们使用 SPI 接口,为什么需要进行这些更改。事实证明,该驱动程序既可用于 I2C 接口,也可用于 SPI 接口,由于 I2C 接口不同,因此仍需进行更改。如果我们不这样做,MicroPython 会抱怨,我们将无法使用该驱动程序。是的,即使我们不用那部分代码。这是因为 MicroPython 将检查导入的整个代码模块的语法。

    像 RTC 驱动程序一样,只需打开文件并进行更改。清单 8-3 显示了使 RTC 驱动程序兼容 WiPy 和 Pyboard 的差异文件。

    --- /Users/cbell/Downloads/Adafruit-uRTC-master_orig/urtc.py    2017-04-21 16:52:32.000000000 -0400
    +++ /Users/cbell/Downloads/Adafruit-uRTC-master/urtc.py         2017-07-20 19:20:38.000000000 -0400
    @@ -40,8 +40,8 @@
    
         def _register(self, register, buffer=None):
             if buffer is None:
    -            return self.i2c.readfrom_mem(self.address, register, 1)[0]
    -        self.i2c.writeto_mem(self.address, register, buffer)
    +            return self.i2c.mem_read(1, self.address, register)[0]
    +        self.i2c.mem_write(buffer, self.address, register)
    
         def _flag(self, register, mask, value=None):
             data = self._register(register)
    @@ -56,8 +56,8 @@
    
         def datetime(self, datetime=None):
             if datetime is None:
    -            buffer = self.i2c.readfrom_mem(self.address,
    -                                           self._DATETIME_REGISTER, 7)
    +            buffer = self.i2c.mem_read(7, self.address,
    +                                           self._DATETIME_REGISTER)
                 if self._SWAP_DAY_WEEKDAY:
                     day = buffer[3]
                     weekday = buffer[4]
    @@ -128,8 +128,8 @@
    
         def alarm_time(self, datetime=None, alarm=0):
             if datetime is None:
    -            buffer = self.i2c.readfrom_mem(self.address,
    -                                           self._ALARM_REGISTERS[alarm], 3)
    +            buffer = self.i2c.mem_read(3, self.address,
    +                                           self._ALARM_REGISTERS[alarm])
                 day = None
                 weekday = None
                 second = None
    @@ -145,8 +145,8 @@
                         if not buffer[1] & 0x80 else None)
                 if alarm == 0:
                     # handle seconds
    -                buffer = self.i2c.readfrom_mem(
    -                    self.address, self._ALARM_REGISTERS[alarm] - 1, 1)
    +                buffer = self.i2c.mem_read(1,
    +                    self.address, self._ALARM_REGISTERS[alarm] - 1)
                     second = (_bcd2bin(buffer[0] & 0x7f)
                               if not buffer[0] & 0x80 else None)
                 return datetime_tuple(
    @@ -219,8 +219,8 @@
    
         def alarm_time(self, datetime=None):
             if datetime is None:
    -            buffer = self.i2c.readfrom_mem(self.address,
    -                                           self._ALARM_REGISTER, 4)
    +            buffer = self.i2c.mem_read(4, self.address,
    +                                           self._ALARM_REGISTER)
                 return datetime_tuple(
                     weekday=_bcd2bin(buffer[3] &
                                      0x7f) if not buffer[3] & 0x80 else None,
    
    Listing 8-3.Changes for the ssd1306.py code module for the Pyboard (difference file)
    
    

    现在我们已经修改了库,可以在我们的板上工作了,让我们看看需要编写的代码。

    规划代码

    既然我们已经有了自己的设计,下载并修改了库,我们就可以开始编写代码了。与其给你看一个长长的清单,说“要么理解,要么毁灭”,不如让我们先浏览一下代码的所有部分,以便理解每一部分。在我们遍历代码的过程中,您可以自己测试各个部分,但是如果您愿意等到最后再测试代码,您也可以这样做。此外,当我们浏览代码时,我们将看到 WiPy 和 Pyboard 所需的差异。让我们从进口部分开始。

    进口

    项目的 imports 部分在所有其他语句之前,但在文件顶部的注释块之后。正如你在前面的例子和第四章中看到的,你应该在文件的顶部包含一些文档来解释代码的作用。你不需要写一个冗长的教程,只需要一个简短的陈述来描述这个项目,包括你的名字和其他信息。如果您希望与他人共享您的代码,并且如果您以后要重新使用这些代码,这是非常重要的。8

    如果您想在我们进行的过程中键入代码,您可以用您喜欢的代码(或文本)编辑器打开一个名为clock.py的新文件。回想一下,最好的编辑器是那些具有 Python 语法检查功能的编辑器,比如 Komodo Edit。

    WiPy 的进口不同于我们对 Pyboard 的需求;然而我们需要相同的库——我们只是从不同的地方导入它们。下面显示了 WiPy 的导入。这是两种板的三个不同之处之一。

    import urtc
    import utime
    from machine import SPI, I2C, RTC as rtc, Pin as pin
    from ssd1306 import SSD1306_SPI as ssd
    
    

    我们需要 Pyboard 的导入包括以下内容。注意我们需要很多库。您将看到我们导入了 Pyboard 库、RTC 库、ssd1306 库以及 I2C 和 SPI 类。还要注意的是,我为一些库使用了别名(“as XXXX”短语),以使键入更容易一些(键入的字符更少)。

    # Imports for the project
    import pyb
    import urtc
    from machine import SPI, Pin as pin
    from pyb import I2C
    from ssd1306 import SSD1306_SPI as ssd
    
    
    建立

    接下来,我们需要设置用于 RTC 和 ssd1306 库的 I2C 和 SPI 接口。也就是说,这些库中的类需要传递给构造函数的接口的对象实例。我们将使用的代码类似于我们在前面的例子中看到的代码。

    这是 WiPy 和 Pyboard 的另一个主要区别。下面显示了 WiPy 的接口设置代码。

    # Setup SPI and I2C
    spi = SPI(0, SPI.MASTER, baudrate=2000000, polarity=0, phase=0)
    
    

    i2c = I2C(0, I2C.MASTER, baudrate=100000, pins=("P9", "P8"))下图显示了 Pyboard 的 I2C 和 SPI 设置。

    spi = SPI(2, baudrate=8000000, polarity=0, phase=0)
    i2c = I2C(1, I2C.MASTER)
    i2c.init(I2C.MASTER, baudrate=500000)
    
    

    请注意,我们对 SPI 使用不同的参数,并为 I2C 指定引脚。我们必须为 I2C 接口指定引脚的原因是,SPI 和 WiPy 上的 I2C 共享时钟引脚。因此,我们必须手动指定用于 I2C 接口的引脚。如果您愿意,可以使用其他引脚,但在将组件连接在一起时,请记住使用正确的引脚。最后,注意我们不需要 WiPy 上的init()函数。

    初始化

    接下来,我们为库中的类初始化对象实例。此时,您需要阅读每个库的文档,以了解初始化对象所需的内容。对于 ssd1306 驱动程序,类构造函数需要显示器的像素数(分辨率是行、列中的像素数)、接口实例(上一节中的 SPI)以及我们将用于 D/C、RST 和 CS 引脚的引脚。对于 RTC 驱动程序,我们只需要传入接口实例(上一节的 I2C)。下面显示了如何为 WiPy 执行这两个步骤。

    # Setup the OLED : D/C, RST, CS
    oled_module = ssd(128,32,spi,pin('P5'),pin('P6'),pin('P7'))
    
    # Setup the RTC
    rtc_module = urtc.DS1307(i2c)
    
    

    Pyboard 的初始化代码非常相似。唯一的区别是我们指定的引脚。

    # Setup the OLED : D/C, RST, CS
    oled_module = ssd(128,32,spi,pin("Y4"),pin("Y3"),pin("Y5"))
    
    # Setup the RTC
    rtc_module = urtc.DS1307(i2c)
    
    

    还有一件事我们需要考虑。当我们第一次使用 RTC 或更换电池时,我们必须初始化日期和时间。我们可以使用驱动程序特性来做到这一点。在这种情况下,我们简单地调用 RTC 实例的datetime()函数,传递一个包含新开始日期和时间的元组——元组元素的顺序如下所示。一旦设置,我们不需要再次运行它。事实上,再次运行它将重置 RTC,我们不需要这样做。因此,对于正常操作,我们将这段代码注释掉,并在需要重置 RTC 时取消注释。下面显示了所需的代码。第一次运行项目时,取消对这段代码的注释,提供正确的当前日期和时间,但稍后将其注释掉。

    #       (year, month, day, weekday, hour, minute, second, millisecond)
    #start_datetime = (2017,07,20,4,9,0,0,0)
    #rtc_module.datetime(start_datetime)
    
    
    新功能

    现在所有的设置或 boiler plate 工作都完成了,我们可以创建一个新的函数来启动并运行我们的项目。也就是说,一旦导入代码模块,我们就可以调用这个函数。例如,我们将文件命名为clock.py,如果我们创建一个名为run()的函数,我们可以用下面的语句开始代码。当我们将项目部署到董事会时,我们将看到更多关于如何使用这些语句的内容。

    import clock
    clock.run()
    
    

    回想一下,我们希望该项目从 RTC 读取日期和时间,并在有机发光二极管上每秒显示一次。因此,我们期望看到某种执行这两个步骤的循环。但是,我们必须再次参考驱动程序文档,在那里我们发现 RTC 以元组(年、月、日、工作日、小时、分钟、秒、毫秒)的形式返回数据。这意味着我们必须格式化日期和时间,以使人们更容易阅读,并适应小有机发光二极管屏幕。

    这是一个或三个助手函数的完美候选。幸运的是,这两种板的这些功能是相同的,因此不需要预测任何变化。

    让我们创建一个名为write_time()的函数,它获取有机发光二极管显示器和 RTC 的一个实例,然后使用datetime()函数(不带参数)读取日期和时间,并使用text()函数将其打印到有机发光二极管屏幕上,该函数获取一个起始列(在文档中称为 X 位置)和一行(Y 位置)作为屏幕上的位置,以便在调用show()函数时打印消息。这是项目的精髓。将它放在一个单独的函数中,可以让您隔离行为,并使维护或修改代码变得更容易——因为“核心”在一个地方。

    # Display the date and time
    def write_time(oled, rtc):
        # Get datetime
        dt = rtc.datetime()
        # Print the date
        oled.text("Date: {0:02}/{1:02}/{2:04}".format(dt[1], dt[2], dt[0]), 0, 0)
        # Print the time
        oled.text("Time: {0:02}:{1:02}:{2:02}".format(dt[4], dt[5], dt[6]), 0, 10)
        # Print the day of the week
        oled.text("Day:  {0}".format(get_weekday(dt[3])), 0, 20)
        # Update the OLED
        oled.show()
    
    

    注意,我们使用print()函数和format()函数从 RTC 获取数据,并将其格式化为大多数时钟使用的预期格式:HH:MM::SSMM/DD/YYYY。注意这里有一个名为get_weekday()的附加函数。这个函数获取从 RTC 返回的一周中的第几天,并返回一个字符串作为这一天的名称。下面显示了该函数的代码。

    # Return a string to print the day of the week
    def get_weekday(day):
        if day == 1: return "Sunday"
        elif day == 2: return "Monday"
        elif day == 3: return "Tuesday"
        elif day == 4: return "Wednesday"
        elif day == 5: return "Thursday"
        elif day == 6: return "Friday"
        else: return "Saturday"
    
    

    增加了一个功能——清除屏幕的功能。该功能只是清空屏幕,让我们用新数据覆盖屏幕。通常这是不需要的,但是如果驱动程序没有为你清除屏幕,这是一个很好的实践。在这种情况下,现在确实如此。这个函数被命名为clear_screen(),如下所示。它只是使用 ssd1306 驱动程序中的fill()show()函数。为fill()函数传入 o 告诉驱动程序用无数据填充屏幕(空白或关闭)。

    # Clear the screen
    def clear_screen(oled):
        oled.fill(0)
        oled.show()
    
    

    现在我们准备为项目编写新的run()函数。我们已经开发了我们的助手函数,所以我们只需要调用它们,并在每次调用时等待一秒钟。下面显示了我们项目的run()函数。这是 Pyboard 与 WiPy 的最后一个不同之处。以下是 Pyboard 的代码。你能找出需要为 WiPy 改变的那一行吗?

    # Here, we make a "run" function to be used from the main.py
    # code module. This is preferable to direct "main" execution.
    def run():
        # Display the deate and time every second
        while True:
            clear_screen(oled_module)
            write_time(oled_module, rtc_module)
            pyb.delay(1000)
    
    

    注意这个函数有多“干净”——我们只能看到三个语句:清空屏幕,显示时间,等待一秒钟。需要为 WiPy 修改的那一行代码是最后一行。在 WiPy 上,我们使用不同的类,如下所示。

    utime.sleep(1)
    
    

    既然我们已经看到了代码各部分的完整演练,那么让我们来讨论一下代码的测试。

    测试代码的各个部分

    既然我们已经计划了代码,并且知道如何对每个部分进行编码,我们还有一件事要做——分别测试分线板。我们通过连接一个分线板并对其进行测试,然后断开该分线板的电源和布线,再连接另一个分线板并对其进行测试。

    出于一个主要原因,这是养成习惯的好习惯。通过一次一个地测试项目的各个部分——尤其是硬件——您将会省去很多麻烦。这不仅可以更容易地缩小问题范围,还可以确保您能够确定问题的根源。也就是说,如果您插上所有硬件,连接所有设备,编写代码,部署它,然后启动它,但没有任何东西工作,您如何知道是哪个部分出了问题?这是我的口头禅之一:一次构建并测试一个部分。

    Tip

    一次测试一部分代码对我来说是一种熟悉的模式,强烈建议您自己采用这个过程。也就是说,一次编写项目的一部分,并单独测试每一部分。

    对于这个项目,有两个部分 RTC 和有机发光二极管。让我们看看如何单独测试它们。我们将看到测试 Pyboard 组件的代码。您可以根据需要使用上面的信息修改代码,以便在您自己的板上工作。提供的代码旨在通过 REPL 控制台运行。我展示了 Pyboard 的代码,并将修改它以在 WiPy 上运行作为练习。提示:回头看看前面的部分,看看需要做哪些更改。

    测试 RTC 分线板

    要测试 RTC,使用下面的代码。这是我们在 Pyboard 演练中看到的代码的压缩形式。

    import urtc
    from pyb import I2C
    from machine import Pin as pin
    i2c = I2C(1, I2C.MASTER)
    i2c.init(I2C.MASTER, baudrate=500000)
    i2c.scan()
    rtc = urtc.DS1307(i2c)
    # year, month, day, weekday, hour, minute, second, millisecond)
    start_datetime = (2017,07,20,4,7,25,0,0)
    rtc.datetime(start_datetime)
    print(rtc.datetime())
    
    

    注意,我们在这个测试中设置了日期和时间。当您自己运行这个测试时,您应该更改日期和时间元组,以包含运行测试时的当前日期和时间。您应该在 REPL 控制台中看到一个表示日期和时间的元组。它应该与您设置的值相同,因为从您设置它到您查询 RTC 这段时间,代码的执行时间不到一秒钟。继续重新输入最后一条语句几次,以确保时间如您所料发生变化。也就是说,等待几秒钟,然后再试一次——应该已经过了几秒钟。

    如果任何陈述失败,请务必检查您的接线并查找任何打字错误。此外,请确保您使用的是正确的、经过修改的驱动程序版本(并且您已经将它们复制到主板上)。

    测试有机发光二极管分线板

    要测试有机发光二极管,请使用下面的代码。这是我们在演练中看到的代码的精简形式。

    import machine
    from machine import Pin as pin
    from ssd1306 import SSD1306_SPI as ssd
    spi = machine.SPI(2, baudrate=8000000, polarity=0, phase=0)
    oled = ssd(128,32,spi,pin("Y4"),pin("Y3"),pin("Y5"))
    oled.fill(0)
    oled.show()
    oled.fill(1)
    oled.show()
    oled.fill(0)
    oled.show()
    oled.text("Hello, World!", 0, 0)
    oled.show()
    
    

    当您运行这段代码时,您应该会看到屏幕空白(从一开始就应该是空白的),然后填充白色-参见fill(1)-然后空白屏幕,最后显示文本消息。如果看不到任何输出,请关闭主板电源,检查所有连接,验证是否使用了正确的引脚,以及是否将正确的驱动程序修改版本复制到主板上。

    Tip

    Adafruit 的有机发光二极管分线板(可能还有其他的)在镜头上有一个保护罩。你可以也应该把它留在原处,以确保镜头不会被损坏。此外,有机发光二极管足够亮,可以透过保护罩看到东西。

    现在,在我们将它部署到我们的 MicroPython 板上之前,让我们看看两个板的完整代码。

    完整代码

    在这一节中,我们将看到 WiPy 和 Pyboard 的完整代码。这些列表供您参考,以确保您拥有适合您的主板的正确代码。以后的项目将展示其中一个电路板的最终代码,并说明如何修改它以用于其他电路板。清单 8-4 显示了在 WiPy 上运行项目的完整代码。

    # MicroPython for the IOT - Chapter 8
    #
    # Project 1: A MicroPython Clock!
    #
    # Required Components:
    # - Pyboard
    # - OLED SPI display
    # - RTC I2C module
    #
    # Note: this only runs on the WiPy. See chapter text
    #       for how to modify this to run on the Pyboard
    #
    
    # Imports for the project
    import urtc
    import utime
    from machine import SPI, I2C, RTC as rtc, Pin as pin
    from ssd1306 import SSD1306_SPI as ssd
    
    # Setup SPI and I2C
    spi = SPI(0, SPI.MASTER, baudrate=2000000, polarity=0, phase=0)
    i2c = I2C(0, I2C.MASTER, baudrate=100000,pins=("P9", "P8"))
    
    # Setup the OLED : D/C, RST, CS
    oled_module = ssd(128,32,spi,pin('P5'),pin('P6'),pin('P7'))
    
    # Setup the RTC
    rtc_module = urtc.DS1307(i2c)
    #
    # NOTE: We only need to set the datetime once. Uncomment these
    #       lines only on the first run of a new RTC module or
    #       whenever you change the battery.
    #       (year, month, day, weekday, hour, minute, second, millisecond)
    #start_datetime = (2017,07,20,4,9,0,0,0)
    #rtc_module.datetime(start_datetime)
    
    # Clear the screen
    def clear_screen(oled):
        oled.fill(0)
        oled.show()
    
    # Return a string to print the day of the week
    def get_weekday(day):
        if day == 1: return "Sunday"
        elif day == 2: return "Monday"
        elif day == 3: return "Tuesday"
        elif day == 4: return "Wednesday"
        elif day == 5: return "Thursday"
        elif day == 6: return "Friday"
        else: return "Saturday"
    
    # Display the date and time
    def write_time(oled, rtc):
        # Get datetime
        dt = rtc.datetime()
        # Print the date
        oled.text("Date: {0:02}/{1:02}/{2:04}".format(dt[1], dt[2], dt[0]), 0, 0)
        # Print the time
        oled.text("Time: {0:02}:{1:02}:{2:02}".format(dt[4], dt[5], dt[6]), 0, 10)
        # Print the day of the week
        oled.text("Day:  {0}".format(get_weekday(dt[3])), 0, 20)
        # Update the OLED
        oled.show()
    
    # Here, we make a "run" function to be used from the main.py
    # code module. This is preferable to direct "main" execution.
    def run():
        # Display the deate and time every second
        while True:
            clear_screen(oled_module)
            write_time(oled_module, rtc_module)
            utime.sleep(1)
    
    Now, let’s see the completed code for the Pyboard. As mentioned, the changes are mostly in the imports and set up with one minor change in the run function. Listing 8-5 shows the complete code for running the project on the Pyboard.
    
    Listing 8-4.MicroPython Clock Code Module clock.py (WiPy)
    
    
    # MicroPython for the IOT - Chapter 8
    #
    # Project 1: A MicroPython Clock!
    #
    # Required Components:
    # - Pyboard
    # - OLED SPI display
    # - RTC I2C module
    #
    # Note: this only runs on the Pyboard. See chapter text
    #       for how to modify this to run on the WiPy
    #
    
    # Imports for the project
    import pyb
    import urtc
    from machine import SPI, Pin as pin
    from pyb import I2C
    from ssd1306 import SSD1306_SPI as ssd
    
    # Setup SPI and I2C
    spi = SPI(2, baudrate=8000000, polarity=0, phase=0)
    i2c = I2C(1, I2C.MASTER)
    i2c.init(I2C.MASTER, baudrate=500000)
    
    # Setup the OLED : D/C, RST, CS
    oled_module = ssd(128,32,spi,pin("Y4"),pin("Y3"),pin("Y5"))
    
    # Setup the RTC
    rtc_module = urtc.DS1307(i2c)
    #
    # NOTE: We only need to set the datetime once. Uncomment these
    #       lines only on the first run of a new RTC module or
    #       whenever you change the battery.
    #       (year, month, day, weekday, hour, minute, second, millisecond)
    #start_datetime = (2017,07,20,4,9,0,0,0)
    #rtc_module.datetime(start_datetime)
    
    # Clear the screen
    def clear_screen(oled):
        oled.fill(0)
        oled.show()
    
    # Return a string to print the day of the week
    def get_weekday(day):
        if day == 1: return "Sunday"
        elif day == 2: return "Monday"
        elif day == 3: return "Tuesday"
        elif day == 4: return "Wednesday"
        elif day == 5: return "Thursday"
        elif day == 6: return "Friday"
        else: return "Saturday"
    
    # Display the date and time
    def write_time(oled, rtc):
        # Get datetime
        dt = rtc.datetime()
        # Print the date
        oled.text("Date: {0:02}/{1:02}/{2:04}".format(dt[1], dt[2], dt[0]), 0, 0)
        # Print the time
        oled.text("Time: {0:02}:{1:02}:{2:02}".format(dt[4], dt[5], dt[6]), 0, 10)
        # Print the day of the week
        oled.text("Day:  {0}".format(get_weekday(dt[3])), 0, 20)
        # Update the OLED
        oled.show()
    
    # Here, we make a "run" function to be used from the main.py
    # code module. This is preferable to direct "main" execution.
    def run():
        # Display the deate and time every second
        while True:
            clear_screen(oled_module)
            write_time(oled_module, rtc_module)
            pyb.delay(1000)
    
    Listing 8-5.MicroPython Clock Code Module clock.py (Pyboard)
    
    

    好了,现在我们准备好执行这个项目了。

    执行!

    我们终于可以将所有文件复制到我们的板上并执行项目代码了。这个过程中有几个推荐的步骤,如下所示。每次您想要部署和测试项目时,您都应该遵循这个过程。

    1. 连接:仔细检查所有硬件连接
    2. 电源:主板上的电源
    3. 复制文件:将驱动程序和代码文件复制到板上
    4. 测试:使用 REPL 控制台测试代码,修复任何问题,并重新复制文件
    5. 执行:满意后,修改main.py然后重启板卡

    第一步怎么说都不为过。每次接通主板电源时,请务必检查您的连接。这是为了防止好奇的手经过并“检查”你的项目,或者你移动了它,或者发生了一些其他事件来拔掉电线。格外小心无妨。

    接下来,我们打开主板电源,检查是否有任何问题。没错,这就是冒烟测试!只需确保所有应该点亮的 led 都点亮(就像板上的那些),不应该点亮的都熄灭。例如,如果您在开机时看到有机发光二极管上有一个实心条,这不是一个好现象。如果有任何疑问,请拔掉电源并检查您的连接。如果事情仍然不对劲,断开所有连接并测试您的主板。有时损坏的组件会导致奇怪的行为。

    接下来,我们将所有想要使用的驱动程序和代码复制到板上。完成后,我们就可以测试代码了。因为我们使用了一个run()函数来包含主代码,所以我们可以简单地导入代码并如下调用该函数。

    >>> import clock
    >>> clock.run()
    
    

    现在启动您的主板,运行所示代码。您应该会看到类似图 8-5 的东西,它展示了项目运行的所有荣耀。

    A447395_1_En_8_Fig5_HTML.jpg

    图 8-5。

    A MicroPython Clock !

    在这一点上,您应该沐浴在您的第一个成功的 MicroPython 硬件项目的奇迹中。花些时间沉浸在出色完成工作的喜悦中。

    这个过程的最后一步是让您的项目在您打开评估板时默认运行。这是一个可选步骤,只有当您想让项目在每次上电时都运行时,才需要执行这个步骤。也就是说,您将在项目中使用该板一段时间。回想一下,板上的main.py代码模块将在启动时执行,因此您的项目将在板通电时执行。您需要做的就是将代码添加到该文件中,以启动您的项目,如下所示。现在就进行更改(您可以在以后撤消更改)。

    # main.py -- put your code here!
    import clock
    clock.run()
    
    

    现在是最后的测试:如果你修改了main.py文件,关掉你的主板,然后再打开。如果日期和时间在几秒钟后出现,您已经完成了!您已经成功地创建了一个项目,您可以打包并在任何您想要的地方运行,只要硬币电池有电,它就不会浪费时间。

    更进一步

    这个项目有很大的修饰潜力。如果你喜欢这个项目,你应该考虑花时间探索一些修饰。这里有一些你可以考虑的。有些很容易,有些可能是一个挑战。

  • 使用不同的 RTC
  • 计算 AM/PM 并显示
  • 将您的主板连接到互联网,并使用 NTP 服务而不是 RTC
  • 使用更大的显示器并显示儒略日
  • 在阳光直射的情况下,使用光传感器关闭或调暗显示器
  • 添加一个扬声器并实现一个警报功能(提示:一些 RTC 有这个功能)
  • 使用不同的世界标准格式化日期和时间,例如 YYYY/MM/DD
  • 当然,如果你想继续下一个项目,欢迎你这样做,但是花些时间探索这些潜在的修饰——这将是一个很好的实践。

    既然我们已经解决了库的问题,如果你认为这个项目是初级的,考虑一下这个:大多数基于传感器的项目,事实上大多数生成数据的项目必须与事件采样的日期和时间相关联。因此,使用 RTC 读取日期和时间将是许多 IOT 项目的考虑因素。

    Building Your Own RTC Module

    如果你像我一样,喜欢修补,你可以使用 RTC DS1307 芯片、两个电阻、一个晶体和一个硬币电池分线板来构建自己的 RTC 模块。你可以在 Adafruit ( www.adafruit.com )、Sparkfun ( www.sparkfun.co m )、Mouser ( www.mouser.com )等大多数网上电子商店找到这些组件。组件列表如下。

  • DS1307 芯片
  • 纽扣电池分线板
  • 3v 纽扣电池
  • 32.768 千赫晶体
  • (2) 1K 电阻器
  • 就这样!下图显示了如何连接试验板上的元件。如果你想实现这个侧边项目,参见 http://www.learningaboutelectronics.com/Articles/DS1307-real-time-clock-RTC-circuit.php 的示例演练。

    A447395_1_En_8_Figa_HTML.jpg

    如果您计划构建大量使用 RTC 的项目,批量购买这些组件并连接您自己的 RTC 1307 模块可能更具成本效益。此外,它增加了你的工具包的酷的因素。

    摘要

    使用分线板等硬件以及我们需要通过 I2C 和 SPI 等专用接口与之对话的驱动程序可能是一项挑战。有时候,就像我们在本章中看到的,你需要修改一个驱动程序来使用你的 MicroPython 板。其原因是由于主板阵列的不断增长,供应商正在创建专门版本的 MicroPython 固件用于这些主板。在某些情况下,比如 ssd1306 驱动程序,我们只需做一些小改动,就可以在我们的电路板上使用该驱动程序。诀窍是理解为什么改变是必要的,并花时间自己去改变。当事情不成功时,放弃是很容易的——不要这样做!慢慢来,了解问题,然后系统解决。

    在本章中,我们看到了一个 MicroPython 时钟的详细演练。我们使用有机发光二极管显示器来显示我们从 RTC 读取的时间。在这个过程中,我们学习了如何规划项目、建立硬件连接,以及编写用于在我们的 MicroPython 板上部署的代码。

    在下一章中,我们将探索一个项目,该项目使用 led、电阻和按钮等分立元件形式的更多低级硬件。这些是构建更复杂的解决方案所需的构件。

    Footnotes 1

    https://en.wikipedia.org/wiki/OLED

    2

    是的,我是那些喜欢印刷材料的触觉传感器印象的人之一。此外,你几乎可以在任何包或口袋里放一小叠文件。

    3

    这就是为什么我只使用那些写得很好并且有完整例子的参考文献。试图猜测一个驱动作者的想法是不值得花费时间和精力的。

    4

    猜猜我是怎么知道的。有时候打破东西是最好的学习方式。

    5

    我想其他工程师可能会说你应该先写代码,但我的看法正好相反。

    6

    https://en.wikipedia.org/wiki/Diff_utility

    7

    [T0](https://en.wikipedia.org/wiki/Patch_(Unix)

    8

    我有时发现自己想知道是谁写了一段代码,却发现是我!记录或“签署”代码可以帮助你记住你写了什么和为什么写。

    作者:绝不原创的飞龙

    物联沃分享整理
    物联沃-IOTWORD物联网 » MicroPython物联网进阶教程(三)

    发表回复