Skip to main content

作为传感器使用 & 使用 Grove


在本 wiki 中,我们将探索当 Watcher 作为传感器使用时,利用其 UART(通用异步收发器)功能所带来的令人兴奋的可能性。通过启用 UART 通信,Watcher 可以通过位于设备背面的 UART 接口传输有价值的数据,如捕获的图像和识别结果。这为将 Watcher 与各种硬件平台集成并创建创新应用程序开辟了无限可能。

在本 wiki 中,我们将深入了解从 Watcher 的 UART 接口读取和解释数据输出的详细信息。此外,我们还将提供关于如何使用流行的开发板和平台(包括 XIAO、Arduino、Raspberry Pi 和 Jetson)解析和利用这些数据的全面教程。

SenseCAP Watcher 高级配置

SenseCAP Watcher 是首个用于智能场所的物理 LLM 代理,能够监控场景、触发动作并基于命令进行交互。本视频将介绍 SenseCAP Watcher 如何基于任务分析选择场景触发模型:设备端模型和 LLM 模型。我们还将展示如何配置 RGB 灯和显示&声音警报,以及通知推送模式:APP、UART、HTTP。

Watcher UART 接线

当您准备使用 UART 进行消息警报时,请按以下方式将 Watcher 连接到您的 MCU。

note

请注意,如果您的 Watcher 和 MCU 是分别供电的,那么您不需要连接 Watcher 和 MCU 的 3.3V 或 5V 引脚。

如果您计划使用 Watcher 为 MCU 供电,那么您可以在图中接线的基础上使用 3.3V 为 MCU 供电。(不要使用 5V 引脚,它们仅用于输入)

如果您计划使用 MCU 为 Watcher 供电,那么您需要使用 5V 输入。(3.3V 可能不足以让 Watcher 正常工作)

在 Watcher 中启用 UART 功能

要充分发挥 Watcher 的 UART 功能潜力,我们首先需要在设备中启用 UART 功能。这在将 Watcher 用作报警系统的场景中特别有用。当触发报警时,Watcher 可以激活其 UART 通信,允许它将关键信息(如捕获的图像和识别结果)传输到外部设备进行进一步处理和分析。

要启用 UART 报警功能,您有两个选项:

  1. 在使用 SenseCraft APP 分配任务时,明确请求 Watcher 通过 UART 通知您。
  1. 在任务的详细设置中手动启用 UART 报警功能:

    • 访问您要配置的任务的详细配置
    • 找到动作部分。
    • 勾选复选框以启用串口 / UART 输出

tip

请根据您的实际应用场景选择是否需要启用图像输出。如果启用了包含 base64 图像,那么您的 MCU 需要至少 70k 内存来缓存图像。

一旦您使用上述任一方法启用了 UART 报警功能,Watcher 将在检测到指定的报警内容时通过 UART 输出必要的报警信息。确保 Watcher 连接到适当的接收设备,如微控制器或带有串行终端的计算机,以捕获和处理通过 UART 传输的报警信息。

读取 Watcher 的 UART 输出

一旦启用了 UART 功能,Watcher 将开始通过其 UART 接口传输数据。在本节中,我们将提供详细的指南,说明如何读取和解释从 Watcher 的 UART 输出接收到的数据。我们将涵盖必要的硬件连接、通信协议和数据格式,以确保顺利成功的数据检索过程。

默认情况下,Watcher 使用以下 UART 配置:波特率为 1152008 数据位无奇偶校验1 停止位,以及无硬件流控制。当连接到 Watcher 的 UART 接口时,确保您的接收设备配置了相同的设置以确保正确通信。

当 Watcher 通过 UART 发送报警信息时,它遵循基于 tf_module_uart_alarm.h 头文件中定义的 tf_module_uart_alarm_t 结构的特定协议和格式。Watcher 的 UART 报警模块的 UART 协议和格式如下:

输出格式

UART 输出的格式由 output_format 字段控制。

  • output_format 设置为 0 时,输出为二进制格式。
  • output_format 设置为 1 时,输出为 JSON 格式。
note

output_format 默认设置为 1 以 JSON 格式输出。

二进制输出格式

output_format 设置为 0 时,UART 输出数据包的结构如下:



  • PKT_MAGIC_HEADER:数据包的魔术头,固定为 "SEEED"(5 字节)。
  • Prompt Str Len:提示字符串的长度,4 字节无符号整数,小端序。
  • Prompt Str:提示字符串,用于简要说明 Watcher 正在执行的任务。如果设置了 text 参数,则使用其值。
  • Big Image Len:大图像的长度,4 字节无符号整数,小端序。仅在 include_big_imagetrue 时包含。
  • Big Image:640*480 JPG 图像,base64 编码,不包含检测到的对象框。仅在 include_big_imagetrue 时包含。
  • Small Image Len:小图像的长度,4 字节无符号整数,小端序。仅在 include_small_imagetrue 时包含。
  • Small Image:240*240 JPG 图像,base64 编码,为检测到的对象绘制了框。仅在 include_small_imagetrue 时包含。
  • Boxes Count:检测到的对象框数量,4 字节无符号整数,小端序。仅在 include_boxestrue 时包含。
  • Box Structure:检测到的对象框的结构,每个框占用 10 字节,包括坐标、分数和目标类别 ID。仅在 include_boxestrue 时包含。
note

目前不会收到识别框(boxes)消息,因为 Watcher 的相应功能仍在开发中,尚未在最新的 v1.1 版本中报告。

JSON 输出格式

output_format 设置为 1 时,UART 输出数据包的结构如下:

{
"prompt": "People detected",
"big_image": "base64 encoded JPG image, if include_big_image is enabled, otherwise this field is omitted",
"inference":{
"boxes": [
{
"x": 100,
"y": 100,
"w": 50,
"h": 60,
"score": 0.8,
"target_cls_id": 1
}
],
"classes_name": ["person"]
},

}

其中,(x,y) 是识别对象的中心点位置,(w,h) 是识别框的高度和宽度,如下图所示。score 是置信度,target_cls_id 是识别对象的id。

配置选项

  • output_format:控制UART输出的格式,默认为1(JSON格式)。
  • text:用于填充输出数据包的prompt字段。
  • include_big_image:布尔值(true | false),控制输出中是否包含大图像,默认为true
  • include_boxes:布尔值(true | false),控制输出中是否包含框,默认为true

注意:如果省略任何配置字段,将使用默认值。

note

此时将不会收到识别框(boxes)消息,因为Watcher的相应功能仍在开发中,尚未在最新的v1.1版本中报告。

XIAO ESP32系列 & Watcher

学习如何将Watcher连接到XIAO ESP32系列开发板并使用Arduino解析UART数据。本节将指导您如何将Watcher连接到XIAO ESP32系列开发板并使用Arduino解析UART数据。

接线

本教程支持以下XIAO系列:

tip

这并不意味着不支持其他XIAO系列。主要是因为Watcher报告的消息数据占用大约100k(至少70k)的内存,我们建议您使用ESP32系列的XIAO进行Watcher的UART部分开发。如果您不需要解析图像数据,那么其他XIAO的内存是完全足够的。



  • 将Watcher的TX引脚连接到XIAO的UART接口的RX引脚。

  • 将Watcher的RX引脚连接到XIAO的UART接口的TX引脚。

  • 将Watcher的GND引脚连接到XIAO的GND引脚。

代码说明

您可以使用任何XIAO ESP32系列开发板,或任何其他ESP32系列开发板来使用以下程序读取Watcher的UART数据流。

note

目前只能输出JSON数据流,因此只提供解析JSON数据流的程序。

其他XIAO并不总是受支持,主要是因为解析JSON流至少需要70k的内存。

#include <ArduinoJson.h>

long int count = 0; // 报警次数

void setup() {
Serial.begin(115200);
Serial1.begin(115200, SERIAL_8N1, D7, D6); // RX, TX
while(!Serial);
delay(100);

Serial.println("设备就绪。等待 Watcher 的 JSON 数据...");
}

void loop() {
if (Serial1.available()) {
// 设置足够的空间来存储解析的 JSON 对象
const size_t capacity = 1024 * 100 + 512; // 至少 70k,保险起见 100k
DynamicJsonDocument doc(capacity);

// 从 Serial1 流式解析
DeserializationError error = deserializeJson(doc, Serial1);

if (error) {
Serial.print("deserializeJson() 失败: ");
Serial.println(error.c_str());
return;
}

// 打印解析的键值对
if (doc.containsKey("prompt")) {
Serial.print("prompt: ");
Serial.println(doc["prompt"].as<String>());
}

if (doc.containsKey("inference")) {
Serial.print("inference: ");
Serial.println(doc["inference"].as<String>());
}

if (doc.containsKey("inference")) {
JsonArray boxes = doc["inference"]["boxes"][0].as<JsonArray>();
Serial.println();
Serial.println("您可以获取框内的数字。");
Serial.print("Box -> ");
Serial.print("x: ");
Serial.print(boxes[0].as<int>());
Serial.print(", y: ");
Serial.print(boxes[1].as<int>());
Serial.print(", widths: ");
Serial.print(boxes[2].as<int>());
Serial.print(", height: ");
Serial.print(boxes[3].as<int>());
Serial.print(", score: ");
Serial.print(boxes[4].as<int>());
Serial.print(", target_cls_id: ");
Serial.println(boxes[5].as<int>());
}

// 您需要在应用中打开"包含 base64 图像"按钮,默认是关闭的。
// 然后,取消注释以下代码。
/*
if (doc.containsKey("big_image")) {
Serial.print("big_image: ");
String big_imageData = doc["big_image"].as<String>();
// 例如,仅打印图像数据的前 100 个字符
Serial.println(big_imageData.substring(0, 100) + "...");
}
*/


count++;
if(count > 2147483646){ // 防止溢出
count = 0;
}
Serial.print("第 ");
Serial.print(count);
Serial.println(" 次报警消息接收完成。等待下一条消息...");
Serial.println("------------------------------------------------------------------");
}
}

提供的代码演示了如何使用 Arduino IDE 和 ArduinoJson 库从 Watcher 接收和解析 JSON 数据。以下是代码的简要说明:

  1. 包含了必要的库 ArduinoJson 来处理 JSON 解析。您可以在 Arduino 的库管理器中搜索并安装它。
  1. setup() 函数中,初始化了 USB 串口(用于调试)和 UART 串口(用于从 Watcher 接收数据)的串口通信。

  2. loop() 函数中,代码检查 UART 串口是否有可用数据。

  3. 如果有可用数据,会创建一个具有指定容量的 DynamicJsonDocument 来存储解析的 JSON 对象。

  4. 使用 deserializeJson() 函数解析 JSON 数据,并处理任何解析错误。

  5. 然后代码检查解析的 JSON 对象中是否存在特定键,如 "prompt"、"big_image" 和 "small_image"。

note

目前无法解析识别框(boxes)的信息,因为 Watcher 的相应功能仍在开发中,在最新的 v1.0.1 版本中尚未报告此信息。

  1. 如果找到键,其对应的值会打印到 USB 串口用于调试目的。

  2. 代码还使用 count 变量跟踪接收到的报警消息数量。

  3. 最后,打印一条消息表示每个报警消息接收的完成,代码等待下一条消息。

将代码上传到 XIAO ESP32 系列

要将代码上传到您的 XIAO ESP32 系列开发板,请按照以下步骤操作:

  1. 使用 USB 线将您的 XIAO ESP32 系列开发板连接到计算机。

  2. 打开 Arduino IDE 并确保您已为 XIAO ESP32 系列安装了必要的开发板支持包。

    • 如果您想在例程中使用 Seeed Studio XIAO ESP32C3,请参考 此教程 完成添加。

    • 如果您想在例程中使用 Seeed Studio XIAO ESP32S3,请参考 此教程 完成添加。

    • 如果您想在例程中使用 Seeed Studio XIAO ESP32C6,请参考 此教程 完成添加。

  3. 在 Arduino IDE 的工具菜单中选择适当的开发板和端口。

  4. 在 Arduino IDE 中打开提供的代码。

  5. 点击 上传 按钮编译代码并上传到您的 XIAO ESP32 系列开发板。

预期结果

一旦代码上传并在您的 XIAO ESP32 系列开发板上运行,在 Watcher 识别目标报警后,您应该看到以下行为:



您也可以尝试使用其他 Arduino 开发板,但请确保它有足够的内存。

Raspberry Pi 与 Watcher

探索将 Watcher 连接到 Raspberry Pi 并使用 Python 脚本解析和分析 UART 数据的过程。

接线

本节将以 Raspberry Pi 5 为例进行说明,如果您需要,可以通过以下链接下单购买。

如果您使用的是其他 Raspberry Pi 系列,代码和使用教程基本相同。



  • 将 Watcher 的 TX 引脚连接到 Raspberry Pi 的 RX 引脚(GPIO 15)。

  • 将 Watcher 的 RX 引脚连接到 Raspberry Pi 的 TX 引脚(GPIO 14)。

  • 将 Watcher 的 GND 引脚连接到 Raspberry Pi 的 GND 引脚。

代码说明

在运行 Python 脚本之前,请确保安装所需的依赖项:

sudo apt update
sudo apt install python3-pip
pip3 install pyserial pillow

检查树莓派上UART接口的设备名称:

ls /dev/ttyAMA*


第一个 Python 脚本通过 UART 从 Watcher 读取 JSON 数据并打印:

import serial

# 设置串口
ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=1)

def read_json_from_serial():
while True:
if ser.in_waiting > 0:
data = ser.readline()
print(data.decode().strip())

if __name__ == "__main__":
print("在树莓派上启动串口 JSON 读取器...")
read_json_from_serial()


note
  1. 我的 UART 接口对应 /dev/ttyAMA0,如果您的不是,请自行修改。

  2. 这是一个测试脚本,您可以使用它来检查树莓派/Watcher 的 UART 是否正常工作。

第二个 Python 脚本基于第一个脚本构建,并添加了 JSON 解析和图像数据保存功能:

import json
import serial
import base64
from PIL import Image
import io

# 设置串口
ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=1)

# 初始化图像计数器
big_image_counter = 1
small_image_counter = 1

def read_json_from_serial():
buffer = ""
try:
while True:
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting).decode()
buffer += data

if '}' in buffer:
end = buffer.rfind('}')
json_data = buffer[:end+1]
buffer = buffer[end+1:]

try:
data = json.loads(json_data)
print("接收到JSON数据,正在处理...")
process_json_data(data)
except json.JSONDecodeError:
print("JSON解码错误")
buffer = json_data + buffer
except Exception as e:
print(f"发生错误: {e}")

def process_json_data(data):
global big_image_counter, small_image_counter # 声明全局变量

# 处理提示信息
if "prompt" in data:
print(f"提示: {data['prompt']}")

# 处理框信息
#if "boxes" in data:
#for index, box in enumerate(data['boxes']):
#print(f"框 {index + 1} - x: {box['x']}, y: {box['y']}, w: {box['w']}, h: {box['h']}, score: {box['score']}, target_cls_id: {box['target_cls_id']}")

if "big_image" in data:
filename = f'big_image_{big_image_counter}.png'
decode_and_save_image(data['big_image'], filename)
print(f"大图像已处理并保存为 {filename}。")
big_image_counter += 1 # 更新全局变量

if "small_image" in data:
filename = f'small_image_{small_image_counter}.png'
decode_and_save_image(data['small_image'], filename)
print(f"小图像已处理并保存为 {filename}。")
small_image_counter += 1 # 更新全局变量

def decode_and_save_image(base64_data, filename):
image_bytes = base64.b64decode(base64_data)
image = Image.open(io.BytesIO(image_bytes))
image.save(filename) # 保存为PNG文件
return image

if __name__ == "__main__":
print("在树莓派上启动串口JSON读取器...")
read_json_from_serial()
note

目前只能输出 JSON 数据流,因此只提供解析 JSON 数据流的程序。

此脚本执行以下操作:

  • 在循环中从 UART 读取 JSON 数据

  • 解码 JSON 数据并调用 process_json_data 来处理它

  • 从 JSON 中提取提示信息和图像数据

note

目前还无法解析识别框(boxes)的相关信息,因为 Watcher 的相应功能仍在开发中,最新的 v1.0.1 版本中尚未报告此信息。

  • 解码 base64 编码的图像数据并使用 decode_and_save_image 保存为 PNG 文件

  • 打印提取的信息和保存图像的文件名

在树莓派上运行代码

  1. 在树莓派上创建一个新的 Python 文件,例如 watcher_uart.py:
nano watcher_uart.py
  1. 将完整的 Python 代码复制并粘贴到文件中。

  2. 按 Ctrl+X,然后按 Y 和 Enter 保存并退出编辑器。

  3. 运行 Python 脚本:

python watcher_uart.py

预期结果



运行脚本后:

  • 从 Watcher 接收到的解析后的 JSON 数据将实时打印在终端中。

  • 接收到的大图像和小图像将自动保存为 big_image_x.png 和 small_image_x.png 文件。

就是这样!您现在已经学会了如何将 Watcher 连接到树莓派,使用 Python 读取 UART 数据,解析 JSON,并保存传输的图像。请随意进一步实验,例如尝试在连接到树莓派的屏幕上实时显示接收到的数据。

reComputer Jetson & Watch

探索将 Watcher 连接到 reComputer(基于 NVIDIA Jetson 的设备)并使用 Python 脚本解析和分析 UART 数据的过程。

接线

本教程将以适合开发者的 J401 reComputer 载板为例进行说明,如果您想购买 reComputer,可以通过下面的链接获取。

理论上,本节的内容和代码适用于所有 NVIDIA Jetson 系列产品。



  • 将 Watcher 的 TX 引脚连接到 reComputer UART 接口的 RX 引脚。

  • 将 Watcher 的 RX 引脚连接到 reComputer UART 接口的 TX 引脚。

  • 将 Watcher 的 GND 引脚连接到 reComputer 上的 GND 引脚。

代码说明

在运行 Python 脚本之前,请确保安装所需的依赖项:

sudo apt-get update
sudo apt-get install python3-serial
sudo apt-get install python3-pillow

如果您不打算在 UART 上使用串行控制台,您应该禁用串行控制台:

systemctl stop nvgetty
systemctl disable nvgetty
udevadm trigger

此时您可能需要重启 reComputer 以使更改生效。

检查 reComputer 上 UART 接口的设备名称:

ls /dev/ttyTHS*


第一个 Python 脚本通过 UART 从 Watcher 读取 JSON 数据并打印:

import serial

# 设置串口
ser = serial.Serial('/dev/ttyTHS0', 115200, timeout=1)

def read_json_from_serial():
while True:
if ser.in_waiting > 0:
data = ser.readline()
print(data.decode().strip())

if __name__ == "__main__":
print("在 reComputer 上启动串口 JSON 读取器...")
read_json_from_serial()


note
  1. 我的 UART 接口对应 /dev/ttyTHS0,如果您的不是,请自行修改。

  2. 这是一个测试脚本,您可以使用它来检查 reComputer/Watcher 的 UART 是否正常工作。

第二个 Python 脚本基于第一个脚本构建,并添加了 JSON 解析和图像数据保存功能:

import json
import serial
import base64
from PIL import Image
import io

# 设置串口
ser = serial.Serial('/dev/ttyTHS0', 115200, timeout=1)

# 初始化图像计数器
big_image_counter = 1
small_image_counter = 1

def read_json_from_serial():
buffer = ""
try:
while True:
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting).decode()
buffer += data

if '}' in buffer:
end = buffer.rfind('}')
json_data = buffer[:end+1]
buffer = buffer[end+1:]

try:
data = json.loads(json_data)
print("接收到JSON数据,正在处理...")
process_json_data(data)
except json.JSONDecodeError:
print("JSON解码错误")
buffer = json_data + buffer
except Exception as e:
print(f"发生错误: {e}")

def process_json_data(data):
global big_image_counter, small_image_counter # 声明全局变量

# 处理提示信息
if "prompt" in data:
print(f"提示: {data['prompt']}")

# 处理框信息
#if "boxes" in data:
#for index, box in enumerate(data['boxes']):
#print(f"框 {index + 1} - x: {box['x']}, y: {box['y']}, w: {box['w']}, h: {box['h']}, score: {box['score']}, target_cls_id: {box['target_cls_id']}")

if "big_image" in data:
filename = f'big_image_{big_image_counter}.png'
decode_and_save_image(data['big_image'], filename)
print(f"大图像已处理并保存为 {filename}。")
big_image_counter += 1 # 更新全局变量

if "small_image" in data:
filename = f'small_image_{small_image_counter}.png'
decode_and_save_image(data['small_image'], filename)
print(f"小图像已处理并保存为 {filename}。")
small_image_counter += 1 # 更新全局变量

def decode_and_save_image(base64_data, filename):
image_bytes = base64.b64decode(base64_data)
image = Image.open(io.BytesIO(image_bytes))
image.save(filename) # 保存为PNG文件
return image

if __name__ == "__main__":
print("在reComputer上启动串口JSON读取器...")
read_json_from_serial()
note

目前只能输出 JSON 数据流,因此只提供解析 JSON 数据流的程序。

此脚本执行以下操作:

  • 在循环中从 UART 读取 JSON 数据

  • 解码 JSON 数据并调用 process_json_data 来处理它

  • 从 JSON 中提取提示信息和图像数据

  • 解码 base64 编码的图像数据并使用 decode_and_save_image 保存为 PNG 文件

note

目前还无法解析识别框(boxes)的相关信息,因为 Watcher 的相应功能仍在开发中,最新的 v1.0.1 版本中尚未报告此信息。

  • 打印提取的信息和保存图像的文件名

将代码上传到 reComputer

在 reComputer 上创建一个新的 Python 文件,例如 watcher_uart.py

nano watcher_uart.py

将完整的 Python 代码复制并粘贴到文件中。按 Ctrl+X,然后按 Y 和 Enter 保存并退出编辑器。运行 Python 脚本:

sudo python watcher_uart.py

预期结果



运行脚本后:

  • 从 Watcher 接收到的解析后的 JSON 数据将实时打印在终端中,包括提示信息。

  • 接收到的大图像和小图像将自动保存为 big_image_x.png 和 small_image_x.png 文件。

就是这样!您现在已经学会了如何将 Watcher 连接到 reComputer,使用 Python 读取 UART 数据,解析 JSON,并保存传输的图像。请随意进一步实验,并根据您在 reComputer 平台上的具体用例调整代码。

资源

技术支持与产品讨论

感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。

Loading Comments...