当前位置:   article > 正文

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

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文件夹)

 

2.项目内容

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

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

CMakeLists.txt:

  1. cmake_minimum_required(VERSION 3.10)
  2. project(mini CXX)
  3. find_package(OpenCV REQUIRED)
  4. set(CMAKE_CXX_STANDARD 11)
  5. #指定库路径
  6. file(GLOB_RECURSE Opencv3_LIB "/usr/lib/python3.8/config-x86_64-linux-gnu/*.so")
  7. #指定头文件路径
  8. set(Opencv4_INLCUDE_DIRS "/usr/include/python3.8")
  9. #添加头文件到工程
  10. include_directories(include ${Opencv4_INLCUDE_DIRS})
  11. include_directories(${OpenCV_INCLUDE_DIRS})
  12. INCLUDE_DIRECTORIES(/usr/include/modbus)
  13. # 通常这样设置就可以,如果你的项目包含qrc文件,那么需要将它们单独添加进来
  14. aux_source_directory(. DIRS_SRCS)
  15. add_executable(mini ${DIRS_SRCS})
  16. #添加库文件到工程
  17. target_link_libraries(mini ${Opencv_LIB})
  18. target_link_libraries(mini libpython3.8.so)
  19. TARGET_LINK_LIBRARIES(mini libmodbus.so)

main.cpp

  1. #define _USE_MATH_DEFINES
  2. #include <cmath>
  3. #include "matplotlibcpp.h"
  4. #include <vector>
  5. #include <time.h>
  6. #include <iostream>
  7. #include <stdio.h>
  8. #include <unistd.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include <errno.h>
  12. #include "modbus.h"
  13. #pragma comment(lib,"modbus.lib")
  14. namespace plt = matplotlibcpp;
  15. int main()
  16. {
  17. double i = 0.1;
  18. int num;
  19. std::vector<double> x;//定义向量x,用于plot显示
  20. //modbus需要的指针和内容寄存数组
  21. modbus_t* mb;
  22. uint16_t tab_reg[10] = { 0 };
  23. //配置端口信息,并判断端口是否开启成功
  24. mb = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 2);
  25. if (mb == NULL) {
  26. fprintf(stderr, "Unable to create the libmodbus context\n");
  27. return -1;
  28. }
  29. //设置从站地址,并判断是否成功
  30. int rc = modbus_set_slave(mb, 254);
  31. if (rc == -1) {
  32. fprintf(stderr, "Invalid slave ID\n");
  33. modbus_free(mb);
  34. return -1;
  35. }
  36. //判断modbus连接是否成功
  37. if (modbus_connect(mb) == -1) {
  38. fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
  39. modbus_free(mb);
  40. return -1;
  41. }
  42. //设置响应超时时间为1s
  43. struct timeval t;
  44. t.tv_sec=0;
  45. t.tv_usec=1000000;
  46. modbus_set_response_timeout(mb,&t);
  47. while(i>0) {
  48. int regs = modbus_read_input_registers(mb, 0, 1, tab_reg); //读取传感器数值
  49. std::cout << tab_reg[0] << " g" << std::endl;//在终端输出传感器数值
  50. usleep(10); //延迟10us
  51. num = tab_reg[0];//传感器数值存放到num中
  52. x.push_back(num);//在x向量最后加上传感器数值
  53. if(num > 5000)
  54. break;//自行增加的程序停止,当传感器压力值大于5000时,停止
  55. //横轴每次循环向前移动0.8,当i>1000时,程序停止
  56. i = i + 0.8;
  57. if(i > 1000)
  58. {i = 0;}//设置的循环次数限制,作为项目的一部分,只需要有一种方式能停止就可以,后续可以通过中断来代替
  59. plt::clf();// 清理先前的plot数据
  60. plt::named_plot("pressure", x);//显示数据x的数值,并在右上角注明线条的指代含义以及颜色
  61. plt::xlim(i - 50, i + 150);//横轴展示的范围
  62. plt::title("Pressure"); // 图像标题
  63. plt::legend();// 使能legend
  64. plt::pause(0.01);// 延迟0.01s
  65. }
  66. plt::save("num.pdf");//将数据保存为一份pdf放在build文件夹内
  67. }

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

3.运行结果

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

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

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

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

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

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

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

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

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/428931
推荐阅读
相关标签
  

闽ICP备14008679号