[Qt][ModBus TCP] Reception d'une trame modbus

Signaler
Messages postés
1
Date d'inscription
mercredi 2 décembre 2009
Statut
Membre
Dernière intervention
3 mai 2010
-
Messages postés
1
Date d'inscription
mardi 8 juin 2010
Statut
Membre
Dernière intervention
29 juin 2010
-
Bonjour à tous,

J'effectue dans le cadre de mon BTS un projet portant sur ModBus.

Le but est de codé un module de communication avec un Automate de type Twido de la marque Télémécanique, J'utilise le protocole ModBus TCP afin de dialoguer entre mon PC(sous Windows XP) et l'automate. Le Twido est relié à une panoplie de capteurs il effectue des relevés seul et constamment, mon but est d'interrogé l'automate afin de récupérer les résultats, ou changé l'état d'un registre.

Mon problème est le suivant :
J'arrive à envoyer une trame à l'automate, j'utilise un analyseur de réseaux afin de le vérifier. Cependant je ne réussi pas à réceptionné les trames de l'automate.
J'ai testé plusieurs solution, et cherché un bon moment, mais je n'y arrive pas.

Le principe de mon programme est simple :
- on a une petite fenêtre permettant la connexion à l'automate par TCP
- on rempli des champs permettant de choisir les paramètres de la trame désiré
- puis un bouton d'envoi.
- après l'envoi de la trame un slot recherche une réponse de l'automate
- lorsqu'une réponse est trouvé on la stock dans une variable
- et enfin on traite la réponse.

Voici quelque partis de code portant sur l'envoi et la réception.

// Code du fichier source
#include "modbus.h"
#include "ui_modbus.h"

// CONSTRUCTEUR DU MODBUS
ModBus::ModBus(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::ModBus)
{
    ui->setupUi(this);

    header[0]=00; // Reset des identifiant de transaction.
    header[1]=01;

    ModBus::connect(&Socket,SIGNAL(readyRead()),this,SLOT(recept())); // Detecte les réponses de l'automate
}

// FONCTION DE CONSTRUCTION DE LA TRAME MODBUS
void ModBus::constTrame()
{

    header[2]=00; // Protocol ModBus.
    header[3]=00;

    header[4]=00; // Longueur de trame de requête.
    header[5]=06;

    pdu[0]=01; // Identifiant de l'esclave, vu qu'il n'y a que 1 esclave : egale à 1.
    switch(ui->Cb_fonction->currentIndex())
    {
        case 0:{pdu[1]=01;} // Fonction lecture coil
            break;
        case 1:{pdu[1]=03;} // Fonction lecture registre
            break;
        case 2:{pdu[1]=05;} // Fonction ecriture coil
            break;
        case 3:{pdu[1]=06;} // Fonction ecriture registre
            break;
        default :{qDebug()<<"Mauvaise fonction choisis"<<endl;}
            break;
    }

    // Adresse
    pdu[2]=ui->Sb_adress->value()>>8;
    pdu[3]=ui->Sb_adress->value()&0x00ff;

    // Donnee
    pdu[4]=ui->Sb_data->value()>>8;
    pdu[5]=ui->Sb_data->value()&0x00ff;

}


// SLOT D'ENVOI DE LA TRAME
void ModBus::on_Bt_Send_clicked()
{
    QDataStream out(&Socket);

    constTrame();

    qDebug()<<"Envoie d'une trame ModBus"<<endl;
    qDebug()<<"    - envoi de l'header"<<endl; // Ecriture dans le debug
    for(int i=0;i<6;i++){
        out<<header[i]; // Envoi de la trame
    }

    qDebug()<<"    - envoi du pdu"<<endl; // Ecriture dans le debug
    for(int i=0;i<6;i++){
        out<>rcvTrame;
    bool *ok;
    if(rcvTrame!="")
    {

        for(int i=0;i<6;i++)
        {
            //header[i]=rcvTrame.toUInt(*ok,10);
        }
    qDebug()<<"    - copie de l'header"<<endl;
        for(int i=6;i<rcvTrame.size();i++)
        {
            pdu[i]=rcvTrame[i];
        }
    qDebug()<<"    - copie du pdu"<<endl;
    qDebug()<<"    - fin de reponse"<<endl;
    }else{
        qDebug()<<"erreur : réponse vide"<<endl;;
    }
}

// Code du fichier d'entête
#ifndef MODBUS_H
#define MODBUS_H

#include <QtGui/QMainWindow>// Utiliser pour défnir la fenêtre
#include <QTcpSocket>       // Utilisation des socket TCP
#include <QDataStream>      // Utilisation des data stream pour envoyer les data et en recevoir
#include <QString>          // Utilisation des chaines de caractère version Qt
#include <QBitArray>        // Utilisation des tableaux d'octects.
#include <QDebug>           // Utilisation d'une console de debugage

namespace Ui
{
    class ModBus;
}

class ModBus : public QMainWindow
{
    Q_OBJECT

public:
    ModBus(QWidget *parent = 0);
    ~ModBus();

private:
    Ui::ModBus *ui;

    QTcpSocket Socket; // socket TCP utiliser pour la connection

    quint8 header[6]; // Contient l'header TCP utiliser pour la trame ModBus
    quint8 pdu[6]; // Contient les information de la trame ModBus
    quint8 headerR[]; // Contient l'header TCP de réponse de l'automate
    quint8 pduR[];// Contient les information de réponse de la trame ModBus, sa longueur peut varier
    QByteArray rcvTrame;

    // Lié à l'interface


private slots:
    void on_Bt_Send_clicked(); // Slot du bouton d'envoie de trame
    void constTrame(); // Fonction de construction de la trame
    void recept(); // Fonction de reception des données envoyer par l'automate
};

#endif // MODBUS_H


J'ai essayer le QBitArray / QByteArray / QString cependant cela n'a rien données, il est possible que je les ai mal utilisé. Je cherche des piste pour savoir comment réceptionné ses trames ou alors des exemples.

Cordialement,
Mayojiko

2 réponses

Messages postés
1
Date d'inscription
mercredi 23 juin 2010
Statut
Membre
Dernière intervention
23 juin 2010
1
Bonjour, as tu trouvé comment résoudre ton souci car j'ai sensiblement le même...
Merci d'avance!
Messages postés
1
Date d'inscription
mardi 8 juin 2010
Statut
Membre
Dernière intervention
29 juin 2010
1
Bonjour,
Je suis aussi dans le même cas que vous. J'ai un automate TWIDO et je dois lui envoyer et recevoir des infos de celui-ci. J'ai tester un soft en C# (le langage que j'utilise pour mon projet) mais lors de la connection celui-ci m'envoi un illegal data adresse..... J'aimerais donc savoir si l'un de vous à avancer ou aurai des pistes à me conseiller