M350b版本
This commit is contained in:
434
Source/WDA/WDACalibration.cpp
Normal file
434
Source/WDA/WDACalibration.cpp
Normal 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;
|
||||
}
|
||||
|
||||
63
Source/WDA/WDACalibration.h
Normal file
63
Source/WDA/WDACalibration.h
Normal 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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user