windows下使用MFC对六维力传感器数据采集与绘制

本文主要通过mfc建立一个对话框,新建个子线程读取传感器数据,在主线程中添加定时器和chartctrl控件进行动态曲线的绘制。运行效果与传感器自带软件效果如下:
在这里插入图片描述
在这里插入图片描述
1 使用控制台程序新建传感器接口的配置和数据的读写如下:
在这里插入图片描述
将OMD库放入根目录下
在这里插入图片描述
在这里插入图片描述
代码如下:

// ss.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <omd/opto.h>

#include <omd/sensorconfig.h>

#include <fstream>
#include<windows.h> 
using namespace std;

int main(int argc, char *argv[])
{

	OptoDAQ daq;

	OptoPorts ports;
	OPort* portlist=ports.listPorts(true);

	SensorConfig sensor;
	sensor.set(sensor_ok,speed_100hz,filter_15hz,mode_raw);
	daq.sendConfig(sensor);

	if (ports.getLastSize()>0)
	{
		daq.open(portlist[0]);

	
		while (1)
		{
		
			Sleep(1000/100);
			if ((daq.getVersion()!=_95) && (daq.getVersion()!=_64)) // It is a 3D sensor 
			{
				OptoPackage pack3D;

				ofstream datafile;
				datafile.open("datafile.txt",ofstream::app);

				int size=daq.read(pack3D,0);    // Reading Sensor #0 (up to 16 Sensors)     
				std::cout<<"x: "<<pack3D.x<<" y: "<<pack3D.y<<" z: "<<pack3D.z<<std::endl;
				datafile << "datafile.txt" << pack3D.x << "" << pack3D.y  << "" << pack3D.z << endl;

			}
			else                      // It is a 6D sensor
			{
				OptoPackage6D pack6D;

				ofstream datafile;
				datafile.open("datafile.txt",ofstream::app);

				int size=daq.read6D(pack6D,false);
				std::cout<<"Fx: "<<pack6D.Fx<<" Fy: "<<pack6D.Fy<<" Fz: "<<pack6D.Fz<<" ";
				std::cout<<"Tx: "<<pack6D.Tx<<" Ty: "<<pack6D.Ty<<" Tz: "<<pack6D.Tz<<std::endl;

				datafile <<  pack6D.Fx << " " <<pack6D.Fy  << " " << pack6D.Fz  << " " << pack6D.Tx << " " << pack6D.Ty << " " << pack6D.Tz << endl;
			}
		
		}

		daq.close();
	}
	else
	{
		std::cout<<"No sensor available"<<std::endl;
	}
	char key;
	std::cin>>key;

	
	
	return 0;
}



Sleep(1000/100) 表示10ms运行一次,与采样频率100HZ相对应
运行效果如下:
在这里插入图片描述
其中fx fy fz需要除以10,单位为N TXTYTZ需要除以1000, 单位为N/m
2. MFC对话框读取数据
如图,新建一个对话框,仿照上述控制台程序进行传感器的相关配置
添加以下控件,传感器的数据将传入这些编辑框内
在这里插入图片描述
控件ID和变量类型和变量名称如下
在这里插入图片描述
在sensor_mutithreadDlg.h下定义一个线程变量
在这里插入图片描述
在sensor_mutithreadDlg.cpp下定义一个结构体,线程函数,一个该结构体的全局变量和该主线程中的全局变量
在这里插入图片描述
该结构体放子线程里的变量,其中,结构体中的Csensor_mutithreadDlg* dlg 将对应主线程中的Csensor_mutithreadDlg* Pdlg;在oninitDialog()中对pdlg初始化。
在这里插入图片描述
双击start按钮,将子线程结构体里的dlg与主线程对话框的pdlg进行绑定
在这里插入图片描述
线程函数代码如下:

