IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Automation Discussion :

Modbus RTU - Communication avec un MeshGate - Linux OpenSuse 10.2


Sujet :

Automation

  1. #1
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut Modbus RTU - Communication avec un MeshGate - Linux OpenSuse 10.2
    Bonjour à tous, je vous expose mon probleme :

    Je suis en train de réaliser un programme en C/C++ sous linux avec kate, permettant l'envoi de trames Modbus au format RTU a un MeshGate, relié en liaison RS232 à mon PC.

    Ce MeshGate est lui-meme en communication avec des "noeuds" par onde radio-électriques, qui mesurent la consommation électrique de divers équipements : Energie active, réactive et apparente ainsi que la tension et l'intensité.

    Tout ce que je souhaite c'est envoyer des trames a cet équipement, ce que je n'arrive pas bien entendu... Les trames sont en hexadecimal, du type suivant

    F7 03 00 01 00 01 90 3C avec

    F7 -> Adresse du peripherique
    03 -> Read/Write
    00 01 -> Registre a interroger
    00 05 -> Longueur
    90 3C -> CRC

    Quelques renseignements sur le matos ici---> http://www.lem.com/hq/fr/content/view/276/304/

    J'utilise une classe RS232 pour la communication qui est deja faite, et dieu sait que c'est bien ennuyeux d'utiliser un source fait par une autre personne que soit

    J'ai bien configuré le port avec minicom aux memes parametres que le peripherique.

    Voici ma classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    //----------------------------------------------------------------------------
    #ifndef	RS232_H
    #define	RS232_H
    
    //----------------------------------------------------------------------------
    #include <stdlib.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <termios.h>
    #include <string.h>
    #include <time.h>
    
    //----------------------------------------------------------------------------
    #define COM1	"/dev/ttyS0"
    #define COM2	"/dev/ttyS1"
    
    //----------------------------------------------------------------------------
    #define BPS9600  9600
    #define BPS19200 19200
    #define BPS57600 57600
    #define BPS115200 115200
    
    //----------------------------------------------------------------------------
    #define BIT8	8
    #define BIT7	7
    
    //----------------------------------------------------------------------------
    #define STOP1	1
    #define STOP2	2
    
    //----------------------------------------------------------------------------
    #define PAS_DE_PARITE  -1
    #define PARITE_PAIRE	  0
    #define PARITE_IMPAIRE  1
    //---------96-------------------------------------------------------------------
    #define AVEC_FINAL	0
    #define SANS_FINAL	1
    
    //----------------------------------------------------------------------------
    #define	AVEC_TIME_OUT	true
    #define	SANS_TIME_OUT	false
    
    //----------------------------------------------------------------------------
    #define OK		        0
    #define ERREUR         	  -1
    #define TIMEOUT	          -2
    #define RIEN_RECU	1
    
    //----------------------------------------------------------------------------
    class tRS232
    	{
    	private:
    		termios Config;
    		char MessageConfigurer[30];
    		int fd;	//Descripteur de fichier
    		int Configurer(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop);
    
       //------------------------------
    	public:
    		tRS232(void);
    		tRS232(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop);
    		~tRS232();
    		void AfficherMessageConfigurer();
    	
    		int EnvoyerOctet(unsigned char Car);
    		int Envoyer(char* pChaine);
    		
    		// Recevoir Nb caracteres
    		int Recevoir(int Nb,char* pChaine);
    		
    		// Recevoir une chaine se terminant par un caractere donne		
                    // (\r, \n ou autre)
    		// avec ou sans time out
    		int Recevoir(char Fin, char* pChaine, int Mode);
    		int Recevoir(char Fin, char* pChaine,int Mode, int Attente);
    	
    		// Recevoir une série de caractees avec time out
    		int RecevoirCaractere(unsigned char* Caractere, int Attente);
    		int returnfd();
       } ;
    
    #endif
    Ainsi que mes fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    #include "tRs232.h"
    
    //-----------------------------------------------------------------------------
    int tRS232::Configurer(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop)
    {
    	int Res;
    	//Ouverture du port série
    	if(!strcmp(pPort, "COM1"))
    		fd = open("/dev/ttyS0",O_RDWR);// | O_NONBLOCK);
    	else if(!strcmp(pPort, "COM2"))
    		fd = open("/dev/ttyS1",O_RDWR );//| O_NONBLOCK);
    	if (fd == -1)
    	{
    		strcpy(MessageConfigurer, "Erreur lors de l'ouverture du port !");
    	   	exit (-1);
       	}
    	else
    	{
    		strcpy(MessageConfigurer, "Ouverture du port reussie.");
    		// Suppression de l'echo
    		Config.c_lflag &= ~(ECHO) ;
    		
    		Config.c_iflag = IGNBRK | IGNPAR;
    		Config.c_oflag = 0;
    		
    		Config.c_cflag = CREAD | CLOCAL;
    	
    		// Vitesse
    		switch (Vitesse)
    		{
    			case BPS9600: 	Config.c_cflag |= B9600;break;
    			case BPS19200: 	Config.c_cflag |= B19200;break;
    			case BPS57600: 	Config.c_cflag |= B57600;break;
    			case BPS115200: Config.c_cflag |= B115200;break;
    			default: 		//fprintf(stderr,"Vitesse non utilisable\n");
    							strcpy(MessageConfigurer, "Vitesse non utilisable !\n");
    							exit (-1);
    		}
    		
    		// Taille data
    		switch (NbBits)
    		{
    			case BIT8: Config.c_cflag |= CS8;break;
    			   case BIT7: Config.c_cflag |= CS7;break;
    			default: 	
    						strcpy(MessageConfigurer, "Taille de donnee non conforme !\n");
    						exit (-1);
    		}
    	
    		// Parite
    		switch (Parite)
    		{
    			case PARITE_PAIRE : Config.c_cflag |=  PARENB; break;
    			   case PARITE_IMPAIRE : Config.c_cflag |= (PARODD | PARENB);break;
    			default : break;
    		}
    		
    		// Nombre de bits de stop
    		switch(NbStop)
    		{
    			case STOP2 : Config.c_cflag |= CSTOPB;break;
    		}
    	
    		// Application de la configuration
    		
    		Res = tcsetattr(fd, TCSANOW, &Config);
    		if (Res == -1)
    		{
    			strcpy(MessageConfigurer, "Erreur lors de l'application de la configuration\n");
    			exit (-1);
    		}
    		tcflush(fd, TCIFLUSH);
    		tcflush(fd, TCOFLUSH);
    	}
    	return 0;
    }
       
    //----------------------------------------------------------------------------
    void tRS232::AfficherMessageConfigurer()
    {
    	printf("%s\n\n", MessageConfigurer);
    }
    
    //----------------------------------------------------------------------------
    tRS232::tRS232(const char* pPort, int Vitesse, int NbBits, int Parite, int NbStop)
    {
       Configurer(pPort,Vitesse,NbBits,Parite,NbStop);
    }
    
    //----------------------------------------------------------------------------
    tRS232::tRS232(void)
    {
       Configurer(COM1,BPS9600,BIT8,PAS_DE_PARITE,STOP1);
    }
    
    //----------------------------------------------------------------------------
    tRS232::~tRS232()
    {
       close(fd);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::EnvoyerOctet(unsigned char Car)
    {
       int Res = write (fd, &Car, 1);
       return (Res);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::Envoyer(char* pChaine)
    {
       int Res = write (fd, pChaine, strlen(pChaine));
       return (Res);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::Recevoir(int Nb, char* pChaine)
    {
    	int i = 0;
    	char Car;
    	int Res;
    	
    	do
    	{
    		Res = read (fd, &Car, 1);
    		if (Res > 0)
    		{
    			pChaine[i] = Car;
    			i++;
    		}
    	} 
    	while (i < Nb);
    	
    	pChaine[i] = '\0';
    	return i;
    }
    
    //----------------------------------------------------------------------------
    int tRS232::Recevoir(char Fin, char* pChaine, int Mode)
    {
    	int i = 0;
    	char Car = 0x00;
    	int Res;
    
    	do
    	{
    		Res = read(fd, &Car, 1);
    		if (Res > 0)
    		{
    			pChaine[i] = Car;
    		   	i++;
    		}
    	} 
    	while (Car != Fin);
    	
    	if (Mode == SANS_FINAL)
    	   i--;
    	
    	pChaine[i] = '\0';
    	tcflush(fd, TCIFLUSH);
    	return i;
    }
    
    //----------------------------------------------------------------------------
    int tRS232::Recevoir(char Fin, char* pChaine, int Mode, int Attente)
    {
    	int i = 0;
    	char Car = 0x00;
    	int Res;
    	time_t TimeRef;
    	time_t Time;
    	
    	TimeRef = time(&TimeRef);
    
    	do
    	{
    		Res = read(fd, &Car, 1);
    		if (Res > 0)
    		{
    			TimeRef = time(&TimeRef);
    			pChaine[i] = Car;
    		   	i++;
    		}
    		
    		Time = time(&Time);
    		if ((Time - TimeRef) >= Attente)
    		{
    			pChaine[i] = '\0';
    			return TIMEOUT;
    		}
    	} 
    	while (Car != Fin);
    	
    	if (Mode == SANS_FINAL)
    	   i--;
    	
    	pChaine[i] = '\0';
    	tcflush(fd, TCIFLUSH);
    	return i;
    }
    
    //----------------------------------------------------------------------------
    int tRS232::RecevoirCaractere(unsigned char* Caractere, int Attente)
    {
    	int Res;
    	unsigned char Car;
    	time_t TimeRef;
    	time_t Time;
    			
    	TimeRef = time(&TimeRef);
    	do
    	{
    		Time = time(&Time);
    		Res = read (fd, &Car, 1);
    	}
    //	while(Res == -1);
    	while((Res <1) && ((Time - TimeRef) < Attente));
    		
    	if (Res > 0)
    	{
    		*Caractere = Car; 
    		return OK;
    	}
    //	return TIMEOUT;
    	return Res;
    }
    
    //-----------------------------------------------------------------------------
    int tRS232::returnfd()
    {
    return fd;
    }
    Ainsi que mon main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include <stdio.h>
    #include <unistd.h>
    #include "tRs232.h"
    #include <iostream>
    using namespace std;
    
    int main(void)
    {
    int b,c,res;
    
    tRS232* instance = new tRS232("COM1", BPS115200, BIT8, PAS_DE_PARITE, STOP1);
    instance -> AfficherMessageConfigurer();
    unsigned char chaine[8] = {0xF7, 0x03, 0x00, 0x01, 0x00, 0x01, 0x90, 0x9C};
    unsigned char chaine2[8]="       ";
    char chaine3[8]="       ";
    
    /*
    int f=open("trame.bin",O_RDWR|O_CREAT,0x777);
    
    cout << "envoi..."<<endl;
    write(f,chaine,8);
    close(f);
    */
    
    for (int i=0; i<8; i++)
    {
    	cout <<"octet "<<i<<" :"<< instance->EnvoyerOctet(chaine[i])<<endl;
    //	if (res!=) break;
    }
    
    cout << "reception ..."<<endl;
    
    for(int a=0; a<8; a++)
    {
    	b = instance->RecevoirCaractere(chaine2+a, 36000000 );
    }
    
    cout << "resultat : " << b <<endl;
    
    for ( int i=0; i<7; i++)
    {	
    	printf("%x ",chaine2[i]);
    }
    
    return 0;
    
    }
    Voici le resultat dans mon terminal, le programme reste dans mon while, il ne recoit apparament rien sur le port serie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    Ouverture du port reussie.
    
    octet 0 :1
    octet 1 :1
    octet 2 :1
    octet 3 :1
    octet 4 :1
    octet 5 :1
    octet 6 :1
    octet 7 :1
    reception ...
    Je remercie d'avance toute personne qui se penchera sur ce probleme. Je vais bientot etre en vacances, et je ne pourrai pas à nouveau disposer du matériel avant le 5 mai
    Nous avons donc du temps pour reflechir ensemble a plusieurs solutions a mon probleme.
    Merci d'avoir pris le temps de lire ce post, si vous avez de la doc a me passer sur ce type de liaison modbus, n'importe quoi, je suis preneur !
    Encore merci

  2. #2
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Hello,

    concernant le calcul du CRC sur la trame que tu donnes en exemple, je ne trouve pas pareil:
    avec les données suivantes: F7 03 00 01 00 01, j'ai C1 5C, au lieu de 90 9C pour toi.
    Peut-on voir ton code de calcul du CRC ?

    Entre la trame et sa décomposition, il y a une différence: la trame indique la lecture de 1 registre, tu dis plus loin que la longueur des données est de 5 (registres). J'ai calculé le CRC avec les deux, je ne trouve pas le même non plus...

    L'équipement avec lequel tu communique a bien l'adresse 247 (F7 dans ta trame) ? C'est compatible avec les spécifications MODBUS, mais c'est inhabituel (pour moi en tout cas).

    Y a-t-il des voyants d'activité de communication sur le MeshGate ?
    Si c'est le cas, ça peut aider à "voir" les trames par le clignotement des leds.

    Sinon, je n'ai pas trouvé de specs techniques sur le MeshGate, en tout cas rien qui décrive la partie MODBUS. As-tu un lien vers la doc ?

  3. #3
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    pour le CRC, c'etait une trame type, donc fausse ... je ne l'ai pas calculé. J'ai des trames préconstruites. F7 est bien l'adresse du meshgate, qui m'a paru inhabituelle pour moi aussi mais qui fonctionne, puisque un logiciel servant a tester l'envoi de trame a été utilisé sous windows par mon professeur pour me montrer le fonctionnement, avec cette meme adresse.

    Il y a 54 registres, et l'on peut en interroger plusieurs en meme temps d'apres la doc.

    J'ai une documentation papier, mais je ne la trouve pas sur le net...
    Il y a bien des voyants sur le meshgate, mais ceux ci signalent uniquement quand le meshgate communique avec le noeud.
    Je n'ai aucun moyen de savoir si ma trame arrive, dans tout les cas la fonction WRITE me dit que celle ci s'est bien passée, meme si rien n'est connecté au port serie. Cela doit etre du a une sorte de tampon au niveau du port.

  4. #4
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    OK.
    Pour tester la communication, peux-tu brancher un PC à la place du MeshGate, et afficher sur celui-ci les données arrivant par la liaison série ?
    Ca permettrait de voir si la requète MODBUS sort bien du port série de la machine sur laquelle tu bosses.
    Pour les trames que tu envoies, peux-tu les poster ici, si tu souhaite qu'on vérifie le format et le CRC ?

  5. #5
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    je le ferai. Comme je le disais, j'aurai a nouveau accès a la machine a la rentrée, vers le 5 mai. Je le ferai donc le plus tôt possible. je posterai également les exemples de trames pré faites.

    J'ai deja testé le port en reliant mon PC avec un autre, en lancant l'hyperterminal. Ce que j'envoyai s'affichais correctement.

    Merci de ton aide !

  6. #6
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    Bonjour a tous !
    De retour de vacances, il faut se remettre au travail ! Mon cher professeur m'a donc aidé en me donnant un petit programme de ce qu'il faut que je fasse, mais celui ci utilise des fonctions "fossil", pour passer par un SC12, le voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    /***************************************************************************
    * Module:     	serie.c
    		Emission / Reception  d'une chaine de caracteres
    *
    /***************************************************************************/
    
    // Includes
    /***************************************************************************/
    #include <stdio.h>
    #include <dos.h>
    #include "clib.h"
    /***************************************************************************/
    
    void Envoi(unsigned char *buffer);
    void Recept(unsigned char *buffer);
    
    unsigned char buffer_1[255];
    /***************************************************************************/
    // Main
    /***************************************************************************/
    int main (void)
    {
    unsigned char buffer_2[] ={0xF7,0x03,0x00,0x00,0x00,0x01,0x90,0x9C};
    int port=0, parity=0,wordlen=8,stopbits=1;
    FOS_FLOW_CTRL flowctrl=FOSSIL_FLOWCTRL_OFF;
    long baudrate=115200L;
    
    fossil_init(port);
    fossil_setbaud(port, baudrate, parity, wordlen, stopbits);
    fossil_purge_input(port);
    fossil_set_flowcontrol(port, flowctrl);
    
    Envoi(buffer_2);
    Recept(buffer_1);
    
    fossil_purge_input(port);
    fossil_purge_output(port);
    fossil_deinit(port);
    return(0);
    }
    
    
    /***************************************************************************
    * Fonction:    	Envoi.c
    		Envoi une chaine de caracteres
    *
    /***************************************************************************/
    
    void Envoi(unsigned char *buffer)
    {
    int port=0,i;
    for(i=0;i<8;i++)
    {
    	fossil_putbyte (port,buffer[i]);
    	while((0x40 & fossil_status_request ( port ))!= 0x40);
    }
    while((0x40 & fossil_status_request ( port ))!=0x40);
    RTX_Sleep_Time(3);
    }
    
    
    
    /***************************************************************************
    * Fonction:    	Recept.c
    		Reception d'une chaine de caracteres
    *
    /***************************************************************************/
    
    void Recept(unsigned char *buffer)
    {
    int port=0,i=-1;
    for(i=0;i<7;i++)
    {
    while((fossil_status_request (port) & 0x01) != 0x01);
    *(buffer+i)=(unsigned char)fossil_getbyte ( port);
    }
    printf("la trame est :");
    for(i=0;i<7;i++)
    {
    printf("- %d",buffer[i]);
    }
    printf("\n");
    }
    Franchement, j'ai beau jeter un oeil à l'API, je ne comprends pas comment tout adapter.
    J'ai retrouvé la doc du MeshGate au format PDF, que je peux vous envoyer si besoin est.
    Merci du temps que vous y consacrez

  7. #7
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Hello,

    Quelques questions:
    1 - le SC12, c'est bien ce type de produit ?

    2 - le code serie.c que ton prof donne est éxécuté par le SC12 ? Et ce programme communique bien avec le MeshGate, on récupère des données cohérentes ?
    Ce qui me surprend, c'est que la requète pour récupérer les données, dans ce code, est définie "en dur" (tableau buffer_2[]), ça a tout de la requète MODBUS RTU (celle que tu avais indiquée dans ton premier post), mais le CRC défini ici ne correspond pas avec celui que je calcule de mon côté (0xC1 0x5C pour moi, au lieu de 0x90 0x9C dans serie.c). Du coup:

    3 - Y-aurait-il quelqu'un pour vérifier ce CRC qui me parait louche (ce serait bien de lever ce doute).

    4 - Si je comprends bien, le système peut se présenter comme cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    [ PC sous GNU/Linux ]        [  MeshGate   ]
    [       /dev/ttyS0 =]--------[= port série ]
    avec le protocole MODBUS sur la liaison série.

    5 - As-tu mis un PC à la place du MeshGate, pour voir les trames envoyées par le PC Linux ?

  8. #8
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    Bonjour a toi !

    1/ Oui c'est ce type de produit, c'est d'ailleurs le meme constructeur

    2/ Ce programme est apparament bel est bien executé par le sc12, je ne l'ai pas vu de mes propres yeux malheureusement, mo professeur me l'a juste donné. Je vais essayer d'en degoter un pour le tester.

    3/ Je vais le recalculer ce CRC, il est bien embêtant ^^ Si d'autre le font, c'est pas mal non plus =)

    4/ Ton schéma est juste, c'est tout a fait ca ! avec le protocole MODBUS en RTU.

    5/J'ai branché un pc a la place du meshgate pour tester si les ports sont en etat de marche, mais avec hyperterminal sous windows. Je vais le faire cet apres-midi =) Je tiens au courant

    edit: J'ai testé en remplacant le meshgate par un pc, j'obitens les caracteres ascii ( des "environs égal", un coeur ... ) qui correspondent a F7 03 etc... donc ma trame ! Je ne visualise par contre pas les zeros car ils correspondent a rien en symbole ^^

    2eme edit : J'ai entierement recomencé mon programme pour que ca soit plus clair.


    Mon main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include "newRs232.h"
    #include <iostream>
    using namespace std;
    
    int main (void)
    {
    
    unsigned char buffer_1[15];
    unsigned char buffer_2[] ={0xF7,0x03,0x00,0x00,0x00,0x01,0x90,0x9C};
    tRS232* instance = new tRS232("COM1",BPS115200,BIT8,PAS_DE_PARITE,STOP1);
    instance->AfficherMessageConfigurer();
    
    for(int i=0;i<8;i++)
    {
    	instance->EnvoyerOctet(buffer_2[i]);
    }
    
    cout << "Envoi effectué." <<endl << "Reception :"<<endl;
    
    for(int a=0;a<8;a++)
    {
    	instance->RecevoirCaractere(buffer_1[a], 5);
    }
    
    cout << "Trame recue : ";
    for(int b=0;b<10;b++)
    {
    	printf("%x ", buffer_1[b]);
    }
    
    return(0);
    
    }
    Ma classe et ses fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    //----------------------------------------------------------------------------
    #ifndef	RS232_H
    #define	RS232_H
    
    //----------------------------------------------------------------------------
    #include <stdlib.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <termios.h>
    #include <string.h>
    #include <time.h>
    #include <signal.h>
    
    //----------------------------------------------------------------------------
    #define COM1	"/dev/ttyS0"
    #define COM2	"/dev/ttyS1"
    
    //----------------------------------------------------------------------------
    #define BPS9600  9600
    #define BPS19200 19200
    #define BPS57600 57600
    #define BPS115200 115200
    
    //----------------------------------------------------------------------------
    #define BIT8	8
    #define BIT7	7
    
    //----------------------------------------------------------------------------
    #define STOP1	1
    #define STOP2	2
    
    //----------------------------------------------------------------------------
    #define PAS_DE_PARITE  -1
    #define PARITE_PAIRE	  0
    #define PARITE_IMPAIRE 1
    //---------96-------------------------------------------------------------------
    #define AVEC_FINAL	0
    #define SANS_FINAL	1
    
    //----------------------------------------------------------------------------
    #define	AVEC_TIME_OUT	true
    #define	SANS_TIME_OUT	false
    
    //----------------------------------------------------------------------------
    #define OK		0
    #define ERREUR 	-1
    #define TIMEOUT	-2
    #define RIEN_RECU	1
    
    //----------------------------------------------------------------------------
    class tRS232
    	{
    
    	private:
    		termios Config;
    		char MessageConfigurer[30];
    		int fd;	//Descripteur de fichier
    		int Configurer(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop);
    
    	public:
    		tRS232(void);
    		tRS232(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop);
    		~tRS232();
    		void AfficherMessageConfigurer();
    		
                    // Envoyer un caractere 
    		int EnvoyerOctet(unsigned char Car);
    		// Recevoir des caracteres avec timeout
    		int RecevoirCaractere(unsigned char Caractere, int Attente);
    		int returnfd();
    };
    
    void tRS232_alarm(int t);
    static bool tRS232_continuer;
    
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    #include "newRs232.h"
    
    //-----------------------------------------------------------------------------
    int tRS232::Configurer(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop)
    {
    	int Res;
    	//Ouverture du port série
    	if(!strcmp(pPort, "COM1"))
    		fd = open("/dev/ttyS0",O_RDWR);// | O_NONBLOCK);
    	else if(!strcmp(pPort, "COM2"))
    		fd = open("/dev/ttyS1",O_RDWR );//| O_NONBLOCK);
    	if (fd == -1)
    	{
    		strcpy(MessageConfigurer, "Erreur lors de l'ouverture du port !");
    	   	exit (-1);
       	}
    	else
    	{
    		strcpy(MessageConfigurer, "Ouverture du port reussie.");
    		
    		// Suppression de l'echo
    		Config.c_lflag &= ~(ECHO) ;
    		// Suppression du controle de flux
    		Config.c_iflag &= ~(IXON|IXOFF|IXANY);
    
    		Config.c_iflag = IGNBRK | IGNPAR;
    		Config.c_oflag = 0;
    		Config.c_cflag = CREAD | CLOCAL;
    	
    		// Vitesse
    		switch (Vitesse)
    		{
    			case BPS9600: 	Config.c_cflag |= B9600;break;
    			case BPS19200: 	Config.c_cflag |= B19200;break;
    			case BPS57600: 	Config.c_cflag |= B57600;break;
    			case BPS115200: Config.c_cflag |= B115200;break;
    			default: 		//fprintf(stderr,"Vitesse non utilisable\n");
    			
    			strcpy(MessageConfigurer, "Vitesse non utilisable !\n");
    			exit (-1);
    		}
    		
    		// Taille data
    		switch (NbBits)
    		{
    			case BIT8: Config.c_cflag |= CS8;break;
    			case BIT7: Config.c_cflag |= CS7;break;
    			default: 	
    			strcpy(MessageConfigurer, "Taille de donnee non conforme !\n");
    			exit (-1);
    		}
    	
    		// Parite
    		switch (Parite)
    		{
    			case PARITE_PAIRE : Config.c_cflag |=  PARENB; break;
    			case PARITE_IMPAIRE : Config.c_cflag |= (PARODD | PARENB);break;
    			default : break;
    		}
    		
    		// Nombre de bits de stop
    		switch(NbStop)
    		{
    			case STOP2 : Config.c_cflag |= CSTOPB;break;
    		}
    	
    		// Application de la configuration
    		Res = tcsetattr(fd, TCSANOW, &Config);
    		if (Res == -1)
    		{
    			strcpy(MessageConfigurer, "Erreur lors de l'application de la configuration\n");
    			exit (-1);
    		}
    		tcflush(fd, TCIFLUSH);
    		tcflush(fd, TCOFLUSH);
    	}
    	return 0;
    }
       
    //----------------------------------------------------------------------------
    void tRS232::AfficherMessageConfigurer()
    {
    	printf("%s\n\n", MessageConfigurer);
    }
    
    //----------------------------------------------------------------------------
    tRS232::tRS232(const char* pPort, int Vitesse, int NbBits, int Parite, int NbStop)
    {
       Configurer(pPort,Vitesse,NbBits,Parite,NbStop);
    }
    
    //----------------------------------------------------------------------------
    tRS232::tRS232(void)
    {
       Configurer(COM1,BPS9600,BIT8,PAS_DE_PARITE,STOP1);
    }
    
    //----------------------------------------------------------------------------
    tRS232::~tRS232()
    {
       close(fd);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::EnvoyerOctet(unsigned char Car)
    {
       int Res = write (fd, &Car, 1);
       return (Res);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::RecevoirCaractere(unsigned char Caractere, int Attente)
    {
    
    	int n;
    	tRS232_continuer = true;
    	signal(SIGALRM, tRS232_alarm);
    	alarm(Attente);
    
    	/* Boucle de lecture */
    	while(tRS232_continuer)
    	{
    		if(read(fd,&Caractere,1) == 1)
    		return(1);
    	}
    
    }
    
    //-----------------------------------------------------------------------------
    int tRS232::returnfd()
    {
    return fd;
    }
    
    //----------------------------------------------------------------------------
    void tRS232_alarm(int t)
    {
    	tRS232_continuer = false;
    }
    J'obtiens ca dans mon terminal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    lemare@lv217 [/home/commun/DOSSIER LEMARE THEME/Projet_bts_energie/Eleve_1]
    $ ./a.out
    Ouverture du port reussie.
    
    Envoi effectué.
    Reception:
     -> 1
     -> 1
     -> 1
     -> 1
     -> 1
     -> 1
     -> 1
     -> 0
    Trame recue : 7a f0 b7 45 3c d9 b7 48 ab e4
    Tout les "1" signifie que ma fonction read arrive a lire quelque chose sur le port, mais j'ai rien de correct dans mon tableau à la reception. J'ai remplacé le CRC par celui que tu as calculé et la j'obtiens que des 0, donc encore pire je n'ai pas de reponse . Apparament la j'en ai une \o/

    Dans tout les cas, j'arrive a ecrire sur le port meme s'il y a rien de connecté.
    Donc je pense que ma trame est maintenant correcte, de plus je gere maintenant mon timeout avec un signal d'alarme donc je suis sur de recevoir quelque chose puisqu'il n'arrive jamais a bout. C'est peut etre a la copie dans le tableau que sa plante.

    Merci a toi !

  9. #9
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Donc, la requète part bien du PC.
    Reste la réception de données, si le MeshGate répond.
    Avec hyperterminal, as-tu essayé de taper quelques caractères ? Si ton programme reçoit quelque chose, tu devrais les retrouver dans la trame reçue.

    Ca pourrait être bien d'initialiser buffer_1[], pour voir si ça n'affiche que des 0 ou bien des octets différents, qui seraient donc renvoyés par le MeshGate.


    Au passage, Laurent LOPES propose, depuis plusieurs années déjà, une bibliothèque dynamique, sous GNU/Linux, pour le protocole MODBUS: http://pes.free.fr/.
    C'en est toujours à la version 0.0.1, probablement plus maintenue, mais ça peut être une bonne lecture.
    De mémoire, il n'a implémenté que les fonctions de lecture / écriture de registres, mais c'est juste ce dont tu aurais besoin, si j'ai bien compris (désolé de réagir si tard là-dessus, si tu n'avais pas vu cette lib).

  10. #10
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    Quand je l'initialise j'obtiens ca ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    lemare@lv217 [/home/commun/DOSSIER LEMARE THEME/Projet_bts_energie/Eleve_1]
    $ ./a.out
    Ouverture du port reussie.
    
    Envoi effectué.
    Reception:
     -> 1
     -> 1
     -> 1
     -> 1
     -> 1
     -> 1
     -> 1
    Trame recue : 0 0 0 0 0 0 0 0 0 0
    rien du tout dans le buffer :'(
    Je connaissais cette lib, j'ai deja regardé. En ce qui concerne le logiciel, je ne l'ai pas testé, je n'ai pas réussi a l'installer, j'ai deja du corriger des lignes dans son programme, il me mettait des erreurs quand je fesais le make ... :/ De plus j'ai pas la librairie de gnome et j'arrive pas à l'installer, je suis sous KDE...
    Je vais jetter quand meme un coup d'oeil aux fichiers sources.

    Quel idiot, j'ai meme pas regardé ce qui se passait si je tappais avec l'autre pc, si mon "read" recevait quelque chose ... il va etre 18h, je pourrais revenir jeudi aprem pour le projet, je le ferai surement la.

    Encore merci a toi pour ton aide !

  11. #11
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Hello,

    bon, désolé, je viens de recalculer le CRC de la trame définie dans ton code: je trouve bien 0x90 0x9C. Celui-ci est bon.

    La sortie de ton programme indique que 7 octets sont recus: La trame émise est donc valide et gérée par le MeshGate, et la longueur de la réponse est cohérente, vu que la requète envoyée demande la valeur d'un registre, la réponse du MeshGate fera bien 7 octets (0xF7 0x03 0x02 0xXX 0xYY 0xZZ 0xZZ, avec 0xXX 0xYY la valeur du registre demandé sur deux octets, et 0xZZ 0xZZ la valeur du CRC, dépendant bien sûr du contenu de la trame de réponse).

    Tu n'en est donc plus très loin ! Reste plus qu'à récupérer les données reçues dans buffer_1[].
    Ne pas oublier de recalculer le CRC de la trame reçue, pour vérifier sa validité

    Bon courage !

  12. #12
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    HOURRA !!!

    J'ai trouvé l'erreur apres avoir refait le programme en entier, je me trompais apparament dans le passage du caractere de la fonction, je ne renvoyais pas le caractere recu dans le main, cette valeur disparaissait apres l'appel de la fonction, dans le neant ... :p

    Du coup revoici mon programme terminé !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    #include "newRs232.h"
    #include <iostream>
    using namespace std;
    
    int main (void)
    {
    
    unsigned char buffer_1[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    unsigned char buffer_2[] ={0xF7,0x03,0x00,0x00,0x00,0x01,0x90,0x9C};
    int b;
    tRS232* instance = new tRS232("COM1",BPS115200,BIT8,PAS_DE_PARITE,STOP1);
    instance->AfficherMessageConfigurer();
    
    for(int i=0;i<8;i++)
    {
    	instance->EnvoyerOctet(buffer_2[i]);
    }
    
    cout << "Envoi effectué." <<endl;
    
    for(int a=0;a<8;a++)
    {
    	b=instance->RecevoirCaractere(buffer_1[a], 2);
    	cout <<"-> " << b << endl;
    }
    
    cout << "Trame recue : ";
    for(int b=0;b<10;b++)
    {
    	printf("%x ", buffer_1[b]);
    }
    
    return(0);
    
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    //----------------------------------------------------------------------------
    #ifndef	RS232_H
    #define	RS232_H
    
    //----------------------------------------------------------------------------
    #include <stdlib.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <termios.h>
    #include <string.h>
    #include <time.h>
    #include <signal.h>
    
    //----------------------------------------------------------------------------
    #define COM1	"/dev/ttyS0"
    #define COM2	"/dev/ttyS1"
    
    //----------------------------------------------------------------------------
    #define BPS9600  9600
    #define BPS19200 19200
    #define BPS57600 57600
    #define BPS115200 115200
    
    //----------------------------------------------------------------------------
    #define BIT8	8
    #define BIT7	7
    
    //----------------------------------------------------------------------------
    #define STOP1	1
    #define STOP2	2
    
    //----------------------------------------------------------------------------
    #define PAS_DE_PARITE  -1
    #define PARITE_PAIRE	  0
    #define PARITE_IMPAIRE 1
    //---------96-------------------------------------------------------------------
    #define AVEC_FINAL	0
    #define SANS_FINAL	1
    
    //----------------------------------------------------------------------------
    #define	AVEC_TIME_OUT	true
    #define	SANS_TIME_OUT	false
    
    //----------------------------------------------------------------------------
    #define OK		0
    #define ERREUR 	-1
    #define TIMEOUT	-2
    #define RIEN_RECU	1
    
    //----------------------------------------------------------------------------
    class tRS232
    	{
    	private:
    		termios Config;
    		char MessageConfigurer[30];
    		int fd;	//Descripteur de fichier
    		int Configurer(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop);
    
    	public:
    		tRS232(void);
    		tRS232(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop);
    		~tRS232();
    		void AfficherMessageConfigurer();
    	
    		// Envoyer un caractere 
    		int EnvoyerOctet(unsigned char Car);
    
    		// Recevoir des caracteres avec timeout
    		int RecevoirCaractere(unsigned char &Caractere, int Attente);
    		int returnfd();
    };
    
    void tRS232_alarm(int t);
    static bool tRS232_continuer;
    
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    #include "newRs232.h"
    
    //-----------------------------------------------------------------------------
    int tRS232::Configurer(const char* pPort,int Vitesse,int NbBits,int Parite,int NbStop)
    {
    	int Res;
    	//Ouverture du port série
    	if(!strcmp(pPort, "COM1"))
    		fd = open("/dev/ttyS0",O_RDWR | O_NONBLOCK); 
    	else if(!strcmp(pPort, "COM2"))
    		fd = open("/dev/ttyS1",O_RDWR | O_NONBLOCK);
    	if (fd == -1)
    	{
    		strcpy(MessageConfigurer, "Erreur lors de l'ouverture du port !");
    	   	exit (-1);
       	}
    	else
    	{
    		strcpy(MessageConfigurer, "Ouverture du port reussie.");
    		
    		// Suppression de l'echo
    		Config.c_lflag &= ~(ECHO) ;
    		// Suppression du controle de flux
    		Config.c_iflag &= ~(IXON|IXOFF|IXANY);
    
    		Config.c_iflag = IGNBRK | IGNPAR;
    		Config.c_oflag = 0;
    		Config.c_cflag = CREAD | CLOCAL;
    	
    		// Vitesse
    		switch (Vitesse)
    		{
    			case BPS9600: 	Config.c_cflag |= B9600;break;
    			case BPS19200: 	Config.c_cflag |= B19200;break;
    			case BPS57600: 	Config.c_cflag |= B57600;break;
    			case BPS115200: Config.c_cflag |= B115200;break;
    			default: 		//fprintf(stderr,"Vitesse non utilisable\n");
    			
    			strcpy(MessageConfigurer, "Vitesse non utilisable !\n");
    			exit (-1);
    		}
    		
    		// Taille data
    		switch (NbBits)
    		{
    			case BIT8: Config.c_cflag |= CS8;break;
    			case BIT7: Config.c_cflag |= CS7;break;
    			default: 	
    			strcpy(MessageConfigurer, "Taille de donnee non conforme !\n");
    			exit (-1);
    		}
    	
    		// Parite
    		switch (Parite)
    		{
    			case PARITE_PAIRE : Config.c_cflag |=  PARENB; break;
    			case PARITE_IMPAIRE : Config.c_cflag |= (PARODD | PARENB);break;
    			default : break;
    		}
    		
    		// Nombre de bits de stop
    		switch(NbStop)
    		{
    			case STOP2 : Config.c_cflag |= CSTOPB;break;
    		}
    	
    		// Application de la configuration
    		Res = tcsetattr(fd, TCSANOW, &Config);
    		if (Res == -1)
    		{
    			strcpy(MessageConfigurer, "Erreur lors de l'application de la configuration\n");
    			exit (-1);
    		}
    		tcflush(fd, TCIFLUSH);
    		tcflush(fd, TCOFLUSH);
    	}
    	return 0;
    }
       
    //----------------------------------------------------------------------------
    void tRS232::AfficherMessageConfigurer()
    {
    	printf("%s\n\n", MessageConfigurer);
    }
    
    //----------------------------------------------------------------------------
    tRS232::tRS232(const char* pPort, int Vitesse, int NbBits, int Parite, int NbStop)
    {
       Configurer(pPort,Vitesse,NbBits,Parite,NbStop);
    }
    
    //----------------------------------------------------------------------------
    tRS232::tRS232(void)
    {
       Configurer(COM1,BPS9600,BIT8,PAS_DE_PARITE,STOP1);
    }
    
    //----------------------------------------------------------------------------
    tRS232::~tRS232()
    {
       close(fd);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::EnvoyerOctet(unsigned char Car)
    {
       int Res = write (fd, &Car, 1);
       return (Res);
    }
    
    //----------------------------------------------------------------------------
    int tRS232::RecevoirCaractere(unsigned char &Caractere, int Attente)
    {
    
    	int n;
    	tRS232_continuer = true;
    
    	signal(SIGALRM, tRS232_alarm);
    	alarm(Attente);
    
    	/* Boucle de lecture */
    	while(tRS232_continuer)
    	{
    		if(read(fd,&Caractere,1) == 1)
    		return(1);
    	}
    
    	return(0);
    }
    
    //-----------------------------------------------------------------------------
    int tRS232::returnfd()
    {
    return fd;
    }
    
    //----------------------------------------------------------------------------
    void tRS232_alarm(int t)
    {
    	tRS232_continuer = false;
    }
    En guise de guide pour les utilisateurs de modbus RTU je laisse ce code a disposition, vous pourrez vous en inspirer !!
    J'obtiens ceci en resultat dans le terminal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    lemare@lv217 [/home/commun/DOSSIER LEMARE THEME/Projet_bts_energie/Eleve_1]
    $ ./a.out
    Ouverture du port reussie.
    
    Envoi effectué.
    -> 1
    -> 1
    -> 1
    -> 1
    -> 1
    -> 1
    -> 1
    -> 0
    Trame recue : f7 3 2 6f 6f 1d 8d 0 0 0
    Merci a toi poildur, merci pour tout !
    Maintenant, l'etape suivante est de construire les trames en dynamique, ca va etre un travail long et fastidieux, mais je pense m'en sortir ! Je reposterai ici si besoin est, Bonne journée !

  13. #13
    Membre habitué
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 90
    Points : 126
    Points
    126
    Par défaut
    Félicitations

    Je n'y pense que maintenant, mais tu as peut-être déjà consulté les spécifications du protocole, dispos ici: Modbus-IDA Technical Resources : Modbus specifications ?
    Ces quelques PDF décrivent le protocole en détail (et en anglais :/), dont le calcul du CRC16, en Modbus RTU, et aussi une approche de la façon d'implémenter tout ça (sachant que, côté "maitre modbus", on peut se permettre quelques simplifications).

    Merci d'avoir posté ton code-qui-marche, ça pourra sûrement servir à d'autres.
    Au fait, ton programme est juste un exercice, ou bien il est destiné à être utilisé en production ?
    Ce sera sous quelle licence ?

  14. #14
    Membre actif
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2009
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2009
    Messages : 186
    Points : 206
    Points
    206
    Par défaut
    L'anglais me derange pas, ca fait dix ans que j'en fait =)
    Oui j'ai deja jeté un petit coup d'oeil la dessus

    Voici une fonction pour calculer le CRC16, qui marche fort bien !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    unsigned int Crc16(unsigned char *Adresse_tab , unsigned char Taille_max)
    {
    unsigned int Crc = 0xFFFF;
    unsigned int Polynome = 0xA001;
    unsigned char CptOctet = 0;
    unsigned char CptBit = 0;
    unsigned char Parity= 0;
    
    Crc = 0xFFFF;
    // Polynôme = 2^15 + 2^13 + 2^0 = 0xA001.
    Polynome = 0xA001; 
    
    for ( CptOctet= 0 ; CptOctet < Taille_max ; CptOctet++)
    {
          //Ou exculsif entre octet message et CRC
            Crc ^= *( Adresse_tab + CptOctet); 
    
    // Mise a 0 du compteur nombre de bits
    for ( CptBit = 0; CptBit <= 7 ; CptBit++) 
    {
    
             Parity= Crc
             // Décalage a droite du crc;
             Crc >>= 1; 
             // Test si nombre impair -> Apres decalage à droite il y aura une retenue
             if (Parity%2 == true) Crc ^= Polynome; 
    } // "ou exclusif" entre le CRC et le polynome generateur.
    
    }
    return(Crc);
    }
    ATTENTION cependant, la taille maximale de la chaine a transmettre est dans unsigned char Mais fonctionne parfaitement ! Le resultat est donné à l'envers, par exemple si le CRC est 0x90 0x9C, dans le "int" il en sera 0x9c 0x90 ( inversion poids fort poids faible )

    Le programme est libre, vous pouvez tous vous en inspirer. Il est destiné a une utilisation professionelle, mais dans notre projet, ne sera pas utilisé par une entreprise, donc si je peut aidre, il n'y a aucun probleme, je commence a connaitre un peu Modbus ! ^^

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 01/12/2013, 14h35
  2. Réponses: 10
    Dernier message: 09/04/2010, 09h24
  3. Communication avec un server LINUX - UNIX
    Par snoopy69 dans le forum Windows Vista
    Réponses: 0
    Dernier message: 09/01/2008, 21h02
  4. Communication avec un automate TCP/IP Modbus
    Par Baxter67 dans le forum C++Builder
    Réponses: 5
    Dernier message: 20/12/2007, 12h00
  5. Communication avec ModBus/TCP
    Par fabou3377 dans le forum Langage
    Réponses: 1
    Dernier message: 18/11/2006, 00h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo