Advertisement
Guest User

automate.cpp

a guest
Oct 31st, 2013
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.79 KB | None | 0 0
  1. #include "automate.h"
  2. #include "ui_mainwindow.h"
  3.  
  4. Automate::Automate()
  5. {
  6. m_interface = new MainWindow();
  7. initialisation();
  8. qDebug("Initialisation faite");
  9. detectionPortCOM();
  10. qDebug("Detection des Ports COM fait");
  11.  
  12. connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(selectPort(QString))); //sélection du port COM
  13. connect(this,SIGNAL(workReady()),this,SLOT(configurationPort())); //lancement de la configuration du port série
  14. connect(timerRepet, SIGNAL(timeout()), this, SLOT(timerRepetTicks())); //timeout du timer d'envoi de trame
  15. connect(timerRecep, SIGNAL(timeout()), this, SLOT(timerRecepTicks())); //timeout du timer de réception de trame
  16. connect(timerChenillard, SIGNAL(timeout()), this, SLOT(timerChenillardTicks())); //timeout du timer de changement d'état du chenillard
  17. }
  18.  
  19. Automate::~Automate()
  20. {
  21.  
  22. }
  23.  
  24. void Automate::initialisation()
  25. {
  26. /*============================
  27. * Description : Initialisation et declaration des composants
  28. * de l'application
  29. *
  30. * Created : 25/09/2013 - 16:20
  31. *
  32. *===========================*/
  33.  
  34. //Initialisation
  35.  
  36. flagComStarted = false;
  37. indiceSortieTOR = 0;
  38. valueTimer = 50;
  39. for(int i = 0; i < 8; i++)
  40. {
  41. sortieTOR[i] = false;
  42. }
  43.  
  44. //Declaration
  45. signalMapper = new QSignalMapper();
  46. serialPort = new QextSerialPort();
  47.  
  48. //Declaration et definition des timers
  49. timerRepet = new QTimer();
  50. timerRepet->setSingleShot(false);
  51. timerRepet->setInterval(1000);
  52.  
  53. timerRecep = new QTimer();
  54. timerRecep->setSingleShot(false);
  55. timerRecep->setInterval(10000);
  56.  
  57. timerChenillard = new QTimer();
  58. timerChenillard->setSingleShot(false);
  59. timerChenillard->setInterval(20 * valueTimer); // Choix de la durée du Timeout du timer de changement d'état du chenillard
  60.  
  61. }
  62.  
  63. void Automate::detectionPortCOM()
  64. {
  65. /*=========================================
  66. * Description : Détection automatique des ports et création des menus
  67. * au lancement du programme
  68. * Created : 25/09/2013 - 17:00
  69. * Notes :
  70. *=========================================*/
  71.  
  72. int i = 0;
  73. ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste
  74. if(ports.isEmpty())
  75. {
  76. m_interface->ajouterMenu(new QMenu("Pas De Port Disponible"));
  77. }
  78. else
  79. {
  80. foreach(QextPortInfo port, ports) // création d'un lien entre chaque port et une action dans le menu
  81. {
  82. QAction *action = new QAction(port.portName, this);
  83.  
  84. action->setCheckable(true);
  85. m_interface->ajouterAction(action);
  86.  
  87.  
  88. signalMapper->setMapping(action, port.portName);
  89. connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
  90.  
  91. actions.append(action);
  92.  
  93. i++;
  94. nombreTotPortCOM = i;
  95. }
  96. }
  97. }
  98.  
  99. void Automate::selectPort(QString name)
  100. {
  101. /*=========================================
  102. * Description : Sélection du port
  103. * Created : 25/09/2013 - 17:03
  104. * Notes :
  105. *=========================================*/
  106. if(!actions.isEmpty()) // lors d'un clic sur un choix de port, celui-ci est marqué par un tick
  107. {
  108. foreach (QAction *act, actions)
  109. {
  110. act->setChecked(false);
  111. if(act->text() == name)
  112. {
  113. portCOMName = name;
  114. act->setChecked(true);
  115. }
  116. }
  117. }
  118. }
  119.  
  120.  
  121.  
  122. /*====================================================================================================================================================
  123. *
  124. * Partie Gestion des Timers
  125. *
  126. *
  127. *===================================================================================================================================================*/
  128.  
  129. void Automate::timerRepetTicks()
  130. {
  131. /*=========================================
  132. * Description : Traitement à faire lors du timeout du Timer : lancement
  133. * de l'envoi des data.
  134. *
  135. * Created : 25/09/2013 - 17:05
  136. * Notes :
  137. *=========================================*/
  138. if(flagComStarted)
  139. {
  140. timerRecep->stop();
  141. action_DebutCommunication();
  142. timerRecep->start();
  143. }
  144. }
  145.  
  146. void Automate::timerRecepTicks()
  147. {
  148. /*=========================================
  149. * Description : Traitement à faire lors du timeout du Timer : lancement
  150. * de la lecture des data.
  151. *
  152. * Created : 25/09/2013 - 17:07
  153. * Notes :
  154. *=========================================*/
  155. if(serialPort->bytesAvailable())
  156. {
  157. timerRepet->stop();
  158. onDataAvailable();
  159. timerRepet->start();
  160. }
  161. }
  162.  
  163. void Automate::timerChenillardTicks()
  164. {
  165. /*=========================================
  166. * Description : Traitement à faire lors du timeout du Timer : gestion
  167. * des LEDs du Chenillard.
  168. *
  169. * Created : 25/09/2013 - 17:10
  170. *
  171. * Notes :
  172. *=========================================*/
  173. sortieTOR[indiceSortieTOR] = !sortieTOR[indiceSortieTOR]; // on fait une séquence de chenillard via cet ensemble de ligne de code
  174. indiceSortieTOR++;
  175. if(indiceSortieTOR == 8)
  176. {
  177. indiceSortieTOR = 0;
  178. }
  179. }
  180.  
  181. /*====================================================================================================================================================
  182. *
  183. *
  184. *
  185. *
  186. *===================================================================================================================================================*/
  187.  
  188. void Automate::action_Connexion()
  189. {
  190. /*=========================================
  191. * Description : Traitement à faire lors d'un click sur le bouton : activation
  192. * des boutons et émission d'un Signal de connexion
  193. *
  194. * Created : 26/09/2013 - 08:23
  195. * Notes :
  196. *=========================================*/
  197. emit workReady();
  198. }
  199.  
  200.  
  201. void Automate::action_DebutCommunication()
  202. {
  203. /*=========================================
  204. * Description : Traitement à faire lors d'un click sur le bouton : activation
  205. * des boutons et émission d'un Signal de connexion
  206. *
  207. * Created : 26/09/2013 - 08:45
  208. * Notes :
  209. *=========================================*/
  210. if(!flagComStarted)
  211. {
  212. startCom();
  213. timerRepet->start();
  214. timerRecep->start();
  215. }
  216. else
  217. {
  218. Tableau *bufferEmission = configurationPortCheckBox();
  219. }
  220. }
  221.  
  222. void Automate::action_Chenillard()
  223. {
  224. /*=========================================
  225. * Description : Traitement à faire lors d'un click sur le bouton : lance
  226. * le timer contrôlant le chenillard
  227. *
  228. * Created : 26/09/2013 - 08:48
  229. * Notes :
  230. *=========================================*/
  231. timerChenillard->start(); // démarrage du timer du chenillard
  232. }
  233.  
  234. void Automate::action_StopChenillard()
  235. {
  236. /*=========================================
  237. * Description : Traitement à faire lors d'un click sur le bouton : arrete
  238. * le timer contrôlant le chenillard
  239. *
  240. * Created : 26/09/2013 - 15:42
  241. * Notes :
  242. *=========================================*/
  243. timerChenillard->stop(); // arret du timer du chenillard
  244. }
  245.  
  246. void Automate::action_LireTrame()
  247. {
  248. /*=========================================
  249. * Description : Traitement à faire lors d'un click sur le bouton : lance
  250. * la lecture des données
  251. *
  252. * Created : 26/09/2013 - 08:50
  253. * Notes :
  254. *=========================================*/
  255. onDataAvailable();
  256.  
  257. }
  258.  
  259. void Automate::action_Quitter()
  260. {
  261. /*=========================================
  262. * Description : Traitement à faire lors d'un click sur le bouton : quitte
  263. * l'application
  264. *
  265. * Created : 26/09/2013 - 08:53
  266. * Notes :
  267. *=========================================*/
  268. serialPort->close();
  269. qApp->quit();
  270. }
  271.  
  272. void Automate::action_LED1()
  273. {
  274. /*=========================================
  275. * Description : Lorsque l'on appuie sur le pushButon LED1, la LED
  276. * doit s'allumer ou s'éteindre
  277. *
  278. * Created : 26/09/2013 - 16:00
  279. * Notes :
  280. *=========================================*/
  281.  
  282. sortieTOR[0] = !sortieTOR[0];
  283.  
  284. }
  285.  
  286. void Automate::action_LED2()
  287. {
  288. /*=========================================
  289. * Description : Lorsque l'on appuie sur le pushButon LED2, la LED
  290. * doit s'allumer ou s'éteindre
  291. *
  292. * Created : 26/09/2013 - 16:00
  293. * Notes :
  294. *=========================================*/
  295.  
  296. sortieTOR[1] = !sortieTOR[1];
  297.  
  298. }
  299.  
  300. void Automate::action_LED3()
  301. {
  302. /*=========================================
  303. * Description : Lorsque l'on appuie sur le pushButon LED3, la LED
  304. * doit s'allumer ou s'éteindre
  305. *
  306. * Created : 26/09/2013 - 16:00
  307. * Notes :
  308. *=========================================*/
  309.  
  310. sortieTOR[2] = !sortieTOR[2];
  311.  
  312. }
  313.  
  314. void Automate::action_LED4()
  315. {
  316. /*=========================================
  317. * Description : Lorsque l'on appuie sur le pushButon LED4, la LED
  318. * doit s'allumer ou s'éteindre
  319. *
  320. * Created : 26/09/2013 - 16:00
  321. * Notes :
  322. *=========================================*/
  323.  
  324. sortieTOR[3] = !sortieTOR[3];
  325.  
  326. }
  327.  
  328. void Automate::action_LED5()
  329. {
  330. /*=========================================
  331. * Description : Lorsque l'on appuie sur le pushButon LED5, la LED
  332. * doit s'allumer ou s'éteindre
  333. *
  334. * Created : 26/09/2013 - 16:00
  335. * Notes :
  336. *=========================================*/
  337.  
  338. sortieTOR[4] = !sortieTOR[4];
  339.  
  340. }
  341.  
  342. void Automate::action_LED6()
  343. {
  344. /*=========================================
  345. * Description : Lorsque l'on appuie sur le pushButon LED6, la LED
  346. * doit s'allumer ou s'éteindre
  347. *
  348. * Created : 26/09/2013 - 16:00
  349. * Notes :
  350. *=========================================*/
  351.  
  352. sortieTOR[5] = !sortieTOR[5];
  353.  
  354. }
  355.  
  356. void Automate::action_LED7()
  357. {
  358. /*=========================================
  359. * Description : Lorsque l'on appuie sur le pushButon LED7, la LED
  360. * doit s'allumer ou s'éteindre
  361. *
  362. * Created : 26/09/2013 - 16:00
  363. * Notes :
  364. *=========================================*/
  365.  
  366. sortieTOR[6] = !sortieTOR[6];
  367.  
  368. }
  369.  
  370. void Automate::action_LED8()
  371. {
  372. /*=========================================
  373. * Description : Lorsque l'on appuie sur le pushButon LED8, la LED
  374. * doit s'allumer ou s'éteindre
  375. *
  376. * Created : 26/09/2013 - 16:00
  377. * Notes :
  378. *=========================================*/
  379.  
  380. sortieTOR[7] = !sortieTOR[7];
  381.  
  382. }
  383.  
  384.  
  385. /*====================================================================================================================================================
  386. *
  387. * Partie Gestion des Ports: Configuration, Lecture, Ecriture
  388. *
  389. *
  390. *===================================================================================================================================================*/
  391.  
  392. QString Automate::configurationPort()
  393. {
  394. /*=========================================
  395. * Description : Configure et ouvre la liaison série
  396. *
  397. * Created : 26/09/2013 - 08:56
  398. *
  399. * Notes :
  400. *=========================================*/
  401.  
  402. // Configuration de la liaison série
  403. PortSettings settings;
  404. settings.BaudRate = BAUD38400;
  405. settings.DataBits = DATA_8;
  406. settings.FlowControl = FLOW_OFF;
  407. settings.StopBits = STOP_1;
  408. settings.Parity = PAR_NONE;
  409. settings.Timeout_Millisec = 1000;
  410.  
  411. // Ouverture de la liaison série et vérification qu'elle est bien ouverte
  412. serialPort = new QextSerialPort(settings,QextSerialPort::Polling);
  413. serialPort->setPortName(portCOMName);
  414. if(!serialPort->open(QIODevice::ReadWrite))
  415. {
  416. //QMessageBox::critical(this,"erreur","pas moyen d'ouvrir la connexion");
  417. etatConnexion = "False";
  418. //ui->label->setText(etatConnexion);
  419. }
  420. else
  421. {
  422. //QMessageBox::information(this,"info","connexion ouverte");
  423. etatConnexion = "True";
  424. //ui->label->setText(etatConnexion);
  425. }
  426. return(etatConnexion);
  427. }
  428.  
  429.  
  430.  
  431. void Automate::onDataAvailable()
  432. {
  433. /*=========================================
  434. * Description : Lecture du port série et écriture de la sortie dans
  435. * un fichier texte
  436. *
  437. * Created : 26/09/2013 - 09:03
  438. *
  439. * Notes :
  440. *=========================================*/
  441.  
  442. QByteArray data = serialPort->readAll(); // lit le port RS485
  443. QString stringData(data.toHex()); // transforme la donnée lue en une string de nombre hexadécimaux
  444.  
  445. // Vérification de la présence de données lues
  446. if(!data.isEmpty())
  447. {
  448. QFile file("TramesLues.txt");
  449. // Ouverture du fichier dans lequel les données lues seront stockées
  450. if(!file.open(QIODevice::WriteOnly))
  451. {
  452. //QMessageBox::information(this,"erreur","pas moyen d'ouvrir le fichier");
  453. }
  454. else
  455. {
  456. qint64 tailleEcrit; // variable de vérification pour l'écriture dans le fichier
  457. //QMessageBox::information(this,"info","fichier ouvert");
  458. tailleEcrit = file.write(stringData.toStdString().c_str()); // transforme la string d'hexa et const char* pouvant être écrit dans un fichier
  459. //QMessageBox::information(this,"info","écrit : " + QString::number(tailleEcrit));
  460. file.close();
  461. }
  462. }
  463. }
  464.  
  465. void Automate::startCom()
  466. {
  467. /*=========================================
  468. * Description : Débute la communication avec l'automate
  469. *
  470. * Created : 26/09/2013 - 09:09
  471. *
  472. * Notes :
  473. *=========================================*/
  474. Tableau *testModbus = new Tableau(6); // création d'un tableau contenant 'MODBUS'
  475. testModbus->elements[0] = 'M';
  476. testModbus->elements[1] = 'O';
  477. testModbus->elements[2] = 'D';
  478. testModbus->elements[3] = 'B';
  479. testModbus->elements[4] = 'U';
  480. testModbus->elements[5] = 'S';
  481.  
  482. sendTrameWriteModBus(2, 16, 2000, 6, testModbus); //envoi d'une trame ModBUS, demandant à l'esclave 2 d'écrire 6 mots consécutifs à partir de l'adresse 2000
  483. flagComStarted = true;
  484. }
  485.  
  486.  
  487. void Automate::sendTrameWriteModBus(char adrSlave, char CodeCommande, int adresseData, int nbrData, Tableau *tableau)
  488. {
  489. /*=========================================
  490. * Description : Formate la trame ModBus et envoi la trame creee
  491. *
  492. * Created :
  493. *
  494. * Notes :
  495. *=========================================*/
  496. int variableLocale;
  497. qint64 nombreOctetsEcris; // variable de vérification pour l'écriture sur le port
  498. Tableau *bufferEmissionModBus = new Tableau((tableau->longueur * 2) + 9); // + 9 car : 7 octets d'entêtes MODBUS, 2 octets de CRC
  499.  
  500. bufferEmissionModBus->elements[0] = adrSlave;
  501. bufferEmissionModBus->elements[1] = CodeCommande;
  502. bufferEmissionModBus->elements[2] = adresseData / 256;
  503. bufferEmissionModBus->elements[3] = adresseData & 255;
  504. bufferEmissionModBus->elements[4] = nbrData / 256;
  505. bufferEmissionModBus->elements[5] = nbrData & 255;
  506. bufferEmissionModBus->elements[6] = nbrData * 2;
  507.  
  508. variableLocale = 7;
  509. for(int i = 0; i < tableau->longueur; i++)
  510. {
  511. bufferEmissionModBus->elements[variableLocale] = tableau->elements[i] / 256;
  512. variableLocale++;
  513. bufferEmissionModBus->elements[variableLocale] = tableau->elements[i] & 255;
  514. variableLocale++;
  515. }
  516.  
  517. addCRC16(bufferEmissionModBus,bufferEmissionModBus->longueur - 2); // ajout du CRC sur les deux derniers octets du tableau 'bufferEmissionModBUS'
  518.  
  519. nombreOctetsEcris = serialPort->write(bufferEmissionModBus->elements, bufferEmissionModBus->longueur); // écriture sur le port série
  520.  
  521. tableauEnvoye = bufferEmissionModBus; //variable à utiliser pour vérifier que l'esclave répond correctement (non implémenté)
  522. //QMessageBox::information(this,"Ecriture Trame MODBUS", QString::number(nombreOctetsEcris) + " octets ont été écris\nNombre d octet a envoyer : " + QString::number(bufferEmissionModBus->longueur));
  523. }
  524.  
  525.  
  526. Tableau* Automate::configurationPortCheckBox()
  527. {
  528. /*=========================================
  529. * Description : Prépare et envoi la trame de contrôle (allumage ou
  530. * extinction) des LEDs de l'automate
  531. *
  532. * Created : 26/09/2013 - 11:43
  533. *
  534. * Notes :
  535. *=========================================*/
  536. Tableau *bufferEmissionPrepare = new Tableau(1);
  537.  
  538. bufferEmissionPrepare->elements[0] = 0;
  539.  
  540. if(sortieTOR[0] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 1;
  541. if(sortieTOR[1] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 2;
  542. if(sortieTOR[2] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 4;
  543. if(sortieTOR[3] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 8;
  544. if(sortieTOR[4] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 16;
  545. if(sortieTOR[5] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 32;
  546. if(sortieTOR[6] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 64;
  547. if(sortieTOR[7] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 128;
  548.  
  549. //QMessageBox::information(this,"etat checkbox",QString::number(bufferEmissionPrepare->elements[0]));
  550.  
  551. sendTrameWriteModBus(2, 16, 0, 1, bufferEmissionPrepare); //une fois le tableau créé on doit le formater selon le protocole ModBUS
  552.  
  553. return bufferEmissionPrepare; //retour d'un tableau, peut être utile durant le débug
  554. }
  555.  
  556.  
  557. /*====================================================================================================================================================
  558. *
  559. * Partie Gestion CRC16
  560. *
  561. *
  562. *===================================================================================================================================================*/
  563.  
  564. void Automate::addCRC16(Tableau *tableau, int longueur)
  565. {
  566. /*=========================================
  567. * Description : Prend en entrée un Tableau
  568. * Calcul et ajoute à ce tableau deux octets de CRC16
  569. *
  570. * Je n'ai pas créé cette fonction, je ne saurais dire comment elle fonctionne
  571. * Created :
  572. * Notes :
  573. *=========================================*/
  574. long crc16 = 0;
  575. int boucle1 = 0, boucle2 = 0;
  576. unsigned char valeurCourante = 0, retenue = 0;
  577.  
  578. crc16 = 65535;
  579. for(boucle1 = 0; boucle1 < longueur; boucle1++)
  580. {
  581. valeurCourante = tableau->elements[boucle1];
  582. crc16 = crc16 ^ valeurCourante;
  583.  
  584. for(boucle2 = 0; boucle2 < 8; boucle2++)
  585. {
  586. retenue = crc16 % 2;
  587. crc16 = crc16 / 2;
  588. if(retenue == 1)
  589. {
  590. crc16 = crc16 ^ 40961;
  591. }
  592. }
  593. }
  594. tableau->elements[longueur] = crc16 % 256;
  595. tableau->elements[longueur + 1] = crc16 / 256;
  596. }
  597.  
  598. bool Automate::testCRC16(Tableau *tableau, int longueur)
  599. {
  600. /*=========================================
  601. * Description : Vérifie que le CRC16 reçu dans le tableau est conforme
  602. * au contenu du tableau
  603. *
  604. * Je n'ai pas créé cette fonction
  605. * Je ne saurais dire comment elle fonctionne
  606. * Created :
  607. * Notes :
  608. *=========================================*/
  609. long crc16 = 0;
  610. char crc16calcule[2];
  611. int boucle1 = 0, boucle2 = 0;
  612. char valeurCourante = 0, retenue = 0;
  613.  
  614. crc16 = 65535;
  615. for(boucle1 = 0; boucle1 < longueur; boucle1++)
  616. {
  617. valeurCourante = tableau->elements[boucle1];
  618. crc16 = crc16 ^ valeurCourante;
  619.  
  620. for(boucle2 = 0; boucle2 < 8; boucle2++)
  621. {
  622. retenue = crc16 % 2;
  623. crc16 = crc16 / 2;
  624. if(retenue == 1)
  625. {
  626. crc16 = crc16 ^ 40961;
  627. }
  628. }
  629. }
  630. crc16calcule[0] = crc16 % 256;
  631. crc16calcule[1] = crc16 / 256;
  632.  
  633. if((crc16calcule[0] == tableau->elements[longueur]) && (crc16calcule[1] == tableau->elements[longueur + 1]))
  634. {
  635. return true;
  636. }
  637. else
  638. {
  639. return false;
  640. }
  641.  
  642. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement