预约试听:15323438773
  


培训资料分类
热门人气资料 / Download More
发布时间: 2017 - 01 - 17
控制卡应用编程技巧几招(1) 声明一下,写下这些编程技巧,即不是什么祖传秘籍,也不是什么必杀招或绝招,在此只为方便同仁们在编程控制软件时,对此可以进行适当的斟酌。以下展现的编程思想及奉上的源代码都非常简易,但并不是随手写写,可都是经过实践的。若没有成功经验作后盾,我也就没有必要在此打字练五笔了。 事实上,正如一个编程大师所言(Michael Abrash),当你的软件正常而且有效率的运行起来时,好像一切都是那么显而易见。故,在此,我仍坚持那句编程口号,将事情变得越简单越好,越简单就越有效率,越稳定。 在以下的介绍中,我将尽可能的展示本人的编程思想,最大可能的给出知其然也知其所然的解释。若你有更好的见解,希望能得到你的指正。人长大了明显标志就是变得不太负责,而且不敢承认自己还需要努力,害怕面对自己的错误。若是这样,放心,我还没长大。因为我无法保证我能面面俱到。 关于源代码的阅读,需要读者有一定的C++编程基础,至少对以下表示形式不会产生误解: const char *pString; //指定pString邦定的数据不能被修改 char * const pString; //指定pString的地址不能被修改 const char * const pString; //含上面两种指定功能 当然,随便提醒一下,这些源代码若需要加入你的软件工程当中,还需要作一些调整和修改,因此,这些源代码实质上称为伪代码也可以,之所以展现它们,是让程序员们有个可视化的快感,特别是那些认为源代码就是一切的程序员。 同时,为了提高针对性,大部分控制卡调用的函数会明确指出是邦定哪些卡的,实际应用时,程序员可自行选择,以体现一下自己的智商是可以写写软件的。  一、 控制卡类的单一实例实现 把控制卡类作一个类来处理,几乎所有C++程序员都为举双手表示赞同,故第一个什么都没有的伪代码就此产生,如下表现: class CCtrlCard { public: …Function public: …attrib }  于是,用这个CctrlCard可以产生n多个控制卡实例,只要内存足够。然而,针对现实世界,情况并不那么美好。通常情况下,PC机内只插同种类型的...

控制卡应用编程技巧

控制卡应用编程技巧几招(1)

 声明一下,写下这些编程技巧,即不是什么祖传秘籍,也不是什么必杀招或绝招,在此只为方便同仁们在编程控制软件时,对此可以进行适当的斟酌。以下展现的编程思想及奉上的源代码都非常简易,但并不是随手写写,可都是经过实践的。若没有成功经验作后盾,我也就没有必要在此打字练五笔了。 

事实上,正如一个编程大师所言(Michael Abrash),当你的软件正常而且有效率的运行起来时,好像一切都是那么显而易见。故,在此,我仍坚持那句编程口号,将事情变得越简单越好,越简单就越有效率,越稳定。 

在以下的介绍中,我将尽可能的展示本人的编程思想,最大可能的给出知其然也知其所然的解释。若你有更好的见解,希望能得到你的指正。人长大了明显标志就是变得不太负责,而且不敢承认自己还需要努力,害怕面对自己的错误。若是这样,放心,我还没长大。因为我无法保证我能面面俱到。 

关于源代码的阅读,需要读者有一定的C++编程基础,至少对以下表示形式不会产生误解: 

const char *pString; //指定pString邦定的数据不能被修改 

char * const pString; //指定pString的地址不能被修改 

const char * const pString; //含上面两种指定功能 

当然,随便提醒一下,这些源代码若需要加入你的软件工程当中,还需要作一些调整和修改,因此,这些源代码实质上称为伪代码也可以,之所以展现它们,是让程序员们有个可视化的快感,特别是那些认为源代码就是一切的程序员。 

同时,为了提高针对性,大部分控制卡调用的函数会明确指出是邦定哪些卡的,实际应用时,程序员可自行选择,以体现一下自己的智商是可以写写软件的。 

 一、 控制卡类的单一实例实现 

把控制卡类作一个类来处理,几乎所有C++程序员都为举双手表示赞同,故第一个什么都没有的伪代码就此产生,如下表现: 

class CCtrlCard

{

public:

…Function

public:

…attrib

}

 于是,用这个CctrlCard可以产生n多个控制卡实例,只要内存足够。然而,针对现实世界,情况并不那么美好。通常情况下,PC机内只插同种类型的控制卡1到2张,在通过调用d1000_board_init或d3000_board_init函数时,它们会负责返回有效卡数nCards,然后从0-nCards*4 - 1自行按排好轴数。初始化函数就是C++的new或malloc的操作,取得系统的资源,但是控制卡的资源与内存不一样,取得资源后必需要释放才可以再次获取,即控制卡资源是唯一的。 

既然控制卡资源是唯一的,那么最好Cctrlcard产生的实例也是唯一的,这样,我们可以方便的需要定义一个全局变量即可:

CctrlCard g_Dmcard;

在其它需要调用的地方,进行外部呼叫: 

extern CctrlCard g_DmcCard;

 以上方法实在太简单了,很多人都会开心起来。实质上,方法还有很多,即然可以产生n多对实例,我们的核心是只要保证调用board_init函数一次即可,故也可以单独定义一个InitBoard函数: 

class CctrlCard

{

public:

static int InitBoard(); //定义一个静态函数,以表警示 

 }

int CctrlCard::InitBoard()

{

return d1000_board_init();

}

 还有一种方法,情况稍加复杂,但表达的功能也要强一些,以下展现可以稍微安慰一下代码狂。 

 Class CctrlCard

{

public:

CctrlCard(); //请注意这个构造函数的定义 

}

 CctrlCard::CctrlCard()

{//呵呵,也很明了 

static int n(0); //注意,是个静态变量 

 n++; //每次调用CctrlCard生成实例时,都会计数一次 

assert( n == 1 ); //在DEBUG版本下,只有n==1的情况下可以通过 

//否则,会出现致命错误,还好,它会告诉你错在哪个文件, 

//哪一行,呵呵,是个好东东啊。 

}

通过强行报警处理,当你有g_DmcCard这个实例时,其它的所有控制卡的定义都只能是以引用或指针的方式进行了,不会再产生新有效的实例了,对于由小组编程的项目软件,而你又恰好负责编程控制卡这一块的话,以上的显性报警,会让其它人心领神会。当然,你也可以将上面的方法加入到InitBoard当中去,可以避你的无意识的多次调用了。 

 附:无意识的多次调用经常发生,特别是那些对MFC机制不明确的程序员,在多文档框架下,不知道这个CctrlCard::InitBoard函数到底是应该放在CmainFrame的OnCreate里面,还是应该放在CchildFrame的OnCreate,或者是Cview的OnInitUpdate里面进行调用。 

在一言难尽MFC的情况下,我建议两个小方法: 

No.1 将CctrlCard的函数置于Cmainframe的OnCreate或者Capp::Initstance内调用 

No.2 将InitBoard函数稍加改造成这样: 

Int CctrlCard::InitBoard()

{

static int n(-1000);//注意,-1000是控制卡函数不可能返回的值 

if( n == -1000 )

n = d1000_board_init();

return n;//这样,即使多次调用也不样怕了,呵呵,雕虫小技也可以除虫啊 

}

 必须额外声明一下,我们不是不重视资源的释放,而是作为一个C++程序员写下这些代码是基本的义务(这也是我为什么要交待读者必须要有一定的C++基础): 

class CctrlCard

{

public:

~CctrlCard()

{//定义析构函数,在此释放资源,对此,我不想再转到读者的眼球了 

d1000_board_close();

}

}

 二、 数据结构及数据类型的定义,部分相关声明 

调用控制卡驱动函数时,经常会有如下形式: 

单轴相对运动 d1000_start_t_move( axis, pulse, start, speed, accel );

单轴绝对运动 d1000_start_ta_move( axis, pulse, start, speed, accel );

两轴相对插补 d1000_start_t_line( axisArray, distArray, start, speed, accel );

两轴绝对插补 d1000_start_ta_line( axisArray, distArray, start, speed, accel );

圆弧相对插补 d3000_start_t_arc( axisArray, C1, C2, E1,E2, dir, start, speed, accel );

圆弧绝对插补 d3000_start_ta_arc( axisArray, C1, C2, E1,E2, dir, start, speed, accel );

 以上的调用,很多重复枯燥,又不直观,难于理解,并且在面向客户时,常常是指每分多少米,或者每秒多少毫米,很少有人问每秒多少脉冲,移动多少脉冲作距离,故需要单位之间的换算。显然,对于这些问题,我想,C++程序员应该找到用武之地了,所以我们一步一步来,慢慢统一各个问题。实质上,在以下的几个技巧,也需要在此澄清一些概念。 

我们先来几个宏定义提高一下情绪: 

# define MAX_AXIS 4 //最多轴数 

# define XCH 0 //定义X轴的值 

# define YCH 1

# define ZCH 2

# define UCH 3

…..(其它以次类推)

 # define M_ABS 0x01 //定义一个绝对标志位 

# define M_INP 0x02 //定义一个插补位 

 接下来深入一点点,再来几个结构定义: 

 typedef struct tag_ARC

{

tag_ARC( double ox=0.0, double oy=0.0, double ex=0.0, double ey=0.0, int dir=0 ):

ox(ox), oy(oy),

ex(ex), ey(ey),

dir(dir)//定义这样一个构造函数需要勇气,看似不合理,但是好用麻 

{

}

double ox,oy;

double ex,ey;

int dir;

}ARC;

 typedef struct tag_SPEED

{

tag_SPEED( double start=0.0, double speed=0.0, double accel=0.0, double decel=0.0,

double scc=0.0 ) :

start(start),

speed(speed),

accel(accel),

decel(decel),

scc(scc)

{

}

 

double start;

double speed;

double accel;

double decel;

double scc;

}SPEED;

 

以上两个ARC和SPEED的结构定义,把几个参数变成一个参数。比如要实现的单轴驱动函数,就变得非常明了: 

void Move( int nAxis, double fMM, const SPEED &speed, int nFlag = M_ABS );//往后我们再具体完善其实现。 

 以上的结构具有类的特性,但是由于其每个成员都可以给外部直接使用,故就不需要什么类的public及其析构函数的定义了。之所以全都采用double的数据类型,是面向客户习惯及单位计算方便的。 

接下来是对控制卡常用的单位计算及部分常用变量的声明: 

class Cctrlcard

{

public:

…(其它略去)

public:

//属性 

mutable int ORGIN; //指定原点状态位 

mutable int LIMIT_A, LIMIT_B; //指定左右限位状态位 

private:

//以下的属性不给外部访问的 

struct tag_AXIS{//单轴属性 

double fUnitPM; //脉冲当量 

long nRP; //每转脉冲数 

double fJourey; //行程 

};

tag_AXIS m_axis[MAX_AXIS];

};

 

定义ORGIN,LIMIT_A, LIMIT_B为变量,是有两个意义: 

No.1 当你访问它们的状态时,不需要每次调用d1000_get_axis_status函数,你可以这样: 

Int nStatus = d1000_get_axis( XCH );

If( nStatus & g_DmcCard.ORGIN == g_dmcCard.ORGIN )

If( nStatus & g_DmcCard.LIMIT_A == g_DmcCard.LIMIT_A )

If( nStatus & g_DmcCard.LIMIT_B == g_DmcCard.LIMIT_B );

No.2 你可以扩展不同的卡,当外部调用的程序逻辑已被确定时,当你需要从DMC1000控制卡升级到DMC3000控制卡时,只需要给ORGIN等状态位指定不同的值即可。指定状态位的值也有一个小小的技巧,以ORGIN为例,在DMC1000控制卡,其位值在2位,则可以这样: 

ORGIN = 1<<2;

在DMC3000控制卡,其值在第9位,则这样: 

ORGIN = 1<<9;

方法都很简单,关键是要想得到。 

 

对于tag_AXIS定义,引出几个函数的声明,专门为其服务: 

void SetUP( nit nAxis, double fMM, double nPulse, double fMax );//设定当量 

double P2M ( int nAxis, long nPulse ); //脉冲转成毫米 pulse to metric

long M2P( int nAxis, double fMM ); //毫米转成脉冲 mitric to pulse

 现在,我们再回过头来完成Move函数的实现,以便获得一点点成就感,同时也展示一下以上的大堆表述是有其意义的。 

 void Move( int nAxis, double fMM, const SPEED &speed, int nFlag = M_ABS )

{

( nFlag & M_ABS == M_ABS ) ?

d1000_start_ta_move( nAxis, //绝对 

M2P( nAxis, fMM),

M2P( nAxis, speed.start ),

M2P( nAxis, speed.speed),

Speed.accel ): //注意是冒号,?:是一个表达式 

d1000_start_t_move( nAxis, //相对 

M2P( nAxis, fMM),

M2P( nAxis, speed.start ),

M2P( nAxis, speed.speed),

Speed.accel );

}

 是不是很简单呢,当外部调用时,客户的观念就直接面对Metric即可,如: 

 Move( XCH, 10.0, SPEED(5,10,0.1), M_ABS );//达到绝对位置10.0毫米处。 

 以上罗嗦了一大堆,对于刚开始C++编程的程序员来说应该是收益不小,对于高手,则希望能够体会一下我的良苦用心。在以下的技巧介绍当中,我将变得很简易。一般来讲,程序员的基础不是太差的话,至少能够在1分钟内明白是什么道理。

 

控制卡应用编程技巧几招(2)

发布日期:2009-3-9 0:42:58  浏览次数:2416

 三、 插补和联动函数 

当程序员决定需要几轴进行插补时,尽量选择最大插补轴数,如在雕铣系统时,有时会用到两轴插补,有时会进行三轴插补,在这个基础上,为简化编程,我的理论只使用三轴插补,当需要进行两轴插补或联动时,根据相对或绝对的坐标关系,将不运动轴填入0偏移或绝对位置即可。 

以下为XYZ三轴联动和插补的函数,由nFlag的M_INP位决定是否进行插补: 

 

void MoveXYZ( double fX, double fY, double fZ, const tag_SPEED &speed,

int nFlag = M_ABS )

{

short axisArray[]={ XCH, YCH, ZCH };

 

if( nFlag & M_INP == M_INP )

{//插补 

long distArray[]={ M2P(XCH, fX), M2P(YCH,fY), M2P(ZCH,fZ) };

long nStart, nSpeed;//计算新的矢量速度,参见DMC1000矢量速度的计算 

(…矢量速度计算在此略去)

 

( nFlag & M_ABS == M_ABS ) ?

d1000_start_ta_line( 3, axisArray, nStart, nSpeed, speed,accel )://绝对 

d1000_start_t_line(3, axisArray, nStart, nSpeed, accel );//相对 

}

else

{//联动 

double fpos[]={ fX, fY, fZ};

for( int I(0); I<3; I++)//发三次单轴移动命令 

Move( axisArray[I], fpos[I], speed, nFlag );

}

}

在我给出的DMC3000控制卡类完整源代码一文中,有其更完善的版本。通过以下的函数封装,将插补和联动,绝对位置,相对位置等等都很好的整合在一起,用户在使用起来具体更准确的目标。 

 

四、 驱动轴状态、位置读取和设定 

对于驱动轴的状态,分为两种:1、指脉冲输出状态;2、指专用输入信号电平状态 

检测脉冲输出是否完成,可以写成如下函数,假设软件总共只用到XYZ三轴: 

 int IsRunning( int nAxis = -1 )//默认为-1是有目的的 

{

if( nAxis != -1 )

return d1000_check_done( nAxis ) == 0 ;

//当nAxis == -1时,检测三个轴是否有一个在运行,这种检测在加工时常用 

return d1000_check_done( XCH ) == 0 ||

d1000_check_done( YCH ) == 0 ||

d1000_check_done( ZCH ) == 0;

}

 当用户等待YCH脉冲发完,则用一个循环检测即可: 

while( g_DmcCard.IsRuning( YCH ) ) ::DoEvents();

 别忘了,IsRuning是CctrlCard的成员函数,而DoEvents函数在DMC1000不能响应系统消息的文章中有详细实现和功能描述。 

在实际加工时,作插补时,常需要等待上次所有运动结束才开始新的运动。故有如下表现: 

 

for( int I(0),step(0); I

{

DoEvents();

switch( m_nworkStatus ){

case Pause:

continue;

case Continue: m_nWorkStatus = Running;

case Running:

{

switch( step ){

case 0:

if( IsRunning() ) break;//检测所有运动结束,否则继续检测 

MoveXYZ( data[I].x, data[I].y, data[I].z …… );

Step ++;

Break;

Case 1:

If( IsRunning() ) break;//同上 

I++; //准备下一段数据,之所以放在此处,是需要考虑在运行过程中,有外部的暂停和继续操作。 

Step = 0;//准备运行新的数据 

Break;

}

} break;

}

 

以上程序框架,有着非常广阔的应用前景,非常简单,可以让程序员随意控制,故而它又非常稳定,比起线程的操作,它具体非常透明的可操作性。 此框架在雕刻,焊接,切割等许多场合都将成为经典,当然,若你不曾深入了解它,则不会发现它的可爱之处。 

 

对于专用输入信号状态的检测,几乎没有什么特别之处: 

int GetStatus( int nAxis )

{

return d1000_get_axis_status( nAxis );

}

 

位置的读取和设定,对于DMC1000比较容易,故在此我将写出DMC3000控制卡的这两个函数,当然用于DMC1000也是没问题的。 

DMC3000控制卡的位置分为指令位置和物理位置(编码器反馈的),所以函数需要有一个小小的选择,先看看位置获取函数: 

 

Double GetPosition( int nAxis, BOOL bCmd = true )// bCmd == true时,读取指令位置,否则为物理位置 

{

long pulse = (bCmd == true ) ?

d3000_get_command_pos( nAxis ):

d3000_get_encoder_pos(nAxis);

return P2M( nAxis, pulse );//脉冲转成毫米然后返回 

}

 位置设定函数多了一点点动作: 

double SetPosition( int nAxis, double fMM, BOOL bCmd = true )

{

double pos = GetPosition( nAxis, bCmd );//先取得原来的位置 

( bCmd == true )?

D3000_set_command_pos( nAxis, M2P(nAxis, fMM )):

D3000_set_encoder_pos( nAxis, M2P(nAxis, fMM) );

Return pos;//返回旧的位置 

}

为什么这样设计?当你用过CPen *pOldPen= pDC->SelectObject( &newPen );时,或者除了复位之外,你真正需要调用这个SetPosition函数时,你会发现这个设计,真是人情味实足。 

 

五、 复位,相对与绝对, 

在如今PC机开发控制卡软件时代,设备上电不复位的几乎没有,在此谈到复位这个问题确实有必要,实现上,复位动作因不同设备的工艺要求而定,故一般而言,控制卡提供的那个复位函数太过简单,有点力不从心,所以,本人自己写了个复位函数,但是代码写起来将会占用很大的面版,故有此需要者,可以来电或E_mail索取。 

其基本思路是采用两次找原点,第一次高速找,停止后退出,再次以较低的速度找原点。并且在执行第二次复位时,会在离原点5毫米处减速(第一次执行做不到)。 

 提供相对和绝对位置的概念是很有必要的,众所周知,现在控制卡能作到最小单位为1个脉冲,当然,作为数字脉冲,到此已不能再小了,故为了提高精度,通常情况下要提高计算当量,即增加每转脉冲数,或减少每转毫米数。 

不论怎么,我们将问题放大并明朗化,可以看看以下片段: 

 for( int I(0); I<10000; I++)// 走10000次 

move( 0.5 );//走相对0.5个脉冲的距离 

 结果是:1个脉冲也发不出,造成很大的累积误差。 

若换成绝对方式: 

for( int I(0); I<10000; I++)

goto( I*0.5 );

 最后的误差,最大也就是1个脉冲以内。虽然还是有误差,但总算达到可容忍的程序,再加上适当的复位操作,让客户至少不必再担心这个巨大的累积误差了。 

 实质上,在整个软件设计时最好采用绝对坐标系,即使要处理加工原点或工面起点等这些参数,也要把它换算成绝对位置,唯手动移动设备可以例外。另外,在CNC系统中,除了有循环用到相对坐标系,其余都是用绝对坐标系为上策,实际上,在实现编程算法上,为统一起见,最好将相对的坐标关系全部转成绝对的坐标关系,这样也便于外部进行暂停或继续的处理。 

 相信,到此为止,若你的设备在加工时有一定的误差漂移,你会意识到自己应该是不是要检查一下采用了什么坐标系了吧。 

 六、 输出输入及软限位 

对于通用的I/O操作,没有什么特别要说明的,只有两点需要注意的,先给出两个小函数,以作参考: 

 int ReadBit( int nIO ); //读指定通用输入口的电平状态,返回1 或 0

int WriteBit( int nIO, int nStatus ); // 输出电平到指定输出端口 

 两点注意: 

No.1 对于ReadBit若需要加入抗干扰处理,则写一个函数: 

 Int RealInput( int nIO, int nStatus, int di=50 )

{

if( ReadBit( nIO ) != nStatus )

return 0;

while( di -- );//耗上几个CPU的周期时间,再读一次 

return ReadBit( nIO ) == nStatus;

}

 

No.2 增加一个变量及函数扩展一下输出功能: 

Long m_nOutStatus= 0x00000000;

再次改造一下WirteBit

void WriteBit( int nIO, int nStatus )

{

if( nStatus ){

m_nOutStatus |= (1<

}

else{

m_nOutStatus &= (~(1<

}

d1000_out_bit( nIO, nStatus );

}

添加的访问输出状态函数: 

int ReadOutbit( int nIO )

{

static int a;

a = 1<<(nIO-1);

a &= m_nOutStatus;

return a!=0;

}

 软限位的思想原本是用于为客户节省正负限位的光电开关成本而产生的,致使使用软件限位正常的话,设备每个驱动轴只需要一个原点开关即可。当然,软限位能正确运作是非常重要的,否则很容易撞坏设备。而其正确运行,就必须依赖正确的复位动作,以找到可靠的机械原点位置。 

软件限位的基本算法非常简单,特别是在一个绝对坐标系当中。其原理如下: 

 if( pos < minPos ) pos = minPos;

if( pos > maxPos ) pos = maxPos;


 实在没有必要再详说下去了。 

  编程技巧介绍至此算是一个了断,若在未来的日子里,有更好的想法,我会拿出来给大家参考,请大家一起来支持这件事情,拿出自己的宝贵经验,算是给数控行业添加强有力的润滑剂吧。 

 谢谢。

 

 抽像一点讲,过程控制渗透在生活的各个角落。特别是在数控行业,尤为明显。早期在PLC时代,几乎是一统天下。当大小不一的控制卡公司如雨后春笋般成长起来时,控制卡在过程控制逐步体现出强劲优势。 其编程手段往往邦定非常成熟的编程工具,如:CB,VC,Dephi,CB。故其推广非常迅速. 很快拥有大量客户群。 

但是,作为编程者,碰到同一程序需要控制多个同样设备时(动作不一定同步),往往在Window多任务系统的影响下,很快想到多线程技术,其实多线程编程对系统依赖性较强,不同级别的处理,将导致程序的维护成本增加,并且还需要考虑线程之间的通讯,使编程起来较为麻烦。事实上,依靠过程编程的思想,会使程序获得更简单的做法。 

纯粹从编程角度来看,过程控制编程应包含几个要素,下面以C++伪码方式来表示一个类,较易说明问题: 

 

/**************************

一个动作封装类,包含一个 

设备的所有执行动作 

**************************/

class CAction

{

public:

CAction():m_nWorkStep(-1000){}

~CAction(){}

public:

enum{ None, Inital, Start, Stop, Pause, Continue };//部分控制标记 

 

public:

int Control( int nStatus, void *pParam ); //要素2: 一定可以接受外部控制 

int Run( void *pParam ); //要素3: 绝对有一个不断推动的执行过程(这是整个过程编程的心脏所在)

 

public:

int m_nWorkStep; //要素1: 必须有一个工作执行步 

private:

void * m_pMemberData; //要素4: 可选,邦定被操作的数据 

// ..其它辅助变量 

};

 

要素5:可选,为了能与外界用户进行沟通,Control函数与Run函数,须选择一个参数,满足用户的输入输出。但由于用户可选项太多,故古人告诉我们,万事皆空即是成功,对于C++而言,没有比void *类型更有前途了(若想体会,需搭配类型转换更有潜力)。早在一年前,本人写过一个过程控制器编程,并有成功实例,但今次版本,更有精装之特点。 

 

住下再参见一下Control函数,及Run函数的一个小样例,这将是程序员发挥强劲功能的场地所在。如下: 

 

int CAction::Control( int nStatus, void *pParam )

{//此处的设计需要一点技巧,当然完全取决程序员的经验,和对控制的理解 

switch( nStatus ){

case Inital:

m_pMemberData = pParam;//初始化邦定的用户数据 

break;

case Start:

m_nWorkStep = 0; //一般令第0步作为开始较易理解 

break;

case Stop:

m_nWorkStep = -1000;//停止 

break;

case …//其它略去 

default: break;

}

return m_nWorkStep;//返回值可自定 

}

 

int CAction::Run( void *pParam )

{//以下为一个动作不断返回,直至接受到停止指令 

switch( m_nWorkStep ){

case 0:

if( IsMove() ) break; //正在忙,不执行 

Move(1600); //正向移动1600单位 

m_nWorkStep++; //跳至下一步 

break;

case 1:

if( IsMove() ) break; //正在忙,不执行 

Move(-1600); //反向移动1600单位 

m_nWorkStep=0; //再回至第0步 

break;

case –1000: break;//停止 

default: break;//此句最好有,以便于理解 

}

return m_nWorkStep; //返回值可自定 

}

对于Run函数须谨记一点:不要有长时间的循环操作,更不要有死循环,否则另外设备无法正确动作,因为另外的设备Run函数无法被激活执行,心脏无法跳动,只好等死吧! 

当然,还须担心一点:多个设备同时执行时,其实时性会下降一点,若没有特别高的要求,在现今CPU狂奔的时代,以上程序框架足已满足90%的需求,还是有学习和理解的必要吧! 

 

 

以上的框架出来了,那么如何操作使设备驱动起来呢,不管在DOS亦或在Window系统环境里,以下的思路都一样,参见伪代码如下: 

 

const int nSize=10; //定义10台设备对象 

CAction exeArray[nSize];

BOOL bRunning=FALSE;//控制整个驱动的标志 

 

Void OnRunAction()//启动函数 

{

//初始化一下 

for( int i(0); i〈nSize; i++)

exeArray[i].Control( CAction::Inital, ( void *)userData );//userData由用户选择 

 

bRunning = true;//外部控制变量 

for( i=0; bRunning; i=(i+1)%nSize)//给予运行时间,即是驱动了 

{

exeArray[i].Run(( void *)userData); //不断驱动Action设备(即激活心脏) 

DoEvents();//做其它事情,如系统消息检测,以防止死机 

}

}

 

DoEvents函数功能的详解可参见本人的〈〈DMC1000控制卡不能响应系统消息〉〉,上面有不同编程工具下的实现源代码。 

 

void OnControlAction()

{

for( int i(0); i〈 nSize; i++)

exeArray[i].Control( Caction::(/*用户想要的动作*/), ( void *)userData);

}

 

void OnOver()

{

bRunning = FALSE;//结束驱动 

}

 

注意:有很多程序员在不同编译器下,需要不同的OnRunAction函数版本,以上实现最为简单,但有一些较特殊。比如:在程序启动时,就驱动所有设备,这点本人在VC6.0环境有过经验,可以分享一下,其它环境下,还需同胞们一起去努力发现。 

 

还有一点声明,多线程技术也不是一无是处,在花费时间较频繁的通讯编程方面,它的优势,还是有相当的诱惑力。

 

 

 

雷泰运动控制卡应用程序开发注意事项

概述:

  对于一些初次使用雷泰运动控制产品的客户,由于对本公司产品的特点以及程序开发流程不够熟悉,在应用程序的开发过程中,难免会疏漏一些细节,从而产生各种问题,浪费很多宝贵的时间。

  如果在应用程序开发前,就可以考虑到那些既重要又容易疏漏的细节,这样可以避免很多不必要的问题产生,从而大大缩短程序的开发周期。本文总结以往的经验,以雷泰运动控制卡DMC2410B为例,为客户在开发应用程序时的初始化过程给出了一些参考与建议(其他产品与此类似),其中包括运动控制卡的初始化、特殊参数的设置及各种信号的设置,如图1虚线框内所示,这些处理过程必须加载至应用程序的初始化过程中,不同编程环境下,应用程序的初始化过程略有不同,例如在VB6.0编程环境下,须在Form_Load()函数中做程序的初始化处理,而在VC6.0编程环境下,须在OnInitDialog()函数中做程序的初始化处理。

 

控制卡应用编程技巧 

 

图1 DMC2410B控制卡应用程序开发流程

  图1所示的控制卡初始化过程中,实线框内所示的参数设置或特殊信号的设置必须在初始化过程中加以处理,而虚线框内的信号在未选择使用时,可以不用设置,而当选择使用这些信号时,必须进行正确设置。下面对这些初始化过程的方法及必要性做出简要的说明。

一、 初始化运动控制卡
相关函数:WORD d2410_board_init (void)
函数功能:为控制卡分配系统资源并初始化控制卡;
  若在应用程序中未初始化控制卡,则系统无法为控制卡分配资源,导致控制卡无法正常使用,程序在运行时提示错误,弹出如图2所示对话框:

控制卡应用编程技巧 


图2 未初始化控制卡时的错误提示

 

  注意:程序在结束运行时,必须关闭运动控制卡,以释放系统资源,否则控制卡将一直占用系统资源,导致再次运行该应用程序时产生错误。关闭控制卡的方法及说明如下:
相关函数:Void d2410_board_close (void)

  函数功能: 释放控制卡占用的系统资源。当程序结束时必须调用此函数,它与d2410_board_init() 函数是一个相反的过程。


二、 脉冲参数设置
  脉冲参数包括指令脉冲类型、脉冲输出有效电平以及方向控制逻辑电平,这些参数需根据电机驱动器的类型及参数来设置,若设置错误时,则会造成控制卡正常发出脉冲,而电机无法正常运转、运转方向错误或只能朝同一个方向运转等现象。以下为脉冲参数设置的相关函数及说明:
相关函数:Void d2410_set_pulse_outmode (WORD axis, WORD outmode )
函数说明:设置指定轴的脉冲输出方式。

  参数说明:axis 指定轴号

Outmode 脉冲输出方式选择,其值如图3所示:

控制卡应用编程技巧 

图3 脉冲类型的选择

 

三、 特殊信号的设置

  特殊信号包括限位信号、原点信号、急停信号等,对这些特殊信号未进行设置或设置错误时,会导致控制卡无法正常输出脉冲、电机无法正常运转、原点回归错误等现象,下面分别对这些信号的设置及用途加以说明:

1. 限位信号的设置

  相关函数:Void d2410_config_EL_MODE (WORD axis, WORD el_mode)
函数功能:设置限位信号的有效电平及制动方式。

参数说明:axis 指定轴号;

el_mode 限位信号的有效电平和制动方式:

  0-立即停、低电平有效;1-减速停、低电平有效;

  2-立即停、高电平有效;3-减速停、高电平有效;

  限位信号的有效电平需根据所使用的限位开关的类型进行设置,DMC2410B控制卡默认为低电平有效,若有效电平设置错误,则控制卡会认为相应轴遇到限位信号而停止输出脉冲。

2. 原点信号的设置
相关函数:Void d2410_set_HOME_pin_logic (WORD axis, WORD org_logic, WORD filter)
函数功能:设置原点信号的有效电平以及允许/禁止滤波功能。

参数说明:axis 指定轴号;

org_logic 原点信号的有效电平:0-低电平有效;1-高电平有效;

filter 允许/禁止滤波功能:0-禁止;1-允许;

  原点信号的有效电平需根据所使用的原点开关的类型进行设置,DMC2410B控制卡默认为低电平有效,若有效电平设置错误,则会导致回原点运动无法启动、回原点方向相反、未遇到原点信号时回原点动作立即结束等现象。


3. 急停信号的设置

  相关函数:Void d2410_config_EMG_PIN (WORD cardno, WORD enable, WORD emg_logic)
函数功能:急停信号设置。急停信号有效时会立即停止所有轴脉冲的输出。

参数说明:cardno 卡号

enable 电平设置使能:0-电平设置无效;1-电平设置有效;

emg_logic 急停信号的有效电平:0-低电平有效;1-高电平有效;

  急停信号的有效电平需根据所使用的急停开关的类型进行设置,DMC2410B控制卡默认为低电平有效,若有效电平设置错误,则控制卡会认为收到急停信号而停止所有轴的脉冲输出。
四、 伺服专用信号的设置

  伺服专用信号是针对伺服电机和驱动器而设置的,包括伺服使能信号、报警信号、误差清除信号、零相信号、编码器反馈输入模式等,当无特殊要求时,可以选择不用控制卡去控制这些信号,但若选择使用这些信号时,必须在程序的初始化过程中进行正确的设置,否则会导致控制卡无法正常输出脉冲、伺服电机无法正常运转、编码器反馈计数无法读取或计数错误等现象,下面分别对这些信号的设置加以说明:


1. 伺服使能(Sevon)信号的设置

  伺服使能信号的有效电平是通过控制卡的拨码开关进行设置,如图4所示,DMC2410B控制卡默认为高电平有效,若此电平设置错误,则会出现控制卡正常输出脉冲,而伺服电机的轴未锁紧而无法运转的情况,此信号端子可用软件控制,其相关函数及说明如下:
相关函数:Void d2410_write_SEVON_PIN (WORD axis, WORD on_off);
函数功能:输出对指定轴的伺服使能端子的控制

参数说明:axis 指定轴号

on_off 设定伺服使能电平状态:0-低电平;1-高电平。

注意:其中SEVON 输出口初始状态可选, 当拨码开关对应的位置为OFF后, 则SEVON 的电平逻辑会取反。

控制卡应用编程技巧4

图4 伺服使能信号电平的设置

2. 伺服报警(Alarm)信号的设置

相关函数:Void d2410_config_ALM_PIN (WORD axis, WORD alm_logic, WORD alm_action)
函数功能:设置伺服报警信号的逻辑电平及其工作方式

参数说明:axis 指定轴号

alm_logic ALM信号的有效电平:0-低电平有效;1-高电平有效;

alm_action ALM信号的制动方式:0-立即停止;1-减速停止;

ALM信号的有效电平需根据伺服驱动器进行设置,DMC2410B控制卡默认为低电平有效,若此电平设置错误,则控制卡会认为相应轴发出报警信号而停止输出脉冲。

3. 伺服误差清除(ERC)信号的设置

相关函数:Void d2410_config_ERC_PIN (WORD axis, WORD enable, WORD erc_logic,

WORD erc_width, WORD erc_off_time)

函数功能:设置允许/禁止ERC 信号及其有效电平和输出方式

参数说明:axis 指定轴号

enable:  0-不自动输出ERC 信号

1-自动输出ERC 信号

erc_logic 设置ERC信号的有效电平:0-低电平有效;1-高电平有效;

erc_width ERC信号的有效输出宽度:单位:us

erc_off_time ERC信号的关断时间:单位:us

  伺服电机是根据位置误差计数器运转的,若将位置误差计数器清零,则伺服电机立即停止运行,而误差清除(ERC)信号便是用来清除位置误差计数器的,若此信号的模式及有效电平设置错误,当控制卡正常输出脉冲时,而伺服驱动器的位置误差计数器一直处于清零状态,故电机无法运行。

 

4. 伺服零相(EZ)信号的设置

相关函数:Void d2410_config_EZ_PIN (WORD axis, WORD ez_logic, WORD ez_mode)

函数功能:设置指定轴的 EZ信号的有效电平及其作用。

参数说明:axis 指定轴号

ez_logic EZ信号的有效电平:0-低电平有效;1-高电平有效;

ez_mode EZ信号的工作方式:0-EZ 信号无效;1-EZ 是计数器复位信号;

  EZ信号可以用来精确回原点运动及复位编码器反馈位置计数器,若此信号的有效电平及工作方式设置错误,则控制卡会一直复位编码器反馈位置计数器,导致无法读取编码器的反馈位置。

 

5. 编码器反馈输入模式的设置

相关函数:Void d2410_counter_config (WORD axis, WORD mode)

函数功能:设置编码器输入口的计数方式。

参数说明:axis 指定轴号

  mode编码器反馈输入模式:

0-非 A/B相脉冲(脉冲+方向);

1-1倍 A/B相脉冲信号;

2-2倍 A/B相脉冲信号;

3-4倍 A/B相脉冲信号;

  DMC2410B控制卡的反馈位置计数器能接收两种模式的脉冲输入:非A/B相(脉冲+方向)模式和A/B相输入模式,这需要根据编码器的类型进行设置,若此模式设置错误,则会造成计数器无法计数或只能朝一个方向计数以及计数值错误等现象。

 总结:

  综上所述,若在应用程序的开发过程中未对控制卡进行正确初始化处理时,会给整个开发过程带来很多不必要的麻烦,而细致全面的初始化过程则可以在程序开发的初期避免这些问题和麻烦的产生,从而使整个程序开发过程事半功倍!

  因此,建议大家自己创建一个初始化函数,将上面描述的各项相关参数包容到其中,然后在应用程序里边再调用,以方便当前项目开发和后续其他的项目开发。

 


相关资料推荐 / Download 查看更多
发布时间: 2018 - 01 - 11
人工智能工程师必备干货如果要问当下互联网什么最热门?毫无疑问是人工智能。目前,世界上主要发达国家都已经将人工智能作为国家级发展战略。那么,踩在下一个时代的风口浪尖上,普通程序员如何向人工智能靠拢?为此特别推荐10款托管在码云上的人工智能开源软件,希望能够给大家带来一点点帮助和启发。当然,如果你很喜欢以下提到的项目,别忘了分享给其他人。1、项目名称:智能家居的架构项目简介: 智能家居的概念(smart home , home auto)很早以前就有了,现在随着硬件成本的下降,及 google 收购 nest 等,智能家居热度升高。 本智能家居的架构,包括服务器端,web 网页,android 手机客户端,各种测试脚本,基本上基础架构都已经实现,并可实际调试。由于精力有限智能控制部分还在合作开发中。2、项目名称:Living-Robot 开源机器人项目简介: 当我们在网上搜索开源机器人时,我们发现都是部分功能的代码和 demo,我们不能找到一个完整的项目,直接下载到我们的树莓派上,上电,然后就可以动、可以玩了。rtp 已经做到这点了;事实上它已经可以动并说话了,它是基于 ros 的完整的机器人代码,找来1块树莓派,接上几个电机和喇叭,ok,它已经可以动、可以玩、可以愉快地添加自己的代码了;虽然粗糙但是基本满足这个需求了(子功能还需要各种完善)。什么是Living-Robot:想象一下当你养了一只兔子、或者一只蜥蜴作为宠物时,它们从来不会和你卖萌扮可爱,根本不会回答你任何或机智或愚蠢透顶的问题;但是我们还是养了这样的宠物;为什么?因为它是“活着的”的。 rtp 要人工创造这种 Living 的感觉,我们称之为“Living-Robot”。3、项目名称:深度学习人脸识别引擎 JAVA SDK项目简介: 本项目是千搜科技第四代人脸识别引擎 java 接口...
发布时间: 2018 - 01 - 09
1、初始化参数  在接线之前,先初始化参数。  在控制卡上:选好控制方式;将PID参数清零;让控制卡上电时默认使能信号关闭;将此状态保存,确保控制卡再次上电时即为此状态。  在伺服电机上:设置控制方式;设置使能由外部控制;编码器信号输出的齿轮比;设置控制信号与电机转速的比例关系。一般来说,建议使伺服工作中的最大设计转速对应9V的控制电压。  2、接线  将控制卡断电,连接控制卡与伺服之间的信号线。以下的线是必须要接的:控制卡的模拟量输出线、使能信号线、伺服输出的编码器信号线。复查接线没有错误后,电机和控制卡(以及PC)上电。此时电机应该不动,而且可以用外力轻松转动,如果不是这样,检查使能信号的设置与接线。用外力转动电机,检查控制卡是否可以正确检测到步进伺服电机位置的变化,否则检查编码器信号的接线和设置  3、试方向  对于一个闭环控制系统,如果反馈信号的方向不正确,后果肯定是灾难性的。通过控制卡打开伺服的使能信号。这是伺服应该以一个较低的速度转动,这就是传说中的“零漂”。  一般控制卡上都会有抑制零漂的指令或参数。使用这个指令或参数,看电机的转速和方向是否可以通过这个指令(参数)控制。如果不能控制,检查模拟量接线及控制方式的参数设置。确认给出正数,电机正转,编码器计数增加;给出负数,电机反转转,编码器计数减小。如果电机带有负载,行程有限,不要采用这种方式。测试不要给过大的电压,建议在1V以下。如果方向不一致,可以修改控制卡或电机上的参数,使其一致。  4、抑制零漂  在闭环控制过程中,零漂的存在会对控制效果有一定的影响,最好将其抑制住。使用控制卡或伺服上抑制零漂的参数,仔细调整,使电机的转速趋近于零。由于零漂本身也有一定的随机性,所以,不必要求伺服电机转速绝对为零。  5、建立闭环控制  再次通过控制卡将伺服使能信号放开,在控制卡上输入一个较小的比例增益,至于多大算较小,这...
发布时间: 2018 - 01 - 06
图像处理与机器视觉第一章 图像增强的研究和发展现状  图像在采集过程中不可避免的会受到传感器灵敏度、噪声干扰以及模数转换时量化问题等各种因素的影响,而导致图像无法达到令人满意的视觉效果,为了实现人眼观察或者机器自动分析、识别的目的,对原始图像所做的改善行为,就被称作图像增强。图像增强包涵了非常广泛的内容,凡是改变原始图像的结构关系以取得更好的判断和应用效果的所有处理手段,都可以归结为图像增强处理,其目的就是为了改善图像的质量和视觉效果,或将图像转换成更适合于人眼观察或机器分析、识别的形式,以便从中获取更加有用的信息。  常用的图像增强处理方式包括灰度变换、直方图修正、图像锐化、噪声去除、几何畸变校正、频域滤波和彩色增强等。由于图像增强与感兴趣的物体特性、观察者的习惯和处理目的密切相关,尽管处理方式多种多样,但它带有很强的针对性。因此,图像增强算法的应用也是有针对性的,并不存在一种通用的、适应各种应用场合的增强算法。于是,为了使各种不同特定目的的图像质量得到改善,产生了多种图像增强算法。这些算法根据处理空间的不同分为基于空间域的图像增强算法和基于变换域的图像增强算法。基于空间域的图像增强算法又可以分为空域的变换增强算法、空域的滤波增强算法以及空域的彩色增强算法;基于变换域的图像增强算法可以分为频域的平滑增强算法、频域的锐化增强算法以及频域的彩色增强算法。  尽管各种图像增强技术已取得了长足的发展,形成了许多成熟、经典的处理方法,但新的增强技术依然在日新月异地发展完善,不断推陈出新,其中尤其以不引起图像模糊的去噪声方法(如空域的局部统计法)和新的频域滤波器增强技术(如小波变换,K-L变换等)最为引人瞩目。  第二章 图像增强的基本方法  一般而言,图像增强是根据具体的应用场景和图像的模糊情况而采用特定的增强方法来突出图像中的某些信息,削弱或消除无关信息,以达到强调图像的整体或局...
发布时间: 2018 - 01 - 05
Python 图像处理库 Pillow 入门(含代码)Pillow是Python里的图像处理库(PIL:Python Image Library),提供了了广泛的文件格式支持,强大的图像处理能力,主要包括图像储存、图像显示、格式转换以及基本的图像处理操作等。 1)使用 Image 类PIL最重要的类是 Image class, 你可以通过多种方法创建这个类的实例;你可以从文件加载图像,或者处理其他图像, 或者从 scratch 创建。要从文件加载图像,可以使用open( )函数,在Image模块中: from PIL import Image im = Image.open("E:/photoshop/1.jpg")加载成功后,将返回一个Image对象,可以通过使用示例属性查看文件内容: print(im.format, im.size, im.mode)('JPEG', (600, 351), 'RGB')format 这个属性标识了图像来源。如果图像不是从文件读取它的值就是None。size属性是一个二元tuple,包含width和height(宽度和高度,单位都是px)。 mode 属性定义了图像bands的数量和名称,以及像素类型和深度。常见的modes 有 “L” (luminance) 表示灰度图像, “RGB” 表示真彩色图像, and “CMYK” 表示出版图像。如果文件打开错误,返回 IOError 错误。只要你有了 Image 类的实例,你就可以通过类的方法处理图像。比如,下列方法可以显示图像:im.show()2)读写图像PIL 模块支持大量图片格式。使用在 Image 模块的 op...
发布时间: 2017 - 12 - 25
当机器视觉遇到“人工智能-工业4.0”.....人们感知外界信息的80%是通过眼睛获得的,图像包含的信息量是最巨大的。机器视觉给机器人装上了“眼睛”,成为工业4.0的重点,互促发展是技术的必然,更是时代的选择。 工业4.0是什么?在人类历史发展前期,生产力的增长几不可察,生活水平的提升也非常缓慢。而从200多年前开始,生产力发生了飞跃性变化,这一翻天覆地的变化得益于工业革命。如果将工业的发展历史分成4个时代,那么工业革命1.0使机器生产代替了手工劳动;工业革命2.0实现了流水线生产;工业革命3.0实现了自动化生产。工业生产方式则依次经历了机械化、流水线生产、自动化。2013年4月,在汉诺威工业博览会上,德国正式推出工业4.0的概念,旨在提升制造业的智能化水平。德国工业4.0是指利用物联信息系统(Cyber—PhysicalSystem简称CPS)将生产中的供应,制造,销售信息数据化、智慧化,最后达到快速、有效、个人化的产品供应。其实质是“互联网+制造”。在成产层面,“工业4.0”是生产设备间的互联、设备和产品的互联、虚拟与现实的互联,甚至是未来的万物互联。工业4.0理念的提出促进了智能工厂的实现,生产方式必将迎来巨大改变。工业4.0--机器视觉是核心目前视觉技术在工业生产中的应用大致可分为两类:质量控制和辅助生产。其中,质量控制主要是指对产品缺陷的检测,识别不良品,此类设备在国内外自动化生产线已有广泛使用。辅助生产则是利用视觉技术给机器人提供动作执行依据,国内市场尚待开发。工业机器人的发展,势必引起机器视觉新增长。我国正处于工业机器人的发展拐点,市场潜力巨大,据国际机器人联盟(IFR)估计,中国市场对工业机器人的发展占主导地位,2018年全球三分之一的工业机器人将会安装在中国,这势必会引发机器视觉的广泛应用。机器视觉是人类视觉的延伸,与多种技术的融合逐步加深,将成...
发布时间: 2017 - 12 - 18
最新机器人视觉系统介绍,给机器人装上“眼睛”机器视觉概述使机器具有像人一样的视觉功能,从而实现各种检测、判断、识别、测量等功能。一个典型的机器视觉系统组成包括:图像采集单元(光源、镜头、相机、采集卡、机械平台),图像处理分析单元(工控主机、图像处理分析软件、图形交互界面),执行单元(电传单元、机械单元)机器视觉系统通过图像采集单元将待检测目标转换成图像信号,并传送给图像处理分析单元。图像处理分析单元的核心为图像处理分析软件,它包括图像增强与校正、图像分割、特征提取、图像识别与理解等方面。输出目标的质量判断、规格测量等分析结果。分析结果输出至图像界面,或通过电传单元(PLC等)传递给机械单元执行相应操作,如剔除、报警等,或通过机械臂执行分拣、抓举等动作。机器视觉优势机器视觉系统具有高效率、高度自动化的特点,可以实现很高的分辨率精度与速度。机器视觉系统与被检测对象无接触,安全可靠。人工检测与机器视觉自动检测的主要区别有: 机器视觉的应用领域•识别标准一维码、二维码的解码光学字符识别(OCR)和确认(OCV)•检测色彩和瑕疵检测零件或部件的有无检测目标位置和方向检测•测量尺寸和容量检测预设标记的测量,如孔位到孔位的距离•机械手引导输出空间坐标引导机械手精确定位 机器视觉系统的分类•智能相机•基于嵌入式•基于PC 机器视觉系统的组成•图像获取:光源、镜头、相机、采集卡、机械平台•图像处理与分析:工控主机、图像处理分析软件、图形交互界面。•判决执行:电传单元、机械单元•光源---种类LED:寿命长/可以有各种颜色/便于做成各种复杂形状/光均匀稳定/可以闪光;荧光灯:光场均匀/价格便宜/亮度较LED高;卤素灯:亮度特别高/通过光纤传输后可做成;氙灯:使用寿命约1000小时/亮度高,色温与日光接近。(大部分机器视觉照明采用LED) •光源---光路...
发布时间: 2017 - 12 - 12
西门子PLC通讯方式你知道多少?西门子作为最早进入中国市场的工控厂家,其市场占有率一直非常高。西门子PLC的品质非常好,其网络稳定性、开放性深受工控人员的喜爱,而且编程软件分类多,使用方便。在国内工控界具有显著地位。虽然大家对西门子PLC都有一定的了解,但要你说出西门子PLC各种通信方式的特点,相信很多人都不能完整答出。下面就是几种常见的西门子通信方式? 一、PPI通讯PPI协议是S7-200CPU最基本的通信方式,通过原来自身的端口(PORT0或PORT1)就可以实现通信,是S7-200 CPU默认的通信方式。 二、RS485串口通讯第三方设备大部分支持,西门子S7 PLC可以通过选择自由口通信模式控制串口通信。最简单的情况是只用发送指令(XMT)向打印机或者变频器等第三方设备发送信息。不管任何情况,都必须通过S7 PLC编写程序实现。当选择了自由口模式,用户可以通过发送指令(XMT)、接收指令(RCV)、发送中断、接收中断来控制通信口的操作。 三、MPI通讯MPI通信是一种比较简单的通信方式,MPI网络通信的速率是19.2Kbit/s~12Mbit/s,MPI网络最多支持连接32个节点,最大通信距离为50M。通信距离远,还可以通过中继器扩展通信距离,但中继器也占用节点。MPI网络节点通常可以挂S7-200、人机介面、编程设备、智能型ET200S及RS485中继器等网络元器件。西门子PLC与PLC之间的MPI通信一般有3种通信方式:1、全局数据包通信方式2、无组态连接通信方式3、组态连接通信方式 四、以太网通讯以太网的核心思想是使用共享的公共传输通道,这个思想早在1968年来源于厦威尔大学。 1972年,Metcalfe和David Boggs(两个都是著名网络专家)设置了一套网络,这套网络把不同的ALTO计算机连接在一起,同时还连...
发布时间: 2017 - 12 - 11
盘点 | 机器人视觉工程师必须知道的工业相机相关问题1:工业相机的丢帧的问题是由什么原因引起的?经常会有一些机器视觉工程师认为USB接口的工业相机会造成丢帧现象。一般而言,工业相机丢帧与工业相机所采用的传输接口是没有关系的,无论是USB,还是1394、GigE、或者是CameraLink。设计不良的驱动程序或工业相机硬件才是造成丢帧的真正原因:设计不良的工业相机之所以会发生丢帧的现象,其实就是资料通道的堵塞,无法及时处理,所以新的图像进来时,前一张可能被迫丢弃,或是新的图像被迫丢弃。要解决这问题,需要设计者针对驱动程序与工业相机硬件资料传输的每个环节进行精密的设计。2:工业相机输入、输出接口有哪些?在机器视觉检测技术中,工业相机的输入、输出接口有Camera Link、IEEE 1394、USB2.0、Ethernet、USB3.0几种;3:知道被测物的长、宽、高以及要求的测量精度,如何来选择CCD 相机和工业镜头,选择以上器件需要注意什么?首先要选择合适的镜头。选择镜头应该遵循以下原则:1).与之相配的相机的芯片尺寸是多大;2).相机的接口类型是哪种的,C 接口,CS 接口还是其它接口;3).镜头的工作距离;4).镜头视场角;5).镜头光谱特性;6).镜头畸变率;7).镜头机械结构尺寸;选择CCD 相机时,应该综合考虑以下几个方面:1).感光芯片类型;CCD 还是CMOS2).视频特点;包括点频、行频。3).信号输出接口;4).相机的工作模式:连续,触发,控制,异步复位,长时间积分。5).视频参数调整及控制方法:Manual、RS232.同时,选择CCD 的时候应该注意,l inch = 16mm 而不是等于25.4mm.4:CCD 相机与CMOS 相机的区别在哪里?(1) 成像过程...
发布时间: 2017 - 12 - 04
工业机器人视觉引导系统MVRobotVision机器人视觉引导系统是配合工业机器人工作的机器视觉系统,提供高效精准的视觉引导功能,适应多维运动工业机器人对视觉系统轻便、高速、高精度的要求,配合工业机器人实现高效智能化的产线改造,为自动化产线,传送带分拣,组装、自动码垛卸垛以及其他复杂加工等机器人应用提供智能视觉引导解决方案。2D视觉引导MVRobotVision机器人2D视觉引导系统主要应用于流水线传送跟踪、精确定位、姿态调整三个方面。3D视觉引导MVRobotVision机器人3D视觉引导系统主要应用于工件分拣、码垛与卸垛、输送机分拣定位三个方面。系统特点柔性化定位工装:节约在多品种情况下传统的机械定位工装设计成本,使工装定位环节实现真正的柔性化。 智能形状识别引擎,智能视觉学习训练:系统内嵌智能形状识别引擎,能够识别常见的基本几何图形。对于复杂形状,系统可以进行模板学习训练,进而实现复杂形状的识别精准数据:降低环境光影响,快速准确获取扫描数据;先进高效的数据分析,实现高速精确定位识别,精度可达0.1mm
下载次数: 1353
人气: 1353
所属分类: 运动控制卡
技术分享
 
2023 / 06 / 28
联为智能教育主要从事计算机软件技术咨询;企业自动化技术培训;教育设备研发生产;自动化设备的研发、有着丰富的教学经验,教学设备齐全,老师手把手...
 
联系方式
深圳市龙华区观澜街道桂香社区桂圆路23号联为智能装备数字产业园
1812977051@qq.com

15323438773 陈老师

0755-29495142

预约免费试听
  • 您的姓名:
  • *
  • 公司名称:
  • 地址:
  • 电话:
  • *
  • 传真:
  • E-mail:
  • 邮政编码:
  • 留言主题:
  • 详细说明:
  • *
     
联为智能教育专业打造自动化教育产、学、研一体化平台,成为智能制造教育领导者。联为plc培训班精心打造专业培训实操基地,专门为学员研发一批教学设备,包括机器人学习教学连线,plc培训学习教学连线,工业机器人培训、plc编程培训等专业的教学设备,让学员真正理论实践一体,学以致用,从实践交流中体会知识的精髓,来一场完美的职业转身。
扫码学习
深圳联为智能教育感谢您的关注!
plc学习
在线直播间
plc培训班
小胡老师
Copyright ©2005 - 2013 深圳市联为智能教育有限公司


犀牛云提供企业云服务
5
电话
  • 15323438773
6
二维码
回到顶部