基于Raspberry Pi 5的蜂窝物联网项目

描述

今天小拜年给大家带来的是来自美国的Maker Rob Lauer的基于树莓派5的蜂窝网络项目,了解如何为新的 Raspberry Pi 5 单板计算机添加低带宽蜂窝连接。

 

材料清单

硬件列表

Raspberry Pi 5(这也适用于Pi 4或Pi Zero 1或2)

Raspberry Pi 摄像头模块 v2

蓝调记事卡手机+WiFi

Blues Notecarrier Pi 帽子

Adafruit BME280 温度/压力/湿度传感器

软件列表

Datacake

Blues Notehub.io

现在几乎成为一年一度的传统,我们在 Raspberry Pi 的朋友发布了我们都知道和喜爱的单板计算机的最新型号 Raspberry Pi 5。

 

Pi 5采用新的电路板布局、更好的性能和新的接口,是一款令人兴奋的产品。Pi 上还有一个实时时钟,可以将你的 Pi 从睡眠模式中唤醒——而且它是可编程的——这使得在电池供电的边缘部署中使用 Pi 稍微逼真一些。

不过我最喜欢的功能是什么?电源按钮!

 

虽然我们在 Pi 上执行的绝大多数工作都在访问家庭/办公室 Wi-Fi 范围内,但我们中有很多人在远程环境中使用 Pi(如果您愿意的话,在前面提到的“边缘”)。

在这些情况下,访问 Wi-Fi 很困难或不可能,唯一有效的连接选项往往是蜂窝(太贵!)或 LoRaWAN(太罕见!)。 嗯,怎么办!?

Blues Notecard 的出现为围绕低功耗和低带宽连接场景而设计,提供了一种简单(但功能强大)的方法,可通过预付费蜂窝网络、Wi-Fi 或 LoRa 将无线连接添加到几乎任何物理设备(是的,包括 Pi)。

RaspberryPi

在Raspberry Pi 5 上准备蜂窝网络    

在这个项目中,我将创建一个 Python 应用程序,它既充当人员计数器,又充当温度/压力/湿度跟踪器。我们将使用 Blues Notecard 将数据与云同步。然后,我们可以使用 Datacake 平台生成路由数据的基于云的仪表板。

应用工作流如下所示:

使用 Pi 的摄像头和 OpenCV 检测人脸。   

记录检测到的人脸数量。

每分钟将人脸计数以及温度/压力/湿度数据发送到云端。

在基于云的仪表板上显示累积数据的报告。

这是一个就简单的项目,但它也展示了收集数据、通过蜂窝网络将其发送到云以及创建仪表板来查看累积数据是多么容易:

RaspberryPi

项目硬件

对于这个项目,我将使用以下硬件:

Raspberry Pi 5(这也适用于Pi 4或Pi Zero 1或2)

Raspberry Pi 摄像头模块 v2

蓝调记事卡手机+WiFi

Blues Notecarrier Pi 帽子

Adafruit BME280 温度/压力/湿度传感器

不涉及任何接线,因为 Notecard 插入 Notecarrier Pi Hat,而 BME280 通过提供的 Qwiic 端口之一连接到 Notecarrier:   

RaspberryPi

带有记事卡的蜂窝网络(或 Wi-Fi 或 LoRa)

Notecard 是这个项目的理想选择,因为它是用来发送和接收小数据包的 JSON 数据包( 在 Blues 术语中称为 Notes)。这非常适合边缘机器学习等方案,在这些方案中,处理是在设备上完成的,唯一需要中继到云的数据是包含生成的推理的小型有效负载。同样,记事卡可以处理从物理世界收集传感器数据并需要每小时、每天、每周一次等提供一次数据的情况。

需要明确的是,Blues Notecard 并不是 Raspberry Pi 上 Wi-Fi 的直接替代品。它专为低带宽数据传输而设计,因此您不会在无人区中浏览网页。

您为记事卡支付一次性费用,它附带 500MB 的数据和 10 年的全球蜂窝服务。没有每月的SIM卡费用或订阅。

还有 Wi-Fi 和 LoRa 选项(相同的开发人员 API,相同的硬件占用空间):   

RaspberryPi

记事卡“正常工作”,因为:

它与名为 Notehub 的云服务安全配对(自动)。 无需认证管理或设备配置。

告诉记事卡它应该连接到哪个 Notehub 项目。

通过两行代码(基于 JSON 的 API 调用),您可以将 Pi 连接到云:

 

1. {"req":"hub.set","product":"com.blues.me:product","mode":"periodic"}
2. {"req":"note.add","body":{"temperature":21.3,"humidity":65.4}}

 

说了这么多,让我们开始这个项目吧!

在安装库和测试相机

我们的项目从 note-python 开始,这是 Blues 支持的 SDK,用于通过 Python 处理记事卡。在 Pi 终端上使用以下命令进行安装:note-python

 

pip3 install note-python

 

接下来安装一些其他 Python 库,包括(用于通过 I2C 与外围设备通信)、(我们将用于面部识别)和( 与 BME280 交互)。python-peripheryopencv-pythonpimoroni-bme280

接下来,使用此命令测试您的相机是否正常运行(您应该看到相机的输入出现在 Pi 桌面上):

 

libcamera-hello –camera 0 -t 0

 

RaspberryPi

都好吗?让我们开始编写一些代码!

Python 代码

仅供参考,完整的 Python 代码可以在(https://gist.github.com/rdlauer/8cecc03e1f44fe5643f50d42b06a9467)中找到

首先包含相关依赖项:

 

#!/usr/bin/python3
import notecard
from notecard import hub
from periphery import I2C
import cv2
import keys
import time
from picamera2 import Picamera2
from smbus2 import SMBus
from bme280 import BME280

 

通过 I2C 总线连接到记事卡,并在 Notehub 上为您的云项目的唯一标识符(例如)添加一个占位符:productUID

 

# init the notecard
productUID = keys.NOTEHUB_PRODUCT_UID
port = I2C("/dev/i2c-1")
nCard = notecard.OpenI2C(port, 0, 0)

 

Notehub 在这里非常有价值,因为它不仅可以充当 Notecard 发送数据的安全云代理,还可以让您快速将数据路由到您的云应用程序(例如 AWS、Azure、Datacake、Ubidots 等)。它可免费用于大多数项目。

将记事卡与您的免费 Notehub 项目链接,并将记事卡的蜂窝调制解调器置于 模式。continuous

这告诉记事卡保持连续的蜂窝连接(这对演示有好处,但对电池寿命不利,这就是为什么记事卡默认为 仅定期发送数据并节省电量的原因):periodic

 

# connect notecard to notehub
rsp = hub.set(nCard, product=productUID, mode="continuous")
print(rsp)

 

初始化 BME280 传感器:

 

# init the BME280
bus = SMBus(1)
bme280 = BME280(i2c_dev=bus, i2c_addr=0x77)

 

接下来,需要从此 GitHub 存储库下载相应的“正面”预训练分类器。我们将使用 OpenCV 来检测图像并将其分类为人脸。此 XML 文件需要保存到您的 Pi 的可访问目录中。

加载分类器 XML 文件并初始化 Pi 相机:

 

# Grab images as numpy arrays and leave everything else to OpenCV.
face_detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
cv2.startWindowThread()
           
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration(main={"format": 'XRGB8888', "size": (640, 480)}))
picam2.start()

 

添加一些变量,用于跟踪检测到的人脸计数以及用于将数据发送到云的时间戳:

 

# keep track of face counts between notes    
face_count = 0
# keep track of seconds for adding faces/syncing
start_secs_face = int(round(time.time()))
start_secs_note = int(round(time.time()))

 

接下来,定义一个函数,该函数将向 Notehub(也称为事件)发送注释。“Note”是围绕任何任意 JSON 有效负载(布尔值、字符串、整数等)的 JSON 修饰:

