10.PMAC上位机-构造一个足够安全的工业设备程序

原创 2015年05月18日 11:23:17

对于编写工业程序来说,大多数时候我们首先保证的是安全和稳定,试想一个几吨的大型机床程序出了问题,可能一个数百万的零件就此报废,甚至危害加工人员的人身安全。本文就在PMAC中如何构造足够安全的工业设备程序给出一点实用方法。


1.状态_迁移图

先想想对于程序来说,怎样才算足够安全?对于每一种可能出现的操作都事先考虑到并给出对应的处理方案,这样的程序就是足够安全的。那么我们首先要做的就是列举每种可能出现的问题,其实前人们早就考虑到这个问题了,人们提出一个“状态_迁移图”的概念,用来描述程序不同的状态和状态之间的跳变过程,如下图对于如下操作界面的程序:


这里为了简便,仅考虑程序运行的状态,可以列表如下:


程序包括三种状态:运行状态、暂停状态和停止状态。不同的状态间跳变,通过点击下方的运行、暂停、继续和停止按钮来完成。

上方的箭头标明不同的转态之间跳变关系,中间为完成某一个跳变必须完成的事件(点击的按钮)。

下方的按钮灰色表示当前按钮不能点击、绿色表示当前按钮能够点击。按钮能不能点击其实就是标明当前状态能否跳变到对应的点击后状态,即上方箭头标明的跳变图和下方灰色和绿色标明的按钮状态列表是等价的


2.编写安全程序方法

那么,我们编写安全程序就可以分别按照如下两种方法:

1.跳变图:当点击某一个按钮时,检查当期的状态能不能跳变到点击后的状态,如果不能则当前点击无效,避免误操作,对应上图的箭头跳变图。这种方法需要一个变量来记录当前的状态,根据不同的点击实时更新当前状态。

2.状态列表:在某一状态下,不能操作的按钮全部灰度化和禁用,只开放可发生状态跳变的按钮供用户点击,对应上图的按钮状态列表。这种方法需要在状态跳变后实时更改当前按钮状态。


3.代码演示

方法1.跳变图

void CTest2Dlg::OnRun() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];

	lstrcpy(szCmd, "&1b40r");

	//判断跳变是否有效,进行相关操作和更新状态
	if (MOVE_STATE_STOP == m_moveState)
	{
		PmacGetResponse(0,szRes,MAX_PATH,szCmd);
		m_moveState = MOVE_STATE_RUN;
	}
	else
	{
		AfxMessageBox(TEXT("当前不能进行该操作!"));
	}
}

void CTest2Dlg::OnPause() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];
	
	lstrcpy(szCmd, "&1b40h");
	
	//判断跳变是否有效,进行相关操作和更新状态
	if (MOVE_STATE_RUN == m_moveState)
	{
		PmacGetResponse(0,szRes,MAX_PATH,szCmd);
		m_moveState = MOVE_STATE_PAUSE;
	}
	else
	{
		AfxMessageBox(TEXT("当前不能进行该操作!"));
	}
}

void CTest2Dlg::OnContinue() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];
	
	lstrcpy(szCmd, "&1b40r");

	//判断跳变是否有效,进行相关操作和更新状态
	if (MOVE_STATE_PAUSE == m_moveState)
	{
		PmacGetResponse(0,szRes,MAX_PATH,szCmd);
		m_moveState = MOVE_STATE_RUN;
	}
	else
	{
		AfxMessageBox(TEXT("当前不能进行该操作!"));
	}
}

void CTest2Dlg::OnStop() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];
	
	lstrcpy(szCmd, "&1b40a");

	//判断跳变是否有效,进行相关操作和更新状态
	if (MOVE_STATE_RUN==m_moveState || MOVE_STATE_PAUSE==m_moveState)
	{
		PmacGetResponse(0,szRes,MAX_PATH,szCmd);
		m_moveState = MOVE_STATE_STOP;
	}
	else
	{
		AfxMessageBox(TEXT("当前不能进行该操作!"));
	}
}


方法2.状态列表

void CTest2Dlg::OnRun() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];

	lstrcpy(szCmd, "&1b40r");
	PmacGetResponse(0,szRes,MAX_PATH,szCmd);
	
	//更新状态,仅开放当前能操作的按钮
	GetDlgItem(IDB_RUN)->EnableWindow(FALSE);
	GetDlgItem(IDB_PAUSE)->EnableWindow(TRUE);
	GetDlgItem(IDB_CONTINUE)->EnableWindow(FALSE);
	GetDlgItem(IDB_STOP)->EnableWindow(TRUE);
}

void CTest2Dlg::OnPause() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];
	
	lstrcpy(szCmd, "&1b40h");
	PmacGetResponse(0,szRes,MAX_PATH,szCmd);

	//更新状态,仅开放当前能操作的按钮
	GetDlgItem(IDB_RUN)->EnableWindow(FALSE);
	GetDlgItem(IDB_PAUSE)->EnableWindow(FALSE);
	GetDlgItem(IDB_CONTINUE)->EnableWindow(TRUE);
	GetDlgItem(IDB_STOP)->EnableWindow(TRUE);
}

void CTest2Dlg::OnContinue() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];
	
	lstrcpy(szCmd, "&1b40r");
	PmacGetResponse(0,szRes,MAX_PATH,szCmd);

	//更新状态,仅开放当前能操作的按钮
	GetDlgItem(IDB_RUN)->EnableWindow(FALSE);
	GetDlgItem(IDB_PAUSE)->EnableWindow(TRUE);
	GetDlgItem(IDB_CONTINUE)->EnableWindow(FALSE);
	GetDlgItem(IDB_STOP)->EnableWindow(TRUE);
}

void CTest2Dlg::OnStop() 
{
	TCHAR szRes[MAX_PATH];
	TCHAR szCmd[MAX_PATH];
	
	lstrcpy(szCmd, "&1b40a");
	PmacGetResponse(0,szRes,MAX_PATH,szCmd);

	//更新状态,仅开放当前能操作的按钮
	GetDlgItem(IDB_RUN)->EnableWindow(TRUE);
	GetDlgItem(IDB_PAUSE)->EnableWindow(FALSE);
	GetDlgItem(IDB_CONTINUE)->EnableWindow(FALSE);
	GetDlgItem(IDB_STOP)->EnableWindow(FALSE);
}

可以看到,方法1相对方法2,可以多了一个状态记录变量m_moveState,可以随时查看当前状态,但是用户操作不能第一时间知道当前操作是否有效,必须点击后才会知道当前操作能不能进行。方法2,每一时刻用户可以进行的操作都很清楚,当时不能实时查看当前状态。

通常,我们使用第二种方法,当需要查询状态时,结合方法1,使用一个变量记录当前状态即可。

这里讲的都是在上位机改变状态,只有用户点击后程序状态才会改变,但是在实际中,当程序运行完毕(如这里的回零按钮实际上也应该加入到状态控制中,开始点击后程序为回零状态,所有按钮都必须灰度化,等待回零完毕后自动改变程序状态为运行状态)或特定动作发生(某一行为触发指定状态改变),程序的状态也会发生改变,如何捕获这一状态改变呢?这是后续中断响应需要讲的内容。


演示源代码下载链接

原创,转载请注明来自http://blog.csdn.net/wenzhou1219


版权声明:本文为博主原创文章,未经博主允许不得转载。

6.PMAC下位机-下位机编程

PMAC的下位机编程包括三种程序:命令序列程序、运动(Program)程序和PLC程序。这里主要介绍三种程序的编写方法和注意事项。...
  • wenzhou1219
  • wenzhou1219
  • 2015年04月11日 20:38
  • 3330

彻底构造一个安全的单例模式

正常情况下构造单例模式主要分为两种,饿汉和懒汉,即懒加载(延迟加载)和直接加载。饿汉方式如下:public class Singleton{ private static final Sing...
  • kid_2412
  • kid_2412
  • 2016年11月30日 10:11
  • 644

项目总结 -- RFID 读写器上位机软件

物联网方向的课程项目:RFID 读写器上位机软件,是一个基于MFC的软件,通过与连接的设备(这里是读卡器)与IC卡进行数据的交换,举个例子来说:校园卡,公司的门禁卡等等,这个属于物联网的终端信息交互的...
  • u012629110
  • u012629110
  • 2016年09月30日 00:29
  • 2299

初涉USB,初学者USB入门总结(5)USB上位机读写开发

上一部分说了固件和驱动的编程,这里再谈一下上位机的程序,因为我开发的范围也就是传传数据,所以太深入的没有去做,不过一般的工程调试应该足够了。     固件的程序和驱动编写好了后,把设备插入就可以正确...
  • JRENSKY
  • JRENSKY
  • 2015年06月23日 13:10
  • 1943

【自己动手写上位机】串口通信

【自己动手写上位机】串口通信 C#编写 本篇主要内容: 介绍C#串口类:SerialPort 封装串口类   名称 描述 Ser...
  • Quex_Jqx
  • Quex_Jqx
  • 2015年09月22日 22:54
  • 4904

上传STM32的USB上位机(VC++源码),动态库(VC++源码),STM32端原代码,驱动程序,全套源码

作者:huxiaoping 转自:http://www.amobbs.com/forum.php?mod=viewthread&tid=3776746 前些时间玩了把STM32,原来想做一个USB...
  • whw8007
  • whw8007
  • 2013年07月30日 21:07
  • 3121

一个串口上位机程序

我们飞思卡尔智能车的比赛已经接近尾声了,23号就要去上海决赛了呵。论文基本完成,Duuboo已经排版结束,排出来还真挺长的。  整个过程都挺累的,持续的时间还这么长,最累的恐怕只有惠哥了,这些比赛完再...
  • dongliqiang2006
  • dongliqiang2006
  • 2009年01月07日 19:48
  • 5744

一个可用于实时采集的图像显示控件-用于数据采集的上位机显示中

具体控件代码: 建立VC工程,插入下面控件!这样你会看到你的工程中多了三个类; 然后在对话框初始化函数中初始化控件,方法如下: regsvr32 NTGraph.ocx regsvr32 /u...
  • salaheiyou77
  • salaheiyou77
  • 2015年03月14日 09:50
  • 1059

VS2013开发上位机并调用MSCcommm控件的方式

此文章适合VC++串口通信入门 一、页面布局及添加控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目comm 注意:点击ok,然...
  • hkwlg1314
  • hkwlg1314
  • 2015年09月06日 19:25
  • 5380

分类算法:朴素贝叶斯分类(Naive Bayesian classification)

本文转载自:http://www.cnblogs.com/leoo2sk/archive/2010/09/17/naive-bayesian-classifier.html 修改了作者部分书写错误! ...
  • sangyongjia
  • sangyongjia
  • 2016年10月27日 17:50
  • 383
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:10.PMAC上位机-构造一个足够安全的工业设备程序
举报原因:
原因补充:

(最多只允许输入30个字)