Funpack3-5 Arduino UNO R4 WiFi和激光测距传感器实现无线测距
该项目使用了Arduino UNO R4 WiFi和激光测距传感器,实现了无线测距的设计,它的主要功能为:通过飞激光测距传感器实现测距,并通过 Arduino UNO R4 WiFi网络连接到智能云端,可以从远程获取传感器的信息。
标签
嵌入式系统
Funpack活动
电子垃圾佬
更新2025-01-14
90

一、项目描述

本项目使用Arduino UNO R4 WiFi和激光测距传感器VL53L3CX实现了无线测距,能够将测距数据上传到智能云端---腾讯云,远程获取传感器数据。Funpack第三季第5期活动描述如下:

任务2:搭配传感器,并通过网络连接到智能云端,可以从远程获取传感器的信息


Arduino UNO R4 WiFi 将瑞萨电子的 RA4M1 微处理器与乐鑫的 ESP32-S3 相结合,为创客打造了一款一体化工具,具有增强的处理能力和多样化的全新外设。凭借其内置的 Wi-Fi® 和蓝牙®功能,UNO R4 WiFi 使制造商能够探索无限的创意可能性。此外,这款多功能板拥有方便的板载 12x8 LED 矩阵和 Qwiic 连接器,为各个级别的创客提供了无与伦比的灵活性和可能性。官网:https://docs.arduino.cc/hardware/uno-r4-wifi/#features

VL53L3CX是意法半导体新推出的一款激光测距传感器,搭配ST的第三代FlightSense算法,在提高了检测精度的同时,测距范围覆盖了25mm到3000mm,还具有自动污迹校正,抗玻璃盖板串扰等特性。VL53L3CX借助算法和巧妙的模块构造,VL53L3CX还能够通过深度了解来检测视场内的不同对象。官网:https://wiki.dfrobot.com.cn/_SKU_SEN0378_DFRobot_VL53L3CX_Tof_Distance_Sensor_Breakout_Board

特性

  • 高精度距离测量
  • 最远距离可达300cm
  • 典型全视角25°
  • 多物体测距
  • 玻璃盖板串扰的抗扰性
  • 污痕补偿功能

应用场景

  • 精准距离测量
  • 机器人障碍物检测
  • 无人机避障/停靠
  • 距离触发开关

技术规格

  • 供电电压:3.3V~5V
  • 工作电流:<20mA
  • 测量距离:25-3000mm
  • 发射器:940 nm不可见激光(VCSEL)
  • 视角范围:25°
  • I2C地址:0x29
  • 工作温度范围:-20℃~85℃
  • 产品尺寸:18*15mm


二、软件流程图及各功能对应的主要代码片段及说明

首先是连线,注意Arduino UNO R4 WiFi的IO电平是5V,它有两个I2C接口,其中Qwiic connectorIIC0,电平是3.3V,软件上使用Wire1区分标准的Wire。 本文使用标准的I2C接口,如下图:

软件流程图如下所示:

上电后,初始化WIFI,连接WIFI,初始化传感器,初始化MQTT客户端,订阅主题,然后定时读取传感器数据通过MQTT发布到智能云端-----腾讯云。这里使用腾讯云平台,在腾讯云平台创建1个物联网公共实例。

填写域名和端口的格式如下:

${productid}.iotcloud.tencentdevices.com:1883

生成username和password方法:

要注意的是username和password是在连接到云端mqtt broker的时候需要填入的,可以通过这个在线工具https://55jy79.csb.app/生成。Hmac签名算法选择HMAC-SHA1。

其中产品ID、设备名、设备秘钥都是腾讯云平台中创建的设备详情页得到的。

(3)填写订阅和发布的消息,可从云平台中获得。

发送的消息指令,具体数据格式可通过云端的调试功能发送一条消息进行测试。

VL53L3CX驱动使用了Arduino的库PWFusion_VL53L3C:

MQTT库使用了PubSubClient:

驱动测试代码如下:

#include <Wire.h>
#include "PWFusion_VL53L3C.h"
VL53L3C TOF;
void setup() {
  // Initialize I2C and serial port
  Wire.begin();
  Wire.setClock(400000);
  Serial.begin(9600);
  Serial.println(F("Initilizing VL53L3"));
  TOF.begin();
  Serial.println(F("VL53L3 Boot Complete"));
  // Set the timing budget (sample period) to 100ms
  TOF.setTimingBudget(100000);
  // Start sampling data
  TOF.startMeasurement();
  Serial.println(F("Starting TOF measurements"));
}
void loop() {
  MeasurmentResult measResult;
  // Has the VL53L3 finished a new distance mesaurement
  if (TOF.dataIsReady())
  {
    // Get the last measurement result and trigger a new measurement
    TOF.getMeasurmentData(&measResult);
    TOF.startNextMeasurement();
   
    // The VL53L3 can track up to four onject simultaneously.  Prind the
    // measured distance to each detected onject.
    Serial.print(F("Range Measurement: "));
    for (int i=0; i<measResult.numObjs; i++)
    {
      Serial.print(measResult.rangeData[i].Range);
      Serial.print(F("mm     "));
    }
    Serial.println();
  }
}

WIFI连接代码如下:

  //连接网络
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    Serial.print(".");
    delay(5000);
  }
  Serial.println("You're connected to the network");
  Serial.println();

MQTT客户端初始化代码如下:

  //连接MQTT
  mqttclient.setServer(mqtt_server, 1883);// connect mqtt server
  mqttclient.setCallback(callback);
  mqttclient.setKeepAlive(65535);
  while (!mqttclient.connect(mqtt_clientid, mqtt_username, mqtt_userpwd))
  {
        Serial.println("mqtt connect fail, reconnect");
        delay(2000);
  }
  Serial.println("mqtt connected!");

根据腾讯云的规范,账号密码如下:

const char *mqtt_server = "F0KI93P7B6.iotcloud.tencentdevices.com";
const char *mqtt_username = "F0KI93P7B6dev1;12010126;5GQQT;1735825267";
const char *mqtt_userpwd  = "8b3f78b4f413e3569c21ef5a6b6899ce062705d5;hmacsha1";
const char *mqtt_clientid = "F0KI93P7B601";

MQTT客户端订阅主题代码如下:

    // sub topic
    boolean ret = mqttclient.subscribe(mqtt_sub_topic);
    if (ret != true) {
        Serial.println("mqtt subscribe topicfail\n");
    }
    Serial.println("mqtt subscribe topic ok\n");

主题根据腾讯云的规范设计,定义如下:

const char *mqtt_pub_topic = "$thing/up/property/F0KI93P7B6/dev1";
const char *mqtt_sub_topic = "$thing/down/property/F0KI93P7B6/dev1";

发送数据到云端的代码如下:

        if (mqttclient.publish(mqtt_pub_topic, report_buf)) {
            Serial.println("mqtt publish topic ok\n");
        } else {
            Serial.println("mqtt publish topic fail\n");
        }

项目完整代码如下:

#include "WiFiS3.h"
#include "PubSubClient.h"
#include <ArduinoJson.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <Wire.h>
#include "PWFusion_VL53L3C.h"


VL53L3C TOF;


WiFiClient wifiClient;
PubSubClient mqttclient(wifiClient);
 
//  设置WIFI
char ssid[] = "xxx";
char pass[] = "xxx";


const char *mqtt_server = "F0KI93P7B6.iotcloud.tencentdevices.com";
const char *mqtt_username = "F0KI93P7B6dev1;12010126;5GQQT;1735825267";
const char *mqtt_userpwd  = "8b3f78b4f413e3569c21ef5a6b6899ce062705d5;hmacsha1";
const char *mqtt_clientid = "F0KI93P7B601";
const char *mqtt_pub_topic = "$thing/up/property/F0KI93P7B6/dev1";
const char *mqtt_sub_topic = "$thing/down/property/F0KI93P7B6/dev1";
bool power_switch;
int distance;  
int power_percent = 95;
DynamicJsonDocument doc(1024);


