serialworker.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. #include "serialworker.h"
  2. #include "QDebug"
  3. #include <QCoreApplication>
  4. #include <QDateTime>
  5. #include <QElapsedTimer>
  6. #include <QtMath>
  7. #include <QSerialPortInfo>
  8. #include <QTimer>
  9. #include <QRegularExpression>
  10. #include <QSettings>
  11. #include <QThread>
  12. #define CHANNEL_COUNT 24
  13. #define MAX_STEP 10
  14. SerialWorker::SerialWorker(QObject *parent) : QObject(parent)
  15. {
  16. }
  17. SerialWorker::~SerialWorker()
  18. {
  19. if(m_portBMC && m_portBMC->isOpen())
  20. {
  21. m_portBMC->close();
  22. }
  23. if(m_portCPLD && m_portCPLD->isOpen())
  24. {
  25. m_portCPLD->close();
  26. }
  27. }
  28. void SerialWorker::initFrame()
  29. {
  30. memset(txFrame, 0, sizeof(txFrame));
  31. txFrame[0] = 0xA5;
  32. txFrame[1] = 0x5A;
  33. txFrame[2] = 0x01;
  34. txFrame[3] = 0x0B;
  35. txFrame[5] = 0x00;
  36. txFrame[6] = 0x00;
  37. txFrame[7] = 0x00;
  38. txFrame[9] = 0x00;
  39. txFrame[10] = 0x00;
  40. txFrame[11] = 0x00;
  41. }
  42. void SerialWorker::start()
  43. {
  44. m_pid.resize(4);
  45. initFrame();
  46. preTimer = new QTimer(this);
  47. static int stime = 0;
  48. connect(preTimer,&QTimer::timeout,this,[=](){
  49. stime++;
  50. qDebug()<<"stime = "<<stime;
  51. QByteArray data = QByteArray::fromHex(
  52. "A55A02006D7B"
  53. );
  54. m_portCPLD->write(data);
  55. m_portCPLD->flush();
  56. });
  57. pidTimer = new QTimer(this);
  58. connect(pidTimer,&QTimer::timeout,this,[=](){
  59. m_portBMC->write("ipmitool raw 0x36 0x6c 0xdf 0xdd 0x00 0x03\r");
  60. m_portBMC->flush();
  61. });
  62. }
  63. void SerialWorker::openBMCSerial(const QString &portname)
  64. {
  65. m_portBMC = new QSerialPort(this);
  66. m_portBMC->setPortName(portname);
  67. m_portBMC->setBaudRate(115200);
  68. m_portBMC->setDataBits(QSerialPort::Data8);
  69. m_portBMC->setParity(QSerialPort::NoParity);
  70. m_portBMC->setStopBits(QSerialPort::OneStop);
  71. m_portBMC->setFlowControl(QSerialPort::NoFlowControl);
  72. if(!m_portBMC->open(QIODevice::ReadWrite))
  73. {
  74. qDebug()<<"bmc串口打开失败";
  75. return;
  76. }
  77. else
  78. {
  79. m_portBMC->write("stty -echo\r");
  80. m_portBMC->flush();
  81. qDebug()<<"bmc串口打开成功";
  82. }
  83. }
  84. void SerialWorker::openCPLDSerial(const QString &portname)
  85. {
  86. m_portCPLD = new QSerialPort(this);
  87. m_portCPLD->setPortName(portname);
  88. m_portCPLD->setBaudRate(115200);
  89. m_portCPLD->setDataBits(QSerialPort::Data8);
  90. m_portCPLD->setParity(QSerialPort::NoParity);
  91. m_portCPLD->setStopBits(QSerialPort::OneStop);
  92. m_portCPLD->setFlowControl(QSerialPort::NoFlowControl);
  93. if(!m_portCPLD->open(QIODevice::ReadWrite))
  94. {
  95. qDebug()<<"cpld串口打开失败";
  96. return;
  97. }
  98. else
  99. {
  100. connect(m_portCPLD,&QSerialPort::readyRead,this,&SerialWorker::onReadyReadCPLD);
  101. qDebug()<<"cpld串口打开成功";
  102. }
  103. }
  104. uint16_t SerialWorker::crc16(const uint8_t *data, uint16_t len)
  105. {
  106. uint16_t crc = 0xFFFF;
  107. for(uint16_t i = 0; i < len; i++)
  108. {
  109. crc ^= ((uint16_t)data[i] << 8);
  110. for(uint8_t j = 0; j < 8; j++)
  111. {
  112. if(crc & 0x8000)
  113. {
  114. crc = (crc << 1) ^ 0x1021;
  115. }
  116. else
  117. {
  118. crc <<= 1;
  119. }
  120. }
  121. }
  122. return crc;
  123. }
  124. void SerialWorker::onStartTest(int index)
  125. {
  126. m_tempIndex = index;
  127. preTimer->start(1000);
  128. }
  129. void SerialWorker::onReadyReadBMC()
  130. {
  131. m_buffer += m_portBMC->readAll();
  132. QString text = QString::fromUtf8(m_buffer);
  133. QRegularExpression re("root@[^#]*#");
  134. QRegularExpressionMatch match = re.match(text);
  135. if (!match.hasMatch())
  136. return;
  137. // 前面的HEX字符串
  138. QString hex = text.left(match.capturedStart());
  139. // 删除已经处理的数据
  140. m_buffer.remove(0, match.capturedEnd());
  141. // 去掉所有空白
  142. hex.remove(QRegularExpression("\\s+"));
  143. // 转二进制
  144. QByteArray data = QByteArray::fromHex(hex.toLatin1());
  145. if(data.size() != 48)
  146. {
  147. return;
  148. }
  149. parseFrame(data);
  150. }
  151. void SerialWorker::onReadyReadCPLD()
  152. {
  153. m_cpldBuffer.append(m_portCPLD->readAll());
  154. while(m_cpldBuffer.size() >= 6)
  155. {
  156. // 查找帧头
  157. int index = m_cpldBuffer.indexOf(QByteArray::fromHex("A55A"));
  158. if(index < 0)
  159. {
  160. m_cpldBuffer.clear();
  161. return;
  162. }
  163. // 删除前面的垃圾数据
  164. if(index > 0)
  165. m_cpldBuffer.remove(0,index);
  166. // 至少需要 Header + Type + Length
  167. if(m_cpldBuffer.size() < 4)
  168. return;
  169. // 判断类型
  170. uint8_t type = (uint8_t)m_cpldBuffer[2];
  171. uint8_t len = (uint8_t)m_cpldBuffer[3];
  172. // 只处理温度帧
  173. if(type != 0x82)
  174. {
  175. m_cpldBuffer.remove(0,2);
  176. continue;
  177. }
  178. // 长度检查
  179. if(len != 0x1B)
  180. {
  181. qDebug()<<"长度错误";
  182. m_cpldBuffer.remove(0,2);
  183. continue;
  184. }
  185. // 完整帧长度
  186. int frameLen = 33;
  187. if(m_cpldBuffer.size() < frameLen)
  188. return;
  189. QByteArray data = m_cpldBuffer.left(frameLen);
  190. m_cpldBuffer.remove(0,frameLen);
  191. qDebug()<<"温度帧:" <<data.toHex(' ');
  192. //--------------------
  193. // CRC
  194. //--------------------
  195. // 小端
  196. uint16_t recvCrc = (uint8_t)data[31] | ((uint8_t)data[32]<<8);
  197. // CRC计算范围
  198. // Type + Length + Payload
  199. // 偏移2开始,共31字节
  200. uint16_t calcCrc = crc16( (uint8_t*)data.data()+2, 29);
  201. if(recvCrc != calcCrc)
  202. {
  203. qDebug()<<"CRC错误";
  204. continue;
  205. }
  206. int temp=(uint8_t)data[23];
  207. qDebug()<<"sensor温度:" <<temp;
  208. if(temp <= 50)
  209. {
  210. txFrame[8] = (uint8_t)40;
  211. }
  212. else
  213. {
  214. txFrame[8] = (uint8_t)20;
  215. }
  216. sendDownCmd();
  217. txFrame[4] = (uint8_t)100;
  218. sendSnapshot();
  219. if(temp >=40 && m_tempIndex==0)
  220. {
  221. preTimer->stop();
  222. QTimer::singleShot(200,this,[=](){
  223. connect(m_portBMC,&QSerialPort::readyRead,this,&SerialWorker::onReadyReadBMC);
  224. qDebug()<<"40°预加热结束";
  225. pidTimer->start(500);
  226. });
  227. }
  228. else if(temp>=70 && m_tempIndex==1)
  229. {
  230. preTimer->stop();
  231. QTimer::singleShot(200,this,[=](){
  232. connect(m_portBMC,&QSerialPort::readyRead,this,&SerialWorker::onReadyReadBMC);
  233. qDebug()<<"70°预加热结束";
  234. pidTimer->start(500);
  235. });
  236. }
  237. }
  238. }
  239. void SerialWorker::parseFrame(const QByteArray &frame)
  240. {
  241. QVector<double> temps;
  242. temps.reserve(CHANNEL_COUNT);
  243. for(int i = 0; i < CHANNEL_COUNT; ++i)
  244. {
  245. quint8 intPart = static_cast<quint8>(frame[i * 2]);
  246. //quint8 decPart = static_cast<quint8>(data[i * 2 + 1]);
  247. if(intPart == 0xFF /*&& decPart == 0xFF*/)
  248. {
  249. temps.append(qQNaN());
  250. }
  251. else
  252. {
  253. temps.append(intPart/* + decPart / 100.0*/);
  254. }
  255. }
  256. qDebug()<<"temps"<<temps;
  257. emit signalNewTemps(temps); //发送给数据给主界面绘制
  258. if(m_tempIndex == 0)
  259. {
  260. controlHeat40(temps); //控温核心代码
  261. }
  262. else if(m_tempIndex == 1)
  263. {
  264. controlHeat(temps); //控温核心代码
  265. }
  266. }
  267. void SerialWorker::controlHeat(const QVector<double> &temps)
  268. {
  269. double target = 70.0;
  270. double sumTemp = 0;
  271. int count = 0;
  272. for(int i = 0; i < 6; i++)
  273. {
  274. double temp = temps[i];
  275. if(qIsNaN(temp))
  276. continue;
  277. sumTemp += temp;
  278. count++;
  279. }
  280. double fanDuty = 0;
  281. double duty = 0;
  282. double avgTemp = 0.0;
  283. if(count > 0)
  284. {
  285. avgTemp = sumTemp / count;
  286. // 第一组计算风扇
  287. fanDuty = m_pid[0].calculateFanDuty(avgTemp);
  288. // PID计算加热
  289. duty = m_pid[0].calculate(target, avgTemp);
  290. txFrame[4] = (uint8_t)duty;
  291. txFrame[8] = (uint8_t)fanDuty;
  292. qDebug()<<"avgTemp = "<<avgTemp<<"duty = "<<duty<<"fanDuty = "<<fanDuty;
  293. }
  294. if(avgTemp >= 70)
  295. {
  296. sendUpCmd();
  297. }
  298. else
  299. {
  300. sendDownCmd();
  301. }
  302. sendSnapshot();
  303. }
  304. void SerialWorker::controlHeat40(const QVector<double> &temps)
  305. {
  306. double sumTemp = 0;
  307. int count = 0;
  308. for(int i = 0; i < 6; i++)
  309. {
  310. double temp = temps[i];
  311. if(qIsNaN(temp))
  312. continue;
  313. sumTemp += temp;
  314. count++;
  315. }
  316. double fanDuty = 0;
  317. double duty = 0;
  318. double avgTemp = 0.0;
  319. if(count > 0)
  320. {
  321. avgTemp = sumTemp / count;
  322. // 第一组计算风扇
  323. fanDuty = m_pid[0].calculateFanDuty1(avgTemp);
  324. txFrame[4] = (uint8_t)duty;
  325. txFrame[8] = (uint8_t)fanDuty;
  326. qDebug()<<"duty = "<<duty<<"fanDuty = "<<fanDuty;
  327. }
  328. if(avgTemp >= 30)
  329. {
  330. sendUpCmd();
  331. }
  332. else
  333. {
  334. sendDownCmd();
  335. }
  336. sendSnapshot();
  337. }
  338. void SerialWorker::sendSnapshot()
  339. {
  340. uint16_t crc = crc16(txFrame + 2, 13);
  341. // CRC小端
  342. txFrame[15] = crc & 0xff;
  343. txFrame[16] = (crc >> 8)&0xff;
  344. QByteArray frame((char*)txFrame,17);
  345. qDebug()<<frame.toHex(' ');
  346. m_portCPLD->write(frame);
  347. m_portCPLD->flush();
  348. }
  349. void SerialWorker::sendDownCmd()
  350. {
  351. if (m_position <= 0)
  352. {
  353. txFrame[12] = 0x00;
  354. txFrame[13] = 0x00;
  355. txFrame[14] = 0x00;
  356. return; // 已经到底了
  357. }
  358. txFrame[12] = 0x02;
  359. txFrame[13] = 0x02;
  360. txFrame[14] = 0x02;
  361. --m_position;
  362. }
  363. void SerialWorker::sendUpCmd()
  364. {
  365. if (m_position >= MAX_STEP)
  366. {
  367. txFrame[12] = 0x00;
  368. txFrame[13] = 0x00;
  369. txFrame[14] = 0x00;
  370. return; // 已经到顶了
  371. }
  372. txFrame[12] = 0x01;
  373. txFrame[13] = 0x01;
  374. txFrame[14] = 0x01;
  375. ++m_position;
  376. }