You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
14 KiB
C++

#include "StdAfx.h"
#include "GratingRuler.h"
#include "Propertie.h"
#include "PropertieMgr.h"
#include "CommPortMgr.h"
#include "LogMgr.h"
#include "BitOperation.h"
#include "AuthorityMgr.h"
#define WE6800_RETURN_BTYE_CNT 17//WE6800 数显表串口协议返回的字节数
CGratingRuler *gGratingRuler = new CGratingRuler;
CGratingRuler::CGratingRuler(void)
{
m_bIni = false;//光栅尺是否初始化
m_bUseGratingRuler = false;//是否使用光栅尺
m_CommPort = -1;//串口编号
m_OriginCalibrationError = 0.02;//原点校准误差(mm)
m_MaxCalibrationTimes = 10;//最大校准次数,避免死循环
m_MeasureErrorGap = 1;//校准平台误差的间隔(mm)(越小分的越细)
m_MaxOriginError = 10;//回原点时平台原点和光栅尺原点最大允许的误差(mm)
}
CGratingRuler::~CGratingRuler(void)
{
}
#if 1
CMFCPropertyGridProperty *CGratingRuler::CreatGridProperty()
{
CString PropertyName;//属性名称
CString Description;//描述
CString Path = _T("GratingRuler");;//存储路径
CString Name;
//-------------------------------------------------------------------------------//
PropertyName = _T("光栅尺");
CMFCPropertyGridProperty* pGroup = new CMFCPropertyGridProperty(PropertyName);
//-------------------------------------------------------------------------------//
if(gAuthorityMgr->CheckAuthority(_FACTORY))
{
//添加属性变量映射
Name = _T("m_CommPort");//变量名字
CPropertie *pPropertie = new CPropertie;
pPropertie->SetpVal((void*)&m_CommPort);
pPropertie->SetType(_PROP_TYPE_INT);
pPropertie->SetpModule(this);
pPropertie->SetPath(Path);
pPropertie->SetName(Name);
pPropertie->WriteRead(true);//读取保存的属性
//添加属性显示
PropertyName = _T("串口号");
Description = _T("光栅尺和PC 通讯的串口号(0~16)");
CMFCPropertyGridProperty* p1 = new CMFCPropertyGridProperty(PropertyName, (_variant_t)m_CommPort, Description);
pGroup->AddSubItem(p1);
gDevicePropertieMgr.Insert(p1, pPropertie);
}
if(gAuthorityMgr->CheckAuthority(_FACTORY))
{
//添加属性变量映射
Name = _T("m_bUseGratingRuler");//变量名字
CPropertie *pPropertie = new CPropertie;
pPropertie->SetpVal((void*)&m_bUseGratingRuler);
pPropertie->SetType(_PROP_TYPE_BOOL);
pPropertie->SetpModule(this);
pPropertie->SetPath(Path);
pPropertie->SetName(Name);
pPropertie->WriteRead(true);//读取保存的属性
//添加属性显示
PropertyName = _T("光栅尺");
Description = _T("光栅尺校准开关");
CMFCPropertyGridProperty* p1 = new CMFCPropertyGridProperty(PropertyName, (_variant_t)m_bUseGratingRuler, Description);
pGroup->AddSubItem(p1);
gDevicePropertieMgr.Insert(p1, pPropertie);
}
if(gAuthorityMgr->CheckAuthority(_FACTORY))
{
//添加属性变量映射
Name = _T("m_OriginCalibrationError");//变量名字
CPropertie *pPropertie = new CPropertie;
pPropertie->SetpVal((void*)&m_OriginCalibrationError);
pPropertie->SetType(_PROP_TYPE_DOUBLE);
pPropertie->SetpModule(this);
pPropertie->SetPath(Path);
pPropertie->SetName(Name);
pPropertie->WriteRead(true);//读取保存的属性
//添加属性显示
PropertyName = _T("原点校准误差");
Description = _T("平台回原点时误差大于这个值需要补偿脉冲(单位: mm)");
CMFCPropertyGridProperty* p1 = new CMFCPropertyGridProperty(PropertyName, (_variant_t)m_OriginCalibrationError, Description);
pGroup->AddSubItem(p1);
gDevicePropertieMgr.Insert(p1, pPropertie);
}
if(gAuthorityMgr->CheckAuthority(_FACTORY))
{
//添加属性变量映射
Name = _T("m_MaxCalibrationTimes");//变量名字
CPropertie *pPropertie = new CPropertie;
pPropertie->SetpVal((void*)&m_MaxCalibrationTimes);
pPropertie->SetType(_PROP_TYPE_INT);
pPropertie->SetpModule(this);
pPropertie->SetPath(Path);
pPropertie->SetName(Name);
pPropertie->WriteRead(true);//读取保存的属性
//添加属性显示
PropertyName = _T("最大校准次数");
Description = _T("平台回原点时误差最大校准次数,避免死循环");
CMFCPropertyGridProperty* p1 = new CMFCPropertyGridProperty(PropertyName, (_variant_t)m_MaxCalibrationTimes, Description);
pGroup->AddSubItem(p1);
gDevicePropertieMgr.Insert(p1, pPropertie);
}
if(gAuthorityMgr->CheckAuthority(_FACTORY))
{
//添加属性变量映射
Name = _T("m_MeasureErrorGap");//变量名字
CPropertie *pPropertie = new CPropertie;
pPropertie->SetpVal((void*)&m_MeasureErrorGap);
pPropertie->SetType(_PROP_TYPE_DOUBLE);
pPropertie->SetpModule(this);
pPropertie->SetPath(Path);
pPropertie->SetName(Name);
pPropertie->WriteRead(true);//读取保存的属性
//添加属性显示
PropertyName = _T("测量间隔");
Description = _T("校准平台误差的间隔(单位: mm)");
CMFCPropertyGridProperty* p1 = new CMFCPropertyGridProperty(PropertyName, (_variant_t)m_MeasureErrorGap, Description);
pGroup->AddSubItem(p1);
gDevicePropertieMgr.Insert(p1, pPropertie);
}
//-------------------------------------------------------------------------------//
return pGroup;
}
void CGratingRuler::ExportPar(ofstream *pFile)
{
(*pFile)<<"[模块] [CGratingRuler]------------------------------------------------"<<endl;
(*pFile)<<"[光栅尺][m_bUseGratingRuler] = "<<m_bUseGratingRuler<<endl;
(*pFile)<<"[串口号][m_CommPort] = "<<m_CommPort<<endl;
(*pFile)<<"[原点校准误差][m_OriginCalibrationError] = "<<m_OriginCalibrationError<<endl;
(*pFile)<<"[最大校准次数][m_MaxCalibrationTimes] = "<<m_MaxCalibrationTimes<<endl;
(*pFile)<<"[测量间隔][m_MeasureErrorGap] = "<<m_MeasureErrorGap<<endl;
(*pFile)<<"[原点最大允许误差][m_MaxOriginError] = "<<m_MaxOriginError<<endl;
}
void CGratingRuler::ExportErrorTable(ofstream *pFile,vector<TypePosError> &ErrorTable)
{
}
#endif
#if 1//读取光栅尺
//读取光栅尺
bool CGratingRuler::ReadGratingRuler(Dbxy &pt)
{
CCommPortMgr com;
//打开串口
if(com.Open(m_CommPort)==false)
{
return false;
}
int DelayTime = 100;
CString str1 = "R";
CString str = str1+char(13)+char(10);
com.Write(str);
Sleep(DelayTime);
//读取串口反馈
char Buffer[WE6800_RETURN_BTYE_CNT];
int len = com.Read(Buffer,WE6800_RETURN_BTYE_CNT);
if(len<WE6800_RETURN_BTYE_CNT)
{
com.Close();
return false;
}
for(int i=0;i<WE6800_RETURN_BTYE_CNT;i++)
{
}
//解析坐标值
if(AnalysisRulerRet(Buffer,pt)==false)
{
com.Close();
return false;
}
com.Close();
return true;
}
//解析光栅尺反馈结果
bool CGratingRuler::AnalysisRulerRet(char *Buffer,Dbxy &pt)
{
bool bIsNegativeX = false;
bool bIsNegativeY = false;
//解析符号位-------------------------------------------
if(AnalysisSymbol(Buffer[1],bIsNegativeX,bIsNegativeY)==false)
{
return false;
}
//解析XY 轴的状态
if(AnalysisXYState(Buffer[2])==false)
{
return false;
}
//解析X 轴坐标值
pt.x = AnalysisCoord(Buffer[3],Buffer[4],Buffer[5],Buffer[6]);
//解析Y 轴坐标值
pt.y = AnalysisCoord(Buffer[7],Buffer[8],Buffer[9],Buffer[10]);
//处理符号
if(bIsNegativeX)
{
pt.x *= -1;
}
if(bIsNegativeY)
{
pt.y *= -1;
}
return true;
}
//解析符号位
bool CGratingRuler::AnalysisSymbol(BYTE byte,bool &bIsNegativeX,bool &bIsNegativeY)
{
if(IsBitOn(byte,4))//判断单位0 是毫米1 是英尺
{
CString str = "[error] [数显表单位设置为英尺]";
gLogMgr->WriteDebugLog(str);
return false;
}
if(IsBitOn(byte,0))//判断x 轴的符号
{
bIsNegativeX = true;
}
if(IsBitOn(byte,1))//判断Y 轴的符号
{
bIsNegativeY = true;
}
return true;
}
//解析XY 轴的状态
bool CGratingRuler::AnalysisXYState(BYTE byte)
{
if(IsBitOn(byte,0))
{
CString str = "[error] [X 轴光栅尺异常]";
gLogMgr->WriteDebugLog(str);
return false;
}
if(IsBitOn(byte,1))
{
CString str = "[error] [Y 轴光栅尺异常]";
gLogMgr->WriteDebugLog(str);
return false;
}
return true;
}
//解析坐标值(压缩BCD 码格式)
double CGratingRuler::AnalysisCoord(BYTE byte1,BYTE byte2,BYTE byte3,BYTE byte4)
{
double coord = 0;
double coefficient = 0.0001;//这个系数是根据光栅尺的精度来取的
double Increment = 10;//每次增加的倍数
//千分位,百分位
{
double high = 0;
double low = 0;
GetTwoNum(byte1,high,low);
coord += low*coefficient;
coefficient *= Increment;
coord += high*coefficient;
coefficient *= Increment;
}
//十分位,个位
{
double high = 0;
double low = 0;
GetTwoNum(byte2,high,low);
coord += low*coefficient;
coefficient *= Increment;
coord += high*coefficient;
coefficient *= Increment;
}
//十位,百位
{
double high = 0;
double low = 0;
GetTwoNum(byte3,high,low);
coord += low*coefficient;
coefficient *= Increment;
coord += high*coefficient;
coefficient *= Increment;
}
//千位,万位
{
double high = 0;
double low = 0;
GetTwoNum(byte4,high,low);
coord += low*coefficient;
coefficient *= Increment;
coord += high*coefficient;
}
return coord;
}
//获取byte 低四位和高四位的数值
void CGratingRuler::GetTwoNum(BYTE byte,double &high,double &low)
{
//低四位
{
BYTE byte1 = byte<<4;//左边清0
int tmp = (int)(byte1>>4);//先转化为整型
low = tmp;
}
//高四位
{
BYTE byte1 = byte>>4;//右边清0
int tmp = (int)(byte1);//先转化为整型
high = tmp;
}
}
#endif
#if 1//坐标相关
//设置当前位置为光栅尺的原点
bool CGratingRuler::SetOriginCoord()
{
Dbxy pt;
if(ReadGratingRuler(pt)==false)//读取当前值
{
return false;
}
m_bIni = true;//初始化成功
m_OriginCoord = pt;//记录当前的读数
return true;
}
//获取光栅尺当前的坐标
bool CGratingRuler::GetCurCoord(Dbxy &pt)
{
if(!m_bIni)
{
return false;
}
Dbxy ReadPt;
if(ReadGratingRuler(ReadPt)==false)
{
return false;
}
//转换为相对坐标
pt.x = ReadPt.x - m_OriginCoord.x;
pt.y = ReadPt.y - m_OriginCoord.y;
return true;
}
#endif
#if 1//平台操作
//平台原点校准(平台此时理论坐标已经回原点,再通过光栅尺来校准其位置)
bool CGratingRuler::PlatformOriginCalibration(CPlatformXY &PlatformXY)
{
if(IsUsed()==false)//没有使用光栅尺,则认为已经校准
{
return true;
}
if(!m_bIni)
{
return false;
}
int i=0;
for(;i<m_MaxCalibrationTimes;i++)
{
//获取光栅尺当前的坐标
Dbxy pt;
if(GetCurCoord(pt)==false)
{
return false;
}
if(pt.x>m_MaxOriginError || pt.y>m_MaxOriginError)
{
//异常情况,误差大于正常值
return false;
}
//XY 轴的误差都小于m_OriginCalibrationError 时,结束校准
if(abs(pt.x)<m_OriginCalibrationError && abs(pt.y)<m_OriginCalibrationError)
{
break;
}
//否则补偿(脉冲变化不计入理论坐标值,这个时候理论坐标是零)
if(abs(pt.x)>m_OriginCalibrationError)
{
if(pt.x>0)
{
PlatformXY.MoveDistance(pt.x,_DIR_L,false);
}
else
{
PlatformXY.MoveDistance(pt.x,_DIR_R,false);
}
}
if(abs(pt.y)>m_OriginCalibrationError)
{
if(pt.y>0)
{
PlatformXY.MoveDistance(pt.x,_DIR_D,false);
}
else
{
PlatformXY.MoveDistance(pt.x,_DIR_U,false);
}
}
}
if(i==m_MaxCalibrationTimes)
{
return false;
}
return true;
}
//测量平台误差
//rect 是需要校准的范围(相对于平台理论坐标)
//PlatformXY 是要校准的平台
bool CGratingRuler::MeasurePlatfromError(DbRect rect,CPlatformXY &PlatformXY)
{
if(IsUsed()==false)
return true;
if(!m_bIni)
{
return false;
}
//x 轴
if(MeasureMotorError(PlatformXY,_X,rect.L,rect.R,m_ErrorTableX)==false)
{
return false;
}
//y 轴
if(MeasureMotorError(PlatformXY,_Y,rect.B,rect.T,m_ErrorTableY)==false)
{
return false;
}
return true;
}
//测量马达的误差(Start,End 是测量范围)
bool CGratingRuler::MeasureMotorError(CPlatformXY &PlatformXY,X_OR_Y xy,double Start,double End,vector<TypePosError> &ErrorTable)
{
ErrorTable.clear();
Dbxy CurPt = PlatformXY.GetCoord();//当前平台坐标,应该是0,0
Dbxy OriginPt;//原点
double CurPos = Start;
while(CurPos <= End)
{
Dbxy MovePt;//当前测量点(平台理论坐标)
if(xy == _X)
{
MovePt.x = CurPos;
MovePt.y = CurPt.y;
}
else
{
MovePt.x = CurPt.x;
MovePt.y = CurPos;
}
PlatformXY.Move(false,MovePt,OriginPt);//移动
//读取光栅尺当前坐标
Dbxy RulerCoord;//光栅尺实际坐标
if(GetCurCoord(RulerCoord)==false)
{
return false;
}
//记录当前误差(实际走位的是否理论值减掉这个误差即可)
double Error;
if(xy == _X)
{
Error = RulerCoord.x - CurPos;
}
else
{
Error = RulerCoord.y - CurPos;
}
TypePosError PosError;
PosError.first = CurPos;
PosError.second = Error;
ErrorTable.push_back(PosError);
}
return true;
}
#endif