百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Qt编写的嵌入式工业控制系统(嵌入式控制系统)

ccwgpt 2024-09-21 13:53 31 浏览 0 评论

一、前言

此系统用于扭力控制,嵌入式平台,采用的开发板为335X,这个还是比较稳定的。

二、开发环境

硬件平台:335X

软件:Qt+嵌入式linux

三、实现功能

1:QSS界面换肤

2:更换主界面背景

3:中文双拼输入法

4:数据图形曲线显示

5:数据统计柱状图显示。

6:串口网络通信

四、效果图

五、核心代码

void Com_RS232_API::ReadData()
{
 if (com->bytesAvailable() <= 0) {
 return;
 }
 myHelper::Sleep(sleep);
 QByteArray data = com->readAll();
 int dataLen = data.length();
 if (dataLen <= 0) {
 return;
 }
 //更新最后心跳时间
 lastHeartTime = QDateTime::currentDateTime();
 QString buffer = myHelper::ByteArrayToAsciiStr(data);
 int len = buffer.length();
 qDebug() << TIMEMS << "接收数据:" << buffer;
 emit ReceiveData(buffer);
 // //将数据加入处理队列,用线程处理数据
 // mutex.lock();
 // App::Buffer.append(data);
 // mutex.unlock();
 // currentFlag=255;
 // sleep=50;
 if (buffer.startsWith("667") && currentFlag == 0) {
 qDebug() << TIMEMS << "命令解析:" << "握手成功" ;
 isOk = true;
 //握手成功后将心跳间隔改为500毫秒
 timerHeart->setInterval(500);
 emit ReceiveHelloOk();
 //如果未启用自动执行,则将心跳和开机交互完成置为真
 if (!isAuto) {
 isHeart = true;
 allFinsh = true;
 }
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadPsetIDNameAll()));
 }
 } else if (buffer.startsWith("301PST") && currentFlag == 1) {
 if (buffer.length() < 7) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "所有Pset索引返回" ;
 QMap<int, QString> psetIDName;
 QString temp = buffer.mid(6, len - 1);
 QStringList list = temp.split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QStringList t = list.at(i).split(":");
 int id = t.at(0).toInt();
 QString name = t.at(1);
 psetIDName.insert(id, name);
 }
 emit ReceivePsetIDNameAll(psetIDName);
 qDebug() << TIMEMS << "命令解析:" << "psetIDName:" << psetIDName;
 } else if (buffer.startsWith("001") && currentFlag == 2) {
 qDebug() << TIMEMS << "命令解析:" << "授权1成功返回" ;
 emit ReceiveAuthor1Ok();
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(Author2()));
 }
 } else if (buffer.startsWith("001") && currentFlag == 3) {
 qDebug() << TIMEMS << "命令解析:" << "授权2成功返回" ;
 emit ReceiveAuthor2Ok();
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadPsetIDCurrent()));
 }
 } else if (buffer.startsWith("332") && currentFlag == 4) {
 if (buffer.length() < 6) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "当前Pset索引返回" ;
 int psetIDCurrent = buffer.mid(3, 3).toInt();
 emit ReceivePsetIDCurrent(psetIDCurrent);
 qDebug() << TIMEMS << "命令解析:" << "psetIDCurrent:" << psetIDCurrent;
 //如果是重发命令确认的回复,则不需要继续执行开机交互命令
 if (isRecheck) { 
 isRecheck = false;
 return;
 }
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(Cooperate()));
 }
 } else if (buffer.startsWith("5691") && currentFlag == 5) {
 qDebug() << TIMEMS << "命令解析:" << "配合成功返回" ;
 emit ReceiveCooperateOk();
 //握手成功后自动执行开机交互命令
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadPsetIDAll()));
 }
 } else if (buffer.startsWith("5710") && currentFlag == 6) {
 qDebug() << TIMEMS << "命令解析:" << "所有已经使用的Pset索引返回" ;
 QList<int> psetIDAll;
 QStringList list = buffer.split(":");
 if (list.count() < 3) {
 return;
 }
 QStringList t = list.at(2).split(";");
 int count = t.count();
 for (int i = 0; i < count; i++) {
 psetIDAll.append(t.at(i).toInt());
 }
 emit ReceivePsetIDAll(psetIDAll);
 qDebug() << TIMEMS << "命令解析:" << "psetIDAll:" << psetIDAll;
 //启动心跳命令
 isHeart = true;
 allFinsh = true;
 } else if (buffer.startsWith("001") && currentFlag == 7) {
 qDebug() << TIMEMS << "命令解析:" << "指定Pset成功返回" ;
 emit ReceiveSelectPset();
 QTimer::singleShot(10, this, SLOT(ReadPsetIDCurrent()));
 isRecheck = true; 
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(500, this, SLOT(StartHeart()));
 } else if (buffer.startsWith("113P") && currentFlag == 8) {
 if (buffer.length() < 8) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "Pset参数返回" ;
 QMap<int, QString> config;
 int psetID = buffer.mid(4, 3).toInt();
 QString temp = buffer.mid(7, len - 1);
 QStringList list = temp.split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 //如果参数号为406则需要转换为正常的日期格式
 //传过来的是从1970年1月1日0时0分0秒到现在经过的秒数
 if (pID == 406) {
 QDateTime d = myHelper::IntToDateTime(pValue.toUInt());
 pValue = d.toString("yyyy-MM-dd HH:mm:ss");
 }
 config.insert(pID, pValue);
 }
 emit ReceivePsetConfig(psetID, config);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "config:" << config;
 qApp->processEvents();
 } else if (buffer.startsWith("001") && currentFlag == 9) {
 qDebug() << TIMEMS << "命令解析:" << "更新Pset准备成功" ;
 emit ReceiveUpdatePsetPrepareOk();
 } else if (buffer.startsWith("001") && currentFlag == 10) {
 qDebug() << TIMEMS << "命令解析:" << "更新Pset成功" ;
 emit ReceiveUpdatePsetOk();
 } else if (buffer.startsWith("00101") && currentFlag == 11) {
 qDebug() << TIMEMS << "命令解析:" << "新建Pset成功" ;
 emit ReceiveNewPsetOk();
 } else if (buffer.startsWith("00101") && currentFlag == 12) {
 qDebug() << TIMEMS << "命令解析:" << "删除Pset成功" ;
 emit ReceiveDeletePsetOk();
 } else if (buffer.startsWith("003")) {
 qDebug() << TIMEMS << "命令解析:" << "心跳应答成功" ;
 emit ReceiveHeartOk();
 //003\x02=003 003\\ACK为有新的结果通知
 if (buffer.startsWith("003\\STX") || buffer.startsWith("003\\ACK")) {
 qDebug() << TIMEMS << "命令解析:" << "有新的拧紧结果可读取" ;
 //立马启动执行读取结果值
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadResultNmDeg()));
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(1800, this, SLOT(StartHeart()));
 }
 }
 } else if (buffer.startsWith("113R")) {
 if (buffer.length() < 8) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "拧紧数值结果返回" ;
 int psetID = buffer.mid(4, 3).toInt();
 double nm = 0;
 int nmOk = 1;
 int deg = 0;
 int degOk = 1;
 int id = 0;
 QString strDate = "";
 QString num = "0";
 QString temp = buffer.mid(7, len - 1);
 QStringList list = temp.split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 if (pID == 100) {
 nm = pValue.toDouble();
 } else if(pID == 101) {
 nmOk = pValue.toInt();
 } else if (pID == 102) {
 deg = pValue.toInt();
 } else if(pID == 103) {
 degOk = pValue.toInt();
 } else if (pID == 300) {
 id = pValue.toInt();
 } else if (pID == 301) {
 strDate += pValue;
 } else if (pID == 302) {
 strDate = QString("%1 %2").arg(strDate).arg(pValue);
 } else if (pID == 305) {
 num = pValue;
 }
 }
 emit ReceiveResultNmDeg(psetID, id, strDate, num, nm, nmOk, deg, degOk);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "结果编号:" << id << "时间:" << strDate << "工具系列号:" << num
 << "扭矩值:" << nm << "扭矩结果:" << nmOk << "角度值:" << deg << "角度结果:" << degOk;
 //立马读取扭矩对时间曲线结果
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadResultNmTimePlot()));
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(1800, this, SLOT(StartHeart()));
 }
 qApp->processEvents();
 } else if (buffer.startsWith("123G")) {
 if (buffer.length() < 5) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "扭矩对时间曲线返回" ;
 int psetID = 0;
 int id = 0;
 QString strDate = "";
 QString num = "0";
 double interval = 0;
 int fenzi = 1;
 int fenmu = 1;
 double targetNm = 0;
 double minNm = 0;
 double maxNm = 0;
 QList<double> result;
 QString temp = buffer.mid(4, len - 1);
 QStringList l = temp.split(";");
 if (l.count() < 2) {
 return;
 }
 //取出分号前的数值
 QStringList list = l.at(0).split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 if (pID == 100) {
 id = pValue.toInt();
 } else if (pID == 101) {
 strDate += pValue;
 } else if (pID == 102) {
 strDate = QString("%1 %2").arg(strDate).arg(pValue);
 } else if (pID == 105) {
 num = pValue;
 } else if (pID == 114) {
 psetID = pValue.toInt();
 } else if (pID == 201) {
 interval = pValue.toDouble();
 } else if (pID == 203) {
 fenzi = pValue.toInt();
 } else if (pID == 204) {
 fenmu = pValue.toInt();
 } else if (pID == 206) {
 targetNm = pValue.toDouble();
 } else if (pID == 210) {
 minNm = pValue.toDouble();
 } else if (pID == 211) {
 maxNm = pValue.toDouble();
 }
 }
 //分号后的数据代表结果
 QString str1 = l.at(1);
 QByteArray ba = myHelper::AsciiStrToByteArray(str1);
 QString str2 = myHelper::ByteArrayToHexStr(ba);
 //保存获取到的扭矩对角度数据
 if (isSaveNm) {
 QString fileName = QString("%1/save/Nm_%2.txt").arg(App::AppPath)
 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
 QFile file(fileName);
 file.open(QFile::WriteOnly | QFile::Text);
 file.write(str2.toLatin1());
 file.close();
 }
 QStringList tempList = str2.split(" ");
 int currentCount = tempList.count();
 //如果不是2的倍数则长度要减去1
 if ( currentCount % 2 != 0) {
 currentCount = (currentCount - 1);
 }
 //逐个取出扭矩值
 for (int i = 0; i < currentCount; i = i + 2) {
 qint16 value = myHelper::StrHexToShort(QString("%1%2").arg(tempList.at(i)).arg(tempList.at(i + 1)));
 double r = (double)(value * fenzi) / fenmu;
 result.append(r);
 }
 emit ReceiveResultNmTimePlot(psetID, id, strDate, num, interval, targetNm, minNm, maxNm, result);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "结果编号:" << id << "时间:" << strDate << "工具系列号:" << num
 << "间隔:" << interval << "目标扭矩:" << targetNm << "扭矩最小:" << minNm << "扭矩最大:" << maxNm
 << "结果集合:" << result;
 //立马读取角度对时间曲线结果
 if (isAuto) {
 QTimer::singleShot(10, this, SLOT(ReadResultDegTimePlot()));
 //延时启动心跳定时器,防止结果未读成功而停止了心跳
 QTimer::singleShot(1800, this, SLOT(StartHeart()));
 }
 qApp->processEvents();
 } else if (buffer.startsWith("125G")) {
 if (buffer.length() < 5) {
 return;
 }
 qDebug() << TIMEMS << "命令解析:" << "角度对时间曲线返回" ;
 int psetID = 0;
 int id = 0;
 QString strDate = "";
 QString num = "0";
 double interval = 0;
 int fenzi = 1;
 int fenmu = 1;
 double targetDeg = 0;
 double minDeg = 0;
 double maxDeg = 0;
 QList<double> result;
 QString temp = buffer.mid(4, len - 1);
 QStringList l = temp.split(";");
 if (l.count() < 2) {
 return;
 }
 //取出分号前的数值
 QStringList list = l.at(0).split("'");
 int count = list.count() - 1;
 for (int i = 0; i < count; i++) {
 QString t = list.at(i);
 int pID = t.mid(0, 3).toInt();
 QString pValue = t.mid(4, t.length());
 if (pID == 100) {
 id = pValue.toInt();
 } else if (pID == 101) {
 strDate += pValue;
 } else if (pID == 102) {
 strDate = QString("%1 %2").arg(strDate).arg(pValue);
 } else if (pID == 105) {
 num = pValue;
 } else if (pID == 114) {
 psetID = pValue.toInt();
 } else if (pID == 201) {
 interval = pValue.toDouble();
 } else if (pID == 204) {
 fenzi = pValue.toInt();
 } else if (pID == 205) {
 fenmu = pValue.toInt();
 } else if (pID == 229) {
 targetDeg = pValue.toDouble();
 } else if (pID == 220) {
 minDeg = pValue.toDouble();
 } else if (pID == 221) {
 maxDeg = pValue.toDouble();
 }
 }
 //分号后的数据代表结果
 QString str1 = l.at(1);
 QByteArray ba = myHelper::AsciiStrToByteArray(str1);
 QString str2 = myHelper::ByteArrayToHexStr(ba);
 //保存获取到的角度对角度数据
 if (isSaveDeg) {
 QString fileName = QString("%1/save/Deg_%2.txt").arg(App::AppPath)
 .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss"));
 QFile file(fileName);
 file.open(QFile::WriteOnly | QFile::Text);
 file.write(str2.toLatin1());
 file.close();
 }
 QStringList tempList = str2.split(" ");
 int currentCount = tempList.count();
 //如果不是2的倍数则长度要减去1
 if ( currentCount % 2 != 0) {
 currentCount = (currentCount - 1);
 }
 //逐个取出角度值
 for (int i = 0; i < currentCount; i = i + 2) {
 qint16 value = myHelper::StrHexToShort(QString("%1%2").arg(tempList.at(i)).arg(tempList.at(i + 1)));
 double r = (double)(value * fenzi) / fenmu;
 //传过来的值放大了100倍,所以真实显示的值要除以100
 double re = r / 100;
 result.append(re);
 }
 emit ReceiveResultDegTimePlot(psetID, id, strDate, num, interval, targetDeg, minDeg, maxDeg, result);
 qDebug() << TIMEMS << "命令解析:" << "psetID:" << psetID << "结果编号:" << id << "时间:" << strDate << "工具系列号:" << num
 << "间隔:" << interval << "最终角度结果:" << targetDeg << "最终角度最小:" << minDeg << "最终角度最大:" << maxDeg
 << "结果集合:" << result;
 //将心跳重新置为真
 isHeart = true;
 qApp->processEvents();
 }
 //currentFlag = 255;
 //sleep = 50;
}

相关推荐

团队管理“布阵术”:3招让你的团队战斗力爆表!

为何古代军队能够以一当十?为何现代企业有的团队高效似“特种部队”,有的却松散若“游击队”?**答案正隐匿于“布阵术”之中!**今时今日,让我们从古代兵法里萃取3个核心要义,助您塑造一支战斗力爆棚的...

知情人士回应字节大模型团队架构调整

【知情人士回应字节大模型团队架构调整】财联社2月21日电,针对原谷歌DeepMind副总裁吴永辉加入字节跳动后引发的团队调整问题,知情人士回应称:吴永辉博士主要负责AI基础研究探索工作,偏基础研究;A...

豆包大模型团队开源RLHF框架,训练吞吐量最高提升20倍

强化学习(RL)对大模型复杂推理能力提升有关键作用,但其复杂的计算流程对训练和部署也带来了巨大挑战。近日,字节跳动豆包大模型团队与香港大学联合提出HybridFlow。这是一个灵活高效的RL/RL...

创业团队如何设计股权架构及分配(创业团队如何设计股权架构及分配方案)

创业团队的股权架构设计,决定了公司在随后发展中呈现出的股权布局。如果最初的股权架构就存在先天不足,公司就很难顺利、稳定地成长起来。因此,创业之初,对股权设计应慎之又慎,避免留下巨大隐患和风险。两个人如...

消息称吴永辉入职后引发字节大模型团队架构大调整

2月21日,有消息称前谷歌大佬吴永辉加入字节跳动,并担任大模型团队Seed基础研究负责人后,引发了字节跳动大模型团队架构大调整。多名原本向朱文佳汇报的算法和技术负责人开始转向吴永辉汇报。简单来说,就是...

31页组织效能提升模型,经营管理团队搭建框架与权责定位

分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!31页组织效能提升模型如何拿到分享的源文件:请您关注本头条号,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...

异形柱结构(异形柱结构技术规程)

下列关于混凝土异形柱结构设计的说法,其中何项正确?(A)混凝土异形柱框架结构可用于所有非抗震和抗震设防地区的一般居住建筑。(B)抗震设防烈度为6度时,对标准设防类(丙类)采用异形柱结构的建筑可不进行地...

职场干货:金字塔原理(金字塔原理实战篇)

金字塔原理的适用范围:金字塔原理适用于所有需要构建清晰逻辑框架的文章。第一篇:表达的逻辑。如何利用金字塔原理构建基本的金字塔结构受众(包括读者、听众、观众或学员)最容易理解的顺序:先了解主要的、抽象的...

底部剪力法(底部剪力法的基本原理)

某四层钢筋混凝土框架结构,计算简图如图1所示。抗震设防类别为丙类,抗震设防烈度为8度(0.2g),Ⅱ类场地,设计地震分组为第一组,第一自振周期T1=0.55s。一至四层的楼层侧向刚度依次为:K1=1...