#define REPORT_DATA_TEMPLATE "{\"method\":\"report\",\"clientToken\":\"0001\",\"params\":{\"distance\":%d,\"power_switch\":%d,\"_mesh_generic_power_percent\":%d}}"
long lastMsg = 0;
char report_buf[1024];
void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.print("--->Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.println();
  Serial.print("payload [");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();


//处理上位机的控制指令
  DeserializationError error = deserializeJson(doc, payload);
    // Test if parsing succeeds.
      if (error) {
        Serial.print("deserializeJson() failed: ");
        Serial.println(error.f_str());
        return;
      }else{
        if (doc["clientToken"]!="00000001") {
          if (doc["params"]["power_switch"] == 1) {
            Serial.print("Power On ");
            power_switch=1;
          } else {
            Serial.print("Power Off ");
            power_switch=0;
          }
        }
      }


}



void setup()
{
  Serial.begin(9600);
  while (!Serial);


  //初始化I2C
  Wire.begin();
  Wire.setClock(400000);


//初始化激光传感器
Serial.println(F("Initilizing VL53L3"));
TOF.begin();
Serial.println(F("VL53L3 Boot Complete"));
//Set the timing budget (sample period) to 100ms
TOF.setTimingBudget(100000);
//Start sampling data
TOF.startMeasurement();
Serial.println(F("Starting TOF measurements"));


  //连接网络
  Serial.print("Attempting to connect to WPA SSID: ");
  Serial.println(ssid);
  while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
    Serial.print(".");
    delay(5000);
  }
  Serial.println("You're connected to the network");
  Serial.println();


  //连接MQTT
  mqttclient.setServer(mqtt_server, 1883);// connect mqtt server
  mqttclient.setCallback(callback);
  mqttclient.setKeepAlive(65535);
  while (!mqttclient.connect(mqtt_clientid, mqtt_username, mqtt_userpwd))
  {
        Serial.println("mqtt connect fail, reconnect");
        delay(2000);
  }
  Serial.println("mqtt connected!");
   
    // sub topic
    boolean ret = mqttclient.subscribe(mqtt_sub_topic);
    if (ret != true) {
        Serial.println("mqtt subscribe topicfail\n");
    }
    Serial.println("mqtt subscribe topic ok\n");


}
 
void loop()
{
  //读取激光传感器数据
  MeasurmentResult measResult;
  //Has the VL53L3 finished a new distance mesaurement
  if (TOF.dataIsReady())
  {
    //Get the last measurement result and trigger a new measurement
    TOF.getMeasurmentData(&measResult);
    TOF.startNextMeasurement();
    //The VL53L3 can track up to four onject simultaneously.  Prind the
    //measured distance to each detected onject.
    Serial.print(F("Range Measurement: "));
    for (int i=0; i<measResult.numObjs; i++)
    {
      Serial.print(measResult.rangeData[i].Range);
      Serial.print(F("mm "));
      distance = measResult.rangeData[i].Range;
    }
    Serial.println();
  }


    // client loop
    mqttclient.loop();
    // pub topic
    long now = millis();
    if (now - lastMsg > 10000)
    {
        lastMsg = now;
        memset(report_buf, 0, 1024);
        sprintf(report_buf, REPORT_DATA_TEMPLATE, distance,power_switch,power_percent);
        Serial.println(report_buf);
        if (mqttclient.publish(mqtt_pub_topic, report_buf))
        {
            Serial.println("mqtt publish topic ok\n");
        }
        else
        {
            Serial.println("mqtt publish topic fail\n");
        }
    }
}

三、功能展示及说明

串口终端显示结果:

腾讯云远程查看传感器的数据:

四、对本活动的心得体会(包括意见或建议)

活动很nice,希望有更多的活动。

附件下载
arduino_uno_r4_wifi_test.zip
arduino代码
团队介绍
捡垃圾的电子佬一枚
团队成员
电子垃圾佬
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号