回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

【创意智造组】手指一挥,光影随形:用64×8 DTOF激光雷达打造“隔空魔法” 简单

头像 云天 2026.03.29 52 1

【项目背景】

       你是否遇到过这样的场景:想在黑暗的环境里控制灯光,却找不到开关;想用手势与机器互动,摄像头却因为光线太差而“瞎了”。传统的摄像头方案依赖可见光,一旦环境变暗或逆光,识别率就会大打折扣。

       最近在DFRobot社区看到一款64×8矩阵DTOF激光雷达(SEN0682),它采用直接飞行时间(DTOF)技术,主动发射激光,不依赖环境光。这让我产生了一个想法:能不能借助Mind+2.0图像分类工具训练模型,用它来做“隔空手势识别”,并且完全不受光线影响?进一步地,识别到的手势能否用来生成酷炫的粒子动画,或者通过物联网控制家里的灯带?

       经过几周的折腾,我实现了这个项目:当手在传感器前变化手指个数,电脑屏幕上会实时汇聚出对应的数字粒子,同时通过MQTT协议无线控制ESP32驱动的RGB灯带。整个过程在完全黑暗的房间里也能稳定工作。

7d0fccb5507cccb51fb46b8af04b8d10_webwxgetmsgimg_&MsgID=1607760598772448881&skey=%40crypt_b90cd10e_764b03d3f77870d4a78863b96d9b8384.jpg

 

f155cc07c78e49fe3d792b851a56b195_webwxgetmsgimg_&MsgID=4103418295978489687&skey=%40crypt_b90cd10e_764b03d3f77870d4a78863b96d9b8384.jpg

【硬件准备】

部件型号/说明作用
DTOF激光雷达DFRobot SEN0682,64×8矩阵,120°×20°视场角,UART接口获取前方512个点的距离与强度数据
主控(训练端)笔记本电脑(Windows)运行Python脚本,采集数据、训练模型、执行推理
主控(执行端)掌控板/ESP32-E接收MQTT指令,控制灯带
RGB灯带WS2812,12颗灯珠呈现不同灯光效果
USB转TTL模块CH340/FT232连接传感器与电脑
5V电源USB充电器(2A)为传感器和ESP32供电

接线提醒:传感器必须使用5V供电,逻辑电平为3.3V,请确保USB转TTL模块支持3.3V输出,或使用电平转换电路。

步骤1 从点云到图像——发现数据中的“灰度图”

       拿到传感器后,我首先按照官方教程连接电脑,打开上位机软件 wy3DViewer.exe。软件界面实时显示传感器前方的点云图,并且可以切换显示深度图灰度图

1668da1a4cb64c1ad9969e67412283bd_9b9fac81a68771b4cfb9aa3a90c301e9.png

       深度图反映的是距离(近亮远暗),灰度图反映的是反射强度(强反射亮,弱反射暗)。我突然想到:灰度图不就是一个64×8像素的“图像”吗?手的不同姿势会在这个“图像”上留下不同的纹理。如果把每一帧数据保存成图片,不就可以用Mind+的AI图像分类功能进行训练,从而识别出手指个数?

       于是,整个项目的技术路线清晰了:

       用Python读取传感器的强度数据(I值),转换为224×224的灰度图。

       采集大量手势图片,按手指个数(1~5指+背景)分类。

       在Mind+中训练图像分类模型。

       用训练好的模型实时推理,根据结果控制粒子动画或MQTT灯带。

步骤2 用Python把传感器数据变成图像

       官方提供了树莓派Python库,我稍作修改,使其在Windows上也能运行。核心函数 intensity_to_image_adaptive() 负责将512个强度值转换为一张图像。

代码
def intensity_to_image_adaptive(i_list, left_crop=12, right_crop=12):
    # 重塑为8行64列
    grid = np.array(i_list).reshape(8, 64).astype(np.float32)
    # 左右各切除12列(去掉边缘无效区域)
    grid = grid[:, left_crop:64-right_crop]
    # 自适应拉伸到0~255
    min_val = grid.min()
    max_val = grid.max()
    img_data = ((grid - min_val) / (max_val - min_val) * 255).astype(np.uint8)
    # 转换为PIL图像,并放大到224×224(Mind+输入尺寸)
    img = Image.fromarray(img_data, mode='L')
    img = img.resize((224, 224), Image.Resampling.BICUBIC)
    return img

采集数据:运行一个循环,每按一次数字键(1-5),就保存一帧图像到对应的文件夹。每个手势采集了约100张,包括不同位置、不同角度。

image.png
image.png
image.png
image.png
image.png

步骤3 Mind+训练手势分类模型

在Mind+ 2.0中新建“图像分类”项目,将采集的图片文件夹导入(自动按文件夹名分为5类+背景类)。训练过程非常快,几分钟后模型准确率就达到了95%以上。

image.png

导出训练好的模型(onnx格式)和yaml标签文件,就可以在Python中调用了。

image.png

步骤4 创意应用①——数字粒子效果

       粒子效果往往能带来很强的视觉冲击。我希望当识别到手指个数时,屏幕上的粒子能汇聚成对应的数字形状。

       实现思路

       用OpenCV提取数字图像的边缘点集(如数字“1”的轮廓点)。

       初始化200个粒子,随机分布在屏幕上。

       每个粒子分配一个目标点(来自当前数字的边缘点集)。

       每帧向目标点移动,同时保留一点随机抖动,看起来像“飞向”数字。

       关键代码片段:

代码
# 生成数字边缘点集
def get_digit_points_edge(digit, max_points=200):
    # 用PIL绘制数字,再用Canny提取边缘
    img = draw_digit_image(digit)
    edges = cv2.Canny(np.array(img), 50, 150)
    points = np.column_stack(np.where(edges > 0))
    points = [(int(p[1]), int(p[0])) for p in points]
    # 采样控制数量
    if len(points) > max_points:
        step = len(points) // max_points
        points = points[::step]
    return points

# 粒子更新
def update(self, dt):
    dx = self.target_x - self.x
    dy = self.target_y - self.y
    dist = math.hypot(dx, dy)
    if dist > 1:
        move = self.speed * dt
        self.x += dx / dist * move
        self.y += dy / dist * move

当识别结果从“2”变为“3”时,只需为每个粒子重新分配新的目标点,粒子就会自动改变运动方向,汇聚成新的数字。

 

eac5e9c41fb8125411869b4f203f4744_webwxgetmsgimg_&MsgID=9183723621574119940&skey=%40crypt_b90cd10e_764b03d3f77870d4a78863b96d9b8384.jpg
0237d1033281605ca509423e3f898649_webwxgetmsgimg_&MsgID=311873005974706686&skey=%40crypt_b90cd10e_764b03d3f77870d4a78863b96d9b8384.jpg

 

 

这个效果在屏幕上非常惊艳,就像有一群萤火虫在空中拼出数字。

步骤5 创意应用②——MQTT无线控制灯带

       光有屏幕上的动画还不够,我想让它能控制现实中的灯光。于是我用手头的掌控板(ESP32)和WS2812灯带做了一个接收端。

       发送端(Python)

       通过paho-mqtt库连接到本地SIoT服务器,当识别到不同手指个数时,向主题 siot/ai 发布不同的字符串指令。

代码
command_map = {
    '1': "ON",
    '2': "OFF",
    '3': "TOGGLE",
    '4': "RAINBOW",
    '5': "CLEAR",
}
if confidence > 0.5 and command != last_command:
    mqtt_client.publish("siot/ai", command)

       接收端(掌控板/Arduino)

       使用DFRobot IoT库订阅同一个主题,根据收到的字符串执行对应的灯效。例如收到“ON”时显示彩虹流光,“OFF”时熄灭,“RAINBOW”时进入旋转模式。

代码
void whensiot47aiReceived0() { neoPixel_P0.showRainbow(0, 11, 1, 360); }
void whensiot47aiReceived1() { neoPixel_P0.clear(); }
void whensiot47aiReceived3() { neoPixel_P0.rotate(1); }

       这样,用手在传感器前比划不同的手指个数,灯带就会实时响应。而且由于DTOF不依赖可见光,哪怕在完全黑暗的房间里,识别依然精准稳定。

e0622ddcbb6981c8f1f13788421db9fc_webwxgetmsgimg_&MsgID=7742889647921828884&skey=%40crypt_b90cd10e_764b03d3f77870d4a78863b96d9b8384.jpg

【项目亮点】

       真正“无光”识别:DTOF主动发射激光,环境光不影响性能,夜间使用体验远超摄像头。

从数据到模型的全流程:用上位机发现灰度图,用Python转图像,用Mind+训练,过程清晰,便于复现。

       双模态输出:既有屏幕上的视觉粒子反馈,也有物理世界的灯光控制,可玩性高。

低门槛扩展:MQTT协议的加入让手势信号可以轻易接入HomeAssistant、Node-RED等智能家居平台。

【总结与展望】

       这个项目将DTOF激光雷达、AI图像分类、粒子动画和物联网控制融合在一起,验证了“深度/强度数据 → 图像化 → 视觉识别”这一路线的可行性。相比摄像头方案,DTOF传感器在黑暗环境、复杂背景下的稳定性优势非常明显。

【完整代码】

1.电脑端Python代码,手势控数字粒子效果

 

代码
# -*- coding: UTF-8 -*-
import os
import sys
import time
import random
import math
import numpy as np
import pygame
import cv2
from PIL import Image, ImageDraw, ImageFont

# 导入传感器和模型模块
sys.path.append("../")
from DFRobot_64x8DTOF import DFRobot_64x8DTOF
from model_mp_core import ImageClassificationInference

# ------------------------- 传感器初始化 -------------------------
sensor = DFRobot_64x8DTOF(port="COM64", baudrate=921600)
if not sensor.begin():
    print("Sensor init failed")
    sys.exit(1)
sensor.config_frame_mode(sensor.FRAME_MODE_SINGLE)
sensor.config_measure_mode()
time.sleep(2)

# ------------------------- 模型初始化 -------------------------
model_path = "best.onnx"
yaml_path = "data.yaml"
inference = ImageClassificationInference(model_path, yaml_path)

# ------------------------- 图像生成函数 -------------------------
def intensity_to_image_adaptive(i_list, rows=8, cols=64, left_crop=12, right_crop=12, flip=False, min_intensity=0):
    grid = np.array(i_list).reshape(rows, cols).astype(np.float32)
    if left_crop > 0 or right_crop > 0:
        grid = grid[:, left_crop:cols-right_crop]
    grid[grid < min_intensity] = 0
    valid_vals = grid[grid > 0]
    if len(valid_vals) > 0:
        min_val = valid_vals.min()
        max_val = valid_vals.max()
        if max_val > min_val:
            img_data = ((grid - min_val) / (max_val - min_val) * 255).astype(np.uint8)
        else:
            img_data = np.zeros_like(grid, dtype=np.uint8)
    else:
        img_data = np.zeros_like(grid, dtype=np.uint8)
    img = Image.fromarray(img_data, mode='L')
    if flip:
        img = img.transpose(Image.FLIP_TOP_BOTTOM)
    img = img.resize((224, 224), Image.Resampling.BICUBIC)
    return img

# ------------------------- 数字边缘点集生成(使用OpenCV边缘检测)-------------------------
def get_digit_points_edge(digit, width=800, height=600, font_size=300, max_points=200):
    """
    生成数字的边缘点集,用于粒子系统。
    :param digit: 数字字符(1-5 或 背景)
    :param width: 最终画布宽度
    :param height: 最终画布高度
    :param font_size: 字体大小
    :param max_points: 最大粒子数量(采样控制)
    :return: 点坐标列表 [(x,y), ...]
    """
    if digit == '背景':
        return []  # 背景时无目标点

    # 创建大临时图像,避免裁剪
    temp_width = width * 2
    temp_height = height * 2
    img = Image.new('L', (temp_width, temp_height), 0)
    draw = ImageDraw.Draw(img)

    # 字体路径尝试
    font_paths = [
        "C:/Windows/Fonts/arial.ttf",
        "C:/Windows/Fonts/consola.ttf",
        "C:/Windows/Fonts/simhei.ttf",
        "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
        "/System/Library/Fonts/Helvetica.ttc"
    ]
    font = None
    for path in font_paths:
        try:
            font = ImageFont.truetype(path, font_size)
            break
        except:
            continue
    if font is None:
        font = ImageFont.load_default()

    # 在临时画布中心绘制数字
    draw.text((temp_width//2, temp_height//2), str(digit), fill=255, font=font, anchor='mm')

    # 裁剪到目标尺寸(居中裁剪)
    crop_left = (temp_width - width) // 2
    crop_top = (temp_height - height) // 2
    img = img.crop((crop_left, crop_top, crop_left+width, crop_top+height))

    # 转换为numpy数组,并提取边缘
    img_np = np.array(img)
    # 使用Canny边缘检测
    edges = cv2.Canny(img_np, 50, 150)
    # 获取边缘点的坐标(注意OpenCV坐标是(row,col))
    points = np.column_stack(np.where(edges > 0))
    # 转换为 (x,y) 格式
    points = [(int(p[1]), int(p[0])) for p in points]

    # 如果边缘点太多,均匀采样
    if len(points) > max_points:
        step = len(points) // (max_points-360)
        points = points[::step]

    return points

# 预生成数字1~5的边缘点集
digit_points = {}
for d in ['1', '2', '3', '4', '5']:
    digit_points[d] = get_digit_points_edge(d, max_points=200)
digit_points['背景'] = []

# 颜色风格(可选)
digit_color = {
    '1': (255, 100, 100),
    '2': (100, 255, 100),
    '3': (100, 100, 255),
    '4': (255, 255, 100),
    '5': (255, 100, 255),
    '背景': (128, 128, 128)
}

# ------------------------- 粒子类 -------------------------
class Particle:
    def __init__(self, x, y, target_pos=None):
        self.x = x
        self.y = y
        self.target_x, self.target_y = target_pos if target_pos else (x, y)
        self.vx = 0
        self.vy = 0
        self.color = (255, 255, 255)
        self.size = random.randint(2, 4)
        self.speed = 80  # 像素/秒,可调节

    def update(self, dt):
        dx = self.target_x - self.x
        dy = self.target_y - self.y
        dist = math.hypot(dx, dy)
        if dist > 1:
            move = self.speed * dt
            if move > dist:
                self.x = self.target_x
                self.y = self.target_y
            else:
                self.x += dx / dist * move
                self.y += dy / dist * move
        # 轻微抖动,增加生动感
        self.x += random.uniform(-0.5, 0.5)
        self.y += random.uniform(-0.5, 0.5)

    def draw(self, screen):
        pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.size)

# ------------------------- 粒子系统 -------------------------
class ParticleSystem:
    def __init__(self, width, height, num_particles=200):
        self.width = width
        self.height = height
        self.num_particles = num_particles
        self.particles = []
        self.current_digit = None
        self.target_points = []

        # 随机初始化粒子位置
        for _ in range(num_particles):
            x = random.randint(0, width)
            y = random.randint(0, height)
            self.particles.append(Particle(x, y))

    def set_digit(self, digit_name):
        if digit_name == self.current_digit:
            return
        self.current_digit = digit_name
        points = digit_points.get(digit_name, [])

        if not points:
            # 背景:随机漫游
            self.target_points = [(random.randint(0, self.width), random.randint(0, self.height)) for _ in range(self.num_particles)]
        else:
            # 使目标点数量与粒子数量一致
            if len(points) != self.num_particles:
                if len(points) < self.num_particles:
                    repeat_times = self.num_particles // len(points) + 1
                    points = points * repeat_times
                self.target_points = points[:self.num_particles]
            else:
                self.target_points = points

        # 更新每个粒子的目标
        for i, p in enumerate(self.particles):
            p.target_x, p.target_y = self.target_points[i]
            p.color = digit_color.get(digit_name, (255,255,255))

    def update(self, dt):
        for p in self.particles:
            p.update(dt)

    def draw(self, screen):
        for p in self.particles:
            p.draw(screen)

# ------------------------- 主程序 -------------------------
def main():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("数字粒子效果 - 手指个数控制")
    clock = pygame.time.Clock()
    font = pygame.font.Font(None, 36)

    particle_sys = ParticleSystem(800, 600, num_particles=200)

    running = True
    last_label = None
    confidence = 0.0

    while running:
        dt = clock.tick(60) / 1000.0

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # 从传感器获取数据并推理
        x, y, z, intensity = sensor.get_data(timeout_ms=200)
        if len(z) == 512:
            img = intensity_to_image_adaptive(intensity, left_crop=12, right_crop=12, flip=False, min_intensity=0)
            img = img.convert('RGB')
            img_np = np.array(img)
            result = inference.inference(img_np)

            # 解析结果
            label = 'unknown'
            confidence = 0.0
            if isinstance(result, dict) and 'result' in result:
                results_list = result['result']
                if results_list:
                    top = results_list[0]
                    label = top['class_name']
                    confidence = top['score']
            else:
                label = str(result)

            # 如果置信度较高才更新数字,避免频繁抖动
            if confidence > 0.5 and label != last_label:
                print(f"切换数字: {label} (置信度: {confidence:.2f})")
                particle_sys.set_digit(label)
                last_label = label

        # 更新粒子
        particle_sys.update(dt)

        # 绘制
        screen.fill((0, 0, 0))
        particle_sys.draw(screen)

        # 显示当前识别的文字
        text_surface = font.render(f"Fingers: {last_label if last_label else 'none'}  (conf: {confidence:.2f})", True, (255, 255, 255))
        screen.blit(text_surface, (10, 10))

        pygame.display.flip()

    sensor.close()
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

2.电脑端Python代码,手势控灯

代码
# -*- coding: UTF-8 -*-
import os
import sys
import time
import random
import numpy as np
import pygame
import paho.mqtt.client as mqtt
from PIL import Image
# 导入传感器和模型模块
sys.path.append("../")
from DFRobot_64x8DTOF import DFRobot_64x8DTOF
from model_mp_core import ImageClassificationInference

# ------------------------- 传感器初始化 -------------------------
sensor = DFRobot_64x8DTOF(port="COM64", baudrate=921600)
if not sensor.begin():
    print("Sensor init failed")
    sys.exit(1)
sensor.config_frame_mode(sensor.FRAME_MODE_SINGLE)
sensor.config_measure_mode()
time.sleep(2)

# ------------------------- 模型初始化 -------------------------
model_path = "best.onnx"
yaml_path = "data.yaml"
inference = ImageClassificationInference(model_path, yaml_path)

# ------------------------- 图像生成函数 -------------------------
def intensity_to_image_adaptive(i_list, rows=8, cols=64, left_crop=12, right_crop=12, flip=False, min_intensity=0):
    grid = np.array(i_list).reshape(rows, cols).astype(np.float32)
    if left_crop > 0 or right_crop > 0:
        grid = grid[:, left_crop:cols-right_crop]
    grid[grid < min_intensity] = 0
    valid_vals = grid[grid > 0]
    if len(valid_vals) > 0:
        min_val = valid_vals.min()
        max_val = valid_vals.max()
        if max_val > min_val:
            img_data = ((grid - min_val) / (max_val - min_val) * 255).astype(np.uint8)
        else:
            img_data = np.zeros_like(grid, dtype=np.uint8)
    else:
        img_data = np.zeros_like(grid, dtype=np.uint8)
    img = Image.fromarray(img_data, mode='L')
    if flip:
        img = img.transpose(Image.FLIP_TOP_BOTTOM)
    img = img.resize((224, 224), Image.Resampling.BICUBIC)
    return img

# ------------------------- MQTT 配置 -------------------------
MQTT_SERVER = "127.0.0.1"          # SIoT 服务器地址(本地)
MQTT_PORT = 1883                   # 默认端口
MQTT_TOPIC = "siot/ai"             # 发布主题
MQTT_USER = "siot"                     # 用户名(如需要)
MQTT_PASS = "dfrobot"                     # 密码

# 手指个数 → MQTT 消息映射(根据您的需求修改)
command_map = {
    '1': "ON",      # 识别为 1 时开灯
    '2': "OFF",     # 识别为 2 时关灯
    '3': "TOGGLE",  # 识别为 3 时切换状态
    '4': "BRIGHT_UP",
    '5': "BRIGHT_DOWN",
    '背景': "NONE"  # 背景不发送指令
}

def on_connect(client, userdata, flags, rc):
    print(f"Connected to MQTT broker with result code {rc}")

def on_publish(client, userdata, mid):
    print(f"Message published (mid: {mid})")

# 创建 MQTT 客户端
mqtt_client = mqtt.Client()
mqtt_client.on_connect = on_connect
mqtt_client.on_publish = on_publish

# 如果需要用户名密码
if MQTT_USER:
    mqtt_client.username_pw_set(MQTT_USER, MQTT_PASS)

# 连接(使用非阻塞方式,在循环中处理网络)
mqtt_client.connect(MQTT_SERVER, MQTT_PORT, 60)
mqtt_client.loop_start()  # 启动网络循环

# ------------------------- Pygame 显示(可选)-------------------------
pygame.init()
screen = pygame.display.set_mode((400, 200))
pygame.display.set_caption("手势控制台灯")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 36)

