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

  1. #1
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut Communication radio mono directionnelle, RadioHead , Tableau de données traitement de l'émission et réception
    Bonsoir,
    Si je débarque ici, ce soir, c'est que toutes mes tentatives et sources ont été épurées. Je ne vais pas mettre la centaines de lien que j'ai consulté en vain.

    Je vais parler un peu radio en parlant de ma problématique et donc des solutions envisagées et problèmes rencontrées.

    Première étape, je dois faire quoi ? Envoyer des datas (une quantité assez importante si on regarde plus loin que le simple "Hello World"). A savoir une trame qui se composerais de plusieurs éléments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Adresse(type hexadécimale ressemblant fort à l'IPV6) + Text + Ligne + Colonne + Texte
    Mais aussi d'autres possibilités tel que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Adresse(type hexadécimale ressemblant fort à l'IPV6) + Clignotement + 1000 + 5000
    Bref autant de datas à transmettre.

    J'ai donc commencé par étudier un peu la solution full String (oui, pas beau) en me disant que "0010:0000:0000:0000:0000:0000:0000:0000,Text,0,0,Hello world" pouvais passer. Hélas, c'est déjà trop lourd. Voir donc méthode 2 : passer par tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tbl[]={'0010','0000','0000','0000','0000','0000','0000','0000', 'Text', '0', '0', 'Hello World'}
    Déjà, c'est beaucoup plus intéressant car on pourra toujours appeler les éléments un par un et comme on le souhaite en réception. Je prendrais donc cela comme point de départ. Mais, il y a un premier mais. J'ai du texte et des chiffres mélangées. De mémoire, sur Arduino (par ce que je ne pratique pas tous les jours) n'aime pas du tout le mélange dans un tableau. Et la galère commence. Comment je peux m'affranchir de ce premier travers ?

    Et essayons enfin de sortir d'une première carte pour arriver dans la seconde en mode radio. Alors, dans ce domaine, j'ai vue plusieurs choses. Je vais commencé par celle qui me semble la plus évidente mais pas du tout compatible avec ce que j'ai évoquer plus haut dans la méthode 2. Je vais parler de Hamming + Manchester.

    Si je suis bien arrivé à faire fonctionner Manchester un coup sur deux, c'est que déjà la bibliothèque Githubienne est pas tout à fait au point. Pas fiable du tout!

    Au final, ce que je cherche à faire c'est transmettre le tableau, soit en entier, soit par infos quitte à borner les infos tel que l'ajout d'un start et d'un stop data (ben oué, faut faire comme en HTML, faut baliser) et transformer ça en modulation de 0/1 qui puissent être modulées par radio ou autre.

    J'ai commencé un bout de code m'appuyant finalement sur RadioHead qui fais pas trop mal le travail puisque je vois bien une trame à l'oscilloscope et que je vois bien un retrour sur écran à la réception.
    Pour l'émission :
    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 <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define TX_PIN 4
     
    RH_ASK driver(speedTR, "", TX_PIN);
     
    void setup() {
      // put your setup code here, to run once:
      driver.init();
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      char data[20];
      data[0] = "<";
      data[1] = "00AB";
      data[2] = "CF2A";
      data[3] = "153D";
      data[4] = "2BAC";
      data[5] = "2384";
      data[6] = "A23D";
      data[7] = "F2FF";
      data[8] = "CA2D";
      data[9] = "TEXT";
      data[10] = "0";
      data[11] = "0";
      data[12] = "Hello world !!!!";
      data[13] = ">";
     
      driver.send((uint8_t*)data, 20);
      driver.waitPacketSent();
      delay(1000);
    }
    Pour le récepteur :
    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
     
    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define RX_PIN 5
     
    RH_ASK driver(speedTR, RX_PIN);
     
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      driver.init();
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      char receivedData[20] = {0};
      uint8_t buflen = sizeof(receivedData);
     
      if (driver.recv((uint8_t*)receivedData, &buflen)) {
        for (byte i = 0; i < 20; i++) {
          Serial.print(receivedData[i]);
          Serial.print(" ");
        }
        Serial.println("");
      }
    }
    Et le résultat :
    r t y ~ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ * * * * 8 ,
    r t y ~ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ * * * * 8 ,
    r t y ~ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ * * * * 8 ,
    r t y ~ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ * * * * 8 ,
    r t y ~ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ * * * * 8 ,
    r t y ~ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ ⸮ * * * * 8 ,
    Bon, ben CQFD, j'ai bien mon retour mais les valeurs sont éronnées.

    Voilà, je m'en remet à des mains plus compétentes que les miennes étant dépassé pour le coup.

    Merci d'avoir pris le temps de me lire et de m'aider.

  2. #2
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Bonsoir,

    Citation Envoyé par Caxton Voir le message
    Première étape, je dois faire quoi ? Envoyer des datas (une quantité assez importante si on regarde plus loin que le simple "Hello World"). A savoir une trame qui se composerais de plusieurs éléments :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Adresse(type hexadécimale ressemblant fort à l'IPV6) + Text + Ligne + Colonne + Texte
    Mais aussi d'autres possibilités tel que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Adresse(type hexadécimale ressemblant fort à l'IPV6) + Clignotement + 1000 + 5000
    Bref autant de datas à transmettre.
    la première question me venant à l'esprit en lisant cette partie, est la suivante : quel est le caractère de fin de chaîne ? Utile pour signifier la fin de la transmission car tes données n'ont pas la même longueur.

    Citation Envoyé par Caxton Voir le message
    J'ai donc commencé par étudier un peu la solution full String (oui, pas beau) en me disant que "0010:0000:0000:0000:0000:0000:0000:0000,Text,0,0,Hello world" pouvais passer. Hélas, c'est déjà trop lourd. Voir donc méthode 2 : passer par tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tbl[]={'0010','0000','0000','0000','0000','0000','0000','0000', 'Text', '0', '0', 'Hello World'}
    Attention : en C++, '0' n'a absolument pas la même signification que "0" !


    Citation Envoyé par Caxton Voir le message
    Déjà, c'est beaucoup plus intéressant car on pourra toujours appeler les éléments un par un et comme on le souhaite en réception. Je prendrais donc cela comme point de départ. Mais, il y a un premier mais. J'ai du texte et des chiffres mélangées. De mémoire, sur Arduino (par ce que je ne pratique pas tous les jours) n'aime pas du tout le mélange dans un tableau. Et la galère commence. Comment je peux m'affranchir de ce premier travers ?
    Avec des structures :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct message{
    int idMessage;
    int addrDest;
    int addrSrc;
    int val1;
    int val2;
    String text1;
    String text2;
    };
     
    message msg;

  3. #3
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Salut Auteur content de te voir ici.

    Bon, oui, j'ai glissé pas mal d'erreur. Je suis un peu rouillé en ce moment niveau code et embarqué.

    Ok, pour le coup du '0' ou "0". Donc fut-t-il que je migre vers '0000' plutôt que tel que ?
    Je viens de tenter et y a une différence !

    TX
    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 <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define TX_PIN 4
     
    RH_ASK driver(speedTR, "", TX_PIN);
     
    void setup() {
      // put your setup code here, to run once:
      driver.init();
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      char data[20];
      data[0] = '<';
      data[1] = '00AB';
      data[2] = 'CF2A';
      data[3] = '153D';
      data[4] = '2BAC';
      data[5] = '2384';
      data[6] = 'A23D';
      data[7] = 'F2FF';
      data[8] = 'CA2D';
      data[9] = 'TEXT';
      data[10] = '0';
      data[11] = '0';
      data[12] = 'Hello world !!!!';
      data[13] = '>';
     
      driver.send((uint8_t*)data, 20);
      driver.waitPacketSent();
      delay(1000);
    }
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    < B A D C 4 D F D T 0 0 ! > * * * * 8 ,
    Je n'ai pas toucher au code du récepteur RX.

    Par contre, les structures, je n'en ai jamais fait. Comment ça fonctionne cette bête. Je veux dire niveau pratique ? Par ce que pour le coup, ça m'intéresse si ça résoud le problème.

    Pour les caractères de début "<" et de fin ">" façon Hache Teu meu Leuh ! Mais on peut mettre autre chose si c'est trop coriace comme caractère.

    Merci pour le coup de pouce.

  4. #4
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    12 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12 604
    Points : 56 721
    Points
    56 721
    Billets dans le blog
    40
    Par défaut
    Bonsoir,

    Citation Envoyé par Caxton Voir le message
    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
    // ...
      char data[20];
      data[0] = '<';
      data[1] = '00AB';
      data[2] = 'CF2A';
      data[3] = '153D';
      data[4] = '2BAC';
      data[5] = '2384';
      data[6] = 'A23D';
      data[7] = 'F2FF';
      data[8] = 'CA2D';
      data[9] = 'TEXT';
      data[10] = '0';
      data[11] = '0';
      data[12] = 'Hello world !!!!';
      data[13] = '>';
    // ...
    Je me trompe ou le type char est fait pour stocker 1 caractère ? Un tableau de chaînes de caractères est forcément un tableau 2D.

    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
      char data[][20] = {
      "<",
      "00AB",
      "CF2A",
      "153D",
      "2BAC",
      "2384",
      "A23D",
      "F2FF",
      "CA2D",
      "TEXT",
      "0",
      "0",
      "Hello world !!!!",
      ">"};

  5. #5
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Bonjour,

    En effet, je comprends un peu mieux la différence entre "envoyer un seul caractère" ou "envoyer une chaine de caractère". J'avous que jusqu'ici, je n'avais jamais eu à m'en soucier directement.

    Du coup, si je comprends bien, le tableau est à 2 dimensions. Ce qui oblige à modifier le récepteur mais ça c'est pas grave.

    Je résume donc, côté émetteur :
    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
    char data[][20] = {
      "<",
      "00AB",
      "CF2A",
      "153D",
      "2BAC",
      "2384",
      "A23D",
      "F2FF",
      "CA2D",
      "TEXT",
      "0",
      "0",
      "Hello world !!!!",
      ">"
      };
     
      driver.send((uint8_t*)data, 20);
    Côté réception :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    < - - - - - - - - - - - - - - - - - - - -
    < - - - - - - - - - - - - - - - - - - - -
    < - - - - - - - - - - - - - - - - - - - -
    < - - - - - - - - - - - - - - - - - - - -
    < - - - - - - - - - - - - - - - - - - - -
    < - - - - - - - - - - - - - - - - - - - -
    Je comprends donc que je reçois bien quelque-chose mais le reste est vide. Je me dis donc 2 choses : "Que contient alors la donnée envoyée et que contient celle reçue ?".

    Pour ce qui est envoyé :
    data[0][0] : <
    data[1][0] : 0
    data[1][1] : 0
    data[1][2] : A...

    Donc, je vais modifier le récepteur pour voir ce que j'obtiens et l'automatiser. Et voilà le résultat :
    Nom : Capture-1.JPG
Affichages : 750
Taille : 67,1 Ko

    Y a comme un petit problème
    Retour au code du récepteur modifié:
    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
     
    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define RX_PIN 5
     
    RH_ASK driver(speedTR, RX_PIN);
     
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      driver.init();
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      char receivedData[][20] = {0};
      uint8_t buflen = sizeof(receivedData);
     
      if (driver.recv((uint8_t*)receivedData, &buflen)) {
        for (byte i = 0; i < 15; i++) {
          for (byte j = 0; j < 20; j++) {
            Serial.print(receivedData[i][j]);
          }
          Serial.print(" - ");
        }
        Serial.println("");
      }
    }

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    en déclarant votre tableau sous forme de vous allouez 20 caractères par lignes

    Rien que pour votre début d'adresse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      "00AB",
      "CF2A",
      "153D",
      "2BAC",
      "2384",
      "A23D",
      "F2FF",
      "CA2D",
    pour envoyer vos 8 codes, ça va vous coûter l'envoi de 8x20=160 octets. C'est déjà bien supérieur à ce que RH_ASK peut envoyer dans un message...

    Comment connaître la taille max du message possible ? Vous utilisez RH_ASK comme driver, et on l'obtient par l'appel à driver.maxMessageLength()

    c'est défini comme étant RH_ASK_MAX_MESSAGE_LEN qui est déclarée ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // Maximum message length (including the headers, byte count and FCS) we are willing to support
    // This is pretty arbitrary
    #define RH_ASK_MAX_PAYLOAD_LEN 67
     
    // The length of the headers we add (To, From, Id, Flags)
    // The headers are inside the payload and are therefore protected by the FCS
    #define RH_ASK_HEADER_LEN 4
     
    // This is the maximum message length that can be supported by this library. 
    // Can be pre-defined to a smaller size (to save SRAM) prior to including this header
    // Here we allow for 1 byte message length, 4 bytes headers, user data and 2 bytes of FCS
    #ifndef RH_ASK_MAX_MESSAGE_LEN
     #define RH_ASK_MAX_MESSAGE_LEN (RH_ASK_MAX_PAYLOAD_LEN - RH_ASK_HEADER_LEN - 3)
    #endif
    soit 67 - 4 - 3 = 60 octets pour TOUT le message --> bref, il faut être plus économe.

    je me dis que pour partie vous émettez des nombres codés sur 2 octets et représentés en ASCII. Chaque chaine va occuper 5 octets (si vous prenez soin de mettre des '0' devant) - les 4 pour l'hexadécimal puis un '\0' de fin de chaîne. c'est hyper bavard et la probabilité de perte de données en réseau sans fil est proportionnelle à la taille de la trame, si ça ne passe pas il faudra tout ré-émettre...

    est-ce que vous voulez un protocole "ASCII" - c'est à dire que tout est transmis textuellement, où un protocole binaire?

    Par exemple, envoyer vos 8 codes si vous tassez un peu, ça pourrait vous coûter l'envoi de 8x5=40 octets. c'est les 2 tiers des 60 octets dispos... Mais si vous envoyez en binaire, chaque nombre est sur 2 octets, vous n'aurez qu'à envoyer 8x2 = 16 octets, ça nous laisse plus de place pour le reste.

    Quand on travaille sur un protocole, il faut convenir d'un marquage de début de trame (fait pour vous par la librairie), puis on essaye de définir ce qui est commun à toutes les trames, ici on dirait que vous avez une adresse ressemblant à l'IPV6 - sans doute longue de 128 bits, soit 16 octets et ensuite il y a un "payload" pour vous qui est variable. Donc il faut lister les variations possibles. Vous pourriez réserver un octet pour les variantes décrivant le payload (255 variantes), puis généralement on a la taille du payload, comme ça on sait combien on doit lire d'octets côté réception, et souvent on ajoute un code de contrôle (CRC) pour s'assurer que la trame est bien arrivée (ce qui est fait pour vous dans la librairie aussi).

    plus d'info sur comment on code une fonction de somme de contrôle CRC ici

    Si vous ne voulez pas vous ennuyer à émettre des tailles variables, on peut mettre cela en dur et réserver la mémoire et comme ça pas besoin d'émettre la longueur. on va partir là dessus.

    On a vu qu'il faut s'assurer que le message au total ne dépasse pas ce que votre driver est capable de gérer soit 60 octets.

    On a 16 octets d'adresse, 1 octet pour la variante, donc reste pour le payload: 60 - 16 - 1 = 43 octets

    vous codez cela dans une struct.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    const uint16_t tailleMaxPayload = 43; // la taille totale de la structure doit être inférieure à driver.maxMessageLength()
    enum variante_t : uint8_t {VARIANTE_1, VARIANTE_2, VARIANTE_3, VARIANTE_4};  // donnez des noms parlants
    struct message_t {
      uint16_t  adresse[8]; // 16 octets 
      variante_t  variante; // 1 octet
      uint8_t   payload[tailleMaxPayload]; // 43 octets 
    } message;
    quand vous voulez émettre vous mettez un truc du genre
    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
      message.adresse[0] = 0x00AB ;
      message.adresse[1] = 0xCF2A ;
      message.adresse[2] = 0x153D ;
      message.adresse[3] = 0x2BAC ;
      message.adresse[4] = 0x2384 ;
      message.adresse[5] = 0xA23D ;
      message.adresse[6] = 0xF2FF ;
      message.adresse[7] = 0xCA2D ;
     
      message.variante = VARIANTE_3 ; // pour expliciter au récepteur ce qu'il doit décoder
     
     strncpy(message.payload, "Texte, 0, 0, Hello World", tailleMaxPayload-1); // http://www.cplusplus.com/reference/cstring/strncpy/
      message.payload[tailleMaxPayload-1] = '\0'; // pour s'assurer d'avoir une chaîne bien formée
     
      // reste plus qu'à émettre la structure
      driver.send((uint8_t *) &message, sizeof(message));
      driver.waitPacketSent();
    côté réception, vous recevez dans la même structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    driver.recv((uint8_t*) &message, &buflen);
    la partie qui ne change pas (adresse et variante) sera au début et vous pouvez utiliser les champs de la structure pour lire les différents éléments, puis vous utilisez le N° de variante pour décoder ce qu'il y dans le payload.

  7. #7
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Ok, je comprends mieux la limitation. Je n'avais pas creuser jusque là. C'est quand même bien différent de ce que je fais habituellement !

    En fait, je n'ai pas de variantes à mettre. On saisie directement des datas via l'USB au travers de Serial, donc le message complet, que l'on cherchera à envoyer par radio. Si je résume :

    (logiciel PC)->USB->FTDI->328p (notre programme TX) -> RH_ASK ------------- RH_ASK -> 328p (notre programme RX) -> LCD
    Je ne peux faire plus simple. Ma question sera alors, est-ce qu'il vaut mieux dès le départ envoyer la structure au travers de ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (Serial.available() > 0) {
      driver.send((uint8_t*)data, 20);
      driver.waitPacketSent();
    }
    A condition que ça soit une structure. Si c'est bon, déjà j'aurais compris une chose.

    Ensuite, je vais me documenter sur les structures afin d'y voir plus clair. D'ailleurs, est-ce qu'on a un lien vers une petite doc arduino pour montrer comment ça fonctionne ce truc ?

    C'est cool d'avoir enfin trouver une piste sérieuse.

  8. #8
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonjour Caxton
    Citation Envoyé par Caxton Voir le message
    Ensuite, je vais me documenter sur les structures afin d'y voir plus clair. D'ailleurs, est-ce qu'on a un lien vers une petite doc arduino pour montrer comment ça fonctionne ce truc ?
    Pour une bonne explication, ici.
    Je développe, actuellement, un programme avec radio NRF24L01 et je transmet une structure. Les structures rendent l'écriture du programme beaucoup plus aisée, surtout si tu as l'autocomplétion dans ton IDE.

    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  9. #9
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Bonjour,

    Il m'arrive quand même de suivre ce que l'on dit et les propositions qui sont faite.

    Ah, Locodiono, comment dire... je m'en sert souvent et c'est très proche de ce que j'utilise quand je bricole. Le site est hyper bien fichu et les infos sont accessibles. Mais pourquoi donc ais-je zappé les structures. J'ai enfin compris. C'est une sorte de modèle, un canevas à respecter et ça simplifie, en effet le code.

    Je me suis inspiré de ce qui m'a été proposé et j'ai compris l'intérêt. Je me suis permis de virer l'énum car inutile pour le moment. cela ne veut pas dire que je n'y reviendrais pas au besoin.

    Ce qui nous amène donc à ce code côté TX:
    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
     
    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define TX_PIN 4
     
    const uint16_t sizeMaxData = 43;  //Taille max du data à envoyer
     
    struct data_t {
      uint16_t addr[8];
      uint8_t dataSend[sizeMaxData];  //Nombre d'octets
    } data;
     
    RH_ASK driver(speedTR, "", TX_PIN);
     
    void setup() {
      // put your setup code here, to run once:
      driver.init();
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      data.addr[0] = 0x00AB;
      data.addr[1] = 0xCF2A;
      data.addr[2] = 0x153D;
      data.addr[3] = 0x2ABC;
      data.addr[4] = 0x2384;
      data.addr[5] = 0xA23D;
      data.addr[6] = 0xF2FF;
      data.addr[7] = 0xCA2D;
     
      strncpy(data.dataSend, "LCD, 0, 0, Hello World!!!!!!!", sizeMaxData-1);
      data.dataSend[sizeMaxData-1] = '\0'; //Fin de chaine
     
      driver.send((uint8_t*)&data, sizeof(data));
      driver.waitPacketSent();
      delay(1000);
    }
    J'ai compilé, ça envoie bien des choses.

    Je me suis attaqué au RX que j'ai remis par défaut. Mais les choses se passent moins bien. Ne cherchez pas encore la structure, je voudrais savoir la tronche de ce qui arrive en réception. En fonction de cela, je chercherais comment se servir de la structure pour retrouver mes datas.
    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
     
    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define RX_PIN 5
     
    RH_ASK driver(speedTR, RX_PIN);
     
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      driver.init();
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      char receivedData[][20] = {0};
      uint8_t buflen = sizeof(receivedData);
     
      if (driver.recv((uint8_t*)receivedData, &buflen)) {
        for (byte i = 0; i < 20; i++) {
          Serial.print(receivedData[i]);
          Serial.print(" ");
        }
        Serial.println("");
      }
    }
    Et le résultat :
    Nom : Capture-2.JPG
Affichages : 767
Taille : 84,0 Ko

    Et ça donne des petits carrés... Donc illisible ! Là, je donne ma langue au chat ou je me reconverti en curé de campagne ! Je plaisante bien sûr

    Donc, soit les données envoyés sont incorrectes (ce qui peut être possible), soit la réception n'est pas correcte (ce qui peut être tout autant possible). Comment puis-je déterminer ce qui ne fonctionne pas ? A l'oscillo, j'ai bien la trame mais je ne sais dire si elle est correct ou non.

  10. #10
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonjour Caxton
    Citation Envoyé par Caxton Voir le message
    Ah, Locodiono, comment dire... je m'en sert souvent et c'est très proche de ce que j'utilise quand je bricole. Le site est hyper bien fichu et les infos sont accessibles. Mais pourquoi donc ais-je zappé les structures. J'ai enfin compris.
    Grâce à Locoduino, tu est retourné sur les rails (HO) de la sagesse et du savoir

    Citation Envoyé par Caxton Voir le message
    Ne cherchez pas encore la structure
    C'est pourtant tout simple, déclarer la même structure (struct data_t {...) côté réception et lire les données reçues comme elles ont été envoyées:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // Côté Tx
      driver.send((uint8_t*)&data, sizeof(data));
    // Côté Rx
      if (driver.recv((uint8_t*)&data, sizeof(data)) {
        for (byte i = 0; i < 20; i++) {
          Serial.print(data[i]);
          Serial.print(" ");
        }
        Serial.println("");
      }
    Je ne comprends pas bien l'utilité de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uint8_t dataSend[sizeMaxData];  //Nombre d'octets
    Citation Envoyé par Caxton Voir le message
    C'est une sorte de modèle, un canevas à respecter et ça simplifie, en effet le code.
    Ou plutôt, dans le cas de transmissions, un mélange de tout type de données (String, int, UINT_64T etc) le tout, envoyées, simplement par le nom de la structure ainsi que sa longueur et reçues, de même..

    A+
    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  11. #11
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Un point important dans les structures : l'ordre des déclarations et la taille des types de données utilisées. Par le passé, il m'est arrivé plusieurs gags notamment lorsque j'utilisais par exemple un programme dans un langage (C++) pour l'envoi des données et un autre langage (Java) pour la réception.

    Par exemple : le int en dans le langage 1 c'est 4 octets et le int dans le langage 2 c'est 2 octets. Même chose pour les chaînes de caractères, notamment les objets String.
    Du coup la taille de ta structure sera de X octets dans l'envoi et tu réceptionneras bien X octets, mais du fait du formatage différents de tes types, tu vas de retrouver complètement décalé quand tu vas vouloir récupérer tes 2 entiers
    Donc si tu utilises 2 langages différents à l'envoi et à la réception vérifie bien que les types de données, des deux côtés, font le même nombre d'octets.

    Le "problème" des chaînes en C++, c'est que tu ne vas forcément envoyer toujours la même longueur (Hello World\0, Coucou\0). Une chaîne en C++ se termine par \0 Donc, je te conseille également d'envoyer en plus de la donnée, la longueur de la chaîne pour que tu puisses, à la réception, recomposer ton message sans risquer un débordement de pile.

  12. #12
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonsoir Auteur

    Je plussoie
    J'ai eu ce genre de problème entre un ESP32 et un Arduino Nano, les 2 compilés dans un IDE Arduino.
    J'ai été "sauvé" par @Jay M, ici.

    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  13. #13
    Expert éminent sénior
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 648
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 648
    Points : 11 137
    Points
    11 137
    Par défaut
    Et effectivement, la compilation d'un même programme par 2 compilo différents (dans ton cas pour le Nano et l'ESP32) peut donner quelques surprises.

  14. #14
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Salut

    Tout à fait en général mais ici comme il envoie des données brutes on devrait retrouver nos petits octets même s’ils sont mélangés

    Pour cela il ne faut pas imprimer des char (ça donne les petits carrés quand c’est pas de l’ascii) mais la valeur binaire (utile pour les 16 premiers octets) Et surtout il faut donner un buffer approprié

    La méthode recv du driver RHASK attend 2 paramètres, un pointeur sur le buffer mémoire où écrire et un pointeur vers un uint8_t (1 octet) qui sera initialisé avant l’appel à la taille du buffer et qui vaudra après l’appel le nombre exact d’octets reçus

    en réception donc il faut faire
    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
    ...
     
    const uint16_t sizeMaxData = 43;  //Taille max du message textuel 60 - le reste de la structure, ici on pourrait donc avoir 44
     
    struct data_t {
      uint16_t addr[8];
      uint8_t dataSend[sizeMaxData];  //Nombre d'octets
    } data;
     
    ...
     
    void loop() {
      uint8_t buflen = sizeof(data); // on initialise avec la place totale dispo
     
      if (driver.recv((uint8_t*) &data, &buflen)) { // a-t-on reçu quelque chose ?
        for (uint8_t i = 0; i < buflen; i++) { // on a reçu buflen octets
          uint8_t octet = *(((uint8_t*) &data)+ i); // l’octet en position i du buffer
          Serial.print(i);
          Serial.print(F(\t0x”));
          Serial.print(octet, HEX); // impression en hexa
          if ((octet >= ‘ ‘) && (octet <= ‘~’)) { // est-ce un caractère affichable ?
            Serial.print(F(\t));
            Serial.print((char) octet); // impression Du caractère 
          }
           Serial.println();
        }
      }
    }
    (code tapé ici depuis ma tablette donc il se peut qu’il y ait des fautes)


    Ensuite effectivement si vous jouez avec 2 plateformes différentes il faut bien utiliser les uint8_t ou uint16_t etc pour garantir la taille mémoire utilisée et marquer la structure comme devant être compacte et ordonnée telle que définie (cf mon post pointé par jpbricole) et donc déclarer la structure des 2 cotés au minimum comme (voire avec alignement mais dans ce cas vérifier les tailles réelles pour ne pas dépasser les 60 octets)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    struct __attribute__((packed)) data_t {
      uint16_t addr[8];
      uint8_t dataSend[sizeMaxData];  //Nombre d'octets
    } data;
    (et perso j’appellerais dataSend autrement, l’habitude c’est payload ou dataBuffer ou juste contenu, bref sans notion de send car d’un côté c’est envoyé mais de l’autre c’est reçu )

    Pour être aussi tranquille c’est parfois bien de ne pas mettre un nombre impair d’octets dans la structure sur une architecture 32 bits et idéalement mettre un multiple de 4, ici on a 16 octets pour l’adresse on pourrait prendre 40 ou 44 octets pour le message (faut rester en dessous de 60 au total)

  15. #15
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Ah oui, en effet, je suis sur de bons rails (HO ou même Net O ).

    Je rebondit sur ce que dit Auteur. Dans mon cas, il y aura du cross développement. Environnement windows (Windev) -> USB -> FTDI et la chaine Arduino. Donc il faudra veiller à ce que les datas rentrent au format structure pour être traités. Je suis tout à fait d'accord avec ce qui a été dit plus haut.

    Maintenant, revenons à l'actualité, ne partons pas trop loin en besognes et recentrons-nous sur le sujet.

    J'ai testé une modification du RX, comme nous venons parfaitement de l'expliquer un peu plus haut. Je remercie au passage toute l'aide que vous prenez le temps de donner afin de faire avancer les choses. C'est un régal de vous lire et moi d'apprendre aussi de nouvelles façons de programmer. Je suis arrivé à un résultat pas trop moche :

    Nom : Capture-3.JPG
Affichages : 704
Taille : 55,2 Ko

    Je suis content que le code fonctionne et de ne plus voir de carrés disgracieux.

    Je ne m'attendais pas à voir à chaque lignes un caractère... Là, j'essaie maintenant d'imaginer comment modifier pour que ça soit parsé et traité. Ne serais-ce que pour en extraire l'adresse. Car je me dis le fonctionnement suivant (en pseudo code) :
    Loop()
    Data reçu ?
    Oui -> nombre de bits reçus ?
    Oui -> adresse correspondante à la carte ?
    Oui -> Lcd ?
    Oui -> Ligne, Colone
    Message = Message reçue
    Non -> Erreur
    Message = "Erreur : Ligne / Colonne"
    Oui -> Options ?
    Traitement options
    Non -> Erreur
    Message = "Erreur : L'erreur..."
    Non -> Ne rien faire
    Non -> Ne rien faire

    Si Message > 1
    Appeler aficheur I2C adresse connue
    Afficher message
    Message = "";
    //Fin loop
    Ne me faites pas tout, je voudrais comprendre déjà pour l'adresse et je me charge de la partie LCD puisque j'ai déjà ma bibliothèque qui tourne et que je vais améliorer (ben oué, je me suis essayés avec des classes et ça rends super bien). En gros, ce que je cherche c'est le parsage correct et le traitement de l'IP.

    Je vais essayer maintenant de commenter mon RX afin de comprendre comment je peux modifier mon code pour recevoir en une ligne. Mais avant, j'aimerais quand même que ça soit correct afin d'éviter de partir dans le vide.

    RX :
    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
     
    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
     
    #define speedTR 1000
    #define RX_PIN 5
     
    const uint16_t sizeMaxData = 43;  //Taille max du data à envoyer
     
    struct data_t {
      uint16_t addr[8];
      uint8_t dataSend[sizeMaxData];  //Nombre d'octets
    } data;
     
    RH_ASK driver(speedTR, RX_PIN); //Librairie RadioHead
     
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600); //Liaison série pour le Débug
      driver.init();  //Initialisation de RH_ASK
    }
     
    void loop() {
      // put your main code here, to run repeatedly:
      uint8_t buflen = sizeof(data);  //Longueur du buffer
     
      //Si des datas sont reçues au tarvers de RH_ASK
      if (driver.recv((uint8_t*) &data, &buflen)) {
     
        //De 0 à Longueur du buffer
        for(uint8_t i = 0; i < buflen; i++) {
     
          uint8_t octet = *(((uint8_t*) &data)+i);  //Un octet
          Serial.print(i);                          //Numéro d'index
          Serial.print(F("\t0x"));                  //Je connais pas ce code ???
          Serial.print(octet, HEX);                 //Affichage en HEXA de la valeur de l'octet
     
          //Si l'octet n'est pas un caractère vide ou un ~
          if((octet >= ' ') && (octet <= '~')) {
            Serial.print(F("\t"));                  //Je connais pas ce code ???
            Serial.print((char)octet);              //Afficher l'octet sous forme de character
     
            //C'est ici que je pense recomposer en datas style data.ADDR[0] -> 00AB...
          }
          Serial.println();
        }
     
        //C'est ici que je compte tester mon adresse
          //C'est ici que je fais mon traitement
      }
    }
    Qu'en pensez-vous ? Est-ce que je commet des erreurs ? Est-ce que mes commentaires sont bons ? Là, il faut que je m'améliore de toute façon !

    Merci,

  16. #16
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    on progresse à grands pas

    Si on regarde ce que vous avez reçu:
    Nom : CaptureOK.JPG
Affichages : 763
Taille : 82,0 Ko

    pour les commentaires:

    dans code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uint8_t octet = *(((uint8_t*) &data)+i);  //Un octet
    ce n'est pas n'importe quel octet, mais le i-ème du buffer. On parcourt chaque octet de la structure pour affichage.

    dans ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Serial.print(F("\t0x"));                  //Je connais pas ce code ???
    ainsi que ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Serial.print(F("\t"));                  //Je connais pas ce code ???
    le \t représente une tabulation, ce qui permet d'aligner bien en colonnes l'impression. C'est ce qu'on appelle une Séquence d'échappement, il y en a un certain nombre à connaître qui sont bien pratiques pour imprimer un guillemet par exemple avec le \"

    (et le 0x c'est pour qu'il soit écrit directement à l'affichage juste avant la valeur de l'octet en binaire comme vous le voyez à l'affichage


    Ne me faites pas tout, je voudrais comprendre déjà pour l'adresse et je me charge de la partie LCD puisque j'ai déjà ma bibliothèque qui tourne et que je vais améliorer (ben oué, je me suis essayés avec des classes et ça rends super bien). En gros, ce que je cherche c'est le parsage correct et le traitement de l'IP.
    En pratique vous recevez bien la structure et l'avantage de la structure c'est que vous n'avez pas besoin de lire octet par octet, tout est déjà rangé dans les variables pour vous (du moment qu'on a bien aligné entre l'émetteur et le récepteur).

    Par exemple étudiez ce code et regardez ce que ça imprime:
    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
    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile
    
    #define speedTR 1000
    #define RX_PIN 5
    
    const uint16_t sizeMaxData = 43;  //Taille max du data à envoyer
    
    struct data_t {
      uint16_t addr[8];
      uint8_t dataSend[sizeMaxData];  //Nombre d'octets
    } data;
    
    RH_ASK driver(speedTR, RX_PIN); //Librairie RadioHead
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600); //Liaison série pour le Débug
      driver.init();  //Initialisation de RH_ASK
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      uint8_t buflen = sizeof(data);  //Longueur du buffer
    
      //Si des data sont reçues au tarvers de RH_ASK
      if (driver.recv((uint8_t*) &data, &buflen)) {
        // on imprime les 8 adresses
        for (uint8_t i = 0; i < 8; i++) {
          Serial.print(F("data.addr["));
          Serial.print(i);
          Serial.print(F("] = 0x"));
          Serial.println(data.addr[i], HEX);
        }
        // puis on imprime le message textuel
        Serial.print(F("Message: "));
        Serial.println((char*) data.dataSend);
      }
    }
    je vous conseille de changer le débit en bauds de votre liaison série de debug Serial.begin(9600); de 9600 en 115200 (et bien sûr ajuster dans la console série à 115200 avec le popup en bas)

  17. #17
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Oh punaise

    Je commence à voir mes trames

    Nom : Capture-4.JPG
Affichages : 741
Taille : 66,8 Ko

    J'ai modifié deux lignes par rapport à l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    uint8_t dataRecv[sizeMaxData];  //Nombre d'octets en réception
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Serial.println((char*) data.dataRecv);
    Donc, à ce stade je retrouve bien mon adresse et le message. A moi maintenant de trouver comment parser. Mais avant de partir dans tous les sens, si ça ne vous ennuie pas de poursuivre un peu ce tread (ou j'en ouvre un autre, vous me direz bien), j'aimerais savoir quelle est la meilleure façon de parser le retour pour son traitement.

  18. #18
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par Caxton Voir le message
    Oh punaise
    Je commence à voir mes trames .
    Magique

    Citation Envoyé par Caxton Voir le message
    J'ai modifié deux lignes par rapport à l'exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uint8_t dataRecv[sizeMaxData];  //Nombre d'octets en réception
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Serial.println((char*) data.dataRecv);
    OK oui, généralement on essaye de définir la structure exactement de la même façon des 2 côtés, ça permet de partager un .h par exemple... (et c'est pour cela qu'on appelle le contenu payload ou autre truc générique)

    Citation Envoyé par Caxton Voir le message
    A moi maintenant de trouver comment parser. Mais avant de partir dans tous les sens, si ça ne vous ennuie pas de poursuivre un peu ce tread (ou j'en ouvre un autre, vous me direz bien), j'aimerais savoir quelle est la meilleure façon de parser le retour pour son traitement
    vu que vous recevez un cString (un buffer de texte), explorez les fonctions des librairies standard dans stdlib.h et aussi dans string.h
    On peut extraire des tokens avec strtok() (attention cette fonction va modifier le buffer)

    Par exemple si vous avez des séparateurs bien définis - ici on dirait que vous optez pour la virgule comme séparateur de champs, ça pourrait ressembler à cela (à condition qu'il n'y ait pas de virgule dans le texte final). (attention j'ai mis la console Série à 115200 bauds)

    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
    char message[] = "LCD, 0, 0, Hello World!!!!!!!";
     
    void analyseMessage(char* texte)
    {
      char * pointeur;
      Serial.print(F("Analyse de ["));
      Serial.print(texte);
      Serial.println(F("]"));
     
      pointeur = strtok (texte, ",");
      while (pointeur) {
        Serial.print(F("["));
        if (*pointeur == ' ') // on saute l'espace si on en a un au début
          Serial.print(pointeur + 1);
        else
          Serial.print(pointeur);
        Serial.println(F("]"));
        pointeur = strtok (NULL, ","); // on passe au token suivant
      }
    }
     
     
    void setup()
    {
      Serial.begin(115200);
      analyseMessage(message);
    }
     
    void loop() {}
    et jetez un oeil à la fonction atoi() pour convertir un entier écrit en ASCII dans une chaîne de caractères vers un entier "mathématique".

  19. #19
    Membre régulier Avatar de Caxton
    Homme Profil pro
    Sans
    Inscrit en
    Janvier 2005
    Messages
    586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Sans

    Informations forums :
    Inscription : Janvier 2005
    Messages : 586
    Points : 123
    Points
    123
    Par défaut
    Je comprends un peu. Pour parser, il faut s'orienter strtok() et les tokens. Ok !

    Bon, je travaille aussi pour recomposer l'adresse. Je suis bien arrivé à compiler quelque-chose mais le résultat ne me plait pas. J'ai du oublier quelque-chose. Je connais mal les cstrings. Il faudra que je m'y fasse.

    Voilà la modification du Loop(). Je synthétise pour me concentrer sur la modification.
    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
     
     // put your main code here, to run repeatedly:
      uint8_t buflen = sizeof(data);  //Longueur du buffer
      uint8_t addrRecv = "";
     
      //Si des datas sont reçues au tarvers de RH_ASK
      if (driver.recv((uint8_t*) &data, &buflen)) {
        //Nous imprimons les 8 adresses
        for(uint8_t i = 0; i < 8; i++) {
          /*Serial.print(F("data.addr["));
          Serial.print(i);
          Serial.print(F("] = 0x"));
          Serial.println(data.addr[i], HEX);*/
          if(i != 8) {
            addrRecv += data.addr[i]+':';
          }
          else {
            addrRecv += data.addr[i];
          }
        }
     
        Serial.println(addrRecv);
     
        //Nous imprimons le message contextuel
        Serial.print(F("Message: "));
        Serial.println((char*) data.dataRecv);
      }
    Si ça semble bien assembler correctement la chaine, son contenu m'interpèle quand je regarde le retour sur le Serial.

    Nom : Capture-5.JPG
Affichages : 663
Taille : 13,5 Ko

    Dans l'idée, si c'est < à 8, on cumule la chaine avec, successivement 00AB:, 00AB:CF2A:, 00AB:CF2A:153D:, 00AB:CF2A:153D:0x2ABC:, 00AB:CF2A:153D:0x2ABC:2384:, 00AB:CF2A:153D:0x2ABC:2384:A23D:, 00AB:CF2A:153D:0x2ABC:2384:A23D:F2FF: et enfin, car c'est = à 8, 00AB:CF2A:153D:0x2ABC:2384:A23D:F2FF:CA2D

    Mais voilà je trouve 255.

    Bon, j'essaie, je fais surement des erreurs et j'avoue que j'ai tester quelques solutions avant de répondre. Mais ça m'amuse de voir aussi ce qui se passe. D'ailleurs, si ça se trouve on peut certainement utiliser les pointeurs pour faire ça. Enfin, bon, là, je m'avance, c'est une piste. Y a peut-être moyen de faire plus simple.

  20. #20
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par Caxton Voir le message
    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
      uint8_t addrRecv = ""; // un uint8_t n’est qu’un seul octet...
    ...
        for(uint8_t i = 0; i < 8; i++) {
          /*Serial.print(F("data.addr["));
          Serial.print(i);
          Serial.print(F("] = 0x"));
          Serial.println(data.addr[i], HEX);*/
          if(i != 8) { // i ne vaudra jamais 8 dans cette boucle...
            addrRecv += data.addr[i]+':'; // ici vous additionnez un uint16_t (entier sur 2 octets) et le code ascii du caractère
          }
          else {
            addrRecv += data.addr[i];
          }
     ...
    Les adresses reçues sont des nombres, en c++ on ne fabrique pas une chaîne en concaténation comme cela...
    Pour bâtir une chaîne il faut un tableau avec assez de caractères pour tout stocker et itoa() et strcact() ou sprintf()... ou alors prendre la classe String mais vous risquez d’aller au devant de soucis mémoire

    Pourquoi souhaitez vous rebâtir une string avec l’adresse ? si c’est juste pour l’afficher, affichez là par petits bouts comme on a fait précédemment



    sinon, voici quelque chose à étudier:
    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
    const uint16_t sizeMaxData = 43;
    struct data_t {
      uint16_t addr[8];
      uint8_t payload[sizeMaxData];  //Nombre d'octets
    } ;
     
    data_t data[] = {
      {
        0x00AB, 0xCF2A, 0x153D, 0x2BAC, 0x2384, 0xA23D, 0xF2FF, 0xCA2D,
        "LCD, 23, 35, Hello LCD!!!!!!!"
      },
      {
        0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888,
        "TFT, 125, 350, Hello TFT!!!!!!!"
      }
    };
     
     
    void analyseMessage(char* texte)
    {
      char * pointeur;
      Serial.print(F("Analyse de ["));
      Serial.print(texte);
      Serial.println(F("]"));
     
      pointeur = strtok (texte, ",");
      while (pointeur) {
        char* debut;
        Serial.print(F("["));
     
        if (*pointeur == ' ') // on saute l'espace si on en a un au début
          debut = pointeur + 1;
        else
          debut = pointeur;
     
        Serial.print(debut);
        Serial.print(F("]"));
     
        if (isdigit(*debut)) {
          long valeur = atol(debut);
          Serial.print(F("  J'ai reconnu le nombre -> 0x"));
          Serial.print(valeur, HEX);
          Serial.print(F(" (en base 10 -> "));
          Serial.print(valeur, DEC);
          Serial.print(F(")"));
        } else {
          Serial.print(F(" (pas un nombre)"));
        }
        Serial.println();
        pointeur = strtok (NULL, ","); // on passe au token suivant
      }
    }
     
    void information(data_t& dataStruct)
    {
      // on imprime les 8 adresses
      for (uint8_t i = 0; i < 8; i++) {
        Serial.print(F("data.addr["));
        Serial.print(i);
        Serial.print(F("] = 0x"));
        Serial.println(dataStruct.addr[i], HEX);
      }
     
      // puis on imprime le message textuel
      Serial.print(F("Message: "));
      Serial.println((char*) dataStruct.payload);
     
      // on fabrique l'adresse en ASCII avec sprintf (ça prend plein de mémoire)
      char adresseASCII[40]; // "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" -> 39 caractères + '\0' final
      sprintf(adresseASCII, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", dataStruct.addr[0], dataStruct.addr[1], dataStruct.addr[2], dataStruct.addr[3], dataStruct.addr[4], dataStruct.addr[5], dataStruct.addr[6], dataStruct.addr[7]); // http://www.cplusplus.com/reference/cstdio/sprintf/
     
      Serial.print(F("Adresse en ASCII: "));
      Serial.println(adresseASCII);
      Serial.println();
      analyseMessage((char*) dataStruct.payload);
    }
     
    void setup() {
      Serial.begin(115200); //Liaison série pour le Débug
     
      information(data[0]);
      Serial.println(F("\n-------------"));
      information(data[1]);
    }
     
    void loop() {}

Discussions similaires

  1. [Toutes versions] tableau qui donne les dates communes (ligne) de 3 noms choisis(colonne)
    Par camad dans le forum Macros et VBA Excel
    Réponses: 12
    Dernier message: 27/10/2011, 18h57
  2. exporter un tableau de donnée vers un document word
    Par demerzel0 dans le forum Access
    Réponses: 2
    Dernier message: 04/11/2005, 11h57
  3. Filtrer un tableau de données
    Par Yux dans le forum Langage
    Réponses: 12
    Dernier message: 13/10/2005, 22h21
  4. [Collections] Transformer un tableau de données en une chaîne
    Par NATHW dans le forum Collection et Stream
    Réponses: 12
    Dernier message: 03/06/2004, 16h44
  5. [Choix SGBD] Application mono-poste mais beaucoup de données
    Par Wavyx dans le forum Décisions SGBD
    Réponses: 5
    Dernier message: 16/03/2003, 18h24

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