文章目录
- yPlot介绍
-
-
-
- 特点:
-
-
- 使用帮助
-
- 1 软件页面说明
-
- ?? 鼠标操作
- 2 如何连接下位机?
- 3 通信协议说明
-
- 3.1 下位机向软件发送波形协议
- 3.2 上位机向下位机发送指令的协议
- 4 STM32示例程序
- 4.1 波形发送
- 4.2 接收代码
- 4.3 波形产生函数
- 4 如何二次开发
yPlot介绍
该软件可以通过波形显示串口接收到的数据,以便于查看数据和调试参数。在电子竞技等场合进行调试PID参数非常方便。 无人机在比赛开始时制作,全靠肉眼调参,然后一遍又一遍地修改参数,编译程序,下载程序。效率低而且慢。后来得知有软件示波器,匿名,山外调试助手,但看波形还可以,网上修改参数不方便。后来又学到了一个叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫叫serialplot的软件,非常好用,但是发送参数还是感觉不合适。所以我想开发一个软件来调参。 这款软件UI新鲜,通信协议简单,发送命令、波形名称显示等更考虑舒适性。但由于波形显示窗口使用Qt自带的QCustomPlot控件。
特点:
-
自适应数据通道,自动添加线名
-
支持超大数据量显示不卡顿
-
支持各种波特率
-
界面美观,性能强
-
PID调试神器
-
鼠标操作非常方便
-
发送到上位机的数据类型只能是 float 型 !!!
- QT5.9.8
- github:https://github.com/syuan7/y-serialplot
- 在上面的连接中选择这里
使用帮助
1 软件页面说明
?? 鼠标操作
-
放大左键框
-
右键按住可拖动线
-
单击右键视图复位
-
突出显示左击线
-
左击图例隐藏线条
-
按钮功能
-
视窗操作
- 命令发送区域
发送命令包括:按下相应的快捷键,鼠标点击发送按钮,输入指令后按下返回按钮。使用起来更方便。
2 如何连接下位机?
- 有线连接
- 无线连接
电脑可以识别单片机的串口,必须有USB-TTL转移模块。因为一般单片机的串口是TTL电平信号,和USB接口的电平信号不兼容,因此需要转移特殊的芯片。常用的芯片有CH340和CP2102。
驱动安装后,串口设备应能在计算机设备管理器中看到。(下图中的芯片是CH340芯片)
这里提供了CH340驱动,一起放在软件目录下。
假如安装失败,先点击卸载,再点击安装。
3 通信协议说明
设备正确连接后,需要根据本通信协议在设备中编写波形发送程序,以显示数据波形。
3.1 下位机向软件发送波形协议
通信协议分为两段,以自动适应波形通道的名称。
-
注意:
-
第一段:name字段
帧头 ch1的名称 分隔符 ch2的名称 分隔符 chn的名称 帧尾 字符 AABBCC name1 , name2 , … CCBBAA 备注 任何长度的字符串都不能用中文使用 英文逗号 任何长度的字符串都不能用中文使用 英文逗号 … -
第二段:数据字段
帧头 ch1的数据 ch2的数据 chn的数据 帧尾 字符 DDEEFF 123 123 … FFEEDD 备注 数据类型为上位机设置的类型 所有通道数据类型一致 所有通道数据类型一致
中间一段莫名其妙的字符,应该可以在第4节的发送函数中得到答案。
3.2 上位机向下位机发送指令的协议
-
本协议根据下位机的分析程序确定,只要能正确分析,就可以决定发送什么。
-
说明这里提供的STM32示例程序中使用的通信协议。
控制字段 分隔符 数据1 分隔符 数据2 分隔符 数据3 结束控制符 字符 3个char = 1个float 英文 , 1个float 英文 , 1个float #
直接输入浮点数就行,下位机中使用C语言的标准库进行格式化。
4 STM32示例程序
在软件包中提供了STM32F103的示例工程。默认使用本软件的同学有STM32或者单片机开发基础。所以就不介绍工程结构和串口初始化部分的程序。没有基础的同学可以可以自行学习一下。
下面主要介绍波形发送、命令接受的程序。
4.1 波形发送
例程中使用的是 STM32 的串口1进行数据收发。
- 波形发送业务代码
void send_wave(void)
{
//定义通道名帧头帧尾
u8 frameNameHead[] = "AABBCC";
u8 frameNameEnd[] = "CCBBAA";
//定义数据帧头帧尾
u8 frameDataHead[] = "DDEEFF";
u8 frameDataEnd[] = "FFEEDD";
//定义通道名
u8 name[] = {
"sin(x),cos(x),cos(2x),2cos(x),P,I,D"};
//赋值数据
float channels[7];
channels[0] = datas[0];
channels[1] = datas[1];
channels[2] = datas[2];
channels[3] = datas[3];
channels[4] = cmd_P;
channels[5] = cmd_I;
channels[6] = cmd_D;
//通过串口1,向上位机发送数据
usart_senddatas(USART1,frameNameHead,sizeof(frameNameHead)-1);
usart_senddatas(USART1,name,sizeof(name)-1);
usart_senddatas(USART1,frameNameEnd,sizeof(frameNameEnd)-1);
usart_senddatas(USART1,frameDataHead,sizeof(frameDataHead)-1);
usart_senddatas(USART1,(u8*)channels,sizeof(channels));
usart_senddatas(USART1,frameDataEnd,sizeof(frameDataEnd)-1);
}
12行的通道名称,是一个字符串,不同通道之间以 英文逗号,
间隔,上位机中设置了多少个通道就写多少个名字。
15行定义了发送的数据数组,数组类型需要和上位机中设置的类型一样一致。数组成员数量需要和上位机中设置的通道数量一致。
16~19行对数组赋值。数据是 getdatas()
函数生成的三角函数。
20~22行对数组赋值。数据是 get_cmd()
函数获取的上位机设置的PID数值。
26~32行使用串口1,通过数据指针将数据发出。usart_senddatas()
函数是自己是自己实现的串口多字节发送函数。
- 波形发送驱动
void usart_senddatas(USART_TypeDef* USARTx,u8* addr,int size)
{
while(size--) //判断数据发送完没有
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == RESET);//等待上一个byte的数据发送结束。
USART_SendData(USARTx,*addr);//调用STM32标准库函数发送数据
addr++; //地址偏移
}
}
4.2 接收代码
- 接收驱动(串口中断函数)
-
这个函数不需要我们调用它,它会在单片机串口每接收到1Byte数据时自动调用。比如发了发送一个 hello 字符,单片机就会自动调用5次这个函数。
-
接受到的字符会存在
usart_readbuff
数组中,当接收到#
时,会停止将数据保存到数组,并且置位usart_readok
,直到我们处理了这一帧数据。 -
使用这种方法会让程序有层次性,但是会出现数据阻塞(必须要处理了上一帧数据才会接收下一帧数据)。
char usart_readbuff[30] = {
0}; //串口接受缓存数组
u8 usart_readok = 0; //一帧数据处理标志
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 temp;
static u8 count = 0; // 接收数组控制变量
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断是否为接收中断
{
temp = USART_ReceiveData(USART1); //读取接收到的数据,并清除中断标志
if(temp == '#' && usart_readok == 0)
{
usart_readbuff[count] = '#';
usart_readok = 1;
count = 0;
}
else if(usart_readok==0)
{
usart_readbuff[count] = temp; //保存接收到的数据到接收缓存数组
count++; //数组下标切换
if(count >= 30) // 防止数据越界
count = 0;
}
}
}
- 解析函数
-
关于
sscanf()和memset()
函数大家自行了解。 -
第6行的
"%3s=%f,%f,%f#"
字符格式化,和第3.2节的接受函数对应。
u8 usart_get_data(char *cmd,float *d1,float *d2,float *d3)
{
u8 flag = 0;
if(usart_readok == 1)
{
if(sscanf(usart_readbuff,"%3s=%f,%f,%f#",
cmd,d1,d2,d3)==4)
{
flag = 1;
}
//清除接收完成标志
memset(usart_readbuff,0,sizeof(usart_readbuff));
usart_readok = 0;
}
return flag;
}
- 接收的业务代码
void get_cmd(void)
{
char u_buff[10];
float u_d1,u_d2,u_d3;
if(usart_get_data(u_buff,&u_d1,&u_d2,&u_d3))
{
if(strcmp(u_buff,"PID") == 0) //比较命令控制字符是否为PID
{
cmd_P = u_d1;
cmd_I = u_d2;
cmd_D = u_d3;
}
}
memset(u_buff,0,sizeof(u_buff));
}
4.3 波形生成函数
- 。
void getdatas(void)
{
static float x = 0.00f * PI;
datas[0] = sinf(x);
datas[1] = cosf(x);
datas[2] = cosf(2 * x);
datas[3] = 2 * cosf(x);
x += 0.05f * PI;
}
4 如何二次开发
需要二次开发请在文章开头,贴的开源仓库连接中拉取项目。
-
开发环境为 QT5.9.8 + QT Creator
-
编译链为 MinGW(MSVC也可以)
-
项目是在Windows 10系统中开发的。
拉取项目后在下图框选的文件夹中使用 QT Creator
打开.pro文件即可进行二次开发。