#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]------------------------------------------------"<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(;im_MaxOriginError || pt.y>m_MaxOriginError) { //异常情况,误差大于正常值 return false; } //XY 轴的误差都小于m_OriginCalibrationError 时,结束校准 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 &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