def send_note(c):

 

   # query the notecard for power supply voltage
    req = {"req": "card.voltage", "mode": "?"}
    rsp = nCard.Transaction(req)
    voltage = rsp["value"]
  
    # get the temp/pressure/humidity from bme280
    temperature = bme280.get_temperature()
    pressure = bme280.get_pressure()
    humidity = bme280.get_humidity()
           
    req = {"req": "note.add"}
    req["file"] = "face.qo"
    req["body"] = {"face_count": c, "voltage": voltage, "temperature": temperature, "pressure": pressure, "humidity": humidity}
    req["sync"] = True
    rsp = nCard.Transaction(req)
           
    print(rsp)

 

最后,启动一个无限循环,并在该循环中:

尝试对人脸进行分类(同时绘制边框并向识别的人脸添加一些标签)。

如果检测到人脸,则递增变量 。face_count

最后,如果一分钟过去了,请执行上述 函数将此数据发送到云端!send_note

 

while True:
    # track the current time
    current_seconds = int(round(time.time()))
  
    im = picam2.capture_array()
               
    grey = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    faces = face_detector.detectMultiScale(grey, 1.1, 5)
           
    # Add text around each face
    font = cv2.FONT_HERSHEY_DUPLEX
    fontScale = 1
    color = (0, 0, 255)
    thickness = 2
  
    # Draw the rectangle around each face
    for (x, y, w, h) in faces:
        cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0))
        face_plural = 's'
        if face_count == 1:
            face_plural = ''
        cv2.putText(im, 'Face found!', (x, y-10), font,
                   fontScale, color, thickness, cv2.LINE_AA)
           
    cv2.imshow("Camera", im)
  
    if len(faces) > 0:
        # check to make sure it's been at least three seconds since the last time we checked for faces
        if current_seconds - start_secs_face >= 3:
            face_count += len(faces)
            print("We found some faces: " + str(len(faces)) + " to be exact! (Pending sync: " + str(face_count) + " faces)")
            start_secs_face = int(round(time.time()))
  
    # create an outbound note every 5 minutes with accumulated face counts
    if current_seconds - start_secs_note >= 60:
        send_note(face_count)
        print("####################")
        print("Sending a new note with " + str(face_count) + " faces.")
        print("####################")
        face_count = 0
        start_secs_note = int(round(time.time()))
  
    cv2.waitKey(1)

 

就是这样!

运行 Python 应用程序,您应该会看到相机窗口出现,开始将数据保存到记事卡上的闪光灯,并立即将该数据同步到 Notehub:   

 

We found some faces: 1 to be exact! (Pending sync: 1 faces)
We found some faces: 1 to be exact! (Pending sync: 2 faces)
We found some faces: 1 to be exact! (Pending sync: 3 faces)
We found some faces: 1 to be exact! (Pending sync: 4 faces)
We found some faces: 1 to be exact! (Pending sync: 5 faces)
We found some faces: 1 to be exact! (Pending sync: 6 faces)
We found some faces: 1 to be exact! (Pending sync: 7 faces)
{'template': True}
####################
Sending a new note with 7 faces.
####################

 

提醒:完整的 Python 代码可以在face-detect.py · GitHub上的这个要点中找到。

Notehub 到云

当项目处于当前状态时,记事卡将在数据进入时立即开始与 Notehub 同步数据(每分钟一次)。您将看到这些注释(或事件)显示在项目的“事件 ”选项卡中:

RaspberryPi

虽然看到这些数据出现很酷,但它并不是那么有用。让我们添加一个快速集成,以使用 Notehub Routes 和 Datacake 构建基于云的仪表板。

Notehub 支持通过 HTTPS 和 MQTT 协议将数据路由到几乎任何托管云服务。 Blues 提供路由教程,引导您完成流程中的每一步。将数据路由到 Datacake

Datacake 是一个低代码平台,可让您在最短的时间内构建 IoT 应用程序(正如我们今天将在这里看到的那样)。   

现在,如果您查看发送到 Notehub 的事件之一并查看 JSON 选项卡,您将看到可以路由到 Datacake 的大量数据:

 

{
    "event": "1ab42897-17c6-4877-b902-c2ee1c1c7e96",
    "session": "e889f105-226d-45f6-a3cc-d8028a655326",
    "best_id": "dev:860322068073292",
    "device": "dev:860322068073292",
    "product": "productfaceml",
    "app": "app:0c85569f-5cd8-4d84-9548-eab244c57f59",
    "received": 1701718035.34947,
    "req": "note.add",
    "when": 1701718034,
    "file": "face.qo",
    "body": {
        "face_count": 8,
        "humidity": 27.78125,
        "pressure": 983.5,
        "temperature": 24.5,
        "voltage": 5.171875
    },
    "best_location_type": "triangulated",
    "best_location_when": 1701462279,
    "best_lat": 43.071243,
    "best_lon": -89.43282,
    "best_location": "Shorewood Hills WI",
    "best_country": "US",
    "best_timezone": "America/Chicago",
    "tri_when": 1701462279,
    "tri_lat": 43.071243,
    "tri_lon": -89.43282,
    "tri_location": "Shorewood Hills WI",
    "tri_country": "US",
    "tri_timezone": "America/Chicago",
    "tri_points": 3,
    "status": "success",
    "fleets": [
        "fleet:664b55a8-d3c0-4e76-8588-90e8fef53d20"
    ]
}

 

我们希望将此数据路由到 Datacake,但我们唯一关心的值是temperature 、 pressure 、 humidity 、 voltage 和 face_count 。

创建Datacake路由

与其重新发明轮子,不如前往 blues.dev 上的完整 Datacake 教程来完成路由的初始创建。来吧,我发誓不会花太长时间!

我们需要对 Datacake 中的字段和有效负载解码器设置的配置进行一些编辑。

在 Datacake 中添加字段

由于我们要向 Datacake 发送上述 temperature 、 pressure 、humidity 、 voltage 和 face_count变量,因此我们需要确保 Datacake 知道预期它们。

导航到 Datacake 中设备配置的“字段”部分。确保这些值与此处显示的值一致(如果您有其他字段,那很好,它们将被仪表板忽略):

RaspberryPi

在 Datacake 中更新 HTTP 有效负载解码器

Datacake 有一个“有效负载解码器”,它将使用您从 Notehub 发送的 JSON 有效负载,然后将该数据调整为在仪表板中表示它所需的格式。

我将为您省去一个步骤,并为您提供我使用的完整有效负载解码器代码:

 

function Decoder(request) {
   
    var data = JSON.parse(request.body);
    var device = data.device;
        
    var file = data.file;
   
    var decoded = {};
   
    decoded.voltage = data.body.voltage;
    decoded.temperature = data.body.temperature;
    decoded.humidity = data.body.humidity;
    decoded.pressure = data.body.pressure;
    decoded.face_count = data.body.face_count;
   
    if (("best_lat" in data) && ("best_lon" in data)) {
        decoded.device_location = "(" + data.best_lat + "," + data.best_lon + ")";
    }
   
    decoded.rssi = data.rssi;
    decoded.bars = data.bars;
   
    // Array where we store the fields that are being sent to Datacake
    var datacakeFields = []
   
    // take each field from decodedElsysFields and convert them to Datacake format
    for (var key in decoded) {
        if (decoded.hasOwnProperty(key)) {          
            datacakeFields.push({field: key.toUpperCase(), value: decoded[key], device: device})
        }
    }     
   
    // forward data to Datacake
    return datacakeFields;
}

 

创建 Datacake 仪表板

接下来,导航到 Datacake 中的“仪表板”选项卡。使用它们提供的 GUI 工具将适当的小部件添加到图表值,如温度、压力、检测到的人脸数量等。   

RaspberryPi

总而言之,您应该拥有一个华丽的基于云的仪表板!

RaspberryPi

下一步是什么?

希望您已经看到向 Raspberry Pi 添加低带宽蜂窝连接是多么容易。需要注意的是,Notecard 还支持几乎所有现代主机 MCU(如 STM32、ESP32、Nordic 等)。您可以使用Blues Starter Kit开始使用STM32主机。

不过,更有可能的是,您正在寻找 Blues Notecarrier Pi 帽子和任何记事卡,以开始在 Pi 上使用蜂窝网络。

 

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分