【聆思CSK6 视觉AI开发套件试用】AI控制直流电机转速接口打通

news2024/12/28 21:22:16

本篇文章来自极术社区与聆思科技组织的CSK6 视觉AI开发套件活动,更多开发板试用活动请关注极术社区网站。作者:oxlm

背景

在访问极术社区时,偶然发现聆思科技的CSK6开发板的评估活动,看CSK6的硬件配置和技术规格,300M的M33核 + 300M的HIFI4 + 128TOPS的NPU,完全有机会在我们公司内部的音视频产品上用上,因此申请了该方案的测评,以便更详细的了解该方案,也期待后续的音频模块,以便集中测试方案的音频部分以及音视频结合部分,确认是否可以满足我们的需求。

很荣幸,在第一批试用名单中被选中。

初步想法为: AI方式控风扇转速和舵机人物跟随,即风扇随人转动,且人靠近时降低转速,离远时提高转速,超出距离关闭风扇。由于目前暂时无自己训练接口,因此暂时先实现手势控风扇转速的功能。即OK手势开启风扇,停止手势关闭风扇,YES手势提高转速,like手势降低转速。

实现原理

风扇实现原理比较简单,本质上为一直流无刷(有刷)电机,通过调节电压大小调节转速,因此只需要使用一个供电切换开关加电容,使用PWM控制便可实现调速,因此在实现上,需要打通PWM接口。并将回调事件给到PWM接口上。
在不接外部电机的情况下,PWM效果可以使用板载LED灯观察,因此使用板载LED灯做功能初步实现。待外设就位后,再将LED灯接到外设看实际使用效果。

AI效果初探

参考:https://docs.listenai.com/chips/600X/ai_usage/hsgd/user_guide

拉取代码

lisa zep create --from-git https://cloud.listenai.com/zephyr/applications/app_algo_hsd_sample_for_csk6.git

打开webusb

在proj.conf中,将宏 CONFIG_WEBUSB改为y

编译代码

lisa zep build -b csk6011a_nano

此处出现过一次编译后的固件电脑报摄像头错误,此时通过运行以下命令重新编译后烧录修复:

lisa zep update
lisa zep build -b csk6001a_nano -p

烧录固件

lisa zep flash

烧录资源文件

板卡在我电脑上识别到的是串口6,因此命令中使用的是COM6

lisa zep exec cskburn -s \\.\COM6 -C 6 0x400000 .\resource\cp.bin -b 748800
lisa zep exec cskburn -s \\.\COM6 -C 6 0x500000 .\resource\res.bin -b 748800

电脑下载摄像头查看工具

git clone https://cloud.listenai.com/zephyr/applications/csk_view_finder_spd.git

安装驱动

由于摄像头查看软件使用的时libusb实现的hid接口,在windows下需使用zadig更换驱动,驱动更换方式如下:

效果验证

初步效果验证,发现误识别率偏高,遂按照文档建议0~3m参数调试

hsd_set_params(hsd, HSD_PARAM_HEAD_SHOULDER_DETECT_THRES, 0.35f);
hsd_set_params(hsd, HSD_PARAM_HEAD_SHOULDER_DETECT_PIXESIZE, 50.0f);

经过验证,此参数在1m左右识别准确度较高,可用于AI调试PWM

代码实现

1. 由于此时不需要再查看webusb,因此在proj.conf中将CONFIG\_WEBUSB置成n,之后编码实现
2. 在proj.conf中添加 CONFIG_PWM=y
3. 编写测试代码

/*
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <stdio.h>
#include <stdlib.h>

#include <csk_malloc.h>
#include <device.h>
#include <drivers/video.h>
#include <licak/licak.h>
#include <zephyr.h>

#define LOG_LEVEL 4
#include <logging/log.h>
LOG_MODULE_REGISTER(main);

#include "bitmap.h"

#include <zephyr/drivers/pwm.h>

#define VIDEO_DEV DT_LABEL(DT_NODELABEL(dvp))

static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(DT_ALIAS(pwm_led0));

#define MAX_PERIOD PWM_MSEC(1U)

// 240p
// #define IMAGE_HEIGHT 240
// #define IMAGE_WIDTH 320
// 480p
#define IMAGE_HEIGHT 480
#define IMAGE_WIDTH  640

#define IMAGE_SIZE (IMAGE_WIDTH * IMAGE_HEIGHT * 3)

#define MOCK_DATA (0)
#if MOCK_DATA
#include "input_640x480.h"
#endif

#define MSGQ_NUMBER 10

typedef struct {
    hsd_head_shoulder_detect result;
    head_shoulder_detect hsd;
    uint32_t data_len;
    hsd_event event;
} msg_data_t;

const struct device *video;

bool is_usb_cfg;

struct k_msgq msg;

int64_t time;

uint32_t max_period = MAX_PERIOD;
int32_t percent = 1u;

void on_receive_hsd_result(hsd_t *hsd, hsd_event event, void *data, void *user_data)
{
    if (event == HSD_EVENT_GESTURE_RECOGNIZE) {
        head_shoulder_detect *result = (head_shoulder_detect *)data;
        // LOG_INF("gesture result id: %d ,state: %d", result->id, result->gesture_state);

        msg_data_t msg_data = {.event = event};

        memcpy(&msg_data.hsd, result, sizeof(msg_data.hsd));

        k_msgq_put(&msg, &msg_data, K_NO_WAIT);
    }
}

void pwm_pulse_set(int32_t per)
{
    int ret;

    if (per <= 1) {
        per = 1;
    } else if (per >= 100) {
        per = 99;
    }

    ret = pwm_set_dt(&pwm_led0, max_period, max_period / 100 * per);
    if (ret) {
        printk("Error %d: failed to set pulse width %d\n", ret, percent / 2U);
        return;
    }
}

void main(void)
{
    if (0 != licak_init()) {
        printk("LICAK init failed,exit.\n");
        return;
    }

    video = device_get_binding(VIDEO_DEV);

    if (video == NULL) {
        LOG_ERR("Video device %s not found, "
            "fallback to software generator.",
            VIDEO_DEV);

        return;
    }

    struct video_format fmt;
    fmt.pixelformat = VIDEO_PIX_FMT_VYUY;
    fmt.width = IMAGE_WIDTH;
    fmt.height = IMAGE_HEIGHT;
    fmt.pitch = fmt.width * 2;
    if (video_set_format(video, VIDEO_EP_OUT, &fmt)) {
        LOG_ERR("Unable to set video format");
        return;
    }

    hsd_t *hsd = hsd_create(HSD_FLAG_HEAD_SHOULDER | HSD_FLAG_GESTURE_RECOGNIZE);
    if (hsd == NULL) {
        LOG_ERR("Create HSD instance failed.");
        return;
    }

    // hsd_event_register(hsd, HSD_EVENT_HEAD_SHOULDER, on_receive_hsd_result, NULL);
    hsd_event_register(hsd, HSD_EVENT_GESTURE_RECOGNIZE, on_receive_hsd_result, NULL);

    printk("- Device name: %s\n", VIDEO_DEV);

    static char buffer[sizeof(msg_data_t) * MSGQ_NUMBER];
    msg_data_t msg_data;
    k_msgq_init(&msg, buffer, sizeof(msg_data_t), MSGQ_NUMBER);

    hsd_set_params(hsd, HSD_PARAM_HEAD_SHOULDER_DETECT_THRES, 0.35f);
    hsd_set_params(hsd, HSD_PARAM_HEAD_SHOULDER_DETECT_PIXESIZE, 50.0f);

    // float value;
    // hsd_get_params(hsd, HSD_PARAM_HEAD_SHOULDER_DETECT_THRES, &value);
    // LOG_INF("GET_PARAMS: %d %f", HSD_PARAM_HEAD_SHOULDER_DETECT_THRES, value);

    // hsd_get_params(hsd, HSD_PARAM_HEAD_SHOULDER_DETECT_PIXESIZE, &value);
    // LOG_INF("GET_PARAMS: %d %f", HSD_PARAM_HEAD_SHOULDER_DETECT_PIXESIZE, value);

    hsd_start(hsd, video);

    if (!device_is_ready(pwm_led0.dev)) {
        printk("Error: PWM device %s is not ready\n", pwm_led0.dev->name);
        return;
    }

    while (1) {
        int ret = k_msgq_get(&msg, &msg_data, K_FOREVER);
        if (ret != 0) {
            LOG_WRN("Get video buffer timeout.");
            continue;
        }

        switch (msg_data.event) {
        case HSD_EVENT_GESTURE_RECOGNIZE:
            switch (msg_data.hsd.gesture_state) {
            case GESTURE_LIKE:
                percent -= 10;
                if (percent < 10) {
                    percent = 10;
                }
                pwm_pulse_set(percent);
                LOG_INF("Speed down %d\n", percent);
                break;

            case GESTURE_OK:
                pwm_pulse_set(percent);
                LOG_INF("On %d\n", percent);
                break;

            case GESTURE_STOP:
                pwm_pulse_set(0);
                LOG_INF("Off");
                break;

            case GESTURE_YES:
                percent += 10;
                if (percent >= 100) {
                    percent = 99;
                }
                pwm_pulse_set(percent);
                LOG_INF("Speed up %d\n", percent);
                break;

            case GESTURE_OTHER:
            case GESTURE_SIX:
            default:
                break;
            }
            break;
        default:
            break;
        }
    }

    hsd_stop(hsd);

    hsd_destroy(hsd);

    LOG_DBG("AP EXEC END\n");
}

实现效果

stop手势时,绿灯亮
OK手势时,绿灯灭
like手势时,绿灯变亮
yes手势时,绿灯变暗

进一步效果需等PWM后级做好后直接接上验证

遇到问题

  • 装有企业版360杀毒软件的电脑无法安装
    由于关闭权限在IT,无法关闭,暂时改用个人电脑编码
  • pwm不能设置成100%占空比和0%占空比
    待继续查看底层实现,确定原因

建议

通过proj.conf方式配置参数开关的方式,其实不是那么方便,比如我需要开PWM,我自己得往里面写一个 CONFIG_PWM=y才行,也就是说,我得知道有这么个宏才能打开PWM。
个人建议要么proj.conf将代码中可用于配置的宏全部添加,不用置为n。要么学RTT和linux驱动方式的配置,通过Kconfig来做功能模块的开关,否则只能通过查看官方文档才能实现功能模块的添加。
从文档上看,该条建议已经实现,之前学时使用时未看到该部分

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript奇淫技巧:变速齿轮

JavaScript奇淫技巧&#xff1a;变速齿轮 在PC时代&#xff0c;曾有个名为“变速齿轮”的神奇软件&#xff0c;可以加快或减慢系统时间。 当时常用来修改游戏速度&#xff0c;可实现外挂一般的效果&#xff0c;很不可思议。 本文&#xff0c;将用JavaScript复刻这一功能&…

maven在无互联网(内网)环境下打包

Maven在内网环境打包 首先需要准备好项目所需的所有依赖包 我们可以在外网环境下&#xff0c;更改idea中Maven的local repository目录&#xff0c;然后刷新一下项目&#xff0c;将项目所需的依赖下载到更换的目录下 将新建的依赖目录和项目一起拷贝到内网环境下将依赖文件拷贝…

带你学懂数据结构中的八大排序(下)

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; 数据结构 | C语言 &#x1f38a;每篇一句&#xff1a; 图片来源 You can avoid reality, but you cannot avoid the consequences of avoiding reality. 你可以逃避现实&#xff0c;但你无法逃避其带来的后果…

《图解TCP/IP》阅读笔记(第八章 8.1~8.4)—— 概要,TELNET、FTP、SMTP、POP、IMAP协议介绍

前言 本篇篇幅较长&#xff0c;请耐心或者选择性阅读。 第八章 应用协议 从本篇开始&#xff0c;将介绍一些应用层协议&#xff0c;一般情况下&#xff0c;人们不太会在意网络应用程序实际上是按照何种机制正常运行的。本章旨在介绍TCP/IP中所使用的几个主要应用协议&#x…

项目管理中,培养高效项目团队的6大优势

大多数项目经理知道合作会促进生产力&#xff0c;并且对不同的团队都很有效。良好的团队合作使你能够顺利地运行不同的项目&#xff0c;克服障碍并实现目标。 它也会使完成项目所需的时间减少&#xff0c;并使资源得到更好的管理。更不用说&#xff0c;高质量的团队合作将有助…

第十四讲:神州交换机链路聚合配置

链路聚合&#xff08;Link Aggregation&#xff09;又称Trunk&#xff0c;是指将多个物理端口捆绑在一起&#xff0c;成 为一个逻辑端口&#xff0c;以实现出/入流量在各成员端口中的负荷分担&#xff0c;交换机根据用户配置的端口负荷分担策略决定报文从哪一个成员端口发送到对…

如何快速理解Python中的for循环?

人生苦短&#xff0c;我用python 这次来给大家带来一点干货&#xff0c; 我们将从一组基本例子和它的语法开始&#xff0c; 还将讨论与 for 循环关联的 else 代码块的用处。 然后我们将介绍迭代对象、迭代器和迭代器协议&#xff0c; 还会学习如何创建自己的迭代对象和迭代器…

微信小程序云开发之用户输入数据后excel表格导出升级版

大家好&#xff0c;我是csdn的小博主lqj_本人&#xff0c;最近在哔哩哔哩开始上传我的制作微信小程序的详细流程&#xff0c;大家可以关注一下哔哩哔哩&#xff1a;小淼前端 本次程序的详细视频教程已上传至哔哩哔哩&#xff1a; 腾讯云开发小程序之用户输入数据excel自动导出系…

HaaS EDU物联网项目实战:微信小程序实现云养花

HaaS EDU K1是一款高颜值、高性能、高集成度的物联网开发板&#xff0c;板载功能强大的4核&#xff08;双核300Mhz M33双核1GHz A7&#xff09;主芯片&#xff0c;2.4G/5G双频Wi-Fi&#xff0c;双模蓝牙&#xff08;经典蓝牙/BLE&#xff09;&#xff0c;并自带丰富的传感器与小…

第一章 vscode安装java环境

要在Visual Studio Code中配置Java环境&#xff0c;需要完成以下步骤&#xff1a; 安装Java Development Kit (JDK)。首先&#xff0c;你需要安装Java Development Kit (JDK)&#xff0c;这是Java的开发环境&#xff0c;包含了Java虚拟机、Java编译器和Java库等。可以前往Oracl…

Python基础知识入门(五)

Python基础知识入门&#xff08;一&#xff09; Python基础知识入门&#xff08;二&#xff09; Python基础知识入门&#xff08;三&#xff09; Python基础知识入门&#xff08;四&#xff09; 一、模块应用 模块是一个包含所有定义的函数和变量的文件&#xff0c;其后缀名…

2022年「博客之星」参赛博主:(天寒雨落)在等您评价 ~

目录 评价方法 参与规则 评选规则 评分规则 活动奖品 评价方法 点击链接&#xff1a;2022年「博客之星」参赛博主&#xff1a;天寒雨落-CSDN社区 在箭头所指位置做出打星评价。 参与规则 1.本次年度评选分为「博客之星|和「博客新星:以及「社区之星|。「博客新星:只针对…

Kafka — 1、基础介绍

1、消息队列简介 &#xff08;1&#xff09;同步&#xff1a;多个服务之间是同步完成一次请求 缺点&#xff1a; a. 性能比较差 b. 稳定性比较差&#xff0c;如果其中一个服务没有执行成功&#xff0c;则整个请求执行失败 &#xff08;2&#xff09;异步&#xff1a;加入【消息…

自动控制原理笔记-线性系统的稳态误差

目录 1.误差与稳态误差 2.计算稳态误差的一般方法 3.静态误差系数法 例题&#xff1a; 稳态误差是系统的稳态性能指标&#xff0c;是系统控制精度的度量。 这里讨论的只是系统的原理性误差&#xff0c;不包括非线性等因素所造成的附加误差。 计算系统的稳态误差以系统稳定…

洛谷千题详解 | P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题【C++语言】

博主主页&#xff1a;Yu仙笙 专栏地址&#xff1a;洛谷千题详解 目录 题目描述 输入格式 输出格式 输入输出样例 解析&#xff1a; C源码&#xff1a; C源码2&#xff1a; C源码3&#xff1a; ------------------------------------------------------------------------------…

2022博客之星年度总评选开始了

作者简介&#xff1a;陶然同学 专注于Java领域开发 熟练掌握Java、js等语言的“Hello World” CSDN原力计划作者、CSDN内容合伙人、Java领域优质作者、Java领域新星作者、51CTO专家、华为云专家、阿里云专家等 &#x1f3ac; 陶然同学&#x1f3a5; 由 陶然同学 原创&#…

Linux之SQL Server数据库安装

一、SQL Server简介 SQL Server 是一个关系数据库管理系统。它最初是由Microsoft Sybase 和Ashton-Tate三家公司共同开发的&#xff0c;于1988 年推出了第一个OS/2 版本。在Windows NT 推出后&#xff0c;Microsoft与Sybase 在SQL Server 的开发上就分道扬镳了&#xff0c;Micr…

密码学 公开密钥管理

PKU概念 Public Key Infrastructure PKI一般指公钥基础设施。 公钥基础设施是一个包括硬件、软件、人员、策略和规程的集合&#xff0c;用来实现基于公钥密码体制的密钥和证书的产生、管理、存储、分发和撤销等功能。 基于PKI的信任模型 如果一个个体假设CA 能够建立并维持一…

ASP.NET Core 3.1系列(21)——EFCore中的更新实体操作

1、前言 前面的博客已经介绍过EFCore中关于新增和删除实体的相关操作&#xff0c;本文开始介绍EFCore中的更新实体操作。与新增实体和删除实体相比&#xff0c;更新实体的操作略微有些复杂&#xff0c;如果在代码的写法上不多加注意&#xff0c;那就很有可能会在后台生成效率低…

利用空余时间成为“业余”的自动驾驶的开发者

作为一名开发者&#xff0c;我时常会阅读一些相关的技术杂志和周刊&#xff0c;了解一些近期比较热门的技术和事件&#xff0c;要说现在技术领域最有发展前景的方向之一&#xff0c;很多人会想到自动驾驶。但现在国内做自动驾驶平台的并不多&#xff0c;其中百度做得是相对比较…