今天小拜年给大家带来的是来自美国的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)。
在Raspberry Pi 5 上准备蜂窝网络
在这个项目中,我将创建一个 Python 应用程序,它既充当人员计数器,又充当温度/压力/湿度跟踪器。我们将使用 Blues Notecard 将数据与云同步。然后,我们可以使用 Datacake 平台生成路由数据的基于云的仪表板。
应用工作流如下所示:
使用 Pi 的摄像头和 OpenCV 检测人脸。
记录检测到的人脸数量。
每分钟将人脸计数以及温度/压力/湿度数据发送到云端。
在基于云的仪表板上显示累积数据的报告。
这是一个就简单的项目,但它也展示了收集数据、通过蜂窝网络将其发送到云以及创建仪表板来查看累积数据是多么容易:
项目硬件
对于这个项目,我将使用以下硬件:
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:
带有记事卡的蜂窝网络(或 Wi-Fi 或 LoRa)
Notecard 是这个项目的理想选择,因为它是用来发送和接收小数据包的 JSON 数据包( 在 Blues 术语中称为 Notes)。这非常适合边缘机器学习等方案,在这些方案中,处理是在设备上完成的,唯一需要中继到云的数据是包含生成的推理的小型有效负载。同样,记事卡可以处理从物理世界收集传感器数据并需要每小时、每天、每周一次等提供一次数据的情况。
需要明确的是,Blues Notecard 并不是 Raspberry Pi 上 Wi-Fi 的直接替代品。它专为低带宽数据传输而设计,因此您不会在无人区中浏览网页。
您为记事卡支付一次性费用,它附带 500MB 的数据和 10 年的全球蜂窝服务。没有每月的SIM卡费用或订阅。
还有 Wi-Fi 和 LoRa 选项(相同的开发人员 API,相同的硬件占用空间):
记事卡“正常工作”,因为:
它与名为 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
都好吗?让我们开始编写一些代码!
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 同步数据(每分钟一次)。您将看到这些注释(或事件)显示在项目的“事件 ”选项卡中:
虽然看到这些数据出现很酷,但它并不是那么有用。让我们添加一个快速集成,以使用 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 中设备配置的“字段”部分。确保这些值与此处显示的值一致(如果您有其他字段,那很好,它们将被仪表板忽略):
在 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 工具将适当的小部件添加到图表值,如温度、压力、检测到的人脸数量等。
总而言之,您应该拥有一个华丽的基于云的仪表板!
下一步是什么?
希望您已经看到向 Raspberry Pi 添加低带宽蜂窝连接是多么容易。需要注意的是,Notecard 还支持几乎所有现代主机 MCU(如 STM32、ESP32、Nordic 等)。您可以使用Blues Starter Kit开始使用STM32主机。
不过,更有可能的是,您正在寻找 Blues Notecarrier Pi 帽子和任何记事卡,以开始在 Pi 上使用蜂窝网络。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !