使用 Ubidots 进行开发
Ubidots 是一个系统集成商、物联网创业者和 OEM 厂商可以轻松构建物联网 (IoT) 应用程序和连接服务的平台,提供数据收集、分析和可视化工具。在套件的规划中,我们选择了 Ubidots 平台作为一种替代方案,无需使用 LoRaWAN®,您可以通过 Wio Terminal 自带的 WiFi 功能,通过 MQTT 协议将所需的传感器数据发送到 Ubidots 仪表板进行数据展示。

在本章节中,我们将向您展示如何通过 Arduino 编程将传感器数据发送到 Ubidots。
前期准备
连接
SeseCAP - K1100 套件中的传感器可以通过 Grove 电缆连接到 Wio Terminal 下的 Grove 接口。下表描述了每个传感器连接的 Grove 接口的位置。

传感器类型 | 通信协议 | 连接的 Grove 接口 |
---|---|---|
Grove 温湿度传感器 (SHT40) | I2C | Wio Terminal 左侧 Grove 接口 |
Grove VOC 和 eCO2 气体传感器 (SGP30) | I2C | Wio Terminal 左侧 Grove 接口 |
Grove 视觉 AI 模块 | I2C | Wio Terminal 左侧 Grove 接口 |
Grove 土壤湿度传感器 | ADC | Wio Terminal 右侧 Grove 接口 |
软件准备
步骤 1. 您需要安装 Arduino 软件。
步骤 2. 启动 Arduino 应用程序。

步骤 3. 将 Wio Terminal 添加到 Arduino IDE。
打开 Arduino IDE,点击 文件 > 首选项
,并将以下 URL 复制到附加开发板管理器 URLs 中:
https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json

点击 工具 > 开发板 > 开发板管理器
,在开发板管理器中搜索 Wio Terminal。

步骤 4. 选择您的开发板和端口
您需要在 工具 > 开发板
菜单中选择与您的 Arduino 对应的条目,选择 Wio Terminal。

从 工具 -> 端口
菜单中选择 Wio Terminal 开发板的串口设备。这通常是 COM3 或更高(COM1 和 COM2 通常保留给硬件串口)。要确认,可以断开 Wio Terminal 开发板并重新打开菜单;消失的条目应该是 Arduino 开发板。重新连接开发板并选择该串口。
对于 Mac 用户,端口可能类似于 /dev/cu.usbmodem141401
。
如果您无法上传代码,大多数情况下是因为 Arduino IDE 无法将 Wio Terminal 切换到引导加载模式(可能是因为 MCU 停止运行或您的程序正在处理 USB)。解决方法是手动将 Wio Terminal 切换到引导加载模式。

步骤 5. 安装所需传感器的库
传感器类型 | 链接 1 | 链接 2 |
---|---|---|
Wio Terminal IMU 传感器 | 下载 | - |
Grove 温湿度传感器 (SHT40) | 下载 | 下载 |
Grove VOC 和 eCO2 气体传感器 (SGP30) | 下载 | - |
Grove 视觉 AI 模块 | 下载 | - |
上表中未列出的传感器表示无需单独下载库。
步骤 6. Wi-Fi 所需的库
我们需要以下库来开始在 Wio Terminal 上使用 Wi-Fi。您可以通过在 Arduino 库管理器的搜索框中输入库名称来搜索这些库。

- Seeed_Arduino_rpcWiFi - 搜索
seeed rpcwifi

- Seeed_Arduino_rpcUnified - 搜索
seeed rpcunified

- Seeed_Arduino_mbedtls - 搜索
seeed mbedtls

- Seeed_Arduino_FS - 搜索
seeed fs

- Seeed_Arduino_SFUD - 搜索
seeed sfud

- PubSubClinet - 搜索
PubSubClient

操作步骤
步骤 1. 注册并登录 Ubidots
如果这是您第一次使用 Ubidots,请访问 Ubidots 网站 并注册一个账户。

注册完成后,请使用您的账户登录 Ubidots。
步骤 2. 分配您的唯一 Ubidots TOKEN
每次向 Ubidots 发出的请求都需要一个 TOKEN。获取 TOKEN 的最简单方法是从用户下拉菜单中点击“API Credentials”。
在用户下拉菜单中点击 API Credentials:

