简易示波器

前言

​ 最近在使用Webots进行机器人仿真,但是软件似乎不支持单步调试,也没有能绘制波形的调试工具。不过好在可以添加display组件,也就像是一块小屏幕,所以可以自己实现一个比较好用的示波器。

​ 我也将代码封装到了一个.h文件中,无论是Webots中的虚拟屏幕,还是平时装在小车上的OLED、LCD,只需要修改一下绘制像素点或者线条的接口函数,修改一下屏幕尺寸,就可以轻松移植使用了。

代码地址

代码中含有”wb”的为webots库函数,需修改。

效果演示

波形demo.gif

结构体介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* @brief 点结构体
*/
typedef struct __Piont_t {
int x,y;
}Point_t;

/**
* @brief 环形存储器
* @note 用于一个通道各个点的存储
*/
typedef struct __RingBuf_t {
Point_t Points[RING_SIZE];
short head, tail;
}RingBuf_t;

/**
* @brief 显示器的一个数据通道
*/
typedef struct __Channel_t {
bool enable; // 通道使能, 0:不使能 1:使能
uint32_t color; // 颜色
RingBuf_t R; // 环形缓存器
double range; // 数据上下限 -range ~ +range
}Channel_t;

/**
* @brief 显示器结构体
*/
typedef struct __Display_t {
int width, height; // 显示器宽高
WbDeviceTag tag; // 显示器tag
Channel_t Channels[CHANNEL_NUM]; // 通道
double data[CHANNEL_NUM]; // 各个通道最新数据
}Display_t;

​ 一个示波器可以绘制CHANNEL_NUM个波形。每个通道的最高处和最低处分别对应该数据的最大值和最小值

使用方法

修改参数

1
2
3
4
#define MAX_WIDTH 512
#define MAX_HEIGHT 256
#define RING_SIZE MAX_WIDTH
#define CHANNEL_NUM 4

​ 通过宏定义修改屏幕长宽,以及想要显示的波形数量

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @brief 初始化显示器
* @param D 显示器指针
* @param name 显示器名字
*/
void displayInit(Display_t *D) {
D->tag = wb_robot_get_device("display");
D->height = wb_display_get_height(D->tag);
D->width = wb_display_get_width(D->tag);
if (D->tag == 0) {
printf("Error: Can't find the display");
return;
}
else { printf("Display found! %d x %d\n", D->width, D->height); }

for(int i=0; i<CHANNEL_NUM; i++) {
D->Channels[i].enable = false;
D->Channels[i].R.head = 0;
D->Channels[i].R.tail = 0;
}

channelEnable(D, 0, 0x0000ff, 1.5);
channelEnable(D, 1, 0xff0000, 1);
channelEnable(D, 2, 0x00ff00, 1);
channelEnable(D, 3, 0xffff00, 1);
return;
}

其中wb开头的函数是webots的库函数,使用的时候修改掉即可。通过channelEnable使能波形通道,定义序号、颜色、范围。

图形绘制

updateDis函数中修改绘制图形的函数为自己的函数即可。

1
2
wb_display_draw_line(D->tag, point.x, point.y, next_point.x, next_point.y); // 绘制线
//wb_display_draw_pixel(D->tag, point.x, point.y); // 绘制像素点

​ 最后在自己任务的while函数(或者再套一个函数)中添加想要示波的数据即可,比如之前的示例

1
2
3
4
5
6
7
8
9
10
11
12
while(...) {
...
//使用channel0显示按键控制的方波
display.data[0] = key;
//生产正弦、余弦和三角波在1、2、3通道显示
display.data[1] = sin(wb_robot_get_time());
display.data[2] = cos(wb_robot_get_time());
display.data[3] = fabs(fmod(wb_robot_get_time(), 2) - 1);
//添加数据并更新
addDisData(&Dormily.display);
updateDis(&Dormily.display);
}