UINT ThreadFunc(LPVOID lpParam)
{

	threadinfo* pinfo = (threadinfo*)lpParam;

	pinfo->mysensor.set(sensor_ok,speed_100hz,filter_15hz,mode_raw);
	pinfo->daq.sendConfig(pinfo->mysensor);

	while(1)
	{
		Sleep(1000/100);
		pinfo->portlist = pinfo->ports.listPorts(true);
		pinfo->daq.open(pinfo->portlist[0]);
		if (pinfo->ports.getLastSize()>0)
		{
			int size=pinfo->daq.read6D(pinfo->pack6D,false);

			//这个无效,因为被后面Pdlg->GetDlgItem(IDC_EDIT_FX)->SetWindowTextW(editfx)覆盖掉
			Pdlg->m_fx = pinfo->pack6D.Fx/10;
			Pdlg->m_fy = pinfo->pack6D.Fy/10;
			Pdlg->m_fz = pinfo->pack6D.Fz/10;
			Pdlg->m_tx = pinfo->pack6D.Tx/100;
			Pdlg->m_ty = pinfo->pack6D.Ty/100;
			Pdlg->m_tz = pinfo->pack6D.Tz/100;
			
           //此处由于FZ的读取有时非常大,原因不明,自动过滤掉
			if (pinfo->pack6D.Fz>10000)
				continue;

			CString editfx;
			editfx.Format(_T("%.2f"),float(pinfo->pack6D.Fx)/10);		
			Pdlg->GetDlgItem(IDC_EDIT_FX)->SetWindowTextW(editfx);

			CString editfy;
			editfy.Format(_T("%.2f"),float(pinfo->pack6D.Fy)/10);
			Pdlg->GetDlgItem(IDC_EDIT_FY)->SetWindowTextW(editfy);

			CString editfz;
			editfz.Format(_T("%.2f"),float(pinfo->pack6D.Fz)/10);
			Pdlg->GetDlgItem(IDC_EDIT_FZ)->SetWindowTextW(editfz);

			CString edittx;
			edittx.Format(_T("%.3f"),float(pinfo->pack6D.Tx)/1000);
			Pdlg->GetDlgItem(IDC_EDIT_TX)->SetWindowTextW(edittx);

			CString editty;
			editty.Format(_T("%.3f"),float(pinfo->pack6D.Ty)/1000);
			Pdlg->GetDlgItem(IDC_EDIT_TY)->SetWindowTextW(editty);

			CString edittz;
			edittz.Format(_T("%.3f"),float(pinfo->pack6D.Tz)/1000);
			Pdlg->GetDlgItem(IDC_EDIT_TZ)->SetWindowTextW(edittz);


			ofstream datafile;
			datafile.open("datafile.txt",ofstream::app);

			datafile <<  float(pinfo->pack6D.Fx)/10 << " " <<float(pinfo->pack6D.Fy)/10  << " " << float(pinfo->pack6D.Fz)/10  << " " << float(pinfo->pack6D.Tx)/1000 << " " <<float(pinfo->pack6D.Ty)/1000 << " " << float(pinfo->pack6D.Tz)/1000  << endl;


			
		}
		
		
	

	}

	return 0;
}

此处pdlg->updata(false)会导致崩溃,可采用这种方法上传

	CString edittz;
	edittz.Format(_T("%.3f"),float(pinfo->pack6D.Tz)/1000);
	Pdlg->GetDlgItem(IDC_EDIT_TZ)->SetWindowTextW(edittz);

至此,该控件可实时读取数据。
3.实时动态绘图
需要下载chartctrl源文件放置根目录下,通过添加现有项导入至目录
在这里插入图片描述
导入后会出现Cchart相关类
在这里插入图片描述
在对话框中添加绘图所需的头文件和一些定义

#include "chartctrl/ChartCtrl.h"
#include "chartctrl/ChartTitle.h"
#include "chartctrl/ChartAxisLabel.h"

#include "chartctrl/ChartLineSerie.h"

#if defined _UNICODE ||defined UNICODE
typedef std::wstring TChartString;
typedef std::wstringstream TChartStringStream;
#else
typedef std::string TChartString;
typedef std::stringstream TChartStringStream;
#endif


放置6个custom control控件用来放置图像
在这里插入图片描述
对应修改相关值
在这里插入图片描述
在对话框头文件里添加如下变量和函数
在这里插入图片描述
将Cchartctrl变量与custom control控件绑定,若绑定失败,在.cpp上加“resource.h”
在这里插入图片描述
Setupmychart_FX()代码如下,其他依次类推:

