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

Arduino Discussion :

ESP32 et BLE


Sujet :

Arduino

  1. #41
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Non désolé Jay M

    Si la chaine d'adresse (peer_addr) est bien celle-ci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    for (size_t i = 0; i < nbClientsPC; i++) {
       memcpy(peerInfo.peer_addr,clients[i].adresse, 6);
      }
    la réponse est toujours la même
    17:02:46.757 -> Btn 1 enfoncé
    17:02:46.757 -> Erreur d'envoi des données PC1

  2. #42
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    si vous faites
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (size_t i = 0; i < nbClientsPC; i++) {
       memcpy(peerInfo.peer_addr,clients[i].adresse, 6);
      }
    vous copiez en boucle dans la zone mémoire peerInfo.peer_addr les 6 octets en provenance des clients... mais c'est au même endroit donc après cette boucle for dans peerInfo.peer_addr vous n'avez que la dernière adresse (qui a écrasé les autres).

    et donc le send n'ira qu'à cette adresse.

    si ce que vous voulez faire c'est quand le bouton N est appuyé vous envoyez un message au client N alors il suffit juste de copier dans peerInfo.peer_addr l'adresse (les 6 octets d'un coup, c'est ce que fait memcpy) de ce Nème client

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     memcpy(peerInfo.peer_addr,clients[N].adresse, 6);
    il ne faut pas faire de boucle for

  3. #43
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Bonjour Jay M

    j'ai procédé à la modification mais le problème est toujours présent
    à savoir :
    09:35:16.204 -> Btn 1 enfoncé
    09:35:16.204 -> Erreur d'envoi des données PC1
    à toute fin utile, je remets la dernière version ( j'y ai ajouté: void InitESPNow() )
    je ne vois pas ce qui cloche

    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
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
     
    // EMETTEUR uPesy ESP32 Wroom DevKit //
     
    #include <SPIFFS.h>
    #include <SPI.h>
    #include <TFT_eSPI.h>
    #include <XPT2046_Touchscreen.h> // https : //github. com/PaulStoffregen/XPT2046_Touchscreen
    #include <esp_now.h>
    #include <WiFi.h>
     
    TFT_eSPI tft = TFT_eSPI();
     
    // Touchscreen pins
    #define XPT2046_IRQ 36   // T_IRQ
    #define XPT2046_MOSI 32  // T_DIN
    #define XPT2046_MISO 39  // T_OUT
    #define XPT2046_CLK 25   // T_CLK
    #define XPT2046_CS 33    // T_CS
     
    SPIClass touchscreenSPI = SPIClass(VSPI);
    XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
     
    #define SCREEN_WIDTH 320
    #define SCREEN_HEIGHT 240
    #define FONT_SIZE 2
     
    // definition des boutons
    #define BUTTON_WIDTH  80
    #define BUTTON_HEIGHT 60
    #define BUTTON_MARGIN 10
     
    // Structure pour représenter un bouton
    struct Button {
      int x, y;
      bool state;
    };
     
    Button buttons[9]; // 9 boutons
     
    // Coordonnées de l'écran tactile : (x, y) et pression (z)
    int x, y, z;
     
    // Imprimer les informations de l'écran tactile concernant X, Y et la pression (Z) sur le moniteur série
    void printTouchToSerial(int touchX, int touchY, int touchZ) {
      Serial.print("X = ");
      Serial.print(touchX);
      Serial.print(" | Y = ");
      Serial.print(touchY);
      Serial.print(" | Pressure = ");
      Serial.print(touchZ);
      Serial.println();
    }
     
    /******************************************************/
    // REPLACE WITH YOUR RECEIVER MAC Address
    //uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
     
    // *** Structure Fichier Config.txt ********************************
    const size_t tailleMaxNom = 16;     // y compris le caractère nul final
    struct ClientPC {
      char nom[tailleMaxNom];           // le nom du client PC
      uint8_t adresse[6];               // les 6 octets de son adresse
    };
     
    const size_t nbMaxClients = 20;     // nombre maximum de clients
    ClientPC clients[nbMaxClients]; 
    size_t nbClientsPC = 0;            // le nombre de clients lu dans le fichier de config
     
    //******************************************************************* 
     
    // ***** Structure du récepteur *************************************
    typedef struct struct_message {
      char a[32]; // ex PC1 
      bool b;     // Etat = 0 ou 1
    } struct_message;
    // Créer une struct_message appelée myData
    struct_message myData;
     
    //........... Etat enoi ********************************************
    esp_now_peer_info_t peerInfo;
    void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
      Serial.print("\r\nÉtat de l'envoi du dernier paquet:\t");
      Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Succès" : "Échec");
    }
    //*********************************************************************
     
    // Init ESP Now with fallback
    void InitESPNow() {
      WiFi.disconnect();
      if (esp_now_init() == ESP_OK) {
        Serial.println("ESPNow Init Success");
      }
      else {
        Serial.println("ESPNow Init Failed");
        // Retry InitESPNow, add a counte and then restart?
        // InitESPNow();
        // or Simply Restart
        ESP.restart();
      }
    }
     
     
    int touchX, touchY, touchZ , i;
     
    //************************************************
    // SETUP
    //************************************************
    void setup()
    {
      Serial.begin(115200);
     
      if(!SPIFFS.begin(true)){
        Serial.println("Une erreur s'est produite lors du montage de SPIFFS");
        return;
      } 
     
      File fichierConfig = SPIFFS.open("/config.txt", FILE_READ);
      if (!fichierConfig) {
        Serial.println("Impossible d'ouvrir le fichier en lecture");
        return;
      }
     
      char bufferLigne[100]; // Buffer pour stocker chaque ligne
      char format[64]; // pour bâtir dynamiquement le format en tenant compte de la longueur max du nom (reco de Kernighan et Pike dans "The Practice of Programming")
      snprintf(format, sizeof format, "%%%ds %%hhx %%hhx %%hhx %%hhx %%hhx %%hhx", tailleMaxNom - 1); // lire une chaine de taille max tailleMaxNom - 1 suivie de 6 octets en hexa
     
      nbClientsPC = 0;
      while (fichierConfig.available() && nbClientsPC < nbMaxClients) {   // tant qu'on peut lire quelque chose et qu'on a de la place pour stocker
        memset(bufferLigne, '\0', sizeof bufferLigne); // Effacer le buffer
        fichierConfig.readBytesUntil('\n', bufferLigne, sizeof bufferLigne); // Lire la ligne dans le buffer
        memset(clients[nbClientsPC].nom, '\0', sizeof clients[nbClientsPC].nom); // on efface le nom pour être tranquille
        int nbChampsLus = sscanf(bufferLigne, format,
                                 clients[nbClientsPC].nom,
                                 &clients[nbClientsPC].adresse[0], &clients[nbClientsPC].adresse[1],
                                 &clients[nbClientsPC].adresse[2], &clients[nbClientsPC].adresse[3],
                                 &clients[nbClientsPC].adresse[4], &clients[nbClientsPC].adresse[5]);
     
        if (nbChampsLus == 7) {
          // la lecture des 7 champs (le nom et 8 octets sous forme hexadécimale) s'est bien passée
          nbClientsPC++;
        } else {
          // on arrête de lire là
          break;
        }
      }
      fichierConfig.close();
      // Affichage des adresses lues depuis le fichier
      for (size_t i = 0; i < nbClientsPC; i++) {
        Serial.printf("%3zu %-*s : ", i+1, tailleMaxNom - 1, clients[i].nom); // l'index sur 3 caractères, le nom sur tailleMaxNom - 1 cadrée à gauche
        for (int j = 0; j < 6; j++) Serial.printf("0x%02X ", clients[i].adresse[j]);
        Serial.println();
      }
     
      // Set device as a Wi-Fi Station
      WiFi.mode(WIFI_STA);
      // Init ESP-NOW
      InitESPNow();
      if (esp_now_init() != ESP_OK) {
        Serial.println("Erreur d'initialisation de l'ESP-NOW");
        return;
      }
      // Une fois que ESPNow est Init avec succès, nous nous inscrirons pour l'envoi du CB .
      // obtenir l'état du paquet transmis.
      esp_now_register_send_cb(OnDataSent);
      // Enregistrer un pair
      //memcpy(peerInfo.peer_addr, broadcastAddress, 1);
      //memcpy(peerInfo.peer_addr, broadcastAddress , 6);
      //memcpy(peerInfo.peer_addr, clients[].adresse , 6);
      /*
      for (size_t i = 0; i < nbClientsPC; i++) {
       memcpy(peerInfo.peer_addr,clients[i].adresse, 6);
      }
      */ 
      peerInfo.channel = 0;  
      peerInfo.encrypt = false;
      // Ajouter un pair        
      if (esp_now_add_peer(&peerInfo) != ESP_OK){
        Serial.println("Échec de l'ajout d'un pair");
        return;
      }
      // Start the SPI for the touchscreen and init the touchscreen
      touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
      touchscreen.begin(touchscreenSPI);
      // Set the Touchscreen rotation in landscape mode
      // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 3: touchscreen.setRotation(3);
      touchscreen.setRotation(3);
     
      // Start the tft display
      tft.init();
      // Set the TFT display rotation in landscape mode
      tft.setRotation(1);
     
      // Clear the screen before writing to it
      tft.fillScreen(TFT_BLACK);
     
      // Initialisation des positions des boutons
      int buttonX = 20;
      int buttonY = 20;
      for (int i = 0; i < 9; ++i) 
      {
        buttons[i].x = buttonX;
        buttons[i].y = buttonY;
        buttons[i].state = false;
     
        // Affichage des boutons
        drawButton(buttonX, buttonY, buttons[i].state);
     
        buttonX += BUTTON_WIDTH + BUTTON_MARGIN;
        if (buttonX + BUTTON_WIDTH > tft.width()) {
          buttonX = 20;
          buttonY += BUTTON_HEIGHT + BUTTON_MARGIN;
        }
      }
     
    }
     
    //************************************************
    // LOOP
    //************************************************
    void loop()
    {
     
      // Checks if Touchscreen was touched, and prints X, Y and Pressure (Z) info on the TFT display and Serial Monitor
      if (touchscreen.tirqTouched() && touchscreen.touched()) 
      {
        // Get Touchscreen points
        TS_Point p = touchscreen.getPoint();
        // Calibrate Touchscreen points with map function to the correct width and height
        touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
        touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
        touchZ = p.z;
     
        //printTouchToSerial(touchX, touchY, touchZ);
     
         for (int i = 0; i < 9; ++i)
         {
            if (touchX >= buttons[i].x && touchX <= buttons[i].x + BUTTON_WIDTH &&
                touchY >= buttons[i].y && touchY <= buttons[i].y + BUTTON_HEIGHT) 
            {
              // Si un bouton est touché, inverse son état et met à jour l'affichage
              buttons[i].state = !buttons[i].state;
              drawButton(buttons[i].x, buttons[i].y, buttons[i].state);
              if (buttons[i].state == 1){
                Serial.print("Btn "); Serial.print(i+1); Serial.println(" enfoncé");
                snprintf(myData.a, sizeof myData.a, "PC%02d=> ON", i+1);
                myData.b =  true;
                memcpy(peerInfo.peer_addr,clients[i].adresse, 6);
                esp_err_t result = esp_now_send(peerInfo.peer_addr,(uint8_t *)&myData, sizeof(myData));
                if (result == ESP_OK) {
                    Serial.print("PC");Serial.print(i+1); Serial.println(" Envoyé avec succès");
                }else {
                    Serial.print("Erreur d'envoi des données PC");Serial.print(i+1);
                } 
              }
     
              if (buttons[i].state == 0)
              {
                Serial.print("Btn "); Serial.print(i+1); Serial.println(" relaché");
                snprintf(myData.a, sizeof myData.a, "PC%02d=> OFF", i+1);
                myData.b =  false;
                memcpy(peerInfo.peer_addr,clients[i].adresse, 6);
                esp_err_t result = esp_now_send(peerInfo.peer_addr,(uint8_t *)&myData, sizeof(myData));
                if (result == ESP_OK) {
                    Serial.print("PC");Serial.print(i+1); Serial.println(" Envoyé avec succès");
                }else {
                    Serial.print("Erreur d'envoi des données PC");Serial.print(i+1);
                } 
              } 
           }  
        //break;
        delay(200);
        }     
      }
    }
     
    // Dessine un bouton à une position donnée avec un état donné
    void drawButton(int x, int y, bool state) {
      uint16_t color = state ? TFT_RED : TFT_GREEN;
      tft.fillRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, color);
      tft.drawRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, TFT_WHITE);
     
    }

  4. #44
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    comme je ne peux pas répliquer votre montage, pourriez vous poster l'intégralité de ce que l'on voit sur le moniteur série lors de l'exécution ?

    pouvez vous décrire aussi exactement la configuration (quels sont les autres ESP dans le réseau et leur code)

  5. #45
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    comme je ne peux pas répliquer votre montage, pourriez vous poster l'intégralité de ce que l'on voit sur le moniteur série lors de l'exécution ?
    voici l'image

    pouvez vous décrire aussi exactement la configuration (quels sont les autres ESP dans le réseau et leur code)
    Adresse 1 seulement active les autres sont bidons

    Question :
    Le fait de mettre des majuscules ou minuscules dans l'adresse MAC cela a-t-il de l'importance ?
    Images attachées Images attachées  

  6. #46
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    ce serait plus simple de poster le texte de la console qu'une image (je lis sur mon iPhone - c'est petit )


    Le fait de mettre des majuscules ou minuscules dans l'adresse MAC cela a-t-il de l'importance
    l'affichage se fait bien donc ça veut dire que le ficher de config a été lu correctement


    modifiez votre code pour faire cela:
    enlevez la variable globale
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    esp_now_peer_info_t peerInfo;
    et enlevez du setup
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      peerInfo.channel = 0;
      peerInfo.encrypt = false;
      // Ajouter un pair
      if (esp_now_add_peer(&peerInfo) != ESP_OK) {
        Serial.println("Échec de l'ajout d'un pair");
        return;
      }

    et dans la partie de gestion des boutons faites

    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
            if (buttons[i].state == 1) {
              Serial.print("Btn "); Serial.print(i + 1); Serial.println(" enfoncé");
              snprintf(myData.a, sizeof myData.a, "PC%02d=> ON", i + 1);
              myData.b =  true;
               esp_now_peer_info_t peerInfo = {};
               memcpy(peerInfo.peer_addr, clients[i].adresse, 6);
               peerInfo.channel = 0;
               peerInfo.encrypt = false;
    
              esp_err_t result = esp_now_send(peerInfo.peer_addr, (uint8_t *)&myData, sizeof(myData));
              if (result == ESP_OK) {
                Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès");
              } else {
                Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1);
              }
            }
    idem quand on relâche le bouton

  7. #47
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Désolé mais c'est idem
    réponse Console

    ets Jul 29 2019 12:21:46
    15:20:03.401 ->
    15:20:03.401 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    15:20:03.401 -> configsip: 0, SPIWP:0xee
    15:20:03.401 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    15:20:03.401 -> mode DIO, clock div:1
    15:20:03.401 -> load:0x3fff0030,len:1344
    15:20:03.401 -> load:0x40078000,len:13964
    15:20:03.401 -> load:0x40080400,len:3600
    15:20:03.401 -> entry 0x400805f0
    15:20:03.681 -> E (210) psram: PSRAM ID read error: 0xffffffff
    15:20:03.869 -> 1 Adresse1 : 0xB4 0xE6 0x2D 0x78 0x83 0x54
    15:20:03.869 -> 2 Adresse2 : 0xC8 0x2B 0x96 0x1F 0x7F 0x77
    15:20:03.869 -> 3 Adresse3 : 0x50 0x02 0x91 0x77 0xEE 0xFA
    15:20:03.869 -> 4 Adresse4 : 0xEC 0xFA 0xBC 0xD8 0x28 0xD6
    15:20:03.869 -> 5 Adresse5 : 0x48 0x3F 0xDA 0x67 0xFD 0x5F
    15:20:03.869 -> 6 Adresse6 : 0xA4 0xCF 0x12 0xFC 0xF9 0x3E
    15:20:03.869 -> 7 Adresse7 : 0x40 0xF5 0x20 0x33 0xA5 0xC8
    15:20:03.869 -> 8 Adresse8 : 0xFC 0xF5 0xC4 0xAA 0x5D 0x61
    15:20:03.869 -> 9 Adresse9 : 0xD8 0xBF 0xC0 0x11 0xE6 0xFE
    15:20:03.915 -> ESPNow Init Success
    15:20:12.392 -> Btn 1 enfoncé
    15:20:12.392 -> Erreur d'envoi des données PC1



    (j'ai réactualisé le fichier Config.txt avec les vraies adresses mais 1 seul module est branché pour l'instant)

    ********************************************************************
    Edit : j'ai retéléversé pour vérifier le croquis d'origine avec 1 seule adresse sous la forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    uint8_t broadcastAddress1[] = {0xb4, 0xe6, 0x2d, 0x78, 0x83, 0x54};
    et la reponse console :

    15:32:55.105 -> Btn 1 enfoncé
    15:32:55.105 -> PC01 Envoyé avec succès
    15:32:55.105 ->
    15:32:55.105 -> État de l'envoi du dernier paquet: Succès
    15:33:04.348 -> Envoyé avec succès
    15:33:04.348 ->
    15:33:04.348 -> État de l'envoi du dernier paquet: Succès


    ************************************************************
    Edit2 : le prog ne passe pas par : esp_now_register_send_cb(OnDataSent);
    je l'ai pourtant déplacé et modifié le void()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
      char macStr[18];
      Serial.print("Packet vers: ");
      // Copies the sender mac address to a string
      snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
               mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
      Serial.print(macStr);
      Serial.print(" send status:\t");
      Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
    }

  8. #48
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    pouvez vous redonner le code d'origine modifié?

  9. #49
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Voici le code avec 1 seule adresse et qui fonctionne

    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
     
    // EMETTEUR uPesy ESP32 Wroom DevKit
    #include <SPI.h>
    #include <TFT_eSPI.h>
    #include <XPT2046_Touchscreen.h> // https : //github. com/PaulStoffregen/XPT2046_Touchscreen
    #include <esp_now.h>
    #include <WiFi.h>
     
    TFT_eSPI tft = TFT_eSPI();
     
    // Touchscreen pins
    #define XPT2046_IRQ 36   // T_IRQ
    #define XPT2046_MOSI 32  // T_DIN
    #define XPT2046_MISO 39  // T_OUT
    #define XPT2046_CLK 25   // T_CLK
    #define XPT2046_CS 33    // T_CS
     
    SPIClass touchscreenSPI = SPIClass(VSPI);
    XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
     
    #define SCREEN_WIDTH 320
    #define SCREEN_HEIGHT 240
    #define FONT_SIZE 2
     
    // definition des boutons
    #define BUTTON_WIDTH  80
    #define BUTTON_HEIGHT 60
    #define BUTTON_MARGIN 10
     
    // Structure pour représenter un bouton
    struct Button {
      int x, y;
      bool state;
    };
     
    Button buttons[9]; // 10 boutons
     
    // Coordonnées de l'écran tactile : (x, y) et pression (z)
    int x, y, z;
     
    // Imprimer les informations de l'écran tactile concernant X, Y et la pression (Z) sur le moniteur série
    void printTouchToSerial(int touchX, int touchY, int touchZ) {
      Serial.print("X = ");
      Serial.print(touchX);
      Serial.print(" | Y = ");
      Serial.print(touchY);
      Serial.print(" | Pressure = ");
      Serial.print(touchZ);
      Serial.println();
    }
     
    /******************************************************/
     
    //******************** Adresse Mac PC01
    uint8_t broadcastAddress1[] = {0xb4, 0xe6, 0x2d, 0x78, 0x83, 0x54};
    // ************** la structure du récepteur
    typedef struct struct_message {
      char a[32];
      bool b;
    } struct_message;
    // Create a struct_message called myData
    struct_message myData;
    esp_now_peer_info_t peerInfo;
    // *****************************rappel lorsque les données sont envoyées
    void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
      Serial.print("\r\nÉtat de l'envoi du dernier paquet:\t");
      Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Succès" : "Échec");
    }
     
    int touchX, touchY, touchZ , i;
     
    //************************************************
    // SETUP
    //************************************************
    void setup()
    {
      Serial.begin(115200);
     
      // Set device as a Wi-Fi Station
      WiFi.mode(WIFI_STA);
      // Init ESP-NOW
      if (esp_now_init() != ESP_OK) {
        Serial.println("Erreur d'initialisation de l'ESP-NOW");
        return;
      }
      // Une fois que ESPNow est Init avec succès, nous nous inscrirons pour l'envoi du CB .
      // obtenir l'état du paquet transmis.
      esp_now_register_send_cb(OnDataSent);
      // Enregistrer un pair
      memcpy(peerInfo.peer_addr, broadcastAddress1, 6);
      peerInfo.channel = 0;  
      peerInfo.encrypt = false;
      // Ajouter un pair        
      if (esp_now_add_peer(&peerInfo) != ESP_OK){
        Serial.println("Échec de l'ajout d'un pair");
        return;
      }
      // Start the SPI for the touchscreen and init the touchscreen
      touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
      touchscreen.begin(touchscreenSPI);
      // Set the Touchscreen rotation in landscape mode
      // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 3: touchscreen.setRotation(3);
      touchscreen.setRotation(3);
     
      // Start the tft display
      tft.init();
      // Set the TFT display rotation in landscape mode
      tft.setRotation(1);
     
      // Clear the screen before writing to it
      tft.fillScreen(TFT_BLACK);
     
      // Initialisation des positions des boutons
      int buttonX = 20;
      int buttonY = 20;
      for (int i = 0; i < 9; ++i) 
      {
        buttons[i].x = buttonX;
        buttons[i].y = buttonY;
        buttons[i].state = false;
     
        // Affichage des boutons
        drawButton(buttonX, buttonY, buttons[i].state);
     
        buttonX += BUTTON_WIDTH + BUTTON_MARGIN;
        if (buttonX + BUTTON_WIDTH > tft.width()) {
          buttonX = 20;
          buttonY += BUTTON_HEIGHT + BUTTON_MARGIN;
        }
      }
     
    }
     
    //************************************************
    // LOOP
    //************************************************
    void loop()
    {
     
      // Checks if Touchscreen was touched, and prints X, Y and Pressure (Z) info on the TFT display and Serial Monitor
      if (touchscreen.tirqTouched() && touchscreen.touched()) 
      {
        // Get Touchscreen points
        TS_Point p = touchscreen.getPoint();
        // Calibrate Touchscreen points with map function to the correct width and height
        touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
        touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
        touchZ = p.z;
     
        //printTouchToSerial(touchX, touchY, touchZ);
     
         for (int i = 0; i < 9; ++i)
         {
            if (touchX >= buttons[i].x && touchX <= buttons[i].x + BUTTON_WIDTH &&
                touchY >= buttons[i].y && touchY <= buttons[i].y + BUTTON_HEIGHT) 
            {
              // Si un bouton est touché, inverse son état et met à jour l'affichage
              buttons[i].state = !buttons[i].state;
              drawButton(buttons[i].x, buttons[i].y, buttons[i].state);
              if ((i==0) && (buttons[0].state ==1)) 
              {
                Serial.println("Btn 1 enfoncé"); 
                // Set values to send
                strcpy(myData.a, "PC01=> ON");
                myData.b =  true;
                // Send message via ESP-NOW
                esp_err_t result = esp_now_send(broadcastAddress1, (uint8_t *) &myData, sizeof(myData));
                if (result == ESP_OK) {
                    Serial.println("PC01 Envoyé avec succès");
                }else {
                    Serial.println("Erreur d'envoi des données PC01");
                } 
              } 
              if((i==0) && (buttons[0].state ==0)) 
              {
                // Set values to send
                strcpy(myData.a, "PC01=> OFF");
                myData.b =  false;
                // Send message via ESP-NOW
                esp_err_t result = esp_now_send(broadcastAddress1, (uint8_t *) &myData, sizeof(myData));
                if (result == ESP_OK)
                {
                  Serial.println("Envoyé avec succès");
                }else{
                  Serial.println("Erreur d'envoi des données");
                }
              }
            }  
        //break;
        delay(200);
        }     
      }
    }
     
    // Dessine un bouton à une position donnée avec un état donné
    void drawButton(int x, int y, bool state) {
      uint16_t color = state ? TFT_RED : TFT_GREEN;
      tft.fillRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, color);
      tft.drawRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, TFT_WHITE);
     
    }

  10. #50
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    ah je vous ai fait enlever complètement l'enregistrement d'un appareil et je n'ai pas remis le code pour les enregistrer tous

    essayez avec ce code (j'ai mis en rouge les changements)

    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
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    // EMETTEUR uPesy ESP32 Wroom DevKit //
    
    #include <SPIFFS.h>
    #include <SPI.h>
    #include <TFT_eSPI.h>
    #include <XPT2046_Touchscreen.h> // https : //github. com/PaulStoffregen/XPT2046_Touchscreen
    #include <esp_now.h>
    #include <WiFi.h>
    
    TFT_eSPI tft = TFT_eSPI();
    
    // Touchscreen pins
    #define XPT2046_IRQ 36   // T_IRQ
    #define XPT2046_MOSI 32  // T_DIN
    #define XPT2046_MISO 39  // T_OUT
    #define XPT2046_CLK 25   // T_CLK
    #define XPT2046_CS 33    // T_CS
    
    SPIClass touchscreenSPI = SPIClass(VSPI);
    XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
    
    #define SCREEN_WIDTH 320
    #define SCREEN_HEIGHT 240
    #define FONT_SIZE 2
    
    // definition des boutons
    #define BUTTON_WIDTH  80
    #define BUTTON_HEIGHT 60
    #define BUTTON_MARGIN 10
    
    // Structure pour représenter un bouton
    struct Button {
      int x, y;
      bool state;
    };
    
    Button buttons[9]; // 9 boutons
    
    // Coordonnées de l'écran tactile : (x, y) et pression (z)
    int x, y, z;
    
    // Imprimer les informations de l'écran tactile concernant X, Y et la pression (Z) sur le moniteur série
    void printTouchToSerial(int touchX, int touchY, int touchZ) {
      Serial.print("X = ");
      Serial.print(touchX);
      Serial.print(" | Y = ");
      Serial.print(touchY);
      Serial.print(" | Pressure = ");
      Serial.print(touchZ);
      Serial.println();
    }
    
    /******************************************************/
    // *** Structure Fichier Config.txt ********************************
    const size_t tailleMaxNom = 16;     // y compris le caractère nul final
    struct ClientPC {
      char nom[tailleMaxNom];           // le nom du client PC
      uint8_t adresse[6];               // les 6 octets de son adresse
    };
    
    const size_t nbMaxClients = 20;     // nombre maximum de clients
    ClientPC clients[nbMaxClients];
    size_t nbClientsPC = 0;            // le nombre de clients lu dans le fichier de config
    
    //*******************************************************************
    
    // ***** Structure du récepteur *************************************
    struct struct_message {
      char a[32]; // ex PC1
      bool b;     // Etat = 0 ou 1
    };
    // Créer une struct_message appelée myData
    struct_message myData;
    
    //........... Etat enoi ********************************************
    esp_now_peer_info_t peerInfo;
    
    
    void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
      Serial.print("\r\nÉtat de l'envoi du dernier paquet:\t");
      Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Succès" : "Échec");
    }
    //*********************************************************************
    
    // Init ESP Now with fallback
    void InitESPNow() {
      WiFi.disconnect();
      if (esp_now_init() == ESP_OK) {
        Serial.println("ESPNow Init Success");
      }
      else {
        Serial.println("ESPNow Init Failed");
        // Retry InitESPNow, add a counte and then restart?
        // InitESPNow();
        // or Simply Restart
        ESP.restart();
      }
    }
    
    
    int touchX, touchY, touchZ , i;
    
    //************************************************
    // SETUP
    //************************************************
    void setup()
    {
      Serial.begin(115200);
    
      if (!SPIFFS.begin(true)) {
        Serial.println("Une erreur s'est produite lors du montage de SPIFFS");
        return;
      }
    
      File fichierConfig = SPIFFS.open("/config.txt", FILE_READ);
      if (!fichierConfig) {
        Serial.println("Impossible d'ouvrir le fichier en lecture");
        return;
      }
    
      char bufferLigne[100]; // Buffer pour stocker chaque ligne
      char format[64]; // pour bâtir dynamiquement le format en tenant compte de la longueur max du nom (reco de Kernighan et Pike dans "The Practice of Programming")
      snprintf(format, sizeof format, "%%%ds %%hhx %%hhx %%hhx %%hhx %%hhx %%hhx", tailleMaxNom - 1); // lire une chaine de taille max tailleMaxNom - 1 suivie de 6 octets en hexa
    
      nbClientsPC = 0;
      while (fichierConfig.available() && nbClientsPC < nbMaxClients) {   // tant qu'on peut lire quelque chose et qu'on a de la place pour stocker
        memset(bufferLigne, '\0', sizeof bufferLigne); // Effacer le buffer
        fichierConfig.readBytesUntil('\n', bufferLigne, sizeof bufferLigne); // Lire la ligne dans le buffer
        memset(clients[nbClientsPC].nom, '\0', sizeof clients[nbClientsPC].nom); // on efface le nom pour être tranquille
        int nbChampsLus = sscanf(bufferLigne, format,
                                 clients[nbClientsPC].nom,
                                 &clients[nbClientsPC].adresse[0], &clients[nbClientsPC].adresse[1],
                                 &clients[nbClientsPC].adresse[2], &clients[nbClientsPC].adresse[3],
                                 &clients[nbClientsPC].adresse[4], &clients[nbClientsPC].adresse[5]);
    
        if (nbChampsLus == 7) {
          // la lecture des 7 champs (le nom et 8 octets sous forme hexadécimale) s'est bien passée
          nbClientsPC++;
        } else {
          // on arrête de lire là
          break;
        }
      }
      fichierConfig.close();
      // Affichage des adresses lues depuis le fichier
      for (size_t i = 0; i < nbClientsPC; i++) {
        Serial.printf("%3zu %-*s : ", i + 1, tailleMaxNom - 1, clients[i].nom); // l'index sur 3 caractères, le nom sur tailleMaxNom - 1 cadrée à gauche
        for (int j = 0; j < 6; j++) Serial.printf("0x%02X ", clients[i].adresse[j]);
        Serial.println();
      }
    
      // Set device as a Wi-Fi Station
      WiFi.mode(WIFI_STA);
      // Init ESP-NOW
      InitESPNow();
      if (esp_now_init() != ESP_OK) {
        Serial.println("Erreur d'initialisation de l'ESP-NOW");
      }
    
      // Une fois que ESPNow est Init avec succès, nous nous inscrirons pour l'envoi du CB .
      // obtenir l'état du paquet transmis.
      esp_now_register_send_cb(OnDataSent);
    
      // Enregistrer les  devices
      for (size_t i = 0; i < nbClientsPC; i++) {
        peerInfo.channel = 0;
        peerInfo.encrypt = false;
        memcpy(peerInfo.peer_addr, clients[i].adresse, 6);
        if (esp_now_add_peer(&peerInfo) != ESP_OK) {
          Serial.printf("Échec de l'ajout de %s\n", clients[i].nom);
          return;
        }
      }
    
      // Start the SPI for the touchscreen and init the touchscreen
      touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
      touchscreen.begin(touchscreenSPI);
      // Set the Touchscreen rotation in landscape mode
      // Note: in some displays, the touchscreen might be upside down, so you might need to set the rotation to 3: touchscreen.setRotation(3);
      touchscreen.setRotation(3);
    
      // Start the tft display
      tft.init();
      // Set the TFT display rotation in landscape mode
      tft.setRotation(1);
    
      // Clear the screen before writing to it
      tft.fillScreen(TFT_BLACK);
    
      // Initialisation des positions des boutons
      int buttonX = 20;
      int buttonY = 20;
      for (int i = 0; i < 9; ++i)
      {
        buttons[i].x = buttonX;
        buttons[i].y = buttonY;
        buttons[i].state = false;
    
        // Affichage des boutons
        drawButton(buttonX, buttonY, buttons[i].state);
    
        buttonX += BUTTON_WIDTH + BUTTON_MARGIN;
        if (buttonX + BUTTON_WIDTH > tft.width()) {
          buttonX = 20;
          buttonY += BUTTON_HEIGHT + BUTTON_MARGIN;
        }
      }
    
    }
    
    //************************************************
    // LOOP
    //************************************************
    void loop()
    {
    
      // Checks if Touchscreen was touched, and prints X, Y and Pressure (Z) info on the TFT display and Serial Monitor
      if (touchscreen.tirqTouched() && touchscreen.touched())
      {
        // Get Touchscreen points
        TS_Point p = touchscreen.getPoint();
        // Calibrate Touchscreen points with map function to the correct width and height
        touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
        touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
        touchZ = p.z;
    
        //printTouchToSerial(touchX, touchY, touchZ);
    
        for (int i = 0; i < 9; ++i)
        {
          if (touchX >= buttons[i].x && touchX <= buttons[i].x + BUTTON_WIDTH &&
              touchY >= buttons[i].y && touchY <= buttons[i].y + BUTTON_HEIGHT)
          {
            // Si un bouton est touché, inverse son état et met à jour l'affichage
            buttons[i].state = !buttons[i].state;
            drawButton(buttons[i].x, buttons[i].y, buttons[i].state);
            if (buttons[i].state == 1) {
              Serial.print("Btn "); Serial.print(i + 1); Serial.println(" enfoncé");
              snprintf(myData.a, sizeof myData.a, "PC%02d=> ON", i + 1);
              myData.b =  true;
              esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData));
              if (result == ESP_OK) {
                Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès");
              } else {
                Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1);
              }
            }
    
            if (buttons[i].state == 0)
            {
              Serial.print("Btn "); Serial.print(i + 1); Serial.println(" relaché");
              snprintf(myData.a, sizeof myData.a, "PC%02d=> OFF", i + 1);
              myData.b =  false;
              esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData));
              if (result == ESP_OK) {
                Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès");
              } else {
                Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1);
              }
            }
          }
          //break;
          delay(200);
        }
      }
    }
    
    // Dessine un bouton à une position donnée avec un état donné
    void drawButton(int x, int y, bool state) {
      uint16_t color = state ? TFT_RED : TFT_GREEN;
      tft.fillRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, color);
      tft.drawRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, TFT_WHITE);
    }

  11. #51
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Super!! Grand Merci Jay M


    18:11:22.080 -> ets Jul 29 2019 12:21:46
    18:11:22.080 ->
    18:11:22.080 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    18:11:22.080 -> configsip: 0, SPIWP:0xee
    18:11:22.080 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    18:11:22.080 -> modeIO, clock div:1
    18:11:22.080 -> load:0x3fff0030,len:1344
    18:11:22.080 -> load:0x40078000,len:13964
    18:11:22.080 -> load:0x40080400,len:3600
    18:11:22.080 -> entry 0x400805f0
    18:11:22.358 -> E (210) psram: PSRAM ID read error: 0xffffffff
    18:11:22.546 -> 1 Adresse1 : 0xB4 0xE6 0x2D 0x78 0x83 0x54
    18:11:22.546 -> 2 Adresse2 : 0xC8 0x2B 0x96 0x1F 0x7F 0x77
    18:11:22.546 -> 3 Adresse3 : 0x50 0x02 0x91 0x77 0xEE 0xFA
    18:11:22.546 -> 4 Adresse4 : 0xEC 0xFA 0xBC 0xD8 0x28 0xD6
    18:11:22.546 -> 5 Adresse5 : 0x48 0x3F 0xDA 0x67 0xFD 0x5F
    18:11:22.546 -> 6 Adresse6 : 0xA4 0xCF 0x12 0xFC 0xF9 0x3E
    18:11:22.546 -> 7 Adresse7 : 0x40 0xF5 0x20 0x33 0xA5 0xC8
    18:11:22.546 -> 8 Adresse8 : 0xFC 0xF5 0xC4 0xAA 0x5D 0x61
    18:11:22.546 -> 9 Adresse9 : 0xD8 0xBF 0xC0 0x11 0xE6 0xFE
    18:11:22.592 -> ESPNow Init Success
    18:11:26.306 -> Btn 1 enfoncé
    18:11:26.306 -> PC1 Envoyé avec succès
    18:11:26.352 ->
    18:11:26.352 -> État de l'envoi du dernier paquet: Échec // Norma l<== le recepteur non actif
    18:11:57.455 -> Btn 1 relaché
    18:11:57.455 -> PC1 Envoyé avec succès
    18:11:57.455 ->
    18:11:57.455 -> État de l'envoi du dernier paquet: Succès
    18:12:01.402 -> Btn 1 enfoncé
    18:12:01.402 -> PC1 Envoyé avec succès
    18:12:01.402 ->
    18:12:01.402 -> État de l'envoi du dernier paquet: Succès

  12. #52
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    Cool !👍

  13. #53
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Merci encore pour votre patience
    Jay M

    -maintenant prochaine étape pour l’Émetteur

    1) passer en mode sommeil
    2) et le réveil de l'ESP32 par touch-ecran TFT

  14. #54
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    Citation Envoyé par cobra38 Voir le message
    1) passer en mode sommeil
    2) et le réveil de l'ESP32 par touch-ecran TFT
    il faudra regarder si les pins liées aux touch permettent de faire une interruption et voir comment vous pouvez couper l'alimentation de l'écran sans couper la partie touch.

    Souvenez vous aussi que lorsque l'on sort du mode sommeil sur un ESP32, c'est comme s'il rebootait donc votre setup() sera appelé puis la loop(). La seule différence c'est que les variables stockées dans la mémoire RTC auront conservé leurs valeurs.

  15. #55
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    il faudra regarder si les pins liées aux touch permettent de faire une interruption et voir comment vous pouvez couper l'alimentation de l'écran sans couper la partie touch.
    je me posais la question s'il n'était pas plus facile d'utiliser par ex GPIO4 comme "touch externe" ( TTP223 ) plutôt que m'embarquer à comptabiliser l'ensemble des TFT_TOUCH et surtout de surveiller l'écran en entier
    pour déclencher le réveil de l'ESP32

    Souvenez vous aussi que lorsque l'on sort du mode sommeil sur un ESP32, c'est comme s'il rebootait donc votre setup() sera appelé puis la loop(). La seule différence c'est que les variables stockées dans la mémoire RTC auront conservé leurs valeurs.
    ok c'est noté, mais le croquis charge déjà dans le setup l'ensemble des adresses des ESP01s
    vous pensez à quoi exactement à l'état des boutons par ex ( 1 ou 0 ) ?
    Images attachées Images attachées  

  16. #56
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    ce serait bcp plus simple en effet d'utiliser un autre bouton "on-off" si l'écran n'offre pas cette possibilité

    je n'avais rien en tête de particulier, je ne sais pas si le code a pour but d'être augmenté et que vous accumulez des infos etc... s'il n'y a pas d'état à mémoriser, oui un reboot n'est pas important

  17. #57
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    n'étant pas très au fait de test écran ,j'ai préféré opter avec un TPP223 (GPIO4) que j'avais sous la main
    Principe : le bouton pour le réveil et l'écran s'éteint au bout 30s si aucune touche n'est appuyée

    le croquis suivant semble fonctionner pour ce qui de la mise en sommeil et du réveil par GPIO4
    mais il me manque 1 dernière chose à savoir , la mise en mémoire de l'état des boutons

    existerait-il un moyen de mettre ces états en Eprom par ex et de rappeler ces états pour les 9 boutons au moment du reveil ?
    pour info : j'utilise déjà RTC_DATA_ATTR int bootCount = 0; pour comptabilser les reboots

    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
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
     
    // EMETTEUR uPesy ESP32 Wroom DevKit //
     
    #include <SPIFFS.h>
    #include <SPI.h>
    #include <TFT_eSPI.h>
    #include <XPT2046_Touchscreen.h> // https : //github. com/PaulStoffregen/XPT2046_Touchscreen
    #include <esp_now.h>
    #include <WiFi.h>
     
    TFT_eSPI tft = TFT_eSPI();
     
    // Touchscreen pins
    #define XPT2046_IRQ 36   // T_IRQ
    #define XPT2046_MOSI 32  // T_DIN
    #define XPT2046_MISO 39  // T_OUT
    #define XPT2046_CLK 25   // T_CLK
    #define XPT2046_CS 33    // T_CS
     
     
     
    SPIClass touchscreenSPI = SPIClass(VSPI);
    XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ);
     
    #define SCREEN_WIDTH 320
    #define SCREEN_HEIGHT 240
    #define FONT_SIZE 2
     
    // definition des boutons
    #define BUTTON_WIDTH  80
    #define BUTTON_HEIGHT 60
    #define BUTTON_MARGIN 10
     
    RTC_DATA_ATTR int bootCount = 0;
     
     
    // Structure pour représenter un bouton *************
    struct Button {
      int x, y;
      bool state;
    };
    Button buttons[9]; // 9 boutons
    /*****************************************************************/
     
    /*Imprimer les informations de l'écran tactile concernant X, Y et la pression (Z) sur le moniteur série*/
    void printTouchToSerial(int touchX, int touchY, int touchZ) {
      Serial.print("X = ");
      Serial.print(touchX);
      Serial.print(" | Y = ");
      Serial.print(touchY);
      Serial.print(" | Pressure = ");
      Serial.print(touchZ);
      Serial.println();
    }
    /*****************************************************************/
     
    /*** Structure Fichier Config.txt ********************************/
    const size_t tailleMaxNom = 16;     // y compris le caractère nul final
    struct ClientPC {
      char nom[tailleMaxNom];           // le nom du client PC
      uint8_t adresse[6];               // les 6 octets de son adresse
    };
     
    const size_t nbMaxClients = 20;     // nombre maximum de clients
    ClientPC clients[nbMaxClients];
    size_t nbClientsPC = 0;            // le nombre de clients lu dans le fichier de config
     
    /*****************************************************************/
     
    // ***** Structure du récepteur *************************************
    struct struct_message {
      char a[32]; // ex PC1
      bool b;     // Etat = 0 ou 1
    };
    // Créer une struct_message appelée myData
    struct_message myData;
     
    //........... Etat enoi ********************************************
    esp_now_peer_info_t peerInfo;
     
     
    void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
      Serial.print("\r\nÉtat de l'envoi du dernier paquet:\t");
      Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Succès" : "Échec");
    }
    //*********************************************************************
     
    // Init ESP Now with fallback
    void InitESPNow() {
      WiFi.disconnect();
      if (esp_now_init() == ESP_OK) {
        Serial.println("ESPNow Init Success");
      }
      else {
        Serial.println("ESPNow Init Failed");
        // Retry InitESPNow, add a counte and then restart?
        // InitESPNow();
        // or Simply Restart
        ESP.restart();
      }
    }
     
    unsigned long currentTime=0;
    unsigned long previousTime=0;
    int touchX, touchY, touchZ , i;
     
    //************************************************
    // SETUP
    //************************************************
    void setup()
    {
      Serial.begin(115200);
      //Incrémente le numéro de démarrage et l'imprime à chaque redémarrage
      ++bootCount;
      Serial.println("Boot number: " + String(bootCount));
     
      // Lire le fichier Config.txt 
      if (!SPIFFS.begin(true)) {
        Serial.println("Une erreur s'est produite lors du montage de SPIFFS");
        return;
      }
      File fichierConfig = SPIFFS.open("/config.txt", FILE_READ);
      if (!fichierConfig) {
        Serial.println("Impossible d'ouvrir le fichier en lecture");
        return;
      }
      char bufferLigne[100]; // Buffer pour stocker chaque ligne
      char format[64]; // pour bâtir dynamiquement le format en tenant compte de la longueur max du nom (reco de Kernighan et Pike dans "The Practice of Programming")
      snprintf(format, sizeof format, "%%%ds %%hhx %%hhx %%hhx %%hhx %%hhx %%hhx", tailleMaxNom - 1); // lire une chaine de taille max tailleMaxNom - 1 suivie de 6 octets en hexa
      nbClientsPC = 0;
      while (fichierConfig.available() && nbClientsPC < nbMaxClients) {   // tant qu'on peut lire quelque chose et qu'on a de la place pour stocker
        memset(bufferLigne, '\0', sizeof bufferLigne); // Effacer le buffer
        fichierConfig.readBytesUntil('\n', bufferLigne, sizeof bufferLigne); // Lire la ligne dans le buffer
        memset(clients[nbClientsPC].nom, '\0', sizeof clients[nbClientsPC].nom); // on efface le nom pour être tranquille
        int nbChampsLus = sscanf(bufferLigne, format,
                                 clients[nbClientsPC].nom,
                                 &clients[nbClientsPC].adresse[0], &clients[nbClientsPC].adresse[1],
                                 &clients[nbClientsPC].adresse[2], &clients[nbClientsPC].adresse[3],
                                 &clients[nbClientsPC].adresse[4], &clients[nbClientsPC].adresse[5]);
     
        if (nbChampsLus == 7) {
          // la lecture des 7 champs (le nom et 8 octets sous forme hexadécimale) s'est bien passée
          nbClientsPC++;
        } else {
          // on arrête de lire là
          break;
        }
      }
      fichierConfig.close();
     
      // Affichage des adresses lues depuis le fichier
      for (size_t i = 0; i < nbClientsPC; i++) {
        Serial.printf("%3zu %-*s : ", i + 1, tailleMaxNom - 1, clients[i].nom); // l'index sur 3 caractères, le nom sur tailleMaxNom - 1 cadrée à gauche
        for (int j = 0; j < 6; j++) Serial.printf("0x%02X ", clients[i].adresse[j]);
        Serial.println();
      }
     
      // Set device as a Wi-Fi Station
      WiFi.mode(WIFI_STA);
     
      // Init ESP-NOW
      InitESPNow();
      if (esp_now_init() != ESP_OK) {
        Serial.println("Erreur d'initialisation de l'ESP-NOW");
      }
      esp_now_register_send_cb(OnDataSent);
      for (size_t i = 0; i < nbClientsPC; i++) {   // Enregistrer les  devices
        peerInfo.channel = 0;
        peerInfo.encrypt = false;
        memcpy(peerInfo.peer_addr, clients[i].adresse, 6);
        if (esp_now_add_peer(&peerInfo) != ESP_OK) {
          Serial.printf("Échec de l'ajout de %s\n", clients[i].nom);
          return;
        }
      }
     
      // Démarrer le SPI pour l'écran tactile et initialiser l'écran tactile
      touchscreenSPI.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
      touchscreen.begin(touchscreenSPI);
      touchscreen.setRotation(3);
      tft.init();
      tft.setRotation(1);
      tft.fillScreen(TFT_BLACK);
     
      // Initialisation des positions des boutons
      int buttonX = 20;
      int buttonY = 20;
      for (int i = 0; i < 9; ++i)
      {
        buttons[i].x = buttonX;
        buttons[i].y = buttonY;
        buttons[i].state = false;
     
        // Affichage des boutons
        drawButton(buttonX, buttonY, buttons[i].state);
     
        buttonX += BUTTON_WIDTH + BUTTON_MARGIN;
        if (buttonX + BUTTON_WIDTH > tft.width()) {
          buttonX = 20;
          buttonY += BUTTON_HEIGHT + BUTTON_MARGIN;
        }
      }
      //Imprimer la raison du réveil de l'ESP32
      print_wakeup_reason();
     
     
      esp_sleep_enable_ext0_wakeup(GPIO_NUM_4,1); //1 = High, 0 = Low
     
      //Go to sleep now
      //Serial.println("Je vais m'endormir maintenant");
      //delay(1000);
      //esp_deep_sleep_start();
     
    }
     
    //************************************************
    // LOOP
    //************************************************
    void loop()
    {
      currentTime=millis();
     
    	  // Vérifie si l'écran tactile a été touché et imprime les informations X, Y et la pression (Z) sur l'écran TFT et le moniteur série.
    	  if (touchscreen.tirqTouched() && touchscreen.touched())
    	  {
    		previousTime=currentTime;  
    		// Get Touchscreen points
    		TS_Point p = touchscreen.getPoint();
    		// Calibrate Touchscreen points with map function to the correct width and height
    		touchX = map(p.x, 200, 3700, 1, SCREEN_WIDTH);
    		touchY = map(p.y, 240, 3800, 1, SCREEN_HEIGHT);
    		touchZ = p.z;
     
    		//printTouchToSerial(touchX, touchY, touchZ);
     
    		for (int i = 0; i < 9; ++i)
    		{
    		  if (touchX >= buttons[i].x && touchX <= buttons[i].x + BUTTON_WIDTH &&
    			  touchY >= buttons[i].y && touchY <= buttons[i].y + BUTTON_HEIGHT)
    		  {
    			// Si un bouton est touché, inverse son état et met à jour l'affichage
    			buttons[i].state = !buttons[i].state;
    			drawButton(buttons[i].x, buttons[i].y, buttons[i].state);
    			if (buttons[i].state == 1) {
    			  Serial.print("Btn "); Serial.print(i + 1); Serial.println(" enfoncé");
    			  snprintf(myData.a, sizeof myData.a, "PC%02d=> ON", i + 1);
    			  myData.b =  true;
    			  esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData));
    			  if (result == ESP_OK) {
    				Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès");
    			  } else {
    				Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1);
    			  }
    			}
     
    			if (buttons[i].state == 0)
    			{
    			  Serial.print("Btn "); Serial.print(i + 1); Serial.println(" relaché");
    			  snprintf(myData.a, sizeof myData.a, "PC%02d=> OFF", i + 1);
    			  myData.b =  false;
    			  esp_err_t result = esp_now_send(clients[i].adresse, (uint8_t *)&myData, sizeof(myData));
    			  if (result == ESP_OK) {
    				Serial.print("PC"); Serial.print(i + 1); Serial.println(" Envoyé avec succès");
    			  } else {
    				Serial.print("Erreur d'envoi des données PC"); Serial.print(i + 1);
    			  }
    			}
    		  }
    		  //break;
    		  delay(200);
    		}
    	  }
    	   if((currentTime-previousTime)>30000){  
    	   //Go to sleep now
             Serial.println("Je vais m'endormir maintenant");
             delay(1000);
             esp_deep_sleep_start();  
    	   }  
    }
     
    // Dessine un bouton à une position donnée avec un état donné
    void drawButton(int x, int y, bool state) {
      uint16_t color = state ? TFT_RED : TFT_GREEN;
      tft.fillRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, color);
      tft.drawRect(x, y, BUTTON_WIDTH, BUTTON_HEIGHT, TFT_WHITE);
    }
     
    /*******************************************************/
    void print_wakeup_reason(){
      esp_sleep_wakeup_cause_t wakeup_reason;
     
      wakeup_reason = esp_sleep_get_wakeup_cause();
     
      switch(wakeup_reason)
      {
        case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Réveil causé par un signal externe utilisant RTC_IO"); break;
        case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Réveil provoqué par un signal externe utilisant RTC_CNTL"); break;
        case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Réveil provoqué par la minuterie"); break;
        case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
        case ESP_SLEEP_WAKEUP_ULP : Serial.println("Réveil causé par le programme ULP"); break;
        default : Serial.printf("Le réveil n'a pas été causé par un sommeil profond : %d\n",wakeup_reason); break;
      }
    }

  18. #58
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    Pour ce qui doit rester un mémoire il faut déclarer votre variable en RTC_DATA_ATTR comme vous avez fait. Ça marche aussi pour les tableaux

    Ensuite je ne sais pas trop à quoi correspond l’état des boutons - si je suis en train de manipuler l’écran alors le système ne devrait pas s’éteindre

  19. #59
    Membre actif
    Inscrit en
    Juillet 2004
    Messages
    797
    Détails du profil
    Informations forums :
    Inscription : Juillet 2004
    Messages : 797
    Points : 230
    Points
    230
    Par défaut
    Pour ce qui doit rester un mémoire il faut déclarer votre variable en RTC_DATA_ATTR comme vous avez fait. Ça marche aussi pour les tableaux
    du genre ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RTC_DATA_ATTR uint8_t etat[] = {0,0,0,0,0,0,0,0,0};
    Ensuite je ne sais pas trop à quoi correspond l’état des boutons - si je suis en train de manipuler l’écran alors le système ne devrait pas s’éteindre
    l'etat 1 = lampe
    l'etat 0 = lampe éteinte

    j'ai mis dans le test clavier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    previousTime=currentTime;
    ce n'est pas suffisant ?


    Pour tester , j'avais mis dans le fichier config.txt et la structure "ClientPC"un champ "etat" supplémentaire , çà évitait d'utiliser l'EEPROM mais çà ne semble pas fonctionner ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    /*** Structure Fichier Config.txt ********************************/
    const size_t tailleMaxNom = 16;     // y compris le caractère nul final
    struct ClientPC {
      char nom[tailleMaxNom];            // le nom du client PC
      bool etat;                               // <=================================
      uint8_t adresse[6];               // les 6 octets de son adresse
    };

  20. #60
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 783
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 783
    Points : 5 591
    Points
    5 591
    Par défaut
    À moins de sauver dans le fichier à chaque modification d’état, la valeur que vous avez dans le fichier, ne va jamais changer

Discussions similaires

  1. Mesh Network via BLE
    Par matthieuboubou dans le forum Projets
    Réponses: 0
    Dernier message: 21/04/2015, 14h10
  2. [WD18] Bluetooth 4.0 et BLE
    Par ihih45 dans le forum WinDev
    Réponses: 4
    Dernier message: 21/04/2015, 13h40
  3. Reconnaissance des grains de blés coupés
    Par arken dans le forum Traitement d'images
    Réponses: 5
    Dernier message: 08/04/2011, 11h04
  4. Comment sauvegarder bles sources des procedures stockées?
    Par tonton67 dans le forum Développement
    Réponses: 2
    Dernier message: 24/02/2009, 08h53
  5. cas des grains de blé
    Par Maxence45 dans le forum Excel
    Réponses: 13
    Dernier message: 07/11/2007, 19h46

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