- 2024-11-04
-
回复了主题帖:
【2024 DigiKey 创意大赛】-
因为这段时间有别的事情要忙,没有对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]
这次比赛申请的雷达传感器物料没怎么研究,就接了个串口线跑了下:
非常平平无奇,但是非常好用。
- 2024-10-31
-
发表了主题帖:
【2024 DigiKey 创意大赛】-
打个草稿
- 2024-09-03
-
发表了主题帖:
【2024 DigiKey 创意大赛】物料开箱
在比赛中下单的树莓派5 8G、IPS25XX编码器、雷达模块收到了一段时间,因为忙于别的事情没法物料开箱,现分享,树莓派5 8G插卡通电测试无任何问题
另外得捷还送了好看的贴纸,非常好贴纸,使我树莓派风扇宣传
- 2024-06-16
-
发表了主题帖:
【2023 DigiKey大赛参与奖】开箱帖,晒照树莓派5 4G内存版本
- 2024-02-03
-
回复了主题帖:
基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统
常见泽1 发表于 2024-1-31 15:09
STM32H7只负责显示吗 大佬
是的啊,本来想用来做网口控制的,启用网口需要改PCB电阻焊点,不舍得动烙铁,毕竟是好板,早知道买树莓派来做一步到位。
- 2024-01-18
-
回复了主题帖:
【DigiKey“智造万物,快乐不停”创意大赛】基于STM32H747Disco和百度语音云的语音...
基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn)
内容已提交至新帖,此帖作废
- 2024-01-17
-
发表了主题帖:
基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统
基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统
作者:donatello1996
一、作品简介(100-200字)
作品采用得捷上购买的STM32H747Disco开发板,使用LVGL图形库做界面交互
,通过串口,信号线及外部高速总线与ARM Linux板通信,访问百度语音云做语音识别、语音合成以及做振动信号采集。STM32H747Disco开发板承担图像显示,信号控制指令以及AD采集工作。
系统框图(图文结合)
如图,STM32H747Disco开发板与ARM Linux开发板的串口通信是双向的,ARM Linux开发板在整个流程中通过串口改变STM32H747Disco开发板显示内容。STM32H747Disco通过一根信号线输出到ARM Linux开发板上,以发出流程开始信号。ARM Linux开发板通过摄像头麦克风录入声音,通过以太网连接百度语音云,并通过扬声器输出声音。
STM32H747Disco开发板软件流程如下,如图,使用了LVGL图形库,SDRAM外扩内存访问以及QSPI字库存储读取:
ARM Linux板软件流程如下,录音、语音识别、访问文心一言、语音合成、语音播报都是独立完成的,分属不同功能:
三、各部分功能说明(图文结合)
使用外部自定义字库需要烧录字库文件到QPI上,所以需要CubeProgrammer软件帮忙:
功能说明与代码片段解读(STM32H747开发板部分):
LVGL界面初始化,需要初始化三个文本框,两个按钮,三个文本框中的最顶部框为状态指示框,分别显示语音识别流程,从录音->录音语音识别->访问文心一言获取回答->将回答进行语音合成->播放五个环节,环节循环进行;
第二个文本框为录音问题提问框,将录音识别而成的文字显示在此框;
第三个文本框位回答显示框,将文心一言的回答文字显示在此框;
【开始流程】按钮按下后录音开始,整个流程也开始;
【清除问题和回答】框将问题文本框和回答文本框的内容全部清除;
LV_FONT_DECLARE(myFont)
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);
}
运行时,按下开始流程按钮,发送指令到ARM Linux开发板:
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 , "");
}
}
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);
}
}
}
功能说明与代码片段解读(ARM Linux开发板部分):
初始化信号脚GPIO:
int MYGPIO_GPIOD_Init()
{
gpiochip3 = gpiod_chip_open("/dev/gpiochip3");
if (!gpiochip3)
{
printf("Open /dev/gpiochip3 failed.\n");
return -1;
}
gpiochip3_a5 = gpiod_chip_get_line(gpiochip3 , 5);
if (!gpiochip3_a5)
{
printf("Get gpiochip1_a2_rst line failed.\n");
return -1;
}
// if (gpiod_line_request_output(gpiochip1_a2_rst , "my_output", GPIOD_LINE_ACTIVE_STATE_LOW))
// {
// printf("Configuring gpiochip1_a2_rst as output failed.\n");
// return -1;
// }
if (gpiod_line_request_rising_edge_events(gpiochip3_a5 , "my_input") < 0)
{
printf("Request gpiochip1_a4_dio0 events failed.\n");
return -1;
}
}
void GPIO3_A5_Read()
{
if (gpiod_line_event_wait(gpiochip3_a5 , NULL) < 0)
{
printf("Wait event failed.\n");
return ;
}
if (gpiod_line_event_read(gpiochip3_a5 , &event) < 0)
{
printf("Wait event failed.\n");
return;
}
printf("GPIO3_A5_Read interrupt detected!\n");
}
GPIO接收到开始录音的上升沿信号,开始程序流程:
MYGPIO_GPIOD_Init();
fd_uart0 = Uart_Open(UART_DEV);
if (fd_uart0 < 0)
{
printf("open %s failed\n" , UART_DEV);
return 0;
}
ret = Uart_Set(fd_uart0, 115200 , 8, 'n', 1, 'n');
if (ret == -1)
{
return 0;
}
while(1)
{
UART3_Send_State(STATE_PROGRAM_START);
UART3_Send_State_Textarea("等待录音...");
GPIO3_A5_Read();
UART3_Send_State_Textarea("正在录音中...");
printf("before system arecord.\n");
UART3_Send_State(STATE_RECORDING);
system("arecord -f S16_LE -c 1 -r 16000 -d 8 -Dhw:2 /home/16k.wav");
printf("after system arecord.\n");
UART3_Send_State(STATE_RECORDED_QUESTIONING);
UART3_Send_State_Textarea("录音完毕,等待语音识别提问...");
sleep(1);
Baidu_TSR(baidu_api_key_test , baidu_secret_key_test , baidu_cuid_test , baidu_tsr_filename_test , baidu_tsr_format_test ,
baidu_tsr_dev_pid_test , baidu_tsr_scope_test , baidu_tsr_rate_test);
UART3_Send_State(STATE_QUESTIONED_ANSWERING);
UART3_Send_State_Textarea("语音识别提问完毕,正在访问文心一言获取回答...");
UART3_Send_Question_Textarea_UTF8(baidu_xtts_text_test);
printf("before Baidu_ERNIE_BOT_4.\n");
answer = Baidu_ERNIE_BOT_4(baidu_xtts_text_test);
printf("answer = %s.\n" , answer.c_str());
printf("after Baidu_ERNIE_BOT_4.\n");
UART3_Send_State(STATE_ANSWERED_XTTSING);
UART3_Send_State_Textarea("文心一言已回答,等待回答电子语音合成...");
UART3_Send_Answer_Textarea_UTF8((char*)answer.c_str());
printf("before Baidu_XTTS_Long_Text.\n");
Baidu_XTTS_Long_Text(answer , baidu_xtts_long_voice_test);
printf("after Baidu_XTTS_Long_Text.\n");
sleep(1);
UART3_Send_State(STATE_XTTSED_PLAYING);
UART3_Send_State_Textarea("文心一言已回答,电子语音合成完毕,扬声器正在播报回答...");
printf("before system madplay.\n");
system("madplay /home/result.mp3");
printf("after system madplay.\n");
}
四、作品源码
download.eeworld.com.cn/detail/donatello1996/630814
五、作品功能演示视频
六、项目总结
(项目文字总结+帖子分享链接汇总)
七、其他
-
上传了资料:
【DigiKey“智造万物,快乐不停”创意大赛】基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统源码
- 2024-01-16
-
回复了主题帖:
【DigiKey“智造万物,快乐不停”创意大赛】基于STM32H747Disco和百度语音云的语音...
本帖最后由 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);
}
}
}
- 2024-01-12
-
加入了学习《【DigiKey创意大赛】多通道微型气相色谱采集单元》,观看 多通道微型气相色谱采集单元
-
发表了主题帖:
【DigiKey“智造万物,快乐不停”创意大赛】基于STM32H747Disco和百度语音云的语音...
本帖最后由 donatello1996 于 2024-1-15 08:18 编辑
【DigiKey“智造万物,快乐不停”创意大赛】基于STM32H747Disco和百度语音云的语音识别智能聊天机器人和信号采集系统
作品采用得捷上购买的STM32H747Disco开发板,通过串口,信号线及外部高速总线与ARM Linux板通信,访问百度语音云做语音识别、语音合成以及做振动信号采集,系统硬件框图如下:
STM32H747Disco开发板软件流程如下,如图,使用了LVGL图形库,SDRAM外扩内存访问以及QSPI字库存储读取:
ARM Linux板软件流程如下,录音、语音识别、访问文心一言、语音合成、语音播报都是独立完成的,分属不同功能:
使用外部自定义字库需要烧录字库文件到QPI上,所以需要CubeProgrammer软件帮忙:
演示视频: