基于QT的控制器系统IO信号诊断功能实现(上)

在我工作的第一年,IO诊断模块是我接触到的首个较为复杂的任务。该模块主要用于检测和诊断系统中的输入、输出及模拟量信号,确保系统正常运行并及时发现潜在故障。作为系统首要的测试功能,在实际测试阶段确实暴露了大量问题,这使它成为了一个非常适合新人锻炼的入门项目。

首先功能需求为:

a.输入诊断(Digital Input Diagnostic):
  • 确保输入信号从传感器或其他设备正确传递到控制器。
  • 检测输入信号的电压、电流是否符合预期范围。
  • 确认输入信号在不同条件下的响应和稳定性。
b.输出诊断(Digital Output Diagnostic):
  • 确保控制器发送给执行器或其他设备的输出信号正确且稳定。
  • 检测输出信号的电压、电流是否在设定值范围内。
  • 验证输出信号的动作和响应是否按预期执行。
c.模拟量诊断(Analog Input/Output Diagnostic):
  • 检测模拟输入信号(如传感器输出的模拟电压或电流)是否在预期的测量范围内。
  • 确认模拟输出信号(如控制器输出的模拟电压或电流)是否在设定的范围内,并且稳定。

系统采用双模块设计:诊断模块和硬件配置模块。这两个模块分别对应物理点和逻辑点。其中,物理点代表硬件连接的实际点位,而逻辑点则可以根据需求灵活配置。由于硬件限制,物理点数量通常少于逻辑点数量。为实现这一功能,首要步骤是完成点位分配功能,允许用户将任意逻辑点自由映射到物理点上。

1.点位分配

根据诊断界面和硬件配置自动匹配相应功能。硬件配置包含所有支持的逻辑点,只需在输入框填写索引值,即可将对应点位显示在诊断页面,实现灵活的点位分配功能。

例如:将某逻辑点索引设为n后,物理点n就会接收该逻辑点对应的数据。通过建立两张映射表(逻辑点表和物理点表)的对应关系,即可实现该功能。

# 理论上说应该是:两张表 logicc[n1] pyhsic[n2]
# 转换公式为:
if logic[n] = t
   pyhsic[t-1] = n+1

t-1是考虑逻辑点从0开始,n+1考虑物理点从1开始

诊断页面的文本控件会根据pyhsic[]数组的值动态显示对应文本内容。这些文本数据从外部文件加载,每个物理点的显示内容都与指定的数组元素相绑定。

2.覆盖 交换 功能

当设置两个点位为相同值时,若同时显示同一设备接入,通常并不合理。此时应根据实际使用需求来定制功能。

弹窗
首先实现这个弹窗显示,在edit接收到值的时候判断:

setPopup(char_t *editText){
//弹窗弹出条件
	//判断此值跟目前存在的值是否相同
	int32_t judge = ieditPopup(iotest->iotest,iotest->para,current_value);
	//qDebug()<<"void wgt_itemedit::setPopup judge = "<<judge;
	if(iotest->iotest[0] != '\0' && judge == 0){
		QTextCodec *codec = QTextCodec::codecForName("GBK");

		wgt_keyboardbackground *test = new wgt_keyboardbackground;
		test->show();

    //创建空白弹窗
    HtPopup *window = new HtPopup(gui_get_main_gui());
        QIcon releaseImg = QIcon(QPixmap("./pic/keyboard_normal.bmp").scaled(80,35));
        QIcon pressImg = QIcon(QPixmap("./pic/keyboard_normal_active.bmp").scaled(80,35));
        QString warmingpicpath("./pic/question_mark.PNG");
		QString showtext(codec->toUnicode("此值已存在,是否替换或直接覆盖?"));

		//按钮--替换
		HtDialogButton *changeBtn = new HtDialogButton(window);
		changeBtn->setGeometry(100,215,150,70);
		changeBtn->setText(codec->toUnicode("替换"));
		changeBtn->setStyleSheet("font-size:17px;");
		changeBtn->setIcons(0, releaseImg);
		changeBtn->setIcons(1, pressImg);
		changeBtn->selectIcon(0);
		QObject::connect(changeBtn, SIGNAL(pressed()), changeBtn, SLOT(onIconChang()));
		QObject::connect(changeBtn, SIGNAL(released()), changeBtn, SLOT(onIconChang()));
		QObject::connect(changeBtn, &HtDialogButton::clicked, [=]() {
			changeValue(iotest->para);
			window->close();
			test->close();
		});

		//按钮--覆盖
		HtDialogButton *resetBtn = new HtDialogButton(window);
		resetBtn->setGeometry(300,215,150,70);
		resetBtn->setText(codec->toUnicode("覆盖"));
		resetBtn->setStyleSheet("font-size:17px;");
		resetBtn->setIcons(0, releaseImg);
		resetBtn->setIcons(1, pressImg);
		resetBtn->selectIcon(0);
		QObject::connect(resetBtn, SIGNAL(pressed()), resetBtn, SLOT(onIconChang()));
		QObject::connect(resetBtn, SIGNAL(released()), resetBtn, SLOT(onIconChang()));
		QObject::connect(resetBtn, &HtDialogButton::clicked, [=]() {
			coverValue(iotest->para);
			window->close();
			test->close();
		});

		//按钮--取消
		HtDialogButton *concelBtn = new HtDialogButton(window);
		concelBtn->setGeometry(500,215,150,70);
		concelBtn->setText(codec->toUnicode("取消"));
		concelBtn->setStyleSheet("font-size:17px;");
		concelBtn->setIcons(0, releaseImg);
		concelBtn->setIcons(1, pressImg);
		concelBtn->selectIcon(0);
		QObject::connect(concelBtn, SIGNAL(pressed()), concelBtn, SLOT(onIconChang()));
		QObject::connect(concelBtn, SIGNAL(released()), concelBtn, SLOT(onIconChang()));

		QObject::connect(concelBtn, &HtDialogButton::clicked, [=]() {
			concelValue(iotest->para);
			window->close();
			test->close();
		});

		//按钮-关闭
		HtButton *closeBtn = new HtButton(window);
		closeBtn->setFixedSize(BTN_SIZE,BTN_SIZE);
		closeBtn->move( window->width() - BTN_SIZE , 0 );
		QObject::connect(closeBtn, &HtButton::clicked, [=]() {
			concelValue(iotest->para);
			window->close();
			test->close();
		});

		// 创建警示label
		HtLabel *warmingLabel = new HtLabel(window);
		warmingLabel->LoadPicturePar(warmingpicpath,120,120);
		warmingLabel->move(60,80);
		warmingLabel->InitForm();

		// 创建内容label
		HtLabel *showlabel = new HtLabel(window);
		showlabel->setText(showtext);
		showlabel->setStyleSheet("font-size:20px;");
		showlabel->setGeometry(200,117,430,50);
		showlabel->setAlignment(Qt::AlignCenter);

		window->PopupShow();
	}
}

3.强制功能

强制功能主要涉及位运算处理。系统接收一个8位二进制值,每位0/1代表不同状态。需要设计一个按钮来解析该值并根据需求进行修改。

		// 修改idata的第bits位
		if (ptrcldata->selectedData) {
				idata |= (1 << ptrcldata->bits); // 将第bits位置1
		}else{
				idata &= ~(1 << ptrcldata->bits); // 将第bits位清零
		}
		
		// 切换按钮状态
		ptrcldata->selectedData = !ptrcldata->selectedData;
		selectBackground(ptrcldata->selectedData);

整个流程如上所述,中间交换的具体逻辑将在下篇文章中详细说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值