M350b版本

This commit is contained in:
xin
2026-01-08 16:00:08 +08:00
parent 7396728ea7
commit a76d4b77e9
213 changed files with 8883 additions and 7196579 deletions

View File

@ -0,0 +1,434 @@
#include "pch.h"
#include "WDACalibration.h"
#include <QRegularExpression>
#include <QThread>
WDACalibration::WDACalibration()
{
}
WDACalibration::~WDACalibration()
{
}
int WDACalibration::ExecuteCalibration(QSerialPort* pSerialPort, double dTemperature)
{
if (!pSerialPort || !pSerialPort->isOpen())
{
qDebug() << "Err:ExecuteCalibration - Serial port not open.Exit Code:1";
return 1;
}
// 将温度转换为5位数字格式例如24.0 -> 00240
int iTempValue = static_cast<int>(dTemperature * 10);
char szTemp[16];
snprintf(szTemp, sizeof(szTemp), "%05d", iTempValue);
std::string sTempValue = szTemp;
qDebug() << QString("开始WDA校准流程校准温度: %1℃ (编码: %2)").arg(dTemperature).arg(sTempValue.c_str());
CalibrationState eState = Calib_Step1_TC0;
int iRetryCount = 0;
int iTryCount = 0;
// 执行校准流程
while (eState != Calib_Idle)
{
// 执行当前步骤
std::string sResponse;
int iResult = ExecuteCalibrationStep(pSerialPort, eState, sTempValue, iRetryCount, iTryCount, sResponse);
if (iResult != 0)
{
// 步骤执行失败
iRetryCount++;
if (iRetryCount > 3)
{
// 错误码映射ExecuteCalibrationStep返回1,2,3,4 -> ExecuteCalibration返回2,3,4,5
// (因为错误码1是串口未打开错误码2由IrisSensor_WDA_P0返回表示WDA正在工作)
qDebug() << "Err:ExecuteCalibration - Too many retries.Exit Code:" << (iResult + 1);
return (iResult + 1);
}
qDebug() << "Warning:ExecuteCalibration - Step failed, retrying...";
continue;
}
// 步骤执行成功,重置重试计数
iRetryCount = 0;
// 特殊处理步骤5需要检查校准是否完成
if (eState == Calib_Step5_AC_Second)
{
if (CheckCalibrationComplete(sResponse))
{
qDebug() << "WDA校准完成所有值均小于10";
// 继续到下一步
eState = Calib_Step6_Restore_KY18;
}
else
{
iTryCount++;
if (iTryCount > 1)
{
qDebug() << "Warning:ExecuteCalibration - Calibration not complete after retries, continuing...";
eState = Calib_Step6_Restore_KY18;
}
else
{
qDebug() << "WDA校准未完成需要重复步骤2-3等待5秒后重试...";
// 等待5秒
QThread::msleep(5000);
// 重新开始步骤2
eState = Calib_Step2_KY18_First;
iRetryCount = 0;
}
continue;
}
}
// 更新到下一步状态
switch (eState)
{
case Calib_Step1_TC0:
eState = Calib_Step2_KY18_First;
break;
case Calib_Step2_KY18_First:
eState = Calib_Step3_AC_First;
break;
case Calib_Step3_AC_First:
eState = Calib_Step4_KY18_Second;
break;
case Calib_Step4_KY18_Second:
eState = Calib_Step5_AC_Second;
break;
case Calib_Step5_AC_Second:
eState = Calib_Step6_Restore_KY18;
break;
case Calib_Step6_Restore_KY18:
eState = Calib_Step7_Restore_TC;
break;
case Calib_Step7_Restore_TC:
qDebug() << "WDA校准流程全部完成";
return 0;
default:
break;
}
// 步骤之间等待500ms
QThread::msleep(500);
}
return 0;
}
int WDACalibration::ExecuteCalibrationStep(QSerialPort* pSerialPort, CalibrationState eStep,
const std::string& sTempValue, int& iRetryCount, int& iTryCount,
std::string& sResponse)
{
// 发送当前步骤的命令
std::string sCommand;
switch (eStep)
{
case Calib_Step1_TC0:
sCommand = "$01,TC0\r\n";
break;
case Calib_Step2_KY18_First:
sCommand = "$01,KY18\r\n";
break;
case Calib_Step3_AC_First:
{
char szCmd[64];
snprintf(szCmd, sizeof(szCmd), "$01,AC%s^**\r\n", sTempValue.c_str());
sCommand = szCmd;
}
break;
case Calib_Step4_KY18_Second:
sCommand = "$01,KY18\r\n";
break;
case Calib_Step5_AC_Second:
{
char szCmd[64];
snprintf(szCmd, sizeof(szCmd), "$01,AC%s^**\r\n", sTempValue.c_str());
sCommand = szCmd;
}
break;
case Calib_Step6_Restore_KY18:
sCommand = "$01,KY18\r\n";
break;
case Calib_Step7_Restore_TC:
sCommand = "$01,TC00001^**\r\n";
break;
default:
return 1;
}
if (SendCalibrationCommand(pSerialPort, sCommand) != 0)
{
qDebug() << "Err:ExecuteCalibrationStep - SendCalibrationCommand failed.Exit Code:2";
return 2;
}
// 接收响应
sResponse.clear();
if (RecvCalibrationResponse(pSerialPort, sResponse, 5000) != 0)
{
qDebug() << "Err:ExecuteCalibrationStep - RecvCalibrationResponse timeout.Exit Code:3";
return 3;
}
// 检查响应
if (!CheckCalibrationResponse(sResponse, eStep))
{
qDebug() << "Err:ExecuteCalibrationStep - Invalid response.Exit Code:4";
return 4;
}
return 0;
}
int WDACalibration::SendCalibrationCommand(QSerialPort* pSerialPort, const std::string& sCommand)
{
if (!pSerialPort || !pSerialPort->isOpen())
{
return 1;
}
QByteArray qbaSend(sCommand.c_str(), (int)sCommand.length());
qint64 qi64Write = pSerialPort->write(qbaSend);
pSerialPort->waitForBytesWritten(50);
if (qi64Write != qbaSend.size())
{
qDebug() << "Err:SendCalibrationCommand - Write failed";
return 1;
}
qDebug() << QString("发送: %1").arg(sCommand.c_str());
return 0;
}
int WDACalibration::RecvCalibrationResponse(QSerialPort* pSerialPort, std::string& sResponse, int iTimeoutMs)
{
if (!pSerialPort || !pSerialPort->isOpen())
{
return 1;
}
sResponse.clear();
QByteArray qbData;
qbData.clear();
// 清空接收缓冲区
pSerialPort->readAll();
// 等待数据到达
int iElapsed = 0;
while (iElapsed < iTimeoutMs)
{
if (pSerialPort->waitForReadyRead(100))
{
QByteArray qbTemp = pSerialPort->readAll();
qbData.append(qbTemp);
// 检查是否收到完整的行(以\r\n或\n结尾
if (qbData.contains("\r\n") || qbData.contains('\n') || qbData.contains('\r'))
{
break;
}
}
iElapsed += 100;
}
if (qbData.isEmpty())
{
return 1;
}
// 提取一行数据
int iLineEnd = -1;
int iLineLength = 0;
if (qbData.contains("\r\n"))
{
iLineEnd = qbData.indexOf("\r\n");
iLineLength = 2;
}
else if (qbData.contains('\n'))
{
iLineEnd = qbData.indexOf('\n');
iLineLength = 1;
}
else if (qbData.contains('\r'))
{
iLineEnd = qbData.indexOf('\r');
iLineLength = 1;
}
else
{
// 没有换行符,使用全部数据
iLineEnd = qbData.size();
iLineLength = 0;
}
QByteArray qbLine = qbData.left(iLineEnd);
QString qstrResponse = QString::fromUtf8(qbLine).trimmed();
sResponse = qstrResponse.toStdString();
if (!sResponse.empty())
{
qDebug() << QString("接收: %1").arg(sResponse.c_str());
}
return 0;
}
bool WDACalibration::CheckCalibrationResponse(const std::string& sResponse, CalibrationState eStep)
{
QString qstrResponse = QString::fromStdString(sResponse);
switch (eStep)
{
case Calib_Step1_TC0:
if (qstrResponse.contains("$WI,TC=0") || qstrResponse.contains("TC=0"))
{
qDebug() << "步骤1完成: TC0设置成功";
return true;
}
break;
case Calib_Step2_KY18_First:
if (qstrResponse.contains("$WI,KY=18") || qstrResponse.contains("KY=18"))
{
qDebug() << "步骤2完成: KY18设置成功";
return true;
}
break;
case Calib_Step3_AC_First:
if (qstrResponse.contains("$WI,AC=") || qstrResponse.contains("AC="))
{
std::string sACValues = ExtractACValues(sResponse);
qDebug() << QString("步骤3完成: 第一次AC校准返回值: %1").arg(sACValues.c_str());
return true;
}
break;
case Calib_Step4_KY18_Second:
if (qstrResponse.contains("$WI,KY=18") || qstrResponse.contains("KY=18"))
{
qDebug() << "步骤4完成: 第二次KY18设置成功";
return true;
}
break;
case Calib_Step5_AC_Second:
if (qstrResponse.contains("$WI,AC=") || qstrResponse.contains("AC="))
{
std::string sACValues = ExtractACValues(sResponse);
qDebug() << QString("步骤5: 第二次AC校准返回值: %1").arg(sACValues.c_str());
return true;
}
break;
case Calib_Step6_Restore_KY18:
if (qstrResponse.contains("$WI,KY=18") || qstrResponse.contains("KY=18"))
{
qDebug() << "步骤6完成: 恢复模式KY18设置成功";
return true;
}
break;
case Calib_Step7_Restore_TC:
if (qstrResponse.contains("$WI,TC=00001") || qstrResponse.contains("TC=00001"))
{
qDebug() << "步骤7完成: 恢复模式TC设置成功";
return true;
}
break;
default:
break;
}
return false;
}
bool WDACalibration::CheckCalibrationComplete(const std::string& sResponse)
{
std::string sACValues = ExtractACValues(sResponse);
return AllValuesLessThan10(sACValues);
}
std::string WDACalibration::ExtractACValues(const std::string& sResponse)
{
QString qstrResponse = QString::fromStdString(sResponse);
QRegularExpression re(R"(\$WI,AC=(.+))");
QRegularExpressionMatch match = re.match(qstrResponse);
if (!match.hasMatch())
{
re.setPattern(R"(AC=(.+))");
match = re.match(qstrResponse);
}
if (match.hasMatch())
{
return match.captured(1).toStdString();
}
return "";
}
bool WDACalibration::AllValuesLessThan10(const std::string& sACValues)
{
if (sACValues.empty())
{
return false;
}
QString qstrACValues = QString::fromStdString(sACValues);
QStringList values = qstrACValues.split(',');
if (values.isEmpty())
{
return false;
}
// 检查从第5个值索引4到最后一个值
int iStartIndex = 4;
if (iStartIndex >= values.size())
{
qDebug() << QString("值数量不足5个无法检查");
return false;
}
QStringList checkedValues;
for (int i = iStartIndex; i < values.size(); i++)
{
QString valueStr = values[i].trimmed();
bool ok;
int iValue = valueStr.toInt(&ok);
if (!ok)
{
qDebug() << QString("无法解析值: %1").arg(valueStr);
return false;
}
checkedValues << valueStr;
if (iValue >= 10)
{
qDebug() << QString("检查值: %1 (第%2到最后一个值: %3),值 %4 >= 10校准未完成")
.arg(valueStr)
.arg(iStartIndex + 1)
.arg(checkedValues.join(","))
.arg(iValue);
return false;
}
}
qDebug() << QString("第%1到最后一个值均小于10 (值: %2),校准完成")
.arg(iStartIndex + 1)
.arg(checkedValues.join(","));
return true;
}

View File

@ -0,0 +1,63 @@
#pragma once
#include "pch.h"
// WDA校正功能类
// 用于执行WDA传感器的自动校准流程
class WDACalibration
{
public:
WDACalibration();
~WDACalibration();
// 执行WDA校正流程
// 参数:
// pSerialPort - 串口指针(必须已打开)
// dTemperature - 校准温度(单位:℃)
// 返回:
// 0 - 成功
// 1 - 串口未打开
// 2 - 发送命令失败(重试次数过多)
// 3 - 接收响应超时(重试次数过多)
// 4 - 响应无效(重试次数过多)
// 5 - 未知错误
// 注意WDA工作状态检查由调用者IrisSensor_WDA_P0负责错误码2由调用者返回
int ExecuteCalibration(QSerialPort* pSerialPort, double dTemperature);
private:
// 校正状态枚举
enum CalibrationState {
Calib_Idle,
Calib_Step1_TC0,
Calib_Step2_KY18_First,
Calib_Step3_AC_First,
Calib_Step4_KY18_Second,
Calib_Step5_AC_Second,
Calib_Step6_Restore_KY18,
Calib_Step7_Restore_TC
};
// 发送校正命令
int SendCalibrationCommand(QSerialPort* pSerialPort, const std::string& sCommand);
// 接收校正响应
int RecvCalibrationResponse(QSerialPort* pSerialPort, std::string& sResponse, int iTimeoutMs = 5000);
// 检查响应是否匹配当前步骤
bool CheckCalibrationResponse(const std::string& sResponse, CalibrationState eStep);
// 检查校正是否完成
bool CheckCalibrationComplete(const std::string& sResponse);
// 从响应中提取AC值
std::string ExtractACValues(const std::string& sResponse);
// 检查所有值是否小于10
bool AllValuesLessThan10(const std::string& sACValues);
// 执行单个校正步骤
// 返回0-成功非0-失败
// sResponse输出参数接收到的响应仅在成功时有效
int ExecuteCalibrationStep(QSerialPort* pSerialPort, CalibrationState eStep, const std::string& sTempValue,
int& iRetryCount, int& iTryCount, std::string& sResponse);
};