# ------------------------- 主循环 -------------------------
last_command = None
print("开始实时识别,按 Ctrl+C 退出")
try:
    while True:
        # 处理 pygame 事件(仅用于退出)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        # 获取传感器数据
        x, y, z, intensity = sensor.get_data(timeout_ms=200)
        if len(z) != 512:
            time.sleep(0.1)
            continue

        # 生成图像并推理
        img = intensity_to_image_adaptive(intensity, left_crop=12, right_crop=12, flip=False, min_intensity=0)
        img = img.convert('RGB')
        img_np = np.array(img)
        result = inference.inference(img_np)

        # 解析结果
        label = 'unknown'
        confidence = 0.0
        if isinstance(result, dict) and 'result' in result:
            results_list = result['result']
            if results_list:
                top = results_list[0]
                label = top['class_name']
                confidence = top['score']
        else:
            label = str(result)

        # 如果置信度足够高,且结果与上次不同,则发送 MQTT 指令
        if confidence > 0.5:
            command = command_map.get(label, None)
            if command and command != last_command:
                # 发布消息
                mqtt_client.publish(MQTT_TOPIC, command)
                print(f"发送指令: {command} (手指个数: {label}, 置信度: {confidence:.2f})")
                last_command = command

        # 在屏幕上显示当前状态
        screen.fill((0, 0, 0))
        text_surface = font.render(f"Fingers: {label}", True, (255, 255, 255))
        screen.blit(text_surface, (20, 50))
        cmd_surface = font.render(f"Last Cmd: {last_command if last_command else 'none'}", True, (200, 200, 200))
        screen.blit(cmd_surface, (20, 100))
        pygame.display.flip()

        time.sleep(0.2)  # 控制帧率

except KeyboardInterrupt:
    print("\n程序退出")

finally:
    mqtt_client.loop_stop()
    mqtt_client.disconnect()
    sensor.close()
    pygame.quit()
    sys.exit()

2.掌控板程序

screenshots-掌控板程序.mp-1774714918573.png

代码
/*!
 * MindPlus
 * mpython
 *
 */
#include <MPython.h>
#include <DFRobot_Iot.h>
#include <DFRobot_NeoPixel.h>

// 动态变量
volatile float mind_n_ZhuangTai;
// 函数声明
void whensiot47aiReceived0();
void whensiot47aiReceived1();
void whensiot47aiReceived2();
void whensiot47aiReceived3();
void whensiot47aiReceived4();
// 静态常量
const String topics[5] = {"","","","",""};
// 创建对象
DFRobot_NeoPixel neoPixel_P0;
DFRobot_Iot      myIot;


// 主程序开始
void setup() {
	mPython.begin();
	myIot.setCustomMqttCallback("siot/ai", "ON", whensiot47aiReceived0);
	myIot.setCustomMqttCallback("siot/ai", "TOGGLE", whensiot47aiReceived1);
	myIot.setCustomMqttCallback("siot/ai", "BRIGHT_UP", whensiot47aiReceived2);
	myIot.setCustomMqttCallback("siot/ai", "BRIGHT_DOWN", whensiot47aiReceived3);
	myIot.setCustomMqttCallback("siot/ai", "OFF", whensiot47aiReceived4);
	neoPixel_P0.begin(P0, 12);
	neoPixel_P0.clear();
	neoPixel_P0.setBrightness(50);
	rgb.write(-1, 0xFF0000);
	myIot.wifiConnect("sxs", "smj080823");
	while (!myIot.wifiStatus()) {yield();}
	rgb.write(-1, 0x0000FF);
	myIot.init("192.168.31.11","siot","7977834249786735","dfrobot", topics, 1883);
	myIot.connect();
	while (!myIot.connected()) {yield();}
	myIot.subscribeTopic("siot/ai");
	rgb.write(-1, 0x00FF00);
	neoPixel_P0.showRainbow(0, 11, 1, 360);
	delay(1000);
	rgb.write(-1, 0x000000);
	neoPixel_P0.clear();
	mind_n_ZhuangTai = 0;
}
void loop() {
	if ((mind_n_ZhuangTai==2)) {
		neoPixel_P0.rotate(1);
		delay(200);
	}
}


// 事件回调函数
void whensiot47aiReceived0() {
	neoPixel_P0.showRainbow(0, 11, 1, 360);
	mind_n_ZhuangTai = 1;
}
void whensiot47aiReceived1() {
	if ((mind_n_ZhuangTai==0)) {
		neoPixel_P0.showRainbow(0, 11, 1, 360);
		mind_n_ZhuangTai = 1;
	}
	else if ((mind_n_ZhuangTai==1)) {
		neoPixel_P0.clear();
		mind_n_ZhuangTai = 0;
	}
}
void whensiot47aiReceived2() {
	neoPixel_P0.showRainbow(0, 11, 1, 360);
	mind_n_ZhuangTai = 2;
}
void whensiot47aiReceived3() {
	neoPixel_P0.clear();
	mind_n_ZhuangTai = 0;
}
void whensiot47aiReceived4() {
	neoPixel_P0.clear();
	mind_n_ZhuangTai = 0;
}

评论

user-avatar
  • 云天

    云天2026.03.29

    cd /d C:\Users\lenovo\AppData\Local\mind+\python-block\local-1\Scripts python -m pip uninstall numpy -y python -m pip install numpy==1.26.4

    0