结构等效重力荷载代表值(等效重力荷载系数)

某五层钢筋混凝土框架结构办公楼,房屋高度25.45m。抗震设防烈度8度,设防类别丙类,设计基本地震加速度0.2g,设计地震分组第二组,场地类别为Ⅱ类,混凝土强度等级C30。该结构平面和竖向均规则。假定...

体系结构已成昭告后世善莫大焉(体系构架是什么意思)

实践先行也理论已初步完成框架结构留余后人后世子孙俗话说前人栽树后人乘凉在夏商周大明大清民国共和前人栽树下吾之辈已完成结构体系又俗话说青出于蓝而胜于蓝各个时期任务不同吾辈探索框架结构体系经历有限肯定发展...

框架柱抗震构造要求(框架柱抗震设计)

某现浇钢筋混凝土框架-剪力墙结构高层办公楼,抗震设防烈度为8度(0.2g),场地类别为Ⅱ类,抗震等级:框架二级,剪力墙一级,混凝土强度等级:框架柱及剪力墙C50,框架梁及楼板C35,纵向钢筋及箍筋均采...

梁的刚度、挠度控制(钢梁挠度过大会引起什么原因)

某办公楼为现浇钢筋混凝土框架结构,r0=1.0,混凝土强度等级C35,纵向钢筋采用HRB400,箍筋采用HPB300。其二层(中间楼层)的局部平面图和次梁L-1的计算简图如图1~3(Z)所示,其中,K...

死要面子!有钱做大玻璃窗,却没有钱做“柱和梁”,不怕房塌吗?

活久见,有钱做2层落地大玻璃窗,却没有钱做“柱子和圈梁”,这样的农村自建房,安全吗?最近刷到个魔幻施工现场,如下图,这栋5开间的农村自建房,居然做了2个全景落地窗仔细观察,这2个落地窗还是飘窗,为了追...

不是承重墙,物业也不让拆?话说装修就一定要拆墙才行么

最近发现好多朋友装修时总想拆墙“爆改”空间,别以为只要避开承重墙就能随便砸!我家楼上邻居去年装修,拆了阳台矮墙想扩客厅,结果物业直接上门叫停。后来才知道,这种配重墙拆了会让阳台承重失衡,整栋楼都可能变...

取消回复欢迎 发表评论: