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

Objective-C Discussion :

Composition et Envoi de Trame Modbus


Sujet :

Objective-C

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Composition et Envoi de Trame Modbus
    Bonjour à tous,

    Dans le cadre d'un projet universitaire, trois collègues et moi même avons pour projet de réaliser un échange d'informations entre un iDevice et un automate Schneider M340. Nous sommes plus ou moins novices dans le domaine de la programmation, voila pourquoi nous éprouvons quelques difficultés.

    Quand je parle d'échange d'informations, je veux dire que nous cherchons à échanger des trames Modbus avec l'automate afin de lire ou écrire une valeur dans un mot %MW de l'automate.

    Voici donc le bout de code pour former et envoyer cette trame:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //Trame
            Trame=[NSString stringWithFormat:@"\x00\x00\x00\x00\x00\x06\x01\x06\x01\x09\x00\x08];
     //Adresse du registre en rouge
    //Valeur du registre en vert
            
            NSLog(@"Le texte est %@",Trame);
            Info.text = [NSString stringWithFormat:@"%@%@%@",Info.text, Trame, @"\r"];
            
            //Envoie de la trame
        NSData *data = [[NSData alloc] initWithData:[Trame dataUsingEncoding:NSASCIIStringEncoding]];
           Info.text = [NSString stringWithFormat:@"%@%@%@",Info.text, data, @"\r"];
            [outputStream write:[data bytes] maxLength:[data length]];
    La trame est en hexadécimal. Lorsque que j'écris la trame manuellement comme ci-dessus, la valeur data envoyée à l'automate (visible dans le log) est <00000000 00060106 01090018>

    Cependant, je souhaite pas écrire ma trame en dur à chaque fois mais plutôt récupérer mes données d'adresse et de valeur du mot de l'automate depuis une variable. (Je ne sais pas si je suis très clair)

    Voici le code en ajoutant les deux variables à la fin de la trame :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //Trame
            Trame=[NSString stringWithFormat:@"\x00\x00\x00\x00\x00\x06\x01\x06%@%@%@%@%@%@%@%@",@"\\x",MSBplc,@"\\x",LSBplc,@"\\x",MSBValeur,@"\\x",LSBValeur];
     
     
            NSLog(@"Le texte est %@",Trame);
            Info.text = [NSString stringWithFormat:@"%@%@%@",Info.text, Trame, @"\r"];
     
            //Envoie de la trame
        NSData *data = [[NSData alloc] initWithData:[Trame dataUsingEncoding:NSASCIIStringEncoding]];
           Info.text = [NSString stringWithFormat:@"%@%@%@",Info.text, data, @"\r"];
            [outputStream write:[data bytes] maxLength:[data length]];
            NSLog(@"La data est %@",data);
    L'idée est de concaténer le début de la trame (qui ne change jamais) avec les deux variables (adresse et valeur).
    La valeur data envoyée à l'automate (visible dans le log) est <00000000 00060106 5c783030 5c783030 5c783030 5c783030>

    Voila donc le soucis, il semble que le programme n'ait pas interprété \x09 comme un hexadécimal mais plutôt comme une suite de caractères (\ - x - 0 et 9) et traduire chaque caractères en ASCII.

    Ma question est la suivante, existe t'il une autre méthode pour concaténer? A t'on réalisé une mauvaise déclaration des variables? Autres ?

    Le problème vous paraitra peut-être évident et je l'espère.

    Si je ne suis pas clair faites le moi savoir.
    Merci de votre aide.

    A bientôt

    Giroquoi

  2. #2
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Modbus étant un protocole basé sur des données binaires, n'utilisez surtout pas NSString qui est une classe faite pour manipuler des chaînes de caractères essentiellement à vocation des UI.

    Manipulez directement vos propres buffers de bytes (unsigned char), surtout qu'à la fin c'est pour faire des write sur un simple stream.

    Même si NSData pourrait à la rigueur être utilisée, c'est quand même un overhead inutile pour des cas aussi simples.

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Voir EDIT plus bas

    Bonjour,

    Merci pour ta réponse rapide JeitEmgie.

    Voila donc une mise à jour du code en fonction de tes observations :

    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
    unsigned char trame[12] = {0}; //buffer de la trame
        
    	char LoAdd; //LSB de l'adresse du mot
    	char HiAdd; //MSB de l'adresse du mot
        
    	LoAdd = (0x09); //LSB de l'adresse
    	HiAdd = (0x01); //MSB de l'adresse
        
    	char LoNbre; //LSB du mots à lire
    	char HiNbre; //MSB du mots à lire
        
    	LoNbre= (0x00); //LSB du nombre
    	HiNbre= (0x12); //MSB du nombre
        
    
        
        //transaction id
        trame[0]=0x00; 
        trame[1]=0x00;
        //type de protocole 0 = Modbus tcp
        trame[2]=0x00;
        trame[3]=0x00;
        //taille restante du message
        trame[4]=0x00;
        trame[5]=0x06;
        //adresse modbus de l'automate
        trame[6]=0x01;
        //code de fonction (3 = lire un registre)
        trame[7]=0x03;
        [COLOR="rgb(255, 140, 0)"]//adresse du mot[/COLOR]
        trame[8]=0x01;
        trame[9]=0x09;
        [COLOR="rgb(255, 140, 0)"]//Valeur du mot[/COLOR]
        trame[10]=0x00;
        trame[11]=0x12;
    
        NSLog(@"la trame est: %c",trame);
    Ce code semble ne pas fonctionner. J'ai les avertissements suivants:
    "Incompatible integer to pointer conversion assigning to 'unsigned char*' from 'int'; Où se trouve l'erreur dans le développement ?

    D'autre part, nous souhaitons récupérer l'adresse et la valeur du mot que l'utilisateur aura renseignés dans deux UITextField.

    Avec un bout de code, on converti en hexadecimal les données récupérées puis on détermine le LSB et le MSB de l'adresse et de la valeur du mot.
    On obtient une variable de ce type :
    Quelle méthode peut-on utiliser pour passer cette variable dans un byte trame[] = 0x00? (l'ajout du "0x" est-il obligatoire?).

    De plus voici une méthode récupérée sur Internet pour envoyer une Trame Modbus vers l'automate:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            //Envoie de la trame
        NSData *data = [[NSData alloc] initWithData:[trame dataUsingEncoding:NSASCIIStringEncoding]];
            [outputStream write:[data bytes] maxLength:[data length]];
            NSLog(@"La data est %@",data);
    Cependant cette fonction ne prend pas en charge le type "char", un format NSString semble fonctionner.
    Quelle fonction devons nous utiliser pour envoyer notre trame sur un flux de sortie?

    Encore une fois ces erreurs vont peut-être vous paraitre évidentes, nous somme néophyte dans le domaine.
    Merci d'avance pour votre aide.

    Bonne journée

    EDIT

    Nous avons modifié le code. Désormais la trame se crée.

    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
     unsigned char trame[12];// = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //buffer de la trame
     
    	unsigned char LoAdd; //LSB de l'adresse du mot
    	unsigned char HiAdd; //MSB de l'adresse du mot
     
    	LoAdd = (0x02); //LSB de l'adresse
    	HiAdd = (0x00); //MSB de l'adresse
        NSLog(@"LoAdd %hhu",LoAdd);
     
    	unsigned char LoNbre; //LSB du mots à lire
    	unsigned char HiNbre; //MSB du mots à lire
     
    	LoNbre= (0x00); //LSB du nombre
        HiNbre= (0x00); //MSB du nombre
     
     
        //transaction id
        trame[0]=0x00; 
        trame[1]=0x00;
        //type de protocole 0 = Modbus tcp
        trame[2]=0x00;
        trame[3]=0x00;
        //taille restante du message
        trame[4]=0x00;
        trame[5]=0x80;
        NSLog(@"trame[5] est %hhu",trame[5]);
        //adresse modbus de l'automate
        trame[6]=0x01;
        //code de fonction (3 = lire un registre)
        trame[7]=0x03;
        //adresse du mot
        trame[8]=((HiAdd));
        trame[9]=((LoAdd));
        //Valeur du mot
        trame[10]=((HiNbre));
        trame[11]=((LoNbre));
    Par contre au moment de l'encodage (avant l'envoi sur le outputStream), nous rencontrons quelques difficultés.

    Voici la fonction pour l'encodage:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        NSString* s = [[NSString alloc] initWithBytes:trame length:sizeof(trame) encoding:NSASCIIStringEncoding];
     
        NSLog(@"la trame NSSTRING est: %@",s);
     
     
        NSData *data = [[NSData alloc] initWithData:[s dataUsingEncoding:NSASCIIStringEncoding]];
     
        NSLog(@"la trame NSDATA ASCII DEGUELASSE est: %@",data);
    L'encodage en ascii a ses limites, il n'accepte que des valeurs inférieures à 128(décimal). Hors dans notre cas les variable peuvent prendre des valeur allant jusqu'à 255.

    Exemple:
    -1) En formant la trame suivante
    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
        unsigned char trame[12]; //buffer de la trame
     
        //transaction id
        trame[0]=0x00; 
        trame[1]=0x00;
        //type de protocole 0 = Modbus tcp
        trame[2]=0x00;
        trame[3]=0x00;
        //taille restante du message
        trame[4]=0x00;
        trame[5]=0x79;
        NSLog(@"trame[5] est %hhu",trame[5]);
        //adresse modbus de l'automate
        trame[6]=0x01;
        //code de fonction (3 = lire un registre)
        trame[7]=0x03;
        //adresse du mot
        trame[8]=0x00;
        trame[9]=0x02;
        //Valeur du mot
        trame[10]=0x00;
        trame[11]=0x00;
    Après encodage on obtient : <00000000 00790103 00020000>

    - 2) En formant la trame suivante
    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
        unsigned char trame[12]; //buffer de la trame
        
        //transaction id
        trame[0]=0x00; 
        trame[1]=0x00;
        //type de protocole 0 = Modbus tcp
        trame[2]=0x00;
        trame[3]=0x00;
        //taille restante du message
        trame[4]=0x00;
        trame[5]=0x80; //80(hex)=128(dec)
        NSLog(@"trame[5] est %hhu",trame[5]);
        //adresse modbus de l'automate
        trame[6]=0x01;
        //code de fonction (3 = lire un registre)
        trame[7]=0x03;
        //adresse du mot
        trame[8]=0x00;
        trame[9]=0x02;
        //Valeur du mot
        trame[10]=0x00;
        trame[11]=0x00;
    Après encodage on obtient : <> (l'encodage ne s'effectue plus)

    Les fonctions "NSUTF8StringEncoding" et "NSNEXTSTEPStringEncoding" pour remplacer "NSASCIIStringEncoding" ne fonctionne pas non plus.

    Une idée de fonction à utiliser pour l'encodage?

    Merci d'avance

    Bonne journée

  4. #4
    Membre expérimenté Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Points : 1 312
    Points
    1 312
    Par défaut
    Citation Envoyé par JeitEmgie Voir le message
    Modbus étant un protocole basé sur des données binaires, n'utilisez surtout pas NSString qui est une classe faite pour manipuler des chaînes de caractères essentiellement à vocation des UI.

    Manipulez directement vos propres buffers de bytes (unsigned char), surtout qu'à la fin c'est pour faire des write sur un simple stream.

    Même si NSData pourrait à la rigueur être utilisée, c'est quand même un overhead inutile pour des cas aussi simples.
    Citation Envoyé par giroquoi Voir le message

    Les fonctions "NSUTF8StringEncoding" et "NSNEXTSTEPStringEncoding" pour remplacer "NSASCIIStringEncoding" ne fonctionne pas non plus.

    Une idée de fonction à utiliser pour l'encodage?
    Comme l'a déjà dit JeitEmgie tu n'es pas censé passer par un NSString (qui va déjà de base te rajouter un caractère supplémentaire à la fin des données) et tu n'as pas à te préoccuper d'un quelconque encodage. Tu as des données brutes, pas du texte. Ensuite il faut voir ce qu'attend ta fonction d'envoi de données : un NSData ou un tableau d'octets ?

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Juin 2012
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Bonjour,

    Merci de votre aide.

    La solution est désormais opérationnelle. Nous n'avons pas utilisé de NSString mais directement un buffet de byte type unsigned char

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char trame[12];// = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //buffer de la trame
    .

    Puis les données sont encodées (je ne sais pas si c'est le bon terme) par l'intermédiaire d'une NSData.

    Enfin on envoie les données sur un NSOutputstream.

    A bientôt

Discussions similaires

  1. Problème d'envoi de trames
    Par skeltryx dans le forum Langage
    Réponses: 2
    Dernier message: 22/03/2007, 15h16
  2. Problème d'envoi de trames
    Par skeltryx dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 22/03/2007, 14h14
  3. Y a t'il envoi de trame beacon dans un réseau adhoc
    Par Kingdomofh dans le forum Développement
    Réponses: 3
    Dernier message: 20/03/2007, 20h17
  4. Réponses: 3
    Dernier message: 28/06/2006, 16h13
  5. Problème de récéption ou d'envoi de Trame UDP
    Par sniperseb dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 10/04/2006, 23h11

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