Tokens:用于 API 请求的临时且可撤销的密钥。请保存 TOKEN,我们稍后会用到。

所有 API 调用仅接受您的 TOKEN。不要尝试使用您的 API Key,它不会起作用!您还可以在用户下拉菜单的 My Profile 设置中访问所有 Ubidots API Keys 部分。选择 My Profile –> API Credentials 查看与您的特定 Ubidots 账户相关的 API TOKEN 列表。

步骤 3. 准备必要的信息
为了建立 MQTT 连接,我们需要提前准备以下信息。
- WiFi SSID
- 填写 Wio Terminal 可以连接的 WiFi SSID。Wio Terminal 将搜索其周围的 WiFi 并尝试连接。
- WiFi SSID 的密码
- 填写 Wio Terminal 可以连接的 WiFi SSID 的密码。
- Ubidots TOKEN
- 这是在 步骤 2 中生成的 TOKEN。
- 变量标签
- 这是用户提供给 Ubidots 的传感器值的名称。Ubidots 根据用户提供的此名称匹配不同的数据。如果变量标签在第一次发送数据之前不存在,Ubidots 将自动创建它们。
- 设备标签
- 这是设备的名称,用户提供的设备名称将被 Ubidots 用来识别设备。如果设备标签在第一次发送数据之前不存在,Ubidots 将自动创建它们。
- MQTT 客户端名称
- 这是特殊的,因为它是您的设备将被代理识别的 ID,因此它 必须 是唯一的。如果您的设备尝试使用已被其他设备占用的 ID 连接,连接将被拒绝。请创建一个由 8-12 个以上字母数字字符组成的唯一 MQTT 客户端名称,并将其相应地输入到代码中。 如果需要帮助创建唯一的 MQTT 客户端名称,请查看此 随机 ASCII 生成器,或者简单地使用设备的 MAC 地址,因为每个 MAC 地址都是全球唯一的。