void Csensor_mutithreadDlg::setupmychart_FX()
{
	//初始化FX数组
	for (int i = 0; i<500; i++)
	{
		FX[i] = 0;
		NUM[i] = i;
	}
	//建立X轴
	CChartAxis* Paxis = NULL;
	Paxis = m_chartctrl_FX.CreateStandardAxis(CChartCtrl::BottomAxis);

	Paxis->SetAutomatic(true);
	Paxis = m_chartctrl_FX.CreateStandardAxis(CChartCtrl::LeftAxis);
	Paxis->SetAutomatic(true);

	//设置表的标题
	TChartString str1;
	str1 = _T("六维力传感器 FX数据采集");
	m_chartctrl_FX.GetTitle()->AddString(str1);

	str1 = _T("FX  (N)");
	Paxis = m_chartctrl_FX.GetLeftAxis();
	m_chartctrl_FX.GetLeftAxis()->GetLabel()->SetText(str1);

	str1 = _T("500组实时数据");
	Paxis = m_chartctrl_FX.GetBottomAxis();
	m_chartctrl_FX.GetBottomAxis()->GetLabel()->SetText(str1);

	m_chartctrl_FX.EnableRefresh(false);

	//创建线序列
	CChartLineSerie *pLineSerie1;
	m_chartctrl_FX.RemoveAllSeries();//先清空
	pLineSerie1 = m_chartctrl_FX.CreateLineSerie();

	//绘制图
	pLineSerie1->AddPoints(NUM, FX,500);

	m_chartctrl_FX.EnableRefresh(true);

}

在OnInitDialog()中完成初始化
在这里插入图片描述
动态左移数组的函数如下:
在这里插入图片描述
添加定时器,设置刷新频率与传感器的采样频率一致,从而可以使数组不断左移
在这里插入图片描述
在start设置频率,即10毫秒刷新一次,对应频率100HZ
在这里插入图片描述
定时器代码如下

void Csensor_mutithreadDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CDialogEx::OnTimer(nIDEvent);
	switch(nIDEvent)
	{	
	case 1:
			
		UpdateData(TRUE);
		
		m_chartctrl_FX.EnableRefresh(false);
		m_chartctrl_FY.EnableRefresh(false);
		m_chartctrl_FZ.EnableRefresh(false);
		m_chartctrl_TX.EnableRefresh(false);
		m_chartctrl_TY.EnableRefresh(false);
		m_chartctrl_TZ.EnableRefresh(false);

		if (m_fz>10000)
		{
			break;
		}
		
		leftmove(FX, 500, m_fx);
		leftmove(FY, 500, m_fy);
		leftmove(FZ, 500, m_fz);
		leftmove(TX, 500, m_tx);
		leftmove(TY, 500, m_ty);
		leftmove(TZ, 500, m_tz);

		CChartLineSerie *pLineSerie1;
		CChartLineSerie *pLineSerie2;
		CChartLineSerie *pLineSerie3;
		CChartLineSerie *pLineSerie4;
		CChartLineSerie *pLineSerie5;
		CChartLineSerie *pLineSerie6;

		m_chartctrl_FX.RemoveAllSeries();//先清空
		pLineSerie1 = m_chartctrl_FX.CreateLineSerie();		
		pLineSerie1->AddPoints(NUM, FX,500);

		m_chartctrl_FY.RemoveAllSeries();//先清空
		pLineSerie2 = m_chartctrl_FY.CreateLineSerie();
		pLineSerie2->AddPoints(NUM, FY,500);

		m_chartctrl_FZ.RemoveAllSeries();//先清空
		pLineSerie3 = m_chartctrl_FZ.CreateLineSerie();
		pLineSerie3->AddPoints(NUM, FZ,500);

		m_chartctrl_TX.RemoveAllSeries();//先清空
		pLineSerie4 = m_chartctrl_TX.CreateLineSerie();
		pLineSerie4->AddPoints(NUM, TX,500);

		m_chartctrl_TY.RemoveAllSeries();//先清空
		pLineSerie5 = m_chartctrl_TY.CreateLineSerie();
		pLineSerie5->AddPoints(NUM, TY,500);

		m_chartctrl_TZ.RemoveAllSeries();//先清空
		pLineSerie6 = m_chartctrl_TZ.CreateLineSerie();
		pLineSerie6->AddPoints(NUM, TZ,500);

		m_chartctrl_FX.EnableRefresh(true);
		m_chartctrl_FY.EnableRefresh(true);
		m_chartctrl_FZ.EnableRefresh(true);
		m_chartctrl_TX.EnableRefresh(true);
		m_chartctrl_TY.EnableRefresh(true);
		m_chartctrl_TZ.EnableRefresh(true);
	
	
		break;

	default:
		break ;
	}
	CDialog::OnTimer(nIDEvent);

}

文中是因为FZ采样时有时候会出来一个很大的值,自行过滤
在这里插入图片描述
至此完成本程序设计。
参考链接
https://blog.csdn.net/czyt1988/article/details/8740500

猜你喜欢

转载自blog.csdn.net/weixin_42355349/article/details/84892935