C++结合libmodbus和matplotlib实现传感器数据的实时图像显示

本篇的内容结合了博主之前的两篇文章,将传感器数据通过libmodbus读取完成后,利用matplotlib调用窗口,将数据实现可视化。

前期准备:python3   libmodbus   matplotlib  Opencv  CMake

这些内容共同支撑起了本篇文章描述的内容实现,如果其中某个环节您没有配置,可以参照下面的两篇文章,根据实际需求进行配置。

Ubuntu下libmodbus的应用_Witty_Hou的博客-CSDN博客

在读学生自学Ubuntu20.04用C++调用matplotlib历程_Witty_Hou的博客-CSDN博客

1.项目搭建 :

仿照CMake,经典流程搭建工程:创建文件夹(源文件  CMakeLists.txt  头文件  build文件夹)

C++结合libmodbus和matplotlib实现传感器数据的实时图像显示_第1张图片

 

2.项目内容

本次内容和之前的差别不大,因为要实现实时数据显示,所以需要调用一下matplotlib,通过设置向量vector,用连续的向量首尾相连绘制出图像。通过不断刷新的向量连接,当刷新率超过30帧的时候,就已经看不出折线的痕迹了。

C++结合libmodbus和matplotlib实现传感器数据的实时图像显示_第2张图片

 类比一下,此图是用matplotlib模拟的三种不同刷新率的正弦函数,matplotlib执行参数自加操作的时候大概是10个数为1s的时间,如图,x每次加0.1,一秒就刷新100次。那么绿色为100fps,蓝色为25fps,黄色为12.5fps,25帧的在转角处可以看到些许折痕。同理,我们延续这种想法,对传感器进行数据采集和显示,只要我们的帧率大于30,就可以达到没有肉眼可见的延时显示。

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(mini CXX)

find_package(OpenCV REQUIRED)

set(CMAKE_CXX_STANDARD 11)
#指定库路径
file(GLOB_RECURSE Opencv3_LIB "/usr/lib/python3.8/config-x86_64-linux-gnu/*.so")
#指定头文件路径
set(Opencv4_INLCUDE_DIRS "/usr/include/python3.8")
#添加头文件到工程
include_directories(include ${Opencv4_INLCUDE_DIRS})
include_directories(${OpenCV_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(/usr/include/modbus)

# 通常这样设置就可以,如果你的项目包含qrc文件,那么需要将它们单独添加进来
aux_source_directory(. DIRS_SRCS)

add_executable(mini ${DIRS_SRCS})
#添加库文件到工程
target_link_libraries(mini ${Opencv_LIB})
target_link_libraries(mini libpython3.8.so)
TARGET_LINK_LIBRARIES(mini libmodbus.so)

main.cpp

#define _USE_MATH_DEFINES
#include 
#include "matplotlibcpp.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "modbus.h"
#pragma comment(lib,"modbus.lib")  

namespace plt = matplotlibcpp;

int main()
{
    double i = 0.1;
   	int num;
    std::vector x;//定义向量x,用于plot显示

	
	//modbus需要的指针和内容寄存数组
	modbus_t* mb;
	uint16_t tab_reg[10] = { 0 };

	//配置端口信息,并判断端口是否开启成功
	mb = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 2);   
	if (mb == NULL) {
		fprintf(stderr, "Unable to create the libmodbus context\n");
		return -1;
	}
	
	//设置从站地址,并判断是否成功
	int rc = modbus_set_slave(mb, 254);   
	if (rc == -1) {
		fprintf(stderr, "Invalid slave ID\n");
		modbus_free(mb);
		return -1;
	}

	//判断modbus连接是否成功
	if (modbus_connect(mb) == -1) {
		fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
		modbus_free(mb);
		return -1;
	}
	
	//设置响应超时时间为1s
	struct timeval t;
          t.tv_sec=0;
          t.tv_usec=1000000;        
          modbus_set_response_timeout(mb,&t);

    while(i>0) {
        int regs = modbus_read_input_registers(mb, 0, 1, tab_reg); //读取传感器数值
		std::cout << tab_reg[0] << " g" << std::endl;//在终端输出传感器数值
		usleep(10); //延迟10us
		

		num = tab_reg[0];//传感器数值存放到num中
        x.push_back(num);//在x向量最后加上传感器数值
	    if(num > 5000)
	    break;//自行增加的程序停止,当传感器压力值大于5000时,停止
	    //横轴每次循环向前移动0.8,当i>1000时,程序停止
		i = i + 0.8;
		if(i > 1000)
		{i = 0;}//设置的循环次数限制,作为项目的一部分,只需要有一种方式能停止就可以,后续可以通过中断来代替
			
            plt::clf();// 清理先前的plot数据 
            plt::named_plot("pressure", x);//显示数据x的数值,并在右上角注明线条的指代含义以及颜色
            plt::xlim(i - 50, i + 150);//横轴展示的范围
            plt::title("Pressure"); // 图像标题            
            plt::legend();// 使能legend          
            plt::pause(0.01);// 延迟0.01s
    }
    plt::save("num.pdf");//将数据保存为一份pdf放在build文件夹内
}

由于需要实现动态显示,博主自己去查资料,大多数都通过ion实现,但是由于技术水平不足,目前还没能完美实现,待到后续研究明白,会单独再发一篇文章来记录。本次动态实现的想法是通过横轴不断刷新来实现的,plt::xlim在while循环中随着i的不断变化可以不断刷新,从而达到动态可视化的目的。

3.运行结果

 4.可能遇到的问题总结:

(1)更改文件夹名称导致CMakeLists.txt错误

C++结合libmodbus和matplotlib实现传感器数据的实时图像显示_第3张图片

 如图:博主将原文件夹的名字mini修改为MINI,其他未作部分未修改,导致CMakeLists.txt错误。

解决方法:将文件夹的名称改回原来的mini。

或者将build文件夹删除,新建一个build重新执行cmake ..   make   ./mini(可执行文件名)

如果删除build再建的方法行不通,就新建一个工程,把所有文件都通过touch指令重新构建一次,把内容复制过来,不要直接把文件复制过来,否则还是会显示冲突。

再不行,那就只能重启大法好,然后再新构建一次工程。有时候,可能是因为程序没有完全停止,重启电脑可以关闭看不到的启动项。

(2)直接复制一个备份,再次编译的时候显示CMakeLists.txt冲突

C++结合libmodbus和matplotlib实现传感器数据的实时图像显示_第4张图片

 解决方法:将复制文件的build文件夹删除,重新建一个build,编译一次。

(3)while循环中没有加终结条件

博主自己在学习过程中,起初都是while(1)直接运行,但是出于不知名的原因,当博主关闭中端之后,传感器还在不断闪烁,代表程序并没有停止。此时再次运行可知性文件,文件并不会报错,但是传感器会速度很慢,并且只输出0,导致没办法调试,因此就不放置错误代码了。写在文章最后,作为一个可能遇到的问题列写出来。如果真的遇到,matplotlib关闭不了,任务管理器也不显示,叉了也会自己启动,像极了电脑中病毒疯狂弹窗的样子。如果遇到,请重启电脑。

如果还有其他问题请留言,或者添加QQ:3122899873,看到都会回复❤

你可能感兴趣的:(matplotlib,调用窗口,c++,嵌入式硬件,python)