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

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

ccwgpt 2024-09-21 13:53 37 浏览 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;
}

相关推荐

十分钟让你学会LNMP架构负载均衡(impala负载均衡)

业务架构、应用架构、数据架构和技术架构一、几个基本概念1、pv值pv值(pageviews):页面的浏览量概念:一个网站的所有页面,在一天内,被浏览的总次数。(大型网站通常是上千万的级别)2、u...

AGV仓储机器人调度系统架构(agv物流机器人)

系统架构层次划分采用分层模块化设计,分为以下五层:1.1用户接口层功能:提供人机交互界面(Web/桌面端),支持任务下发、实时监控、数据可视化和报警管理。模块:任务管理面板:接收订单(如拣货、...

远程热部署在美团的落地实践(远程热点是什么意思)

Sonic是美团内部研发设计的一款用于热部署的IDEA插件,本文其实现原理及落地的一些技术细节。在阅读本文之前,建议大家先熟悉一下Spring源码、SpringMVC源码、SpringBoot...

springboot搭建xxl-job(分布式任务调度系统)

一、部署xxl-job服务端下载xxl-job源码:https://gitee.com/xuxueli0323/xxl-job二、导入项目、创建xxl_job数据库、修改配置文件为自己的数据库三、启动...

大模型:使用vLLM和Ray分布式部署推理应用

一、vLLM:面向大模型的高效推理框架1.核心特点专为推理优化:专注于大模型(如GPT-3、LLaMA)的高吞吐量、低延迟推理。关键技术:PagedAttention:类似操作系统内存分页管理,将K...

国产开源之光【分布式工作流调度系统】:DolphinScheduler

DolphinScheduler是一个开源的分布式工作流调度系统,旨在帮助用户以可靠、高效和可扩展的方式管理和调度大规模的数据处理工作流。它支持以图形化方式定义和管理工作流,提供了丰富的调度功能和监控...

简单可靠高效的分布式任务队列系统

#记录我的2024#大家好,又见面了,我是GitHub精选君!背景介绍在系统访问量逐渐增大,高并发、分布式系统成为了企业技术架构升级的必由之路。在这样的背景下,异步任务队列扮演着至关重要的角色,...

虚拟服务器之间如何分布式运行?(虚拟服务器部署)

  在云计算和虚拟化技术快速发展的今天,传统“单机单任务”的服务器架构早已难以满足现代业务对高并发、高可用、弹性伸缩和容错容灾的严苛要求。分布式系统应运而生,并成为支撑各类互联网平台、企业信息系统和A...

一文掌握 XXL-Job 的 6 大核心组件

XXL-Job是一个分布式任务调度平台,其核心组件主要包括以下部分,各组件相互协作实现高效的任务调度与管理:1.调度注册中心(RegistryCenter)作用:负责管理调度器(Schedule...

京东大佬问我,SpringBoot中如何做延迟队列?单机与分布式如何做?

京东大佬问我,SpringBoot中如何做延迟队列?单机如何做?分布式如何做呢?并给出案例与代码分析。嗯,用户问的是在SpringBoot中如何实现延迟队列,单机和分布式环境下分别怎么做。这个问题其实...

企业级项目组件选型(一)分布式任务调度平台

官网地址:https://www.xuxueli.com/xxl-job/能力介绍架构图安全性为提升系统安全性,调度中心和执行器进行安全性校验,双方AccessToken匹配才允许通讯;调度中心和执...

python多进程的分布式任务调度应用场景及示例

多进程的分布式任务调度可以应用于以下场景:分布式爬虫:importmultiprocessingimportrequestsdefcrawl(url):response=re...

SpringBoot整合ElasticJob实现分布式任务调度

介绍ElasticJob是面向互联网生态和海量任务的分布式调度解决方案,由两个相互独立的子项目ElasticJob-Lite和ElasticJob-Cloud组成。它通过弹性调度、资源管控、...

分布式可视化 DAG 任务调度系统 Taier 的整体流程分析

Taier作为袋鼠云的开源项目之一,是一个分布式可视化的DAG任务调度系统。旨在降低ETL开发成本,提高大数据平台稳定性,让大数据开发人员可以在Taier直接进行业务逻辑的开发,而不用关...

SpringBoot任务调度:@Scheduled与TaskExecutor全面解析

一、任务调度基础概念1.1什么是任务调度任务调度是指按照预定的时间计划或特定条件自动执行任务的过程。在现代应用开发中,任务调度扮演着至关重要的角色,它使得开发者能够自动化处理周期性任务、定时任务和异...

取消回复欢迎 发表评论: