serialworker.cpp.kznwOI 9.1 KB

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