Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "automate.h"
- #include "ui_mainwindow.h"
- Automate::Automate()
- {
- initialisation();
- detectionPortCOM();
- connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(selectPort(QString))); //sélection du port COM
- connect(this,SIGNAL(workReady()),this,SLOT(configurationPort())); //lancement de la configuration du port série
- connect(timerRepet, SIGNAL(timeout()), this, SLOT(timerRepetTicks())); //timeout du timer d'envoi de trame
- connect(timerRecep, SIGNAL(timeout()), this, SLOT(timerRecepTicks())); //timeout du timer de réception de trame
- connect(timerChenillard, SIGNAL(timeout()), this, SLOT(timerChenillardTicks())); //timeout du timer de changement d'état du chenillard
- }
- Automate::~Automate()
- {
- delete ui;
- }
- void Automate::initialisation()
- {
- /*============================
- * Description : Initialisation et declaration des composants
- * de l'application
- *
- * Created : 25/09/2013 - 16:20
- *
- *===========================*/
- //Initialisation
- flagComStarted = false;
- indiceSortieTOR = 0;
- valueTimer = 50;
- for(int i = 0; i < 8; i++)
- {
- sortieTOR[i] = false;
- }
- //Declaration
- signalMapper = new QSignalMapper(this);
- serialPort = new QextSerialPort();
- //Declaration et definition des timers
- timerRepet = new QTimer(this);
- timerRepet->setSingleShot(false);
- timerRepet->setInterval(1000);
- timerRecep = new QTimer(this);
- timerRecep->setSingleShot(false);
- timerRecep->setInterval(10000);
- timerChenillard = new QTimer(this);
- timerChenillard->setSingleShot(false);
- timerChenillard->setInterval(20 * valueTimer); // Choix de la durée du Timeout du timer de changement d'état du chenillard
- }
- void Automate::detectionPortCOM()
- {
- /*=========================================
- * Description : Détection automatique des ports et création des menus
- * au lancement du programme
- * Created : 25/09/2013 - 17:00
- * Notes :
- *=========================================*/
- int i = 0;
- ports = QextSerialEnumerator::getPorts(); //recuperation de l'ensemble des ports COM dans une liste
- if(ports.isEmpty())
- {
- ui->menuSelection_portCOM->addMenu("Pas de Port Disponible");
- }
- else
- {
- foreach(QextPortInfo port, ports) // création d'un lien entre chaque port et une action dans le menu
- {
- QAction *action = new QAction(port.portName, this);
- action->setCheckable(true);
- ui->menuSelection_portCOM->addAction(action);
- signalMapper->setMapping(action, port.portName);
- connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));
- actions.append(action);
- i++;
- nombreTotPortCOM = i;
- }
- }
- }
- void Automate::selectPort(QString name)
- {
- /*=========================================
- * Description : Sélection du port
- * Created : 25/09/2013 - 17:03
- * Notes :
- *=========================================*/
- if(!actions.isEmpty()) // lors d'un clic sur un choix de port, celui-ci est marqué par un tick
- {
- ui->pushButton_Connexion->setEnabled(true);
- foreach (QAction *act, actions)
- {
- act->setChecked(false);
- if(act->text() == name)
- {
- portCOMName = name;
- act->setChecked(true);
- }
- }
- }
- }
- /*====================================================================================================================================================
- *
- * Partie Gestion des Timers
- *
- *
- *===================================================================================================================================================*/
- void Automate::timerRepetTicks()
- {
- /*=========================================
- * Description : Traitement à faire lors du timeout du Timer : lancement
- * de l'envoi des data.
- *
- * Created : 25/09/2013 - 17:05
- * Notes :
- *=========================================*/
- if(flagComStarted)
- {
- timerRecep->stop();
- on_pushButton_DebutCommunication_clicked();
- timerRecep->start();
- }
- }
- void Automate::timerRecepTicks()
- {
- /*=========================================
- * Description : Traitement à faire lors du timeout du Timer : lancement
- * de la lecture des data.
- *
- * Created : 25/09/2013 - 17:07
- * Notes :
- *=========================================*/
- if(serialPort->bytesAvailable())
- {
- timerRepet->stop();
- onDataAvailable();
- timerRepet->start();
- }
- }
- void Automate::timerChenillardTicks()
- {
- /*=========================================
- * Description : Traitement à faire lors du timeout du Timer : gestion
- * des LEDs du Chenillard.
- *
- * Created : 25/09/2013 - 17:10
- *
- * Notes :
- *=========================================*/
- sortieTOR[indiceSortieTOR] = !sortieTOR[indiceSortieTOR]; // on fait une séquence de chenillard via cet ensemble de ligne de code
- indiceSortieTOR++;
- if(indiceSortieTOR == 8)
- {
- indiceSortieTOR = 0;
- }
- }
- /*====================================================================================================================================================
- *
- *
- *
- *
- *===================================================================================================================================================*/
- void Automate::action_Connexion()
- {
- /*=========================================
- * Description : Traitement à faire lors d'un click sur le bouton : activation
- * des boutons et émission d'un Signal de connexion
- *
- * Created : 26/09/2013 - 08:23
- * Notes :
- *=========================================*/
- emit workReady();
- }
- void Automate::action_DebutCommunication()
- {
- /*=========================================
- * Description : Traitement à faire lors d'un click sur le bouton : activation
- * des boutons et émission d'un Signal de connexion
- *
- * Created : 26/09/2013 - 08:45
- * Notes :
- *=========================================*/
- if(!flagComStarted)
- {
- startCom();
- timerRepet->start();
- timerRecep->start();
- }
- else
- {
- Tableau *bufferEmission = configurationPortCheckBox();
- }
- }
- void Automate::action_Chenillard()
- {
- /*=========================================
- * Description : Traitement à faire lors d'un click sur le bouton : lance
- * le timer contrôlant le chenillard
- *
- * Created : 26/09/2013 - 08:48
- * Notes :
- *=========================================*/
- timerChenillard->start(); // démarrage du timer du chenillard
- }
- void Automate::on_pushButton_StopChenillard_clicked()
- {
- /*=========================================
- * Description : Traitement à faire lors d'un click sur le bouton : arrete
- * le timer contrôlant le chenillard
- *
- * Created : 26/09/2013 - 15:42
- * Notes :
- *=========================================*/
- timerChenillard->stop(); // arret du timer du chenillard
- }
- void Automate::action_LireTrame()
- {
- /*=========================================
- * Description : Traitement à faire lors d'un click sur le bouton : lance
- * la lecture des données
- *
- * Created : 26/09/2013 - 08:50
- * Notes :
- *=========================================*/
- onDataAvailable();
- }
- void Automate::action_Quitter()
- {
- /*=========================================
- * Description : Traitement à faire lors d'un click sur le bouton : quitte
- * l'application
- *
- * Created : 26/09/2013 - 08:53
- * Notes :
- *=========================================*/
- serialPort->close();
- qApp->quit();
- }
- void Automate::action_LED1()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED1, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[0] = !sortieTOR[0];
- }
- void Automate::action_LED2()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED2, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[1] = !sortieTOR[1];
- }
- void Automate::action_LED3()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED3, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[2] = !sortieTOR[2];
- }
- void Automate::action_LED4()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED4, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[3] = !sortieTOR[3];
- }
- void Automate::action_LED5()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED5, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[4] = !sortieTOR[4];
- }
- void Automate::action_LED6()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED6, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[5] = !sortieTOR[5];
- }
- void Automate::action_LED7()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED7, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[6] = !sortieTOR[6];
- }
- void Automate::action_LED8()
- {
- /*=========================================
- * Description : Lorsque l'on appuie sur le pushButon LED8, la LED
- * doit s'allumer ou s'éteindre
- *
- * Created : 26/09/2013 - 16:00
- * Notes :
- *=========================================*/
- sortieTOR[7] = !sortieTOR[7];
- }
- /*====================================================================================================================================================
- *
- * Partie Gestion des Ports: Configuration, Lecture, Ecriture
- *
- *
- *===================================================================================================================================================*/
- void Automate::configurationPort()
- {
- /*=========================================
- * Description : Configure et ouvre la liaison série
- *
- * Created : 26/09/2013 - 08:56
- *
- * Notes :
- *=========================================*/
- // Configuration de la liaison série
- PortSettings settings;
- settings.BaudRate = BAUD38400;
- settings.DataBits = DATA_8;
- settings.FlowControl = FLOW_OFF;
- settings.StopBits = STOP_1;
- settings.Parity = PAR_NONE;
- settings.Timeout_Millisec = 1000;
- // Ouverture de la liaison série et vérification qu'elle est bien ouverte
- serialPort = new QextSerialPort(settings,QextSerialPort::Polling);
- serialPort->setPortName(portCOMName);
- if(!serialPort->open(QIODevice::ReadWrite))
- {
- //QMessageBox::critical(this,"erreur","pas moyen d'ouvrir la connexion");
- etatConnexion = "False";
- ui->label->setText(etatConnexion);
- }
- else
- {
- //QMessageBox::information(this,"info","connexion ouverte");
- etatConnexion = "True";
- ui->label->setText(etatConnexion);
- }
- }
- void Automate::onDataAvailable()
- {
- /*=========================================
- * Description : Lecture du port série et écriture de la sortie dans
- * un fichier texte
- *
- * Created : 26/09/2013 - 09:03
- *
- * Notes :
- *=========================================*/
- QByteArray data = serialPort->readAll(); // lit le port RS485
- QString stringData(data.toHex()); // transforme la donnée lue en une string de nombre hexadécimaux
- // Vérification de la présence de données lues
- if(!data.isEmpty())
- {
- QFile file("TramesLues.txt");
- // Ouverture du fichier dans lequel les données lues seront stockées
- if(!file.open(QIODevice::WriteOnly))
- {
- //QMessageBox::information(this,"erreur","pas moyen d'ouvrir le fichier");
- }
- else
- {
- qint64 tailleEcrit; // variable de vérification pour l'écriture dans le fichier
- //QMessageBox::information(this,"info","fichier ouvert");
- tailleEcrit = file.write(stringData.toStdString().c_str()); // transforme la string d'hexa et const char* pouvant être écrit dans un fichier
- //QMessageBox::information(this,"info","écrit : " + QString::number(tailleEcrit));
- file.close();
- }
- }
- }
- void Automate::startCom()
- {
- /*=========================================
- * Description : Débute la communication avec l'automate
- *
- * Created : 26/09/2013 - 09:09
- *
- * Notes :
- *=========================================*/
- Tableau *testModbus = new Tableau(6); // création d'un tableau contenant 'MODBUS'
- testModbus->elements[0] = 'M';
- testModbus->elements[1] = 'O';
- testModbus->elements[2] = 'D';
- testModbus->elements[3] = 'B';
- testModbus->elements[4] = 'U';
- testModbus->elements[5] = 'S';
- 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
- flagComStarted = true;
- }
- void Automate::sendTrameWriteModBus(char adrSlave, char CodeCommande, int adresseData, int nbrData, Tableau *tableau)
- {
- /*=========================================
- * Description : Formate la trame ModBus et envoi la trame creee
- *
- * Created :
- *
- * Notes :
- *=========================================*/
- int variableLocale;
- qint64 nombreOctetsEcris; // variable de vérification pour l'écriture sur le port
- Tableau *bufferEmissionModBus = new Tableau((tableau->longueur * 2) + 9); // + 9 car : 7 octets d'entêtes MODBUS, 2 octets de CRC
- bufferEmissionModBus->elements[0] = adrSlave;
- bufferEmissionModBus->elements[1] = CodeCommande;
- bufferEmissionModBus->elements[2] = adresseData / 256;
- bufferEmissionModBus->elements[3] = adresseData & 255;
- bufferEmissionModBus->elements[4] = nbrData / 256;
- bufferEmissionModBus->elements[5] = nbrData & 255;
- bufferEmissionModBus->elements[6] = nbrData * 2;
- variableLocale = 7;
- for(int i = 0; i < tableau->longueur; i++)
- {
- bufferEmissionModBus->elements[variableLocale] = tableau->elements[i] / 256;
- variableLocale++;
- bufferEmissionModBus->elements[variableLocale] = tableau->elements[i] & 255;
- variableLocale++;
- }
- addCRC16(bufferEmissionModBus,bufferEmissionModBus->longueur - 2); // ajout du CRC sur les deux derniers octets du tableau 'bufferEmissionModBUS'
- nombreOctetsEcris = serialPort->write(bufferEmissionModBus->elements, bufferEmissionModBus->longueur); // écriture sur le port série
- tableauEnvoye = bufferEmissionModBus; //variable à utiliser pour vérifier que l'esclave répond correctement (non implémenté)
- //QMessageBox::information(this,"Ecriture Trame MODBUS", QString::number(nombreOctetsEcris) + " octets ont été écris\nNombre d octet a envoyer : " + QString::number(bufferEmissionModBus->longueur));
- }
- Tableau* Automate::configurationPortCheckBox()
- {
- /*=========================================
- * Description : Prépare et envoi la trame de contrôle (allumage ou
- * extinction) des LEDs de l'automate
- *
- * Created : 26/09/2013 - 11:43
- *
- * Notes :
- *=========================================*/
- Tableau *bufferEmissionPrepare = new Tableau(1);
- bufferEmissionPrepare->elements[0] = 0;
- if(sortieTOR[0] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 1;
- if(sortieTOR[1] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 2;
- if(sortieTOR[2] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 4;
- if(sortieTOR[3] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 8;
- if(sortieTOR[4] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 16;
- if(sortieTOR[5] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 32;
- if(sortieTOR[6] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 64;
- if(sortieTOR[7] == true) bufferEmissionPrepare->elements[0] = bufferEmissionPrepare->elements[0] | 128;
- //QMessageBox::information(this,"etat checkbox",QString::number(bufferEmissionPrepare->elements[0]));
- sendTrameWriteModBus(2, 16, 0, 1, bufferEmissionPrepare); //une fois le tableau créé on doit le formater selon le protocole ModBUS
- return bufferEmissionPrepare; //retour d'un tableau, peut être utile durant le débug
- }
- /*====================================================================================================================================================
- *
- * Partie Gestion CRC16
- *
- *
- *===================================================================================================================================================*/
- void Automate::addCRC16(Tableau *tableau, int longueur)
- {
- /*=========================================
- * Description : Prend en entrée un Tableau
- * Calcul et ajoute à ce tableau deux octets de CRC16
- *
- * Je n'ai pas créé cette fonction, je ne saurais dire comment elle fonctionne
- * Created :
- * Notes :
- *=========================================*/
- long crc16 = 0;
- int boucle1 = 0, boucle2 = 0;
- unsigned char valeurCourante = 0, retenue = 0;
- crc16 = 65535;
- for(boucle1 = 0; boucle1 < longueur; boucle1++)
- {
- valeurCourante = tableau->elements[boucle1];
- crc16 = crc16 ^ valeurCourante;
- for(boucle2 = 0; boucle2 < 8; boucle2++)
- {
- retenue = crc16 % 2;
- crc16 = crc16 / 2;
- if(retenue == 1)
- {
- crc16 = crc16 ^ 40961;
- }
- }
- }
- tableau->elements[longueur] = crc16 % 256;
- tableau->elements[longueur + 1] = crc16 / 256;
- }
- bool Automate::testCRC16(Tableau *tableau, int longueur)
- {
- /*=========================================
- * Description : Vérifie que le CRC16 reçu dans le tableau est conforme
- * au contenu du tableau
- *
- * Je n'ai pas créé cette fonction
- * Je ne saurais dire comment elle fonctionne
- * Created :
- * Notes :
- *=========================================*/
- long crc16 = 0;
- char crc16calcule[2];
- int boucle1 = 0, boucle2 = 0;
- char valeurCourante = 0, retenue = 0;
- crc16 = 65535;
- for(boucle1 = 0; boucle1 < longueur; boucle1++)
- {
- valeurCourante = tableau->elements[boucle1];
- crc16 = crc16 ^ valeurCourante;
- for(boucle2 = 0; boucle2 < 8; boucle2++)
- {
- retenue = crc16 % 2;
- crc16 = crc16 / 2;
- if(retenue == 1)
- {
- crc16 = crc16 ^ 40961;
- }
- }
- }
- crc16calcule[0] = crc16 % 256;
- crc16calcule[1] = crc16 / 256;
- if((crc16calcule[0] == tableau->elements[longueur]) && (crc16calcule[1] == tableau->elements[longueur + 1]))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement