Advertisement
Guest User

automate.cpp

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