From: SnickerSun Date: Fri, 28 Nov 2025 12:44:34 +0000 (+0800) Subject: 添加rgb sensor读取功能直接显示颜色 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=f90e2d7821de79116e5527b31cf86904739ffee8;p=mirrors%2Ffactory_tool.git 添加rgb sensor读取功能直接显示颜色 --- diff --git a/HiBTMacWriteTool.pro b/HiBTMacWriteTool.pro index be0c714..8b97794 100644 --- a/HiBTMacWriteTool.pro +++ b/HiBTMacWriteTool.pro @@ -17,6 +17,7 @@ SOURCES += main.cpp\ mythread.cpp \ result_thread.cpp \ custom.cpp \ + rgb_serial_reader.cpp \ sqldbmanager.cpp \ settings.cpp \ dialogsettings.cpp \ @@ -27,6 +28,7 @@ HEADERS += mainwindow.h \ result_thread.h \ common.h \ custom.h \ + rgb_serial_reader.h \ sqldbmanager.h \ settings.h \ dialogsettings.h \ diff --git a/mainwindow.cpp b/mainwindow.cpp index 99f3305..c01b1a9 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -95,46 +95,46 @@ MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index) case 0: widgets.txtb_dispaly = ui->txtb_dispaly; widgets.label_runtime_status = ui->label_runtime_status1; - widgets.label_result_success = ui->label_result_success1; widgets.label_result_fail = ui->label_result_fail1; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1; + widgets.cbox_uart_com_select_rgb = ui->cbox_uart_com_select_rgb1; widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_1; break; case 1: widgets.txtb_dispaly = ui->txtb_dispaly_2; widgets.label_runtime_status = ui->label_runtime_status2; - widgets.label_result_success = ui->label_result_success2; widgets.label_result_fail = ui->label_result_fail2; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_2; + widgets.cbox_uart_com_select_rgb = ui->cbox_uart_com_select_rgb2; widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_2; break; case 2: widgets.txtb_dispaly = ui->txtb_dispaly_3; widgets.label_runtime_status = ui->label_runtime_status3; - widgets.label_result_success = ui->label_result_success3; widgets.label_result_fail = ui->label_result_fail3; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_3; + widgets.cbox_uart_com_select_rgb = ui->cbox_uart_com_select_rgb3; widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_3; break; case 3: widgets.txtb_dispaly = ui->txtb_dispaly_4; widgets.label_runtime_status = ui->label_runtime_status4; - widgets.label_result_success = ui->label_result_success4; widgets.label_result_fail = ui->label_result_fail4; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_4; + widgets.cbox_uart_com_select_rgb = ui->cbox_uart_com_select_rg_4; widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_4; break; default: widgets.txtb_dispaly = ui->txtb_dispaly; widgets.label_runtime_status = ui->label_runtime_status1; - widgets.label_result_success = ui->label_result_success1; widgets.label_result_fail = ui->label_result_fail1; widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1; + widgets.cbox_uart_com_select_rgb = ui->cbox_uart_com_select_rgb1; widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_1; break; } @@ -163,15 +163,15 @@ void MainWindow::connectPortControllerSignals(TestPortController* controller, in // 连接显示消息信号 connect(controller, &TestPortController::displayMessage, [widgets](QString str, bool inOrOut) { if (widgets.txtb_dispaly) { - widgets.txtb_dispaly->moveCursor(QTextCursor::End); + widgets.txtb_dispaly->moveCursor(QTextCursor::End); if (inOrOut) { - widgets.txtb_dispaly->setTextColor(QColor(127, 255, 0)); + widgets.txtb_dispaly->setTextColor(QColor(127, 255, 0)); } else { - widgets.txtb_dispaly->setTextColor(Qt::red); - } - widgets.txtb_dispaly->insertPlainText(str); - widgets.txtb_dispaly->moveCursor(QTextCursor::End); - } + widgets.txtb_dispaly->setTextColor(Qt::red); + } + widgets.txtb_dispaly->insertPlainText(str); + widgets.txtb_dispaly->moveCursor(QTextCursor::End); +} }); // 连接结果显示信号 @@ -415,7 +415,7 @@ void MainWindow::uart_rx_dispaly1(int buf_len, u8Piont buf) Q_UNUSED(buf); // 此函数已废弃,数据回显现在由TestPortController处理 if (buf) { - free(buf); + free(buf); } } @@ -432,43 +432,71 @@ void MainWindow::uart_com_select() }); // 保存当前选中的串口(如果有) - QStringList currentSelections; - currentSelections << ui->cbox_uart_com_select_1->currentText(); - currentSelections << ui->cbox_uart_com_select_2->currentText(); - currentSelections << ui->cbox_uart_com_select_3->currentText(); - currentSelections << ui->cbox_uart_com_select_4->currentText(); + QStringList currentDutSelections; + currentDutSelections << ui->cbox_uart_com_select_1->currentText(); + currentDutSelections << ui->cbox_uart_com_select_2->currentText(); + currentDutSelections << ui->cbox_uart_com_select_3->currentText(); + currentDutSelections << ui->cbox_uart_com_select_4->currentText(); + + QStringList currentRgbSelections; + currentRgbSelections << ui->cbox_uart_com_select_rgb1->currentText(); + currentRgbSelections << ui->cbox_uart_com_select_rgb2->currentText(); + currentRgbSelections << ui->cbox_uart_com_select_rgb3->currentText(); + currentRgbSelections << ui->cbox_uart_com_select_rg_4->currentText(); - // 更新所有4个串口选择框 - QComboBox *comboBoxes[] = { + // 更新所有4个DUT串口选择框 + QComboBox *dutComboBoxes[] = { ui->cbox_uart_com_select_1, ui->cbox_uart_com_select_2, ui->cbox_uart_com_select_3, ui->cbox_uart_com_select_4 }; + // 更新所有4个RGB串口选择框 + QComboBox *rgbComboBoxes[] = { + ui->cbox_uart_com_select_rgb1, + ui->cbox_uart_com_select_rgb2, + ui->cbox_uart_com_select_rgb3, + ui->cbox_uart_com_select_rg_4 + }; + + // 更新DUT串口选择框 + for (int i = 0; i < MAX_SERIAL_PORTS; i++) { + dutComboBoxes[i]->clear(); + dutComboBoxes[i]->addItem(tr("None")); + dutComboBoxes[i]->addItems(strlist); + + if (!currentDutSelections[i].isEmpty() && currentDutSelections[i] != tr("None")) { + int index = dutComboBoxes[i]->findText(currentDutSelections[i]); + if (index >= 0) { + dutComboBoxes[i]->setCurrentIndex(index); + } else { + dutComboBoxes[i]->setCurrentIndex(0); + } + } else { + dutComboBoxes[i]->setCurrentIndex(0); + } + } + + // 更新RGB串口选择框 for (int i = 0; i < MAX_SERIAL_PORTS; i++) { - comboBoxes[i]->clear(); - // 添加 "None" 作为第一个选项(默认值) - comboBoxes[i]->addItem(tr("None")); - // 添加可用串口列表 - comboBoxes[i]->addItems(strlist); + rgbComboBoxes[i]->clear(); + rgbComboBoxes[i]->addItem(tr("None")); + rgbComboBoxes[i]->addItems(strlist); - // 尝试恢复之前的选择(如果仍然存在) - if (!currentSelections[i].isEmpty() && currentSelections[i] != tr("None")) { - int index = comboBoxes[i]->findText(currentSelections[i]); + if (!currentRgbSelections[i].isEmpty() && currentRgbSelections[i] != tr("None")) { + int index = rgbComboBoxes[i]->findText(currentRgbSelections[i]); if (index >= 0) { - comboBoxes[i]->setCurrentIndex(index); + rgbComboBoxes[i]->setCurrentIndex(index); } else { - // 如果之前的串口不存在了,设置为 "None" - comboBoxes[i]->setCurrentIndex(0); + rgbComboBoxes[i]->setCurrentIndex(0); } } else { - // 如果没有之前的选择,设置为 "None" - comboBoxes[i]->setCurrentIndex(0); + rgbComboBoxes[i]->setCurrentIndex(0); } } - qDebug() << tr("已更新所有串口选择框,共找到") << strlist.size() << tr("个可用串口"); + qDebug() << tr("已更新所有串口选择框(DUT和RGB),共找到") << strlist.size() << tr("个可用串口"); } void MainWindow::uart_com_switch(QString com) { @@ -479,7 +507,7 @@ void MainWindow::uart_com_switch(QString com) void MainWindow::uart_baud_switch(QString baud) { Q_UNUSED(baud); - QString str_com = ui->cbox_uart_com_select_1->currentText(); + QString str_com = ui->cbox_uart_com_select_1->currentText(); Q_UNUSED(str_com); } // nIndex为索引号 bValue选择返回值为key还是value,默认为value @@ -591,8 +619,18 @@ void MainWindow::spp_connect(int port_index) QMessageBox::information(this, tr("提示"), tr("端口%1未选择串口,请先选择串口").arg(port_index + 1)); return; } - + + // 连接DUT串口 controller->connectPort(com_name, baud_rate.toInt()); + + // 同时连接RGB串口(如果已选择) + // RGB串口固定使用9600波特率,8,n,1 + if (widgets.cbox_uart_com_select_rgb) { + QString rgb_com_name = widgets.cbox_uart_com_select_rgb->currentText(); + if (!rgb_com_name.isEmpty() && rgb_com_name != tr("None") && rgb_com_name != "None") { + controller->connectRgbPort(rgb_com_name, 9600); // RGB串口固定9600波特率 + } + } } else { // 停止工作 controller->disconnectPort(); diff --git a/mainwindow.h b/mainwindow.h index 8e2797e..eb10c3a 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -61,7 +61,8 @@ private: QLabel *label_runtime_status; QLabel *label_result_success; QLabel *label_result_fail; - QComboBox *cbox_uart_com_select; // 串口选择框 + QComboBox *cbox_uart_com_select; // DUT串口选择框 + QComboBox *cbox_uart_com_select_rgb; // RGB串口选择框 QPushButton *pbtn_spp_reconnect; // 连接按钮 }; diff --git a/rgb_serial_reader.cpp b/rgb_serial_reader.cpp index 9a8cdfc..00b19b9 100644 --- a/rgb_serial_reader.cpp +++ b/rgb_serial_reader.cpp @@ -9,11 +9,17 @@ RgbSerialReader::RgbSerialReader(int port_index, QObject *parent) : QObject(parent) , m_port_index(port_index) , m_rgb_serial(new QSerialPort(this)) + , m_query_timer(new QTimer(this)) + , m_last_color_name("") { // 连接串口信号 connect(m_rgb_serial, &QSerialPort::readyRead, this, &RgbSerialReader::onReadyRead); connect(m_rgb_serial, QOverload::of(&QSerialPort::error), this, &RgbSerialReader::onError); + + // 连接定时器信号(每秒查询一次RGB数据) + connect(m_query_timer, &QTimer::timeout, this, &RgbSerialReader::sendQueryRgbcCommand); + m_query_timer->setInterval(1000); // 1秒 = 1000毫秒 } RgbSerialReader::~RgbSerialReader() @@ -50,6 +56,9 @@ void RgbSerialReader::connectPort(const QString& com_name, int baud_rate) // 清空接收缓冲区 m_receive_buffer.clear(); + // 重置颜色名称(重新连接时清空上一次的颜色) + m_last_color_name = ""; + if (m_rgb_serial->open(QIODevice::ReadWrite)) { // RGB串口需要读写(发送指令) qDebug() << tr("端口%1 RGB串口打开成功").arg(m_port_index + 1); emit connectionStatusChanged(true); @@ -60,7 +69,10 @@ void RgbSerialReader::connectPort(const QString& com_name, int baud_rate) QTimer::singleShot(50, this, [this]() { sendSaveLedCommand(); // 保存LED设置 QTimer::singleShot(50, this, [this]() { - sendQueryRgbcCommand(); // 查询RGBC数据 + sendQueryRgbcCommand(); // 首次查询RGBC数据 + // 启动定时器,每秒自动查询一次RGB数据 + m_query_timer->start(); + qDebug() << tr("端口%1 RGB串口启动自动查询定时器(每秒一次)").arg(m_port_index + 1); }); }); }); @@ -74,6 +86,12 @@ void RgbSerialReader::connectPort(const QString& com_name, int baud_rate) void RgbSerialReader::disconnectPort() { + // 停止定时器 + if (m_query_timer->isActive()) { + m_query_timer->stop(); + qDebug() << tr("端口%1 RGB串口停止自动查询定时器").arg(m_port_index + 1); + } + if (m_rgb_serial->isOpen()) { qDebug() << tr("端口%1关闭RGB串口").arg(m_port_index + 1); m_rgb_serial->close(); @@ -82,6 +100,9 @@ void RgbSerialReader::disconnectPort() // 清空接收缓冲区 m_receive_buffer.clear(); + + // 重置颜色名称 + m_last_color_name = ""; } void RgbSerialReader::onReadyRead() @@ -288,13 +309,24 @@ void RgbSerialReader::parseRgbcData(const QByteArray& buffer) quint16 blue = ((quint16)b_high << 8) | b_low; quint16 clear = ((quint16)c_high << 8) | c_low; + // 检测颜色名称 + QString colorName = detectColorName(red, green, blue, clear); + // 输出调试信息(包含原始十六进制数据) QString hexFrame = frame.toHex(' ').toUpper(); qDebug() << tr("端口%1 RGB串口解析RGBC数据帧: %2").arg(m_port_index + 1).arg(hexFrame); - qDebug() << tr("端口%1 RGB串口RGBC值: R=%2, G=%3, B=%4, C=%5") - .arg(m_port_index + 1).arg(red).arg(green).arg(blue).arg(clear); + qDebug() << tr("端口%1 RGB串口RGBC值: R=%2, G=%3, B=%4, C=%5, 颜色: %6") + .arg(m_port_index + 1).arg(red).arg(green).arg(blue).arg(clear).arg(colorName); + + // 只有颜色变化时才发送信号更新UI + if (colorName != m_last_color_name) { + m_last_color_name = colorName; + // 发送带颜色名称的信号(只发送颜色名称,不发送RGBC数值) + emit rgbcDataParsedWithColor(m_port_index, red, green, blue, clear, colorName); + qDebug() << tr("端口%1 颜色变化: %2").arg(m_port_index + 1).arg(colorName); + } - // 发送解析后的RGBC数据信号 + // 发送解析后的RGBC数据信号(保持向后兼容,用于其他用途) emit rgbcDataParsed(m_port_index, red, green, blue, clear); } @@ -309,3 +341,81 @@ void RgbSerialReader::parseRgbcData(const QByteArray& buffer) } } +QString RgbSerialReader::detectColorName(quint16 red, quint16 green, quint16 blue, quint16 clear) +{ + // 如果Clear值太低,可能是黑色或没有物体 + if (clear < 50) { + return tr("黑色/无物体"); + } + + // 计算RGB的总和和最大值 + quint32 rgbSum = red + green + blue; + quint16 maxValue = qMax(qMax(red, green), blue); + quint16 minValue = qMin(qMin(red, green), blue); + + // 如果RGB总和太低,可能是黑色 + if (rgbSum < 100) { + return tr("黑色"); + } + + // 如果RGB值都很高且接近,可能是白色 + if (maxValue > 500 && minValue > maxValue * 0.7) { + return tr("白色"); + } + + // 计算各通道的相对比例 + double rRatio = (double)red / rgbSum; + double gRatio = (double)green / rgbSum; + double bRatio = (double)blue / rgbSum; + + // 判断主要颜色通道 + quint16 diff = maxValue - minValue; + + // 如果差异太小,可能是灰色 + if (diff < maxValue * 0.2) { + if (maxValue > 300) { + return tr("浅灰色"); + } else { + return tr("深灰色"); + } + } + + // 根据主要通道判断颜色 + if (red == maxValue) { + // 红色为主 + if (green > maxValue * 0.6) { + if (blue < maxValue * 0.3) { + return tr("黄色"); + } else { + return tr("橙色"); + } + } else if (green > maxValue * 0.4) { + return tr("橙红色"); + } else { + return tr("红色"); + } + } else if (green == maxValue) { + // 绿色为主 + if (red > maxValue * 0.6) { + if (blue < maxValue * 0.3) { + return tr("黄绿色"); + } else { + return tr("青绿色"); + } + } else if (blue > maxValue * 0.5) { + return tr("青色"); + } else { + return tr("绿色"); + } + } else { + // 蓝色为主 + if (red > maxValue * 0.5 && green > maxValue * 0.5) { + return tr("青色"); + } else if (red > maxValue * 0.4) { + return tr("紫色"); + } else { + return tr("蓝色"); + } + } +} + diff --git a/rgb_serial_reader.h b/rgb_serial_reader.h index f294cab..039f49c 100644 --- a/rgb_serial_reader.h +++ b/rgb_serial_reader.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -39,6 +40,7 @@ signals: // RGBC数据解析信号(当Byte2=0x15时) void rgbcDataParsed(int port_index, quint16 red, quint16 green, quint16 blue, quint16 clear); // 解析后的RGBC数据 + void rgbcDataParsedWithColor(int port_index, quint16 red, quint16 green, quint16 blue, quint16 clear, const QString& colorName); // 解析后的RGBC数据(带颜色名称) // 状态信号 void connectionStatusChanged(bool connected); // 连接状态变化 @@ -54,6 +56,9 @@ private: // 串口对象 QSerialPort *m_rgb_serial; + + // 定时器(用于每秒查询一次RGB数据) + QTimer *m_query_timer; // 数据缓冲区(用于处理分包数据) QByteArray m_receive_buffer; @@ -61,9 +66,13 @@ private: // 最大缓冲区大小(防止内存溢出) static const int MAX_BUFFER_SIZE = 32768; // 32KB + // 上一次检测到的颜色名称(用于判断颜色是否变化) + QString m_last_color_name; + // 数据解析函数 void parseRgbcData(const QByteArray& data); // 解析RGBC数据(查找Byte2=0x15的数据包) bool findRgbcFrame(const QByteArray& buffer, int& startPos, int& endPos); // 查找完整的RGBC数据帧 + QString detectColorName(quint16 red, quint16 green, quint16 blue, quint16 clear); // 根据RGB值判断颜色名称 }; #endif // RGB_SERIAL_READER_H diff --git a/test_port_controller.cpp b/test_port_controller.cpp index b792cc5..9f41cca 100644 --- a/test_port_controller.cpp +++ b/test_port_controller.cpp @@ -1,4 +1,5 @@ #include "test_port_controller.h" +#include "rgb_serial_reader.h" #include "settings.h" #include #include @@ -8,7 +9,8 @@ TestPortController::TestPortController(int port_index, QObject *parent) : QObject(parent) , m_port_index(port_index) , m_dut_serial(new QSerialPort(this)) - , m_rgb_serial(new QSerialPort(this)) + , m_rgb_serial(new QSerialPort(this)) // 保留用于向后兼容 + , m_rgb_reader(new RgbSerialReader(port_index, this)) , m_spp_timer_handle(new QTimer(this)) , m_result_thread(new Result_Thread(nullptr, port_index + 1)) , m_bytesToWrite(0) @@ -24,10 +26,32 @@ TestPortController::TestPortController(int port_index, QObject *parent) // 连接定时器信号 connect(m_spp_timer_handle, &QTimer::timeout, this, &TestPortController::onTimerTimeout); - // 连接串口信号 + // 连接DUT串口信号 connect(m_dut_serial, &QSerialPort::readyRead, this, &TestPortController::onReadyRead); connect(m_dut_serial, &QSerialPort::bytesWritten, this, &TestPortController::onBytesWritten); + // 连接RGB串口读取器信号 + connect(m_rgb_reader, &RgbSerialReader::dataReceived, this, [this](const QByteArray& data) { + // RGB串口接收到原始数据(用于调试) + QString hexData = data.toHex(' ').toUpper(); + qDebug() << tr("端口%1 RGB串口接收到数据,长度:%2, 内容: %3") + .arg(m_port_index + 1).arg(data.length()).arg(hexData); + }); + + // 连接RGBC数据解析信号(带颜色名称) + connect(m_rgb_reader, &RgbSerialReader::rgbcDataParsedWithColor, this, + [this](int port_index, quint16 red, quint16 green, quint16 blue, quint16 clear, const QString& colorName) { + // 只显示颜色名称(颜色变化时才更新) + QString colorInfo = tr("颜色: %1\r\n").arg(colorName); + emit displayMessage(colorInfo, true); + qDebug() << tr("端口%1 检测到颜色: %2").arg(m_port_index + 1).arg(colorName); + }); + + connect(m_rgb_reader, &RgbSerialReader::errorOccurred, this, [this](const QString& error) { + qDebug() << tr("端口%1 RGB串口错误:").arg(m_port_index + 1) << error; + emit displayMessage(tr("RGB串口错误: ") + error + tr("\r\n"), false); + }); + // 启动结果线程 m_result_thread->start(); m_result_thread->pause(); @@ -118,6 +142,23 @@ void TestPortController::disconnectPort() if (m_dut_serial->isOpen()) { m_dut_serial->close(); } + + // 同时断开RGB串口 + disconnectRgbPort(); +} + +void TestPortController::connectRgbPort(const QString& rgb_com_name, int baud_rate) +{ + if (m_rgb_reader) { + m_rgb_reader->connectPort(rgb_com_name, baud_rate); + } +} + +void TestPortController::disconnectRgbPort() +{ + if (m_rgb_reader) { + m_rgb_reader->disconnectPort(); + } } void TestPortController::poweroffWatch() diff --git a/test_port_controller.h b/test_port_controller.h index b25c36b..6e21501 100644 --- a/test_port_controller.h +++ b/test_port_controller.h @@ -13,6 +13,7 @@ class QSerialPort; class QTimer; class Result_Thread; +class RgbSerialReader; // 测试端口控制器类 - 封装每个测试端口的所有变量和函数 class TestPortController : public QObject @@ -29,6 +30,7 @@ public: // 串口对象访问 QSerialPort* dutSerial() const { return m_dut_serial; } QSerialPort* rgbSerial() const { return m_rgb_serial; } + RgbSerialReader* rgbReader() const { return m_rgb_reader; } // 状态访问 bool isWorking() const { return m_working_state; } @@ -37,7 +39,9 @@ public: // 公共接口函数 void connectPort(const QString& com_name, int baud_rate); + void connectRgbPort(const QString& rgb_com_name, int baud_rate); // 连接RGB串口 void disconnectPort(); + void disconnectRgbPort(); // 断开RGB串口 void poweroffWatch(); void setMacAddress(const QString& mac); @@ -68,7 +72,10 @@ private: // 串口对象 QSerialPort *m_dut_serial; - QSerialPort *m_rgb_serial; + QSerialPort *m_rgb_serial; // 保留用于向后兼容,实际使用m_rgb_reader + + // RGB串口读取器 + RgbSerialReader *m_rgb_reader; // 定时器 QTimer *m_spp_timer_handle;