| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- #include "serialworker.h"
- #include "QDebug"
- #include <QCoreApplication>
- #include <QDateTime>
- #include <QElapsedTimer>
- #include <QtMath>
- #include <QSerialPortInfo>
- #include <QTimer>
- #include <QRegularExpression>
- #include <QSettings>
- #include <QThread>
- //#define FRAME_LEN 66
- #define CHANNEL_COUNT 24
- #define MAX_STEP 9
- SerialWorker::SerialWorker(QObject *parent) : QObject(parent)
- {
- }
- SerialWorker::~SerialWorker()
- {
- if(m_portBMC && m_portBMC->isOpen())
- {
- m_portBMC->close();
- }
- if(m_portCPLD && m_portCPLD->isOpen())
- {
- m_portCPLD->close();
- }
- }
- void SerialWorker::initFrame()
- {
- memset(txFrame, 0, sizeof(txFrame));
- txFrame[0] = 0xA5;
- txFrame[1] = 0x5A;
- txFrame[2] = 0x02;
- txFrame[3] = 0x04;
- txFrame[4] = 0x07;
- txFrame[5] = 0x00;
- txFrame[6] = 0x00;
- txFrame[7] = 0x00;
- txFrame[8] = 0x00;
- txFrame[9] = 0x00;
- txFrame[10] = 0x00;
- txFrame[11] = 0x00;
- txFrame[12] = 0x00;
- txFrame[13] = 0x22;
- txFrame[14] = 0x2A;
- txFrame[15] = 0x00;
- txFrame[44] = 0x00;
- txFrame[45] = 0x00;
- txFrame[46] = 0x00;
- txFrame[47] = 0x00;
- }
- void SerialWorker::start()
- {
- m_pid.resize(4);
- initFrame();
- QString path = QCoreApplication::applicationDirPath() + "/motor.ini";
- QSettings settings(path, QSettings::IniFormat);
- // 读取保存的位置,没有则默认0
- m_position = settings.value("Motor/Position", 0).toInt();
- qDebug()<<m_position;
- static int a = 0;
- preTimer = new QTimer(this);
- connect(preTimer,&QTimer::timeout,this,[=](){
- a++;
- qDebug()<<"a = "<<a;
- QByteArray data = QByteArray::fromHex(
- "A55A020405000000000000000004280000009E0C"
- );
- m_portCPLD->write(data);
- m_portCPLD->flush();
- sendDownCmd();
- for(int fan = 0; fan < 24; fan++)
- {
- txFrame[16 + fan] = (uint8_t)100;
- }
- for(int fan = 0; fan < 4; fan++)
- {
- txFrame[40 + fan] = (uint8_t)30;
- }
- sendSnapshot();
- });
- pidTimer = new QTimer(this);
- connect(pidTimer,&QTimer::timeout,this,[=](){
- m_portBMC->write("ipmitool raw 0x36 0x6c 0xdf 0xdd 0x00 0x03\r");
- m_portBMC->flush();
- });
- }
- void SerialWorker::openBMCSerial(const QString &portname)
- {
- m_portBMC = new QSerialPort(this);
- m_portBMC->setPortName(portname);
- m_portBMC->setBaudRate(115200);
- m_portBMC->setDataBits(QSerialPort::Data8);
- m_portBMC->setParity(QSerialPort::NoParity);
- m_portBMC->setStopBits(QSerialPort::OneStop);
- m_portBMC->setFlowControl(QSerialPort::NoFlowControl);
- if(!m_portBMC->open(QIODevice::ReadWrite))
- {
- qDebug()<<"bmc串口打开失败";
- return;
- }
- else
- {
- m_portBMC->write("stty -echo\r");
- m_portBMC->flush();
- qDebug()<<"bmc串口打开成功";
- }
- }
- void SerialWorker::openCPLDSerial(const QString &portname)
- {
- m_portCPLD = new QSerialPort(this);
- m_portCPLD->setPortName(portname);
- m_portCPLD->setBaudRate(921600);
- m_portCPLD->setDataBits(QSerialPort::Data8);
- m_portCPLD->setParity(QSerialPort::NoParity);
- m_portCPLD->setStopBits(QSerialPort::OneStop);
- m_portCPLD->setFlowControl(QSerialPort::NoFlowControl);
- if(!m_portCPLD->open(QIODevice::ReadWrite))
- {
- qDebug()<<"cpld串口打开失败";
- return;
- }
- else
- {
- connect(m_portCPLD,&QSerialPort::readyRead,this,&SerialWorker::onReadyReadCPLD);
- qDebug()<<"cpld串口打开成功";
- }
- }
- uint16_t SerialWorker::crc16(const uint8_t *data, uint16_t len)
- {
- uint16_t crc = 0xFFFF;
- for(uint16_t i = 0; i < len; i++)
- {
- crc ^= ((uint16_t)data[i] << 8);
- for(uint8_t j = 0; j < 8; j++)
- {
- if(crc & 0x8000)
- {
- crc = (crc << 1) ^ 0x1021;
- }
- else
- {
- crc <<= 1;
- }
- }
- }
- return crc;
- }
- void SerialWorker::onStartTest(int index)
- {
- m_tempIndex = index;
- preTimer->start(1000);
- }
- void SerialWorker::onReadyReadBMC()
- {
- m_buffer += m_portBMC->readAll();
- QString text = QString::fromUtf8(m_buffer);
- QRegularExpression re("root@[^#]*#");
- QRegularExpressionMatch match = re.match(text);
- if (!match.hasMatch())
- return;
- // 前面的HEX字符串
- QString hex = text.left(match.capturedStart());
- // 删除已经处理的数据
- m_buffer.remove(0, match.capturedEnd());
- // 去掉所有空白
- hex.remove(QRegularExpression("\\s+"));
- // 转二进制
- QByteArray data = QByteArray::fromHex(hex.toLatin1());
- if(data.size() != 48)
- {
- return;
- }
- parsePIDData(data);
- }
- void SerialWorker::onReadyReadCPLD()
- {
- m_cpldBuffer.append(m_portCPLD->readAll());
- while(m_cpldBuffer.size() >= 6)
- {
- // 找帧头
- int index = m_cpldBuffer.indexOf(
- QByteArray::fromHex("A55A"));
- if(index < 0)
- {
- m_cpldBuffer.clear();
- return;
- }
- // 删除前面的垃圾
- if(index > 0)
- m_cpldBuffer.remove(0,index);
- // 不够判断类型
- if(m_cpldBuffer.size() < 6)
- return;
- // 判断帧类型
- uint8_t cmd1 = (uint8_t)m_cpldBuffer[4];
- uint8_t cmd2 = (uint8_t)m_cpldBuffer[5];
- // 只处理温度帧
- if(cmd1 != 0x10 || cmd2 != 0x1B)
- {
- // 不是温度帧,丢掉这一帧
- m_cpldBuffer.remove(0,2);
- continue;
- }
- // 等待完整35字节
- if(m_cpldBuffer.size() < 35)
- return;
- QByteArray data =
- m_cpldBuffer.left(35);
- m_cpldBuffer.remove(0,35);
- qDebug()<<"温度帧:"
- <<data.toHex();
- //--------------------
- // CRC
- //--------------------
- uint16_t recvCrc =
- ((uint8_t)data[34]<<8)
- |
- (uint8_t)data[33];
- uint16_t calcCrc =
- crc16((uint8_t*)data.data()+2,31);
- if(recvCrc != calcCrc)
- {
- qDebug()<<"CRC错误";
- continue;
- }
- int temp=(uint8_t)data[25];
- qDebug()<<"sensor温度:"
- <<temp;
- if(temp >=40 && m_tempIndex==0)
- {
- preTimer->stop();
- QTimer::singleShot(200,this,[=](){
- connect(m_portBMC,&QSerialPort::readyRead,this,&SerialWorker::onReadyReadBMC);
- pidTimer->start(500);
- });
- }
- else if(temp>=70 && m_tempIndex==1)
- {
- preTimer->stop();
- QTimer::singleShot(200,this,[=](){
- connect(m_portBMC,&QSerialPort::readyRead,this,&SerialWorker::onReadyReadBMC);
- pidTimer->start(500);
- });
- }
- }
- }
- void SerialWorker::parsePIDData(const QByteArray &data)
- {
- QVector<double> temps;
- temps.reserve(CHANNEL_COUNT);
- for(int i = 0; i < CHANNEL_COUNT; ++i)
- {
- quint8 intPart = static_cast<quint8>(data[i * 2]);
- //quint8 decPart = static_cast<quint8>(data[i * 2 + 1]);
- if(intPart == 0xFF /*&& decPart == 0xFF*/)
- {
- temps.append(qQNaN());
- }
- else
- {
- temps.append(intPart/* + decPart / 100.0*/);
- }
- }
- qDebug()<<"temps"<<temps;
- emit signalNewTemps(temps); //发送给数据给主界面绘制
- if(m_tempIndex == 0)
- {
- controlHeat40(temps); //控温核心代码
- }
- else if(m_tempIndex == 1)
- {
- controlHeat(temps); //控温核心代码
- }
- }
- void SerialWorker::controlHeat(const QVector<double> &temps)
- {
- double target = 70.0;
- double sumTemp = 0.0;
- int count = 0;
- for(int i = 0; i < 6; i++)
- {
- double temp = temps[i];
- if(qIsNaN(temp))
- continue;
- sumTemp += temp;
- count++;
- }
- double fanDuty = 0.0;
- double duty = 0.0;
- double avgTemp = 0.0;
- if(count > 0)
- {
- avgTemp = sumTemp / count;
- // 第一组计算风扇
- fanDuty = m_pid[0].calculateFanDuty(avgTemp);
- // PID计算加热
- duty = m_pid[0].calculate(target, avgTemp);
- if(avgTemp > target)
- {
- sendUpCmd();
- }
- else
- {
- sendDownCmd();
- }
- for(int fan = 0; fan < 24; fan++)
- {
- txFrame[16 + fan] = (uint8_t)duty;
- }
- for(int fan = 0; fan < 4; fan++)
- {
- txFrame[40 + fan] = (uint8_t)fanDuty;
- }
- sendSnapshot();
- qDebug()<<"duty = "<<duty<<"fanDuty = "<<fanDuty;
- }
- }
- void SerialWorker::controlHeat40(const QVector<double> &temps)
- {
- double sumTemp = 0.0;
- int count = 0;
- for(int i = 0; i < 6; i++)
- {
- double temp = temps[i];
- if(qIsNaN(temp))
- continue;
- sumTemp += temp;
- count++;
- }
- double fanDuty = 0.0;
- double duty = 0.0;
- double avgTemp = 0.0;
- if(count > 0)
- {
- avgTemp = sumTemp / count;
- // 第一组计算风扇
- fanDuty = m_pid[0].calculateFanDuty1(avgTemp);
- if(avgTemp >= 40)
- {
- sendUpCmd();
- }
- else
- {
- sendDownCmd();
- }
- for(int fan = 0; fan < 24; fan++)
- {
- txFrame[16 + fan] = (uint8_t)duty;
- }
- for(int fan = 0; fan < 4; fan++)
- {
- txFrame[40 + fan] = (uint8_t)fanDuty;
- }
- sendSnapshot();
- qDebug()<<"duty = "<<duty<<"fanDuty = "<<fanDuty;
- }
- }
- void SerialWorker::sendSnapshot()
- {
- uint16_t crc = crc16(txFrame + 2,46);
- txFrame[48] = crc & 0xff;
- txFrame[49] = (crc >> 8)&0xff;
- QByteArray frame((char*)txFrame,50);
- m_portCPLD->write(frame);
- m_portCPLD->flush();
- }
- void SerialWorker::sendDownCmd()
- {
- if (m_position <= 0)
- {
- qDebug()<<m_position;
- return; // 已经到底了
- }
- QByteArray dataX = QByteArray::fromHex(
- "A55A02041100000000000000000835000103C20100001C32"
- );
- QByteArray dataY = QByteArray::fromHex(
- "A55A02041100000000000000000835010003C2010000DDCF"
- );
- m_portCPLD->write(dataX);
- m_portCPLD->write(dataY);
- m_portCPLD->flush();
- --m_position;
- qDebug()<<m_position;
- saveMotorPosition();
- }
- void SerialWorker::sendUpCmd()
- {
- if (m_position >= MAX_STEP)
- {
- qDebug()<<m_position;
- return; // 已经到顶了
- }
- QByteArray dataX = QByteArray::fromHex(
- "A55A02041100000000000000000835000003C2010000BC77"
- );
- QByteArray dataY = QByteArray::fromHex(
- "A55A02041100000000000000000835010103C20100007D8A"
- );
- m_portCPLD->write(dataX);
- m_portCPLD->write(dataY);
- m_portCPLD->flush();
- ++m_position;
- qDebug()<<m_position;
- saveMotorPosition();
- }
- void SerialWorker::saveMotorPosition()
- {
- QString path = QCoreApplication::applicationDirPath() + "/motor.ini";
- QSettings settings(path, QSettings::IniFormat);
- settings.setValue("Motor/Position", m_position);
- settings.sync();
- }
|