在下面的程序开头,我们将在代码顶部定义这些要求,请根据需要填写您的信息。
// 示例
#define WIFISSID "<YOUR-WIFISSD>" // 在此处填写您的 WifiSSID
#define PASSWORD "<YOUR-WIFI-PASSWORD>" // 在此处填写您的 WiFi 密码
#define TOKEN "<YOUR-UBIDOTS-TOKEN>" // 在此处填写您的 Ubidots TOKEN
#define VARIABLE_LABEL "light" // 分配变量标签
#define DEVICE_LABEL "wio-terminal" // 分配设备标签
#define MQTT_CLIENT_NAME "r6y1ax7mq8" // MQTT 客户端名称
将内置传感器数据发送到 Ubidots
如果您想将 Wio Terminal 内置传感器的检测数据发送到 Ubidots,请将以下完整代码粘贴到 Arduino 中并上传到 Wio Terminal。
#include <PubSubClient.h>
#include <rpcWiFi.h>
#include <TFT_eSPI.h>
#include"LIS3DHTR.h"
LIS3DHTR<TwoWire> lis;
// 必需信息
#define WIFISSID "<YOUR-WIFISSD>" // 在此处填写您的 WifiSSID
#define PASSWORD "<YOUR-WIFI-PASSWORD>" // 在此处填写您的 WiFi 密码
#define TOKEN "<YOUR-UBIDOTS-TOKEN>" // 在此处填写您的 Ubidots TOKEN
#define VARIABLE_LABEL1 "light" // 分配变量标签
#define VARIABLE_LABEL2 "IMUx"
#define VARIABLE_LABEL3 "IMUy"
#define VARIABLE_LABEL4 "IMUz"
#define VARIABLE_LABEL5 "sound"
#define DEVICE_LABEL "wio-terminal" // 分配设备标签
#define MQTT_CLIENT_NAME "r6y1ax7mq8" // MQTT 客户端名称
const long interval = 100;
unsigned long previousMillis = 0;
TFT_eSPI tft;
char mqttBroker[] = "industrial.api.ubidots.com";
WiFiClient wifiClient;
PubSubClient client(wifiClient);
// 传感器值
static int lightValue = 0;
static float imuxValue = 0;
static float imuyValue = 0;
static float imuzValue = 0;
static int soundValue = 0;
// 存储要发送的值的空间
static char str_light[6];
static char str_imux[6];
static char str_imuy[6];
static char str_imuz[6];
static char str_sound[6];
char payload[700];
char topic[150];
void callback(char* topic, byte* payload, unsigned int length){
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
}
void reconnect() {
// 循环直到重新连接
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// 尝试连接
if (client.connect(MQTT_CLIENT_NAME, TOKEN,"")) {
Serial.println("connected");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 2 seconds");
// 等待 2 秒后重试
delay(2000);
}
}
}
// 读取内置传感器值
void read_builtin()
{
lightValue = analogRead(WIO_LIGHT);
Serial.print("Light = ");
Serial.println(lightValue);
imuxValue = lis.getAccelerationX();
Serial.print("IMU_x = ");
Serial.println(imuxValue);
imuyValue = lis.getAccelerationY();
Serial.print("IMU_y = ");
Serial.println(imuyValue);
imuzValue = lis.getAccelerationZ();
Serial.print("IMU_z = ");
Serial.println(imuzValue);
soundValue = analogRead(WIO_MIC);
Serial.print("Sound = ");
Serial.println(soundValue);
}
// 发送数据到 Ubidots
void send_data()
{
dtostrf(lightValue, 4, 0, str_light);
dtostrf(imuxValue, 4, 3, str_imux);
dtostrf(imuyValue, 4, 3, str_imuy);
dtostrf(imuzValue, 4, 3, str_imuz);
dtostrf(soundValue, 4, 0, str_sound);
if (!client.connected()) {
reconnect();
}
// 构建主题
sprintf(topic, "%s", ""); // 清空主题内容
sprintf(topic, "%s%s", "/v2.0/devices/", DEVICE_LABEL);
// 构建负载
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL1); // 添加变量标签
sprintf(payload, "%s%s", payload, str_light); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL2); // 添加变量标签
sprintf(payload, "%s%s", payload, str_imux); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL3); // 添加变量标签
sprintf(payload, "%s%s", payload, str_imuy); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL4); // 添加变量标签
sprintf(payload, "%s%s", payload, str_imuz); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL5); // 添加变量标签
sprintf(payload, "%s%s", payload, str_sound); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
client.loop();
}
void setup() {
Serial.begin(115200);
lis.begin(Wire1);
pinMode(WIO_MIC, INPUT);
pinMode(WIO_LIGHT, INPUT);
tft.begin();
tft.setRotation(3);
tft.setTextSize(2);
tft.fillScreen(TFT_BLACK);
lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); // 数据输出速率
lis.setFullScaleRange(LIS3DHTR_RANGE_2G);
// while(!Serial);
// 将 WiFi 设置为站点模式并断开之前连接的 AP
WiFi.mode(WIFI_STA);
WiFi.disconnect();
tft.drawString("Connecting to WiFi...",20,120);
WiFi.begin(WIFISSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(WIFISSID, PASSWORD);
}
tft.fillScreen(TFT_BLACK);
tft.drawString("Connected to the WiFi",20,120);
delay(1000);
client.setServer(mqttBroker, 1883);
client.setCallback(callback);
}
void loop() {
read_builtin(); // 读取内置传感器值
send_data(); // 发送数据到 Ubidots
delay(5000);
}
将 Grove 土壤湿度传感器数据发送到 Ubidots
如果您想将 Grove 土壤湿度传感器数据发送到 Ubidots,请将以下完整代码粘贴到 Arduino 中并上传到 Wio Terminal。
#include <PubSubClient.h>
#include <rpcWiFi.h>
#include <TFT_eSPI.h>
// 必需的信息
#define WIFISSID "<YOUR-WIFISSD>" // 在此处填写您的 WiFi SSID
#define PASSWORD "<YOUR-WIFI-PASSWORD" // 在此处填写您的 WiFi 密码
#define TOKEN "<YOUR-UBIDOTS-TOKEN>" // 在此处填写您的 Ubidots TOKEN
#define VARIABLE_LABEL "light" // 分配变量标签
#define DEVICE_LABEL "wio-terminal" // 分配设备标签
#define MQTT_CLIENT_NAME "r6y1ax7mq8" // MQTT 客户端名称
const long interval = 100;
unsigned long previousMillis = 0;
TFT_eSPI tft;
char mqttBroker[] = "industrial.api.ubidots.com";
WiFiClient wifiClient;
PubSubClient client(wifiClient);
// 土壤湿度传感器引脚和传感器值
int sensorPin = A0;
static int soilValue = 0;
// 用于存储发送值的空间
char str_soil[6];
char payload[700];
char topic[150];
void callback(char* topic, byte* payload, unsigned int length){
Serial.print("收到消息 [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
}
void reconnect() {
// 循环直到重新连接
while (!client.connected()) {
Serial.println("尝试连接 MQTT...");
// 尝试连接
if (client.connect(MQTT_CLIENT_NAME, TOKEN,"")) {
Serial.println("已连接");
}
else {
Serial.print("连接失败, 错误代码=");
Serial.print(client.state());
Serial.println(" 2秒后重试");
// 重试前等待2秒
delay(2000);
}
}
}
// 读取土壤湿度传感器值
void read_soil()
{
soilValue = analogRead(sensorPin);
Serial.print("湿度 = ");
Serial.println(soilValue);
}
// 将数据发送到 Ubidots
void send_data()
{
dtostrf(soilValue, 4, 0, str_soil);
if (!client.connected()) {
reconnect();
}
// 构建主题
sprintf(topic, "%s", ""); // 清空主题内容
sprintf(topic, "%s%s", "/v2.0/devices/", DEVICE_LABEL);
// 构建有效负载
sprintf(payload, "%s", ""); // 清空有效负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL); // 添加变量标签
sprintf(payload, "%s%s", payload, str_soil); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
client.loop();
}
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(3);
tft.setTextSize(2);
tft.fillScreen(TFT_BLACK);
// 将 WiFi 设置为站点模式并断开与之前连接的 AP 的连接
WiFi.mode(WIFI_STA);
WiFi.disconnect();
tft.drawString("正在连接 WiFi...",20,120);
WiFi.begin(WIFISSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(WIFISSID, PASSWORD);
}
tft.fillScreen(TFT_BLACK);
tft.drawString("已连接到 WiFi",20,120);
delay(1000);
client.setServer(mqttBroker, 1883);
client.setCallback(callback);
}
void loop() {
read_soil(); // 读取土壤湿度传感器值
send_data(); // 将数据发送到 Ubidots
delay(5000);
}
将 Grove VOC 和 eCO2 气体传感器数据发送到 Ubidots
如果您想将 Grove VOC 和 eCO2 气体传感器数据发送到 Ubidots,请将以下完整代码粘贴到 Arduino 中并上传到 Wio Terminal。
#include <PubSubClient.h>
#include <rpcWiFi.h>
#include <TFT_eSPI.h>
#include "sensirion_common.h"
#include "sgp30.h"
#define WIFISSID "<YOUR-WIFISSD>" // 在此处填写您的 WiFi SSID
#define PASSWORD "<YOUR-WIFI-PASSWORD>" // 在此处填写您的 WiFi 密码
#define TOKEN "<YOUR-UBIDOTS-TOKEN>" // 在此处填写您的 Ubidots TOKEN
#define VARIABLE_LABEL1 "voc" // 分配变量标签
#define VARIABLE_LABEL2 "co2"
#define DEVICE_LABEL "wio-terminal" // 分配设备标签
#define MQTT_CLIENT_NAME "r6y1ax7mq8" // MQTT 客户端名称
const long interval = 100;
unsigned long previousMillis = 0;
char mqttBroker[] = "industrial.api.ubidots.com";
WiFiClient wifiClient;
PubSubClient client(wifiClient);
TFT_eSPI tft = TFT_eSPI();
static unsigned short int VOC = 0;
static unsigned short int CO2 = 0;
// 用于存储发送值的空间
char str_voc[6];
char str_co2[6];
char payload[700];
char topic[150];
void callback(char* topic, byte* payload, unsigned int length){
Serial.print("收到消息 [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
}
void reconnect() {
// 循环直到重新连接
while (!client.connected()) {
Serial.println("尝试连接 MQTT...");
// 尝试连接
if (client.connect(MQTT_CLIENT_NAME, TOKEN,"")) {
Serial.println("已连接");
}
else {
Serial.print("连接失败, 错误代码=");
Serial.print(client.state());
Serial.println(" 2秒后重试");
// 重试前等待2秒
delay(2000);
}
}
}
void read_sgp30()
{
s16 err = 0;
sgp_measure_iaq_blocking_read(&VOC, &CO2);
if (err == STATUS_OK) {
Serial.print("tVOC 浓度:");
Serial.print(VOC);
Serial.println("ppb");
Serial.print("CO2eq 浓度:");
Serial.print(CO2);
Serial.println("ppm");
} else {
Serial.println("读取 IAQ 值时出错\n");
}
}
void send_data()
{
dtostrf(VOC, 4, 0, str_voc);
dtostrf(CO2, 4, 0, str_co2);
if (!client.connected()) {
reconnect();
}
// 构建主题
sprintf(topic, "%s", ""); // 清空主题内容
sprintf(topic, "%s%s", "/v2.0/devices/", DEVICE_LABEL);
// 构建有效负载
sprintf(payload, "%s", ""); // 清空有效负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL1); // 添加变量标签
sprintf(payload, "%s%s", payload, str_voc); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
Serial.println(payload);
delay(500);
sprintf(payload, "%s", ""); // 清空有效负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL2); // 添加变量标签
sprintf(payload, "%s%s", payload, str_co2); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
Serial.println(payload);
delay(500);
client.loop();
}
void setup() {
Serial.begin(115200);
while (sgp_probe() != STATUS_OK) {
Serial.println("SGP 初始化失败");
}
sgp_set_absolute_humidity(13000);
sgp_iaq_init();
tft.begin();
tft.setRotation(3);
tft.setTextSize(2);
tft.fillScreen(TFT_BLACK);
// while(!Serial);
// 将 WiFi 设置为站点模式并断开与之前连接的 AP 的连接
WiFi.mode(WIFI_STA);
WiFi.disconnect();
tft.drawString("正在连接 WiFi...",20,120);
WiFi.begin(WIFISSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(WIFISSID, PASSWORD);
}
tft.fillScreen(TFT_BLACK);
tft.drawString("已连接到 WiFi",20,120);
delay(1000);
client.setServer(mqttBroker, 1883);
client.setCallback(callback);
}
void loop() {
read_sgp30(); // 读取 sgp30 传感器值
send_data(); // 将数据发送到 Ubidots
delay(5000);
}
将 Grove 温湿度传感器数据发送到 Ubidots
如果您想将 Grove 温湿度传感器数据发送到 Ubidots,请将以下完整代码粘贴到 Arduino 中并上传到 Wio Terminal。
#include <PubSubClient.h>
#include <rpcWiFi.h>
#include <TFT_eSPI.h>
#include <SensirionI2CSht4x.h>
#include <Wire.h>
#define WIFISSID "<YOUR-WIFISSD>" // 在此处填写您的 WiFi SSID
#define PASSWORD "<YOUR-WIFI-PASSWORD" // 在此处填写您的 WiFi 密码
#define TOKEN "<YOUR-UBIDOTS-TOKEN>" // 在此处填写您的 Ubidots TOKEN
#define VARIABLE_LABEL1 "temperature" // 分配变量标签
#define VARIABLE_LABEL2 "humidity"
#define DEVICE_LABEL "wio-terminal" // 分配设备标签
#define MQTT_CLIENT_NAME "r6y1ax7mq8" // MQTT 客户端名称
const long interval = 100;
unsigned long previousMillis = 0;
char mqttBroker[] = "industrial.api.ubidots.com";
WiFiClient wifiClient;
PubSubClient client(wifiClient);
TFT_eSPI tft = TFT_eSPI();
SensirionI2CSht4x sht4x;
static float temp = 0;
static float humi = 0;
// 用于存储发送值的空间
char str_temp[6];
char str_humi[6];
char payload[700];
char topic[150];
void callback(char* topic, byte* payload, unsigned int length){
Serial.print("收到消息 [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
}
void reconnect() {
// 循环直到重新连接
while (!client.connected()) {
Serial.println("尝试 MQTT 连接...");
// 尝试连接
if (client.connect(MQTT_CLIENT_NAME, TOKEN,"")) {
Serial.println("已连接");
}
else {
Serial.print("连接失败, 错误代码=");
Serial.print(client.state());
Serial.println(" 2秒后重试");
// 重试前等待2秒
delay(2000);
}
}
}
void read_sht40()
{
uint16_t error;
char errorMessage[256];
error = sht4x.measureHighPrecision(temp, humi);
if (error) {
Serial.print("执行 measureHighPrecision() 时出错: ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("温度:");
Serial.print(temp);
Serial.print("\t");
Serial.print("湿度:");
Serial.println(humi);
}
}
void send_data()
{
dtostrf(temp, 4, 2, str_temp);
dtostrf(humi, 4, 2, str_humi);
if (!client.connected()) {
reconnect();
}
// 构建主题
sprintf(topic, "%s", ""); // 清空主题内容
sprintf(topic, "%s%s", "/v2.0/devices/", DEVICE_LABEL);
// 构建负载
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL1); // 添加变量标签
sprintf(payload, "%s%s", payload, str_temp); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL2); // 添加变量标签
sprintf(payload, "%s%s", payload, str_humi); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
client.loop();
}
void setup() {
Serial.begin(115200);
Wire.begin();
sht4x.begin(Wire);
tft.begin();
tft.setRotation(3);
tft.setTextSize(2);
tft.fillScreen(TFT_BLACK);
// while(!Serial);
// 将 WiFi 设置为站点模式并断开之前连接的 AP
WiFi.mode(WIFI_STA);
WiFi.disconnect();
tft.drawString("正在连接 WiFi...",20,120);
WiFi.begin(WIFISSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(WIFISSID, PASSWORD);
}
tft.fillScreen(TFT_BLACK);
tft.drawString("已连接到 WiFi",20,120);
delay(1000);
client.setServer(mqttBroker, 1883);
client.setCallback(callback);
}
void loop() {
read_sht40(); // 读取 sht40 传感器值
send_data(); // 将数据发送到 Ubidots
delay(5000);
}
将 Grove Vision Ai 模块数据发送到 Ubidots
如果您想将 Grove Vision Ai 模块数据发送到 Ubidots,请将以下完整代码粘贴到 Arduino 中并上传到 Wio Terminal。
#include <PubSubClient.h>
#include <rpcWiFi.h>
#include <TFT_eSPI.h>
#include"LIS3DHTR.h"
#include "Seeed_Arduino_GroveAI.h"
// 必需信息
#define WIFISSID "<YOUR-WIFISSD>" // 在此处填写您的 WiFi SSID
#define PASSWORD "<YOUR-WIFI-PASSWORD" // 在此处填写您的 WiFi 密码
#define TOKEN "<YOUR-UBIDOTS-TOKEN>" // 在此处填写您的 Ubidots TOKEN
#define VARIABLE_LABEL1 "num" // 分配变量标签
#define VARIABLE_LABEL2 "confidence"
#define DEVICE_LABEL "wio-terminal" // 分配设备标签
#define MQTT_CLIENT_NAME "r6y1ax7mq8" // MQTT 客户端名称
const long interval = 100;
unsigned long previousMillis = 0;
char mqttBroker[] = "industrial.api.ubidots.com";
WiFiClient wifiClient;
PubSubClient client(wifiClient);
GroveAI ai(Wire);
uint8_t state = 0;
TFT_eSPI tft = TFT_eSPI();
static int num = 0;
static int conf = 0;
// 用于存储发送值的空间
char str_num[6];
char str_conf[6];
char payload[700];
char topic[150];
void callback(char* topic, byte* payload, unsigned int length){
Serial.print("收到消息 [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
}
void reconnect() {
// 循环直到重新连接
while (!client.connected()) {
Serial.println("尝试 MQTT 连接...");
// 尝试连接
if (client.connect(MQTT_CLIENT_NAME, TOKEN,"")) {
Serial.println("已连接");
}
else {
Serial.print("连接失败, 错误代码=");
Serial.print(client.state());
Serial.println(" 2秒后重试");
// 重试前等待2秒
delay(2000);
}
}
}
// Vision AI 初始化
void VisionAI_Init()
{
Serial.println("开始");
if (ai.begin(ALGO_OBJECT_DETECTION, MODEL_EXT_INDEX_1)) // 对象检测和预训练模型1
{
state = 1;
}
else
{
Serial.println("算法初始化失败。");
}
}
// 读取 VisionAI 值:识别的字符数量,每个人的置信度
void read_VisionAI()
{
if (state == 1)
{
uint32_t tick = millis();
if (ai.invoke()) // 开始调用
{
while (1) // 等待调用完成
{
CMD_STATE_T ret = ai.state();
if (ret == CMD_STATE_IDLE)
{
break;
}
delay(20);
}
uint8_t len = ai.get_result_len(); // 接收检测到的人数
if(len)
{
Serial.print("人数: ");
num = len;
Serial.println(num);
object_detection_t data; // 获取数据
for (int i = 0; i < len; i++)
{
ai.get_result(i, (uint8_t*)&data, sizeof(object_detection_t)); // 获取结果
Serial.print("置信度:");
conf = data.confidence;
Serial.println(conf);
}
}
else
{
Serial.println("未识别到");
num = 0;
conf = 0;
}
}
else
{
Serial.println("调用失败。");
num = 0;
conf = 0;
delay(1000);
}
}
}
void send_data()
{
dtostrf(num, 4, 0, str_num);
dtostrf(conf, 4, 0, str_conf);
if (!client.connected()) {
reconnect();
}
// 构建主题
sprintf(topic, "%s", ""); // 清空主题内容
sprintf(topic, "%s%s", "/v2.0/devices/", DEVICE_LABEL);
// 构建负载
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL1); // 添加变量标签
sprintf(payload, "%s%s", payload, str_num); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
sprintf(payload, "%s", ""); // 清空负载
sprintf(payload, "{\"%s\":", VARIABLE_LABEL2); // 添加变量标签
sprintf(payload, "%s%s", payload, str_conf); // 添加值
sprintf(payload, "%s}", payload); // 关闭字典括号
client.publish(topic, payload);
delay(500);
client.loop();
}
void setup() {
Serial.begin(115200);
Wire.begin();
tft.begin();
tft.setRotation(3);
tft.setTextSize(2);
tft.fillScreen(TFT_BLACK);
VisionAI_Init();
// 将 WiFi 设置为站点模式并断开之前连接的 AP
WiFi.mode(WIFI_STA);
WiFi.disconnect();
tft.drawString("正在连接 WiFi...",20,120);
WiFi.begin(WIFISSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
WiFi.begin(WIFISSID, PASSWORD);
}
tft.fillScreen(TFT_BLACK);
tft.drawString("已连接到 WiFi",20,120);
delay(1000);
client.setServer(mqttBroker, 1883);
client.setCallback(callback);
}
void loop() {
read_VisionAI(); // 读取 VisionAI 传感器值
send_data(); // 将数据发送到 Ubidots
delay(5000);
}
Ubidots 面板
代码上传完成后,我们可以开始设置仪表板,以查看数据是如何上传的。
Ubidots 拥有非常简单的界面,如果您想查看设备的相关信息,可以在仪表板顶部选择 Devices。


点击设备名称,即可查看所有的历史标签。这是由代码中的 VARIABLE_LABEL 决定的。

Ubidots 的免费版本仅支持创建 一个 TOKEN 和 十个标签。一旦超过十个标签,您上传的标签和数据将会被丢弃。
如果您想查看设备的数据信息,可以选择 Data。

您还可以在主页面左上角选择不同的仪表板界面。默认情况下,Ubidots 会自动为您创建一个名为 Demo Dashboard 的仪表板。一旦 Wio Terminal 联网并发送数据,您将能够看到一个名为 wio terminal dashboard 的仪表板。这是在代码中的 DEVICE_LABEL 定义的。

您可以在当前仪表板下添加不同的面板,这需要您点击右上角的 + 号。

以下是 Ubidots 支持的面板列表。

下面以创建折线图表为例。如果您想绘制 IMU 传感器值的折线图,那么您需要创建三个标签,并且 标签的名称需要与代码中的 VARIABLE_LABEL 匹配,然后将其余的交给 Ubidots,它会自动为您生成图表。

Ubidots 还具有非常强大的自定义功能,例如是否显示数值、Y 轴名称以及显示多少数据,所有这些您都可以自由调整。
资源
本教程中使用的所有代码请点击图标访问。
技术支持与产品讨论
感谢您选择我们的产品!我们为您提供多种支持渠道,确保您使用我们的产品时体验顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。
声明
- LoRa® 标志是 Semtech Corporation 或其子公司的商标。
- LoRaWAN® 是根据 LoRa Alliance® 授权使用的标志。