donatello1996

    1. 【2024 DigiKey 创意大赛】- 2/330 DigiKey得捷技术专区 2024-11-04
      因为这段时间有别的事情要忙,没有对7月份报名的这个得捷比赛有很高的完成度,但是这段时间对语音合成感兴趣,用VITS语音合成库做了一些有意思的东西,并且由于VITS库目前只有Python代码,还顺带简单了解了下Python的一些机制以及学习如何将Python代码和C++工程相结合,也就是在C++ makefile工程里直接调用Python的工程。目前我在网上找到的容易入门且实用的VITS语音合成库是出自CjangCjengh这位B站UP主在github分享的MoeGoe应用代码库,以及,功能多样,代码使用Python搭建,可支持Windows和Linux多平台部署,所以可以部署在树莓派等ARM aarch64架构的单板计算机上面。如图所示:   左上角为MoeGoe源码,第二行第二列的MoeGoe_GUI是基于MoeGoe应用源码的C#上位机,可以直接在Windows上运行,这个上位机清楚演示了MoeGoe源码的基本功能,如选择VITS AI语音模型,语音配置,说话人语气配置,生成的mp3文件的存放目录等,比如我这里选择的是《碧蓝档案》手游天童爱丽丝的AI语音模型,以及(《赛马娘》手游日文名:ウマ娘)的草上飞语气:   Windows的部署和运行,UP主已经做好,要做的就是在报名参赛的物料树莓派5B单板计算机上部署,将源码拷到树莓派5B上:   需要留意树莓派最新版本镜像所选的Python版本,这是跟后续安装的wheel支持库紧密相关的,如图,这是3.11.2版本:   修改Python代码,将AI模型文件等参数以函数形参的方式传入,这样的话,给外部的C++工程调用就可以直接传参指定参数了:   Python是脚本语言,不需要编译,直接运行即可: Python3 MoeGoe.py 在运行过程中需要安装非常多的支持库,Python可支持在线安装和离线安装,离线安装wheel文件的方式和在线安装是一样的,都是通过 pip3 install 指令进行: 并且由于树莓派环境的特殊性,安装的时候需要加入参数--break-system-packages来打破系统限制,不然装不了外部wheel文件: pip3 install scipy --break-system-packages pip3 install torch --break-system-packages   运行时指定输入的普通话语音(当然也支持日语),即可生成mp3文件,不过受限于树莓派5B的CPU和RAM限制,无法生成太长的语音,会中途闪退结束程序。   下面分享一下在C++工程中调用Python代码的方式: void Python_Local_VITS_API(string str) { str = "\"[ZH]" + str + "[ZH]\""; str = removeNewlines(str); printf("str = %s.\n" , str.c_str()); Py_Initialize(); if (!Py_IsInitialized()) { printf("ERROR:C++ Python API init fail.\n"); } PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('/home/MoeGoe-3.0.1/')"); PyObject *pModule = PyImport_ImportModule("MoeGoe"); if (pModule == NULL) { printf("ERROR:MoeGoe.py loaded failed!\n"); } PyObject *pFunc = PyObject_GetAttrString(pModule , "moegoe_main"); if (!PyCallable_Check(pFunc)) { printf("ERROR:Python fun moegoe_main load failed.\n"); } PyObject* args = PyTuple_New(4); PyTuple_SetItem(args , 0 , Py_BuildValue("s" , "/home/voice_model/alice.pth")); PyTuple_SetItem(args , 1 , Py_BuildValue("s" , str.c_str())); PyTuple_SetItem(args , 2 , Py_BuildValue("i" , 1)); PyTuple_SetItem(args , 3 , Py_BuildValue("s" , "/home/1.wav")); if (!PyCallable_Check(pFunc)) { printf("ERROR:Python fun args load failed.\n"); } PyObject* ret = PyObject_CallObject(pFunc , args); // PyArg_Parse(ret , "i" , &result); // printf("result = %d.\n" , result); printf("After PyObject_CallObject.\n"); Py_DECREF(pFunc); Py_DECREF(pModule); Py_Finalize(); printf("After Py_Finalize.\n"); } Py_Initialize()和Py_Finalize()是搭建和解散Python运行环境的操作,PyImport_ImportModule()是加载py文件,也就是可以使用py文件里面的函数进行操作, PyTuple_SetItem()用于设置参数,s代表字符串,i代表整数,PyObject_CallObject()运行函数,可带参可无参,第二个参数填NULL就是无参,将函数运行之后,生成语音文件保存在本地目录/home/1.wav:   使用本地语音合成功能有两个好处,第一是语音生成的时间短,第二是可以很方便的合成各种数据检测数据,比如:   [localvideo]6cd6dff533f0412993606e56267b1f19[/localvideo]   这次比赛申请的雷达传感器物料没怎么研究,就接了个串口线跑了下:   非常平平无奇,但是非常好用。
    2. 常见泽1 发表于 2024-1-31 15:09 STM32H7只负责显示吗 大佬
      是的啊,本来想用来做网口控制的,启用网口需要改PCB电阻焊点,不舍得动烙铁,毕竟是好板,早知道买树莓派来做一步到位。
    3. 基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) 内容已提交至新帖,此帖作废
    4. 本帖最后由 donatello1996 于 2024-1-16 23:27 编辑   功能解析与代码片段解读(STM32H747开发板部分): LVGL界面初始化,需要初始化三个文本框,两个按钮,三个文本框中的最顶部框为状态指示框,分别显示语音识别流程,从录音->录音语音识别->访问文心一言获取回答->将回答进行语音合成->播放五个环节,环节循环进行; 第二个文本框为录音问题提问框,将录音识别而成的文字显示在此框; 第三个文本框位回答显示框,将文心一言的回答文字显示在此框; 【开始流程】按钮按下后录音开始,整个流程也开始; 【清除问题和回答】框将问题文本框和回答文本框的内容全部清除;       void lv_mainstart(void) { uint8_t utf8_chinese[200]; dropdown_font = &myFont; //dropdown_font = &lv_font_montserrat_22; dropdown_width = 150; ta_state = lv_textarea_create(lv_scr_act()); lv_obj_align(ta_state , LV_ALIGN_TOP_LEFT , 10 , 10); lv_obj_set_style_text_font(ta_state , dropdown_font, LV_STATE_DEFAULT); //lv_obj_add_event_cb(ta,textarea_Show1_event_cb,LV_EVENT_READY,ta); lv_obj_set_size(ta_state , 700 , 50); lv_obj_add_state(ta_state , LV_STATE_FOCUSED); ta_question = lv_textarea_create(lv_scr_act()); lv_obj_align(ta_question , LV_ALIGN_TOP_LEFT , 10 , 60); lv_obj_set_style_text_font(ta_question , dropdown_font, LV_STATE_DEFAULT); //lv_obj_add_event_cb(ta,textarea_Show1_event_cb,LV_EVENT_READY,ta); lv_obj_set_size(ta_question , 700 , 99); lv_obj_add_state(ta_question , LV_STATE_FOCUSED); //lv_obj_add_state(ta1 , LV_STATE_DEFAULT); btn_start = lv_btn_create(lv_scr_act()); lv_obj_set_size(btn_start, 200 , 50); lv_obj_align(btn_start, LV_ALIGN_TOP_LEFT, 10 , 160); lv_obj_add_event_cb(btn_start, btn_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_t* label_btn_start = lv_label_create(btn_start); lv_obj_set_style_text_font(label_btn_start , dropdown_font, LV_PART_MAIN); lv_obj_set_align(label_btn_start , LV_ALIGN_CENTER); ANSI_to_UTF8("开始流程" , utf8_chinese); lv_label_set_text(label_btn_start , utf8_chinese); btn_clean = lv_btn_create(lv_scr_act()); lv_obj_set_size(btn_clean , 300 , 50); lv_obj_align(btn_clean , LV_ALIGN_TOP_LEFT, 220 , 160); lv_obj_add_event_cb(btn_clean , btn_event_cb, LV_EVENT_CLICKED, NULL); lv_obj_t* label_btn_clean = lv_label_create(btn_clean); lv_obj_set_style_text_font(label_btn_clean , dropdown_font, LV_PART_MAIN); lv_obj_set_align(label_btn_clean , LV_ALIGN_CENTER); ANSI_to_UTF8("清除问题和回答" , utf8_chinese); lv_label_set_text(label_btn_clean , utf8_chinese); ta_answer = lv_textarea_create(lv_scr_act()); lv_obj_align(ta_answer , LV_ALIGN_TOP_LEFT , 10 , 211); lv_obj_set_style_text_font(ta_answer , dropdown_font, LV_STATE_DEFAULT); //lv_obj_add_event_cb(ta,textarea_Show1_event_cb,LV_EVENT_READY,ta); lv_obj_set_size(ta_answer , 700 , 268); lv_obj_add_state(ta_answer , LV_STATE_DEFAULT); }   点击按钮控制GPIO发送上升沿信号,GPIO初始化状态为低电平,状态文本框会在不同阶段实时改变: static void btn_event_cb(lv_event_t* e) { lv_obj_t *target = lv_event_get_target(e); if(target == btn_start) { printf("btn_start.\n"); HAL_GPIO_WritePin(GPIOJ , GPIO_PIN_0 , GPIO_PIN_SET); } else if(target == btn_clean) { printf("btn_clean.\n"); lv_textarea_set_text(ta_question , ""); lv_textarea_set_text(ta_answer , ""); } } void GPIOJ0_Init() { GPIO_InitTypeDef GPIO_InitStruct; __HAL_RCC_GPIOJ_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOJ , &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOJ , GPIO_PIN_0 , GPIO_PIN_SET); } lv_init(); lv_port_disp_init(); lv_port_indev_init(); lv_mainstart(); while(1) { count ++; if(count > 100) { count = 0; HAL_GPIO_WritePin(GPIOJ , GPIO_PIN_0 , GPIO_PIN_RESET); } lv_task_handler(); lv_tick_inc(1); if(uart8_recv_end_flag) { uart8_recv_end_flag = 0; printf("rx8_buf[0] == 0x%x && rx8_buf[1] == 0x%x.\n" , rx8_buf[0] , rx8_buf[1]); if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x11) { ANSI_to_UTF8(rx8_buf + 2 , utf8_global); lv_textarea_set_text(ta_state , utf8_global); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x12) { ANSI_to_UTF8(rx8_buf + 2 , utf8_global); lv_textarea_set_text(ta_question , utf8_global); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x13) { ANSI_to_UTF8(rx8_buf + 2 , utf8_global); lv_textarea_set_text(ta_answer , utf8_global); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x14) { lv_textarea_set_text(ta_question , rx8_buf + 2); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x15) { lv_textarea_set_text(ta_answer , rx8_buf + 2); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x16 && rx8_buf[2] == 1) { BSP_LED_Off(LED_RED); BSP_LED_Off(LED_ORANGE); BSP_LED_Off(LED_BLUE); BSP_LED_Off(LED_GREEN); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x16 && rx8_buf[2] == 2) { BSP_LED_On(LED_RED); BSP_LED_Off(LED_ORANGE); BSP_LED_Off(LED_BLUE); BSP_LED_Off(LED_GREEN); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x16 && rx8_buf[2] == 3) { BSP_LED_Off(LED_RED); BSP_LED_On(LED_ORANGE); BSP_LED_Off(LED_BLUE); BSP_LED_Off(LED_GREEN); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x16 && rx8_buf[2] == 4) { BSP_LED_Off(LED_RED); BSP_LED_Off(LED_ORANGE); BSP_LED_On(LED_BLUE); BSP_LED_Off(LED_GREEN); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x16 && rx8_buf[2] == 5) { BSP_LED_Off(LED_RED); BSP_LED_Off(LED_ORANGE); BSP_LED_Off(LED_BLUE); BSP_LED_On(LED_GREEN); } else if(rx8_buf[0] == 0x11 && rx8_buf[1] == 0x16 && rx8_buf[2] == 6) { BSP_LED_On(LED_RED); BSP_LED_On(LED_ORANGE); BSP_LED_On(LED_BLUE); BSP_LED_On(LED_GREEN); } } }  
    5. 【基于AI摄像头的场景重现项目】项目提交 11/3365 DigiKey得捷技术专区 2022-11-02
      Brother Long is qiangility
    6. Dalao Xu is lihaility
    7. Leader Qiao is niubility
    8. ly87802541 发表于 2022-10-28 12:38 可以可以,干货满满!  
      谢谢
    9. ly87802541 发表于 2022-10-28 11:41 厉害了我的哥!
      看截图效果还行,但是实际上显示效果很差,树莓派的CPU算力去做classify并没有想象中的快,刷新频率几秒才一帧,太挫了,要商用更是扯淡
    10. 希望前两位大佬能搞一下IMX8MP的片上NPU模块,不要浪费资源
    11. 【Perf-V评测】点灯实验 1/2514 FPGA/CPLD 2021-02-15
      你哪里是小菜鸟,Verilog我看都看不懂呢,啥子玩意噢
    12. 搞事情预警~~~~啦啦啦~快进帖前排了解 14/2086 测评中心专版 2021-01-15
      米尔FZ5
    13. 个人信息无误,确认可以完成评测计划。
    14. freebsder 发表于 2020-9-8 16:03 图片不错。搞了这么多事情,楼主算是把F769摸透了
      一个月之前的帖子...
    15. littleshrimp 发表于 2020-9-8 09:25 这个板子的屏幕不错,H7好像也是这块屏,看你的代码简单改一下,弄成TF卡加载JPG文件就可以实现一个电子相 ...
      读取JPG文件之前有帖子写了,并不顺利
    16. freebsder 发表于 2020-8-11 20:54 挺好啊,写的很详细,幸好我转手了,要不和你比就相形见绌了。
      谢谢道长,道长过奖了
    17. freebsder 发表于 2020-8-10 18:59 你这是想搞到100分啊?
      哈哈道长见笑了,反正这段时间都有在玩这板,写一下心得罢了
    18. 初步推测,能输出更高频率PWM方波跟定时器本身有关系,试下换TIM2 TIM3这些更常用的定时器,看看能能不能输出更高频率的方波,做这个PWM实验的一大难题是开发板引出的GPIO引脚极其稀少,大部分都被FMC和LTDC两个接口的外设占用掉了,Arduino接口上引出的那些引脚每一个都是非常宝贵的资源。
    19. 又有板子开箱!这回是兆易GD32307E-START开发板 13/2527 国产芯片交流 2020-08-10
      接口啥的不介意,反正搞嵌入式的是不允许出现缺数据线的情况的,比较介意的地方是外设太少了,光秃秃一块核心板,不说液晶屏SDRAM那些,至少传感器焊几粒啊,真的没兴趣
    20. freebsder 发表于 2020-8-6 22:16 啥问题?简单说。。。
      使用echo方式测试TCP,第一,接收TCP报文的次数有限,接收了几条之后就哑火了,没法接续接收了,第二,TCP服务器在接入一段时间之后自动断开了

最近访客

< 1/6 >

统计信息

已有294人来访过

  • 芯积分:146
  • 好友:1
  • 主题:65
  • 回复:91

留言

你需要登录后才可以留言 登录 | 注册


早晨五点 2018-7-13
在吗哥,我想请教您一个问题。我用HAL库的接收中断接收数据为什么接收到的数据总是变换次序?比如第2个数据变成第一个,第三个编程第二个。。。我应该怎么办呢?希望您能帮助我一下
查看全部