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 :

Pretzel Board IOT - Bug bizarre


Sujet :

Arduino

  1. #1
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut Pretzel Board IOT - Bug bizarre
    Bonjour à tous,

    Je commence à travailler avec le coffret "Franzis Maker Kit IOT".
    Il est basé sur une carte "Pretzel Wifi", c'est une carte compatible Arduino Nano (Nano ESP) avec module ESP8266 WIFI.

    Je code avec l'IDE Arduino v1.8.12 sous Windows 7 pro 64, configuré comme suit :
    - Type de carte "Arduino Nano"
    - Processeur "ATmega328P (Old Bootloader)"
    - Programmateur "USBasp"

    On arrive à un truc intéressant avec l'horloge TCP.
    La carte Pretzel est configurée en client Wifi qui se connecte régulièrement à un site web qui donne l'heure atomique, la carte affiche l'heure et la date sur un écran à cristaux liquides de 2 lignes de 16 caractères.

    J'ai adapté le code pour me familiariser avec la carte et le langage C Arduino.
    Je voulais afficher le nom du jour, et le mois en toutes lettres. Ca 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
    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
    #include <SD.h>
     
    #define SSID "XXXX"
    #define PASSWORD "MA_CLEF_WEP"
     
    #define DEBUG true
     
    #define LED_WLAN 13
     
    #include <SoftwareSerial.h>
    #include <TimeLib.h>
    #include <LiquidCrystal.h>
     
    LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
    SoftwareSerial esp8266(11, 12); // RX, TX
     
    void setup() {
      Serial.begin(19200);
      esp8266.begin(19200);
     
     
      lcd.begin(16, 2);
      lcd.setCursor(0, 0);
      lcd.print("Horloge Web");
     
     
      if (!espConfig()) serialDebug();
      else digitalWrite(LED_WLAN, HIGH);
     
     
      lcd.setCursor(0, 1);
      lcd.print("Liaison WIFI OK");
     
     
      getTime("chronic.herokuapp.com", "/utc/in+two+hours"); //Gets Time from Page and Sets it
    }
     
    void loop() {
      String shour, sminute, ssecond, sday, smonth, sweekday;
     
      delay(1000);
     
      if (hour() <= 9) shour = "0" + String(hour()); else shour = String(hour()); // adjust for 0-9
      if (minute() <= 9) sminute = "0" + String(minute());  else sminute = String(minute());
      if (second() <= 9) ssecond = "0" + String(second());  else ssecond = String(second());
     
    sweekday = String(weekday()) + " Jeudi";
     
      String Time =  shour + "h" + sminute + ":" + ssecond + " " + sweekday;
     
    sday = String(day());
    switch (month()) {
      case 1:
        smonth = "janvier";
        break;
      case 2:
        smonth = "fevrier";
        break;
      case 3:
        smonth = "mars";
        break;
      case 4:
        smonth = "avril";
        break;
      case 5:
        smonth = "mai";
        break;
      case 6:
        smonth = "juin";
        break;
      case 7:
        smonth = "juillet";
        break;
      case 8:
        smonth = "aout";
        break;
      case 9:
        if (sday.length()>1) {
          smonth = "septembr";  
        } else {
          smonth = "septembre";
        }
        break;
      case 10:
        smonth = "octobre";
        break;
      case 11:
        smonth = "novembre";
        break;
      default:
        smonth = "decembre";
        break;
    }
     
      String Date = sday + " " + smonth + " " + String(year()) ;
     
      int LgTxt;
      int NbSp;
      LgTxt = Date.length();
      if (LgTxt<16) {
        NbSp = (16 - LgTxt) / 2;
        for (int i=1;i<=NbSp;i++) {
          Date = " " + Date;    
        }
        NbSp = 16 - LgTxt - NbSp;
        for (int i=1;i<=NbSp;i++) {
          Date = Date + " ";
        }
      }
     
      debug(Date);
      debug(Time);
     
      lcd.setCursor(0, 0);
      lcd.print(Time);
     
      lcd.setCursor(0, 1);
      lcd.print(Date);
     
    }
     
     
    String getTCP(String Host, String Subpage)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      return sendCom(getRequest);
    }
     
    boolean getTime(String Host, String Subpage)
    {
      boolean success = true;
      int xyear, xmonth, xday, xhour, xminute, xsecond;  //lokal variables
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      esp8266.println(getRequest);
     
      if (esp8266.find("+IPD"))
      {
        if (esp8266.find("\r\n\r\n"))
        {
          xyear = esp8266.parseInt();
          xmonth = esp8266.parseInt();
          xday = esp8266.parseInt();
          xhour = esp8266.parseInt();
          xminute = esp8266.parseInt();
          xsecond = esp8266.parseInt();
     
          if (xday < 0) xday *= -1;          //Because of date seperator - parseInt detects negativ integer
          if (xmonth < 0) xmonth *= -1;    //Because of date seperator - parseInt detects negativ integer
     
     
          setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
          sendCom("AT+CIPCLOSE", "OK");
          return true;
        }
        else return false;
      }
      else return false;
    }
     
    //-----------------------------------------Config ESP8266------------------------------------
     
    boolean espConfig()
    {
      boolean success = true;
      esp8266.setTimeout(5000);
      success &= sendCom("AT+RST", "ready");
      esp8266.setTimeout(1000);
      if (configStation(SSID, PASSWORD)) {
        success &= true;
        debug("WLAN Connected");
        debug("My IP is:");
        debug(sendCom("AT+CIFSR"));
      }
      else
      {
        success &= false;
      }
      //shorter Timeout for faster wrong UPD-Comands handling
      success &= sendCom("AT+CIPMODE=0", "OK");  //So rum scheit wichtig!
      success &= sendCom("AT+CIPMUX=0", "OK");
     
      return success;
    }
     
    boolean configTCPServer()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=1", "OK"));
      success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
    boolean configTCPClient()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      //success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
     
    boolean configStation(String vSSID, String vPASSWORT)
    {
      boolean success = true;
      success &= (sendCom("AT+CWMODE=1", "OK"));
      esp8266.setTimeout(20000);
      success &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK"));
      esp8266.setTimeout(1000);
      return success;
    }
     
    boolean configAP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CWMODE=2", "OK"));
      success &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0", "OK"));
     
      return success;
    }
     
    boolean configUDP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMODE=0", "OK"));
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.255.255\",90,91,2", "OK"); //Importand Boradcast...Reconnect IP
      return success;
    }
     
    //-----------------------------------------------Controll ESP-----------------------------------------------------
     
    boolean sendUDP(String Msg)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2), ">");    //+",\"192.168.4.2\",90", ">");
      if (success)
      {
        success &= sendCom(Msg, "OK");
      }
      return success;
    }
     
     
    boolean sendCom(String command, char respond[])
    {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR"))
      {
        return true;
      }
      else
      {
        debug("ESP SEND ERROR: " + command);
        return false;
      }
    }
     
    String sendCom(String command)
    {
      esp8266.println(command);
      return esp8266.readString();
    }
     
     
    void serialDebug() {
      while (true)
      {
        if (esp8266.available())
          Serial.write(esp8266.read());
        if (Serial.available())
          esp8266.write(Serial.read());
      }
    }
     
    void debug(String Msg)
    {
      if (DEBUG)
      {
        Serial.println(Msg);
      }
    }
    Voici une photo de la carte en fonctionnement (le port USB assure l'alimentation, la programmation via le PC et le monitoring série) :

    Nom : Pretzel.jpg
Affichages : 226
Taille : 316,5 Ko

    Mais quand je souhaite remplacer la ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sweekday = String(weekday()) + " Jeudi";
    par le code suivant :

    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
    switch (weekday()) {
    //switch (second()%7+1) {
      case 1:
        sweekday = "Dimanch";
        break;
      case 2:
        sweekday = "  Lundi";
        break;
      case 3:
        sweekday = "  Mardi";
        break;
      case 4:
        sweekday = "Mercred";
        break;
      case 5:
        sweekday = "  Jeudi";
        break;
      case 6:
        sweekday = "Vendred";
        break;
      default:
        sweekday = " Samedi";
        break;
    }
    Ca ne marche plus !

    Ca compile sans soucis, ça se téléverse sans soucis, mais l'afficheur LCD reste bloqué sur "Horloge Web"

    Je ne vois pas le message "Liaison WIFI OK", ni l'heure et la date qui s'affiche ensuite dans le LCD

    Le moniteur série reste lui aussi muet, mais il réagit normalement si je lui tape une commande comme par exemple "AT+GMR"

    20:12:05.376 -> AT+GMR
    20:12:05.376 -> AT version:0.22.0.0(Mar 20 2015 10:04:26)
    20:12:05.410 -> SDK version:1.0.0
    20:12:05.410 -> compile time:Mar 20 2015 11:00:32
    20:12:05.410 ->
    20:12:05.410 -> OK

    Bizarrement dans le menu admin de ma freebox, je vois que ma carte PRETZEL est connectée, et qu'elle communique chaque seconde :

    Nom : Freebox.jpg
Affichages : 199
Taille : 204,4 Ko

    (c'est la carte "Espressif Inc.")

    Donc c'est à moitié planté
    - l'affichage ne se fait plus sur l'écran LCD ni sur le moniteur série
    - mais la carte continuer à tourner, elle accède à Internet régulièrement et elle réagit aux commandes du terminal...

    Je viens de passer l'après midi sur ce problème sans comprendre pourquoi ça ne fonctionne pas...

    Je pense que c'est lié à la bibliothèque de l'afficheur car si dans le code qui marche bien je remplace "Horloge Web" par "Horloge Internet" (texte faisant pile 16 caractères) ça plante de la même façon

    La bibliothèque LCD doit planter quelque chose au niveau des entrées sorties, peut-être à cause d'un problème de mémoire mais je ne sais pas quoi !

    Avez-vous une piste ?

    Merci

    A bientôt

  2. #2
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 817
    Points : 5 674
    Points
    5 674
    Par défaut
    C’est un peu dépassé comme carte (2015 je ne sais pas quelle version firmware il y a dans l’esp), j’espère que vous ne venez pas de l’acheter...

    Faudrait voir tout le code qui bug et quelle bibliothèque vous avez installé (version d’origine il y a quelques années ou la dernière version)

    L’usage de software serial en conjonction avec d’autres interruptions (écran qui est lent) peut aussi mettre le bazar... vous avez essayé avec juste un affichage sur la console série en la mettant à 115200 bauds et en enlevant tout le code du lcd pour séparer les problèmes (même si hardware serial utilise aussi des interruption)

  3. #3
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Citation Envoyé par Jay M Voir le message
    C’est un peu dépassé comme carte (2015 je ne sais pas quelle version firmware il y a dans l’esp), j’espère que vous ne venez pas de l’acheter...

    Faudrait voir tout le code qui bug et quelle bibliothèque vous avez installé (version d’origine il y a quelques années ou la dernière version)

    L’usage de software serial en conjonction avec d’autres interruptions (écran qui est lent) peut aussi mettre le bazar... vous avez essayé avec juste un affichage sur la console série en la mettant à 115200 bauds et en enlevant tout le code du lcd pour séparer les problèmes (même si hardware serial utilise aussi des interruption)
    Bonjour,

    j'ai acheté le kit contenant cette carte le 22/05/2017

    le kit a dormi sur une étagère jusqu'à ce que grâce au coronavirus j'ai de nouveau du temps libre pour faire de l'électronique

    J'ai les dernières versions des bibliothèques livrées avec l'IDE Arduino v1.8.12 que je viens d'installer

    J'ai du remplacer Time.h par TimeLib.h dans le code

    J'ai essayé ce que vous avez dit : j'ai retiré tout ce qui concerne l'afficheur LCD dans le code pour ne laisser que l'interface série.

    Tout fonctionne !

    Vous avez vu juste : cumuler les bibliothèques utilisant chacune des interruptions n'est pas une bonne idée

    D'ailleurs je trouve bizarre que la bibliothèque LCD utilise des interruptions... Pour ma carte à 8051, je gère un clavier multiplexé et un LCD, je n'ai utilisé qu'une interruption pour mesurer précisément le temps pour la fonction minuterie. (https://www.developpez.net/forums/d2...annage-maison/)

    A bientôt

    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
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    #include <SD.h>
     
    /*
    TCP Time Sync.
     
    Time Source:
    http://chronic.herokuapp.com/
     
    Change SSID and PASSWORD.
    */
     
    #define SSID "BOX"
    #define PASSWORD "WEP"
     
    #define DEBUG true
     
    #define LED_WLAN 13
     
    #include <SoftwareSerial.h>
    #include <TimeLib.h>
    //#include <LiquidCrystal.h>
     
    // RS, E, D4, D5, D6, D7
    //LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
    SoftwareSerial esp8266(11, 12); // RX, TX
     
    void setup() {
      Serial.begin(19200);
      esp8266.begin(19200);
     
     
      //lcd.begin(16, 2);
      //lcd.setCursor(0, 0);
      //lcd.print("Horloge Web");
     
     
      if (!espConfig()) serialDebug();
      else digitalWrite(LED_WLAN, HIGH);
     
     
      //lcd.setCursor(0, 1);
      //lcd.print("Liaison WIFI OK");
     
     
      getTime("chronic.herokuapp.com", "/utc/in+two+hours"); //Gets Time from Page and Sets it
    }
     
    void loop() {
      String shour, sminute, ssecond, sday, smonth, sweekday;
     
      delay(1000);
     
      if (hour() <= 9) shour = "0" + String(hour()); else shour = String(hour()); // adjust for 0-9
      if (minute() <= 9) sminute = "0" + String(minute());  else sminute = String(minute());
      if (second() <= 9) ssecond = "0" + String(second());  else ssecond = String(second());
     
     
    //switch (weekday()) {
    switch (second()%7+1) {
      case 1:
        sweekday = "Dimanch";
        break;
      case 2:
        sweekday = "  Lundi";
        break;
      case 3:
        sweekday = "  Mardi";
        break;
      case 4:
        sweekday = "Mercred";
        break;
      case 5:
        sweekday = "  Jeudi";
        break;
      case 6:
        sweekday = "Vendred";
        break;
      default:
        sweekday = " Samedi";
        break;
    }
     
     
    //sweekday = String(weekday()) + " Jeudi";
     
      String Time =  shour + "h" + sminute + ":" + ssecond + " " + sweekday;
     
    //  String Time = "    " + shour + "h" + sminute + ":" + ssecond + "   ";
     
    sday = String(day()); 
    switch ((month()+second())%12+1) {   // Code pour tester l'affichage de chaque mois
    //switch (month()) {
      case 1:
        smonth = "janvier";
        break;
      case 2:
        smonth = "fevrier";
        break;
      case 3:
        smonth = "mars";
        break;
      case 4:
        smonth = "avril";
        break;
      case 5:
        smonth = "mai";
        break;
      case 6:
        smonth = "juin";
        break;
      case 7:
        smonth = "juillet";
        break;
      case 8:
        smonth = "aout";
        break;
      case 9:
        if (sday.length()>1) {
          smonth = "septembr";  
        } else {
          smonth = "septembre";
        }
        break;
      case 10:
        smonth = "octobre";
        break;
      case 11:
        smonth = "novembre";
        break;
      default:
        smonth = "decembre";
        break;
    }
     
      String Date = sday + " " + smonth + " " + String(year()) ;
     
      //Code pour centrer la date :
      int LgTxt;
      int NbSp;
      LgTxt = Date.length();
      if (LgTxt<16) {
        NbSp = (16 - LgTxt) / 2;
        for (int i=1;i<=NbSp;i++) {
          Date = " " + Date;    
        }
        NbSp = 16 - LgTxt - NbSp;
        for (int i=1;i<=NbSp;i++) {
          Date = Date + " ";
        }
      }
     
      debug(Date);
      debug(Time);
     
    /*
      lcd.setCursor(0, 0);
      lcd.print(Time);
     
      lcd.setCursor(0, 1);
      lcd.print(Date);
    */
    }
     
     
    String getTCP(String Host, String Subpage)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      return sendCom(getRequest);
    }
     
    boolean getTime(String Host, String Subpage)
    {
      boolean success = true;
      int xyear, xmonth, xday, xhour, xminute, xsecond;  //lokal variables
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      esp8266.println(getRequest);
     
      if (esp8266.find("+IPD"))
      {
        if (esp8266.find("\r\n\r\n"))
        {
          xyear = esp8266.parseInt();
          xmonth = esp8266.parseInt();
          xday = esp8266.parseInt();
          xhour = esp8266.parseInt();
          xminute = esp8266.parseInt();
          xsecond = esp8266.parseInt();
     
          if (xday < 0) xday *= -1;          //Because of date seperator - parseInt detects negativ integer
          if (xmonth < 0) xmonth *= -1;    //Because of date seperator - parseInt detects negativ integer
     
     
          setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
          sendCom("AT+CIPCLOSE", "OK");
          return true;
        }
        else return false;
      }
      else return false;
    }
     
    //-----------------------------------------Config ESP8266------------------------------------
     
    boolean espConfig()
    {
      boolean success = true;
      esp8266.setTimeout(5000);
      success &= sendCom("AT+RST", "ready");
      esp8266.setTimeout(1000);
      if (configStation(SSID, PASSWORD)) {
        success &= true;
        debug("WLAN Connected");
        debug("My IP is:");
        debug(sendCom("AT+CIFSR"));
      }
      else
      {
        success &= false;
      }
      //shorter Timeout for faster wrong UPD-Comands handling
      success &= sendCom("AT+CIPMODE=0", "OK");  //So rum scheit wichtig!
      success &= sendCom("AT+CIPMUX=0", "OK");
     
      return success;
    }
     
    boolean configTCPServer()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=1", "OK"));
      success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
    boolean configTCPClient()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      //success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
     
    boolean configStation(String vSSID, String vPASSWORT)
    {
      boolean success = true;
      success &= (sendCom("AT+CWMODE=1", "OK"));
      esp8266.setTimeout(20000);
      success &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK"));
      esp8266.setTimeout(1000);
      return success;
    }
     
    boolean configAP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CWMODE=2", "OK"));
      success &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0", "OK"));
     
      return success;
    }
     
    boolean configUDP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMODE=0", "OK"));
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.255.255\",90,91,2", "OK"); //Importand Boradcast...Reconnect IP
      return success;
    }
     
    //-----------------------------------------------Controll ESP-----------------------------------------------------
     
    boolean sendUDP(String Msg)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2), ">");    //+",\"192.168.4.2\",90", ">");
      if (success)
      {
        success &= sendCom(Msg, "OK");
      }
      return success;
    }
     
     
    boolean sendCom(String command, char respond[])
    {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR"))
      {
        return true;
      }
      else
      {
        debug("ESP SEND ERROR: " + command);
        return false;
      }
    }
     
    String sendCom(String command)
    {
      esp8266.println(command);
      return esp8266.readString();
    }
     
     
     
    //-------------------------------------------------Debug Functions------------------------------------------------------
    void serialDebug() {
      while (true)
      {
        if (esp8266.available())
          Serial.write(esp8266.read());
        if (Serial.available())
          esp8266.write(Serial.read());
      }
    }
     
    void debug(String Msg)
    {
      if (DEBUG)
      {
        Serial.println(Msg);
      }
    }

  4. #4
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Histoire de fou

    Le code suivant fonctionne,

    mais dès que j'enlève "//" devant la ligne "//LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);" ça ne fonctionne pas, la carte ne se connecte plus en WIFI

    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
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    #include <SD.h>
     
    /*
    TCP Time Sync.
     
    Time Source:
    http://chronic.herokuapp.com/
     
    Change SSID and PASSWORD.
    */
     
    #define SSID "BOX"
    #define PASSWORD "WEP"
     
    #define DEBUG false
     
    #define LED_WLAN 13
     
    #include <SoftwareSerial.h>
    #include <TimeLib.h>
    #include <LiquidCrystal.h>
     
    // RS, E, D4, D5, D6, D7
    //LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
    SoftwareSerial esp8266(11, 12); // RX, TX
     
    void setup() {
      Serial.begin(19200);
      esp8266.begin(19200);
     
     
      //lcd.begin(16, 2);
      //lcd.setCursor(0, 0);
      //lcd.print("Horloge Web");
      Serial.println("Horloge Web");
     
      if (!espConfig()) {
        //lcd.setCursor(0, 1);
        //lcd.print("Pas de WIFI");
        Serial.println("Pas de WIFI");
      }  else {
        digitalWrite(LED_WLAN, HIGH);
        //lcd.setCursor(0, 1);
        //lcd.print("Liaison WIFI OK");
        Serial.println("Liaison WIFI OK");
      }
     
      getTime("chronic.herokuapp.com", "/utc/in+two+hours"); //Gets Time from Page and Sets it
    }
     
    void loop() {
      String shour, sminute, ssecond, sday, smonth, sweekday;
     
      delay(1000);
     
      if (hour() <= 9) shour = "0" + String(hour()); else shour = String(hour()); // adjust for 0-9
      if (minute() <= 9) sminute = "0" + String(minute());  else sminute = String(minute());
      if (second() <= 9) ssecond = "0" + String(second());  else ssecond = String(second());
     
     
    switch (weekday()) {
    //switch (second()%7+1) {
      case 1:
        sweekday = "Dimanch";
        break;
      case 2:
        sweekday = "  Lundi";
        break;
      case 3:
        sweekday = "  Mardi";
        break;
      case 4:
        sweekday = "Mercred";
        break;
      case 5:
        sweekday = "  Jeudi";
        break;
      case 6:
        sweekday = "Vendred";
        break;
      default:
        sweekday = " Samedi";
        break;
    }
     
     
    //sweekday = String(weekday()) + " Jeudi";
     
      String Time =  shour + "h" + sminute + ":" + ssecond + " " + sweekday;
     
    //  String Time = "    " + shour + "h" + sminute + ":" + ssecond + "   ";
     
    sday = String(day()); 
    //switch ((month()+second())%12+1) {   // Code pour tester l'affichage de chaque mois
    switch (month()) {
      case 1:
        smonth = "janvier";
        break;
      case 2:
        smonth = "fevrier";
        break;
      case 3:
        smonth = "mars";
        break;
      case 4:
        smonth = "avril";
        break;
      case 5:
        smonth = "mai";
        break;
      case 6:
        smonth = "juin";
        break;
      case 7:
        smonth = "juillet";
        break;
      case 8:
        smonth = "aout";
        break;
      case 9:
        if (sday.length()>1) {
          smonth = "septembr";  
        } else {
          smonth = "septembre";
        }
        break;
      case 10:
        smonth = "octobre";
        break;
      case 11:
        smonth = "novembre";
        break;
      default:
        smonth = "decembre";
        break;
    }
     
      String Date = sday + " " + smonth + " " + String(year()) ;
     
      //Code pour centrer la date :
      int LgTxt;
      int NbSp;
      LgTxt = Date.length();
      if (LgTxt<16) {
        NbSp = (16 - LgTxt) / 2;
        for (int i=1;i<=NbSp;i++) {
          Date = " " + Date;    
        }
        NbSp = 16 - LgTxt - NbSp;
        for (int i=1;i<=NbSp;i++) {
          Date = Date + " ";
        }
      }
     
      Serial.println(Time + " " + Date);
      //lcd.setCursor(0, 0);
      //lcd.print(Time);
      //lcd.setCursor(0, 1);
      //lcd.print(Date);
     
    }
     
     
    String getTCP(String Host, String Subpage)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      return sendCom(getRequest);
    }
     
    boolean getTime(String Host, String Subpage)
    {
      boolean success = true;
      int xyear, xmonth, xday, xhour, xminute, xsecond;  //lokal variables
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      esp8266.println(getRequest);
     
      if (esp8266.find("+IPD"))
      {
        if (esp8266.find("\r\n\r\n"))
        {
          xyear = esp8266.parseInt();
          xmonth = esp8266.parseInt();
          xday = esp8266.parseInt();
          xhour = esp8266.parseInt();
          xminute = esp8266.parseInt();
          xsecond = esp8266.parseInt();
     
          if (xday < 0) xday *= -1;          //Because of date seperator - parseInt detects negativ integer
          if (xmonth < 0) xmonth *= -1;    //Because of date seperator - parseInt detects negativ integer
     
     
          setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
          sendCom("AT+CIPCLOSE", "OK");
          return true;
        }
        else return false;
      }
      else return false;
    }
     
    //-----------------------------------------Config ESP8266------------------------------------
     
    boolean espConfig()
    {
      boolean success = true;
      esp8266.setTimeout(5000);
      success &= sendCom("AT+RST", "ready");
      esp8266.setTimeout(1000);
      if (configStation(SSID, PASSWORD)) {
        success &= true;
        //debug("WLAN Connected");
        //debug("My IP is:");
        //debug(sendCom("AT+CIFSR"));
      }
      else
      {
        success &= false;
      }
      //shorter Timeout for faster wrong UPD-Comands handling
      success &= sendCom("AT+CIPMODE=0", "OK");  //So rum scheit wichtig!
      success &= sendCom("AT+CIPMUX=0", "OK");
     
      return success;
    }
     
    boolean configTCPServer()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=1", "OK"));
      success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
    boolean configTCPClient()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      //success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
     
    boolean configStation(String vSSID, String vPASSWORT)
    {
      boolean success = true;
      success &= (sendCom("AT+CWMODE=1", "OK"));
      esp8266.setTimeout(20000);
      success &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK"));
      esp8266.setTimeout(1000);
      return success;
    }
     
    boolean configAP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CWMODE=2", "OK"));
      success &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0", "OK"));
     
      return success;
    }
     
    boolean configUDP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMODE=0", "OK"));
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.255.255\",90,91,2", "OK"); //Importand Boradcast...Reconnect IP
      return success;
    }
     
    //-----------------------------------------------Controll ESP-----------------------------------------------------
     
    boolean sendUDP(String Msg)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2), ">");    //+",\"192.168.4.2\",90", ">");
      if (success)
      {
        success &= sendCom(Msg, "OK");
      }
      return success;
    }
     
     
    boolean sendCom(String command, char respond[])
    {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR"))
      {
        return true;
      }
      else
      {
        //debug("ESP SEND ERROR: " + command);
        return false;
      }
    }
     
    String sendCom(String command)
    {
      esp8266.println(command);
      return esp8266.readString();
    }
     
     
     
    //-------------------------------------------------Debug Functions------------------------------------------------------
    /*
     void serialDebug() {
      while (true)
      {
        if (esp8266.available())
          Serial.write(esp8266.read());
        if (Serial.available())
          esp8266.write(Serial.read());
      }
    }
    */
    /*
    void debug(String Msg)
    {
      if (DEBUG)
      {
        Serial.println(Msg);
      }
    }
    */
    Le code suivant fonctionne mais sans connections WIFI (tout s'affiche sur le LCD mais avec la date du 01/01/1970 logique puisque le programme n'a pas pu se connecter)

    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
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    #include <SD.h>
     
    /*
    TCP Time Sync.
     
    Time Source:
    http://chronic.herokuapp.com/
     
    Change SSID and PASSWORD.
    */
     
    #define SSID "BOX"
    #define PASSWORD "WEP"
     
    #define DEBUG false
     
    #define LED_WLAN 13
     
    #include <SoftwareSerial.h>
    #include <TimeLib.h>
    #include <LiquidCrystal.h>
     
    // RS, E, D4, D5, D6, D7
    LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
    SoftwareSerial esp8266(11, 12); // RX, TX
     
    void setup() {
      Serial.begin(19200);
      esp8266.begin(19200);
     
     
      lcd.begin(16, 2);
      lcd.setCursor(0, 0);
      lcd.print("Horloge Web");
      //Serial.println("Horloge Web");
     
      if (!espConfig()) {
        lcd.setCursor(0, 1);
        lcd.print("Pas de WIFI");
        //Serial.println("Pas de WIFI");
      }  else {
        digitalWrite(LED_WLAN, HIGH);
        lcd.setCursor(0, 1);
        lcd.print("Liaison WIFI OK");
        //Serial.println("Liaison WIFI OK");
      }
     
      getTime("chronic.herokuapp.com", "/utc/in+two+hours"); //Gets Time from Page and Sets it
    }
     
    void loop() {
      String shour, sminute, ssecond, sday, smonth, sweekday;
     
      delay(1000);
     
      if (hour() <= 9) shour = "0" + String(hour()); else shour = String(hour()); // adjust for 0-9
      if (minute() <= 9) sminute = "0" + String(minute());  else sminute = String(minute());
      if (second() <= 9) ssecond = "0" + String(second());  else ssecond = String(second());
     
     
    switch (weekday()) {
    //switch (second()%7+1) {
      case 1:
        sweekday = "Dimanch";
        break;
      case 2:
        sweekday = "  Lundi";
        break;
      case 3:
        sweekday = "  Mardi";
        break;
      case 4:
        sweekday = "Mercred";
        break;
      case 5:
        sweekday = "  Jeudi";
        break;
      case 6:
        sweekday = "Vendred";
        break;
      default:
        sweekday = " Samedi";
        break;
    }
     
     
    //sweekday = String(weekday()) + " Jeudi";
     
      String Time =  shour + "h" + sminute + ":" + ssecond + " " + sweekday;
     
    //  String Time = "    " + shour + "h" + sminute + ":" + ssecond + "   ";
     
    sday = String(day()); 
    //switch ((month()+second())%12+1) {   // Code pour tester l'affichage de chaque mois
    switch (month()) {
      case 1:
        smonth = "janvier";
        break;
      case 2:
        smonth = "fevrier";
        break;
      case 3:
        smonth = "mars";
        break;
      case 4:
        smonth = "avril";
        break;
      case 5:
        smonth = "mai";
        break;
      case 6:
        smonth = "juin";
        break;
      case 7:
        smonth = "juillet";
        break;
      case 8:
        smonth = "aout";
        break;
      case 9:
        if (sday.length()>1) {
          smonth = "septembr";  
        } else {
          smonth = "septembre";
        }
        break;
      case 10:
        smonth = "octobre";
        break;
      case 11:
        smonth = "novembre";
        break;
      default:
        smonth = "decembre";
        break;
    }
     
      String Date = sday + " " + smonth + " " + String(year()) ;
     
      //Code pour centrer la date :
      int LgTxt;
      int NbSp;
      LgTxt = Date.length();
      if (LgTxt<16) {
        NbSp = (16 - LgTxt) / 2;
        for (int i=1;i<=NbSp;i++) {
          Date = " " + Date;    
        }
        NbSp = 16 - LgTxt - NbSp;
        for (int i=1;i<=NbSp;i++) {
          Date = Date + " ";
        }
      }
     
      //Serial.println(Time + " " + Date);
      lcd.setCursor(0, 0);
      lcd.print(Time);
      lcd.setCursor(0, 1);
      lcd.print(Date);
     
    }
     
     
    String getTCP(String Host, String Subpage)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      return sendCom(getRequest);
    }
     
    boolean getTime(String Host, String Subpage)
    {
      boolean success = true;
      int xyear, xmonth, xday, xhour, xminute, xsecond;  //lokal variables
     
      success &= sendCom("AT+CIPSTART=\"TCP\",\"" + Host + "\",80", "OK");
      String getRequest = "GET " + Subpage + " HTTP/1.1\r\nHost:" + Host + "\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
     
      esp8266.println(getRequest);
     
      if (esp8266.find("+IPD"))
      {
        if (esp8266.find("\r\n\r\n"))
        {
          xyear = esp8266.parseInt();
          xmonth = esp8266.parseInt();
          xday = esp8266.parseInt();
          xhour = esp8266.parseInt();
          xminute = esp8266.parseInt();
          xsecond = esp8266.parseInt();
     
          if (xday < 0) xday *= -1;          //Because of date seperator - parseInt detects negativ integer
          if (xmonth < 0) xmonth *= -1;    //Because of date seperator - parseInt detects negativ integer
     
     
          setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
          sendCom("AT+CIPCLOSE", "OK");
          return true;
        }
        else return false;
      }
      else return false;
    }
     
    //-----------------------------------------Config ESP8266------------------------------------
     
    boolean espConfig()
    {
      boolean success = true;
      esp8266.setTimeout(5000);
      success &= sendCom("AT+RST", "ready");
      esp8266.setTimeout(1000);
      if (configStation(SSID, PASSWORD)) {
        success &= true;
        //debug("WLAN Connected");
        //debug("My IP is:");
        //debug(sendCom("AT+CIFSR"));
      }
      else
      {
        success &= false;
      }
      //shorter Timeout for faster wrong UPD-Comands handling
      success &= sendCom("AT+CIPMODE=0", "OK");  //So rum scheit wichtig!
      success &= sendCom("AT+CIPMUX=0", "OK");
     
      return success;
    }
     
    boolean configTCPServer()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=1", "OK"));
      success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
    boolean configTCPClient()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      //success &= (sendCom("AT+CIPSERVER=1,80", "OK"));
     
      return success;
     
    }
     
     
    boolean configStation(String vSSID, String vPASSWORT)
    {
      boolean success = true;
      success &= (sendCom("AT+CWMODE=1", "OK"));
      esp8266.setTimeout(20000);
      success &= (sendCom("AT+CWJAP=\"" + String(vSSID) + "\",\"" + String(vPASSWORT) + "\"", "OK"));
      esp8266.setTimeout(1000);
      return success;
    }
     
    boolean configAP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CWMODE=2", "OK"));
      success &= (sendCom("AT+CWSAP=\"NanoESP\",\"\",5,0", "OK"));
     
      return success;
    }
     
    boolean configUDP()
    {
      boolean success = true;
     
      success &= (sendCom("AT+CIPMODE=0", "OK"));
      success &= (sendCom("AT+CIPMUX=0", "OK"));
      success &= sendCom("AT+CIPSTART=\"UDP\",\"192.168.255.255\",90,91,2", "OK"); //Importand Boradcast...Reconnect IP
      return success;
    }
     
    //-----------------------------------------------Controll ESP-----------------------------------------------------
     
    boolean sendUDP(String Msg)
    {
      boolean success = true;
     
      success &= sendCom("AT+CIPSEND=" + String(Msg.length() + 2), ">");    //+",\"192.168.4.2\",90", ">");
      if (success)
      {
        success &= sendCom(Msg, "OK");
      }
      return success;
    }
     
     
    boolean sendCom(String command, char respond[])
    {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR"))
      {
        return true;
      }
      else
      {
        //debug("ESP SEND ERROR: " + command);
        return false;
      }
    }
     
    String sendCom(String command)
    {
      esp8266.println(command);
      return esp8266.readString();
    }
     
     
     
    //-------------------------------------------------Debug Functions------------------------------------------------------
    /*
     void serialDebug() {
      while (true)
      {
        if (esp8266.available())
          Serial.write(esp8266.read());
        if (Serial.available())
          esp8266.write(Serial.read());
      }
    }
    */
    /*
    void debug(String Msg)
    {
      if (DEBUG)
      {
        Serial.println(Msg);
      }
    }
    */

  5. #5
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Bonjour,

    J'ai réussi à mettre à jour le firmware de l'ESP8266 mais cela ne change rien

    SoftwareSerial est indispensable pour que la partie Arduino Nano de la carte communique avec la partie ESP8266

    C'est franchement merdique !

    A bientôt

  6. #6
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    J'ai essayé AltSoftSerial.h mais ça ne fonctionne plus du tout

    Je vais tenter une autre librairie pour écrire dans l'afficheur LCD

    A bientôt

  7. #7
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 817
    Points : 5 674
    Points
    5 674
    Par défaut
    au prix d'un ESP8086 ou ESP32 de nos jours, je ne me prendrais pas trop la tête sur ce genre de machin exotique....

  8. #8
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Citation Envoyé par Jay M Voir le message
    au prix d'un ESP8086 ou ESP32 de nos jours, je ne me prendrais pas trop la tête sur ce genre de machin exotique....
    Il n'y a pas que l'argent dans la vie ! J'ai des tas de puces bien plus anciennes "qui ne valent plus rien" mais qui fonctionnent toujours

    J'avais quand même payé le coffret Franzis Maker Kit dans les 70€ il y a 3 ans le coffret est tout de même sympa et il y a pas mal d'accessoires.

    Ce machin n'est pas si exotique que ça. Plusieurs magazines d'électronique en ont parlé et il est relativement répandu.

    Les autres exemples fonctionnent correctement, mais j'aimerais bien connaitre l'origine de ce mystérieux bug...

    J'envisage d'intégrer cette carte en mode serveur dans mon futur système domotique, pour piloter deux fonctions :
    - mise en marche VMC pendant deux heures à plein régime
    - puis mise en marche du chauffage à plein régime pendant deux heures

    L'idée étant de pouvoir, quand je rentre de déplacement, retrouver une maison bien aérée et chauffée

    Bien sûr il faudra blinder les aspects sécurités.

    La carte sera reliée au reste du système domotique de façon "analogique", avec des sécurités (thermostats, temporisateurs) pour qu'en cas de plantage ni le chauffage ni la VMC ne fonctionne trop longtemps ou de façon excessive.

    Voilà

  9. #9
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 817
    Points : 5 674
    Points
    5 674
    Par défaut
    Bien sûr la puissance ou le prix ne sont pas des critères toujours important, souvent la meilleure carte pour un prototype (voir un projet en ces temps confinés) est celle qu'on a sous la main

    Mon point était que pour faire quelque chose qui allie WiFi et Arduino, quitte à avoir un ESP autant programmer directement l'ESP plutôt que d'avoir à dépendre d'une liaison Sofwtare Serial qui est toujours source de bug, de contention sur les interruptions etc... (Un LOLIN D1 mini V3.1.0 ça vaut 5 ou 6€ et pour 10/12 euros sur Amazon (prime) vous avez un ESP32 NodeMCU)

    c'est quoi la fonction espConfig() que vous appelez ? vous avez le code source quelque part ?

  10. #10
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Bonjour,

    la fonction espConfig() fait partie du code (vers la fin)

    Je pense que le bug que j'ai avec l'horloge web vient d'une possible incompatibilité entre les trois librairies SoftwareSerial, TimeLib et LiquidCrystal.
    Parce que tous les autres exemples livrés avec la carte (une vingtaine) fonctionnent sans bug, et j'arrive à les modifier pour ajouter des fonctionnalités.

    Sinon je suis arrivé à faire ce que je veux avec cette carte en mode serveur TCP : elle génère une page web qui :
    - affiche la valeur de trois capteurs
    - permet de saisir un texte qui est affiché sur l'écran LCD et de choisir la couleur d'une led RGB branché sur trois broches de sorties

    Pour le moment tout est en HTTP donc non sécurisé.

    Bonne nouvelle le firmware de la partie ESP8266 que j'avais mis à jour prend en charge SSL / TLS ; je vais me pencher là-dessus.

    Bref cette carte est très intéressante et même s'il y a mieux aujourd'hui elle sera largement suffisante pour mon besoin final.

    A bientôt

  11. #11
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 817
    Points : 5 674
    Points
    5 674
    Par défaut
    ah oui j'avais pas vu tout le code.. (j'avais pas scrollé )

    Je pense que vous êtes victime de conflit sur les interruptions, le LCD est relativement lent et vous dépendez de SofwareSerial à un débit pas rapide (donc bloque longtemps) pour discuter avec l'ESP. Le challenge c'est que vous ne pouvez pas trop augmenter la vitesse de discussion avec l'ESP car SoftwareSerial perdra aussi ses petits si les données arrivent trop vite

  12. #12
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Bonjour,

    Je continue à avoir d'autres bugs bizarres...

    Mais cette fois si je pense avoir trouvé l'origine du problème et des solutions.

    Mes programmes ont un point commun : ils utilisent beaucoup de chaines de caractères.
    Le problème vient de là.
    Arduino a voulu rendre la programmation des microcontrôleurs facile en créant un langage C/C++ le plus proche possible de celui utilisé sur nos ordinateurs.
    Mais un microcontrôleur a très peu de ressources, et une gestion de la mémoire vive bien moins efficace.

    L'enfer est pavé de bonnes intentions : la classe String qui rend la programmation si facile consomme énormément de mémoire de façon dynamique lors de l’exécution
    Le soucis c'est qu'on ne s'en rend pas compte :
    - ni niveau de la compilation (impossible de prédire l'usage dynamique)
    - ni au niveau de l’exécution (l'Arduino n'affiche pas de message "out of memory")

    Les petits exemples fonctionnent tous car ils sont... petits !
    Même s'ils ne sont pas du tout optimisés et remplis de mauvaises pratiques

    Conséquence : on arrive à des bugs incompréhensibles faute comprendre ce qu'il se passe vraiment, et à devoir se dire que pour qu'un programme fonctionne il faut garder beaucoup de mémoire libre sans savoir combien exactement et sans garantie...

    On est loin de l'assembleur où on peut utiliser 100% de la ROM et de la RAM car on maîtrise toutes les ressources à l'octet près...

    Le site Internet suivant explique tout en détail : https://cpp4arduino.com/
    Je vais m'y mettre

    A bientôt

  13. #13
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 817
    Points : 5 674
    Points
    5 674
    Par défaut
    oui autant votre ESP a de la mémoire et en gérant correctement les Strings on se débrouille autant votre Nano est extrêmement limité et il est déconseillé de faire appel à la classe String sans pré-réserver la mémoire nécessaire. il faut aussi autant que faire se peut éviter les concaténations (le + entre deux Strings qui crée des Strings intermédiaires) ainsi que de passer des String en paramètre à des fonctions si ce n'est par référence (sinon une copie est créée)

    Il faut essayer de passer votre code en cStrings, des tableaux de char qui se terminent par un caractère nul et utiliser les fonctions des bibliothèques standard du C et C++ que sont stdlib.h et string.h

    Si vous êtes limité en mémoire programme (flash) évitez aussi d'utiliser sscanf() et sprintf() car ça rajouter pas mal de code, préférez la construction petit à petit avec des strcat() ou strcpy() et des atoi() ou atol() ou dtostr() pour convertir des valeurs.

  14. #14
    Membre expérimenté
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    667
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 667
    Points : 1 462
    Points
    1 462
    Par défaut
    Bonjour,

    Il y a aussi le fait que l'utilisation de fonctionnalités comme les interruptions par exemple, rend indisponible certains pins pour un usage personnel.

  15. #15
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Bonjour

    Après un épluchage des astuces évoquées plus haut, j'ai fait un comparatif bonnes et mauvaises pratiques

    En plus j'ai découvert la fonction snprintf_P() qui va beaucoup me simplifier la vie

    Les exemples de code donnés dans mon kit étaient vraiment mauvais !

    Donc ci-dessous deux programmes, qui font exactement la même chose :

    - programme "mauvaise pratiques" :
    5890 octets de ROM (19%)
    526 octets de RAM (25%) - ce chiffre est sous-évalué car il ne tiens pas compte des allocations dynamiques
    280824 µs de durée d’exécution

    - programme "bonnes pratiques" :
    5626 octets de ROM (18%)
    336 octets de RAM (16%)
    280304 µs de durée d’exécution

    C'est une bonne surprise : le programme "bonnes pratiques" :
    - utilise à peine moins de ROM (je m'attendais au contraire !)
    - utilise beaucoup moins de RAM
    - est un peu plus rapide

    Voici les programmes :

    - Mauvaises pratiques :

    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
    /*
    Software Serial Examples.
    No change necessary.
     */
    #include <SoftwareSerial.h>
     
    // SoftwareSerial esp8266(11, 12);
     
    //#include <string.h>
    //#include <avr/pgmspace.h>
    //#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
     
    #define RESOURCE "qflknqjlsgkbzkjfbkj"
    #define API_KEY "216513213515335"
     
    // Une chaine constante en ROM utilisable dans tout le programme
    //const char* srom_1 = "Chaine de caractères globale en ROM"; // revient au même
    const char srom_1[] = "Chaine de caractères globale en ROM";
     
    // Un tableau de chaines constantes en ROM utilisables dans tout le programme
    const char srom_err1[]  = "Plus de papier";
    const char srom_err2[]  = "Plus d'encre";
    const char srom_err3[]  = "Bourrage papier";
    const char* const  tab_srom_erreurs[] = {
      srom_err1,
      srom_err2,
      srom_err3 
    };
     
    // Un tableau de données en ROM utilisable dans tout le programme :
    const byte tab_octets[] = {
      0,
      12,
      255,
      28,
      128,
      60
    };
     
    void setup()
    {
      long duree;
     
      // Open serial communications and wait for port to open:
      Serial.begin(19200);
      duree = micros();
     
      Serial.println(F("==================== TEST MAUVAISES PRATIQUES ===================="));
     
      char s2[]="Chaine de caractères locale en RAM";
     
      Serial.println(srom_1);
      Serial.println(s2);
     
      Serial.println("texte en rom dans une fonction locale");
     
      printError("autre texte en rom dans une fonction locale");
     
      printErrorN(0);
      printErrorN(1);
      printErrorN(2);
     
      for (int i=0;i<6;i++) {
        Serial.print(tab_octets[i]);
        Serial.print(" ; ");
      }
      Serial.println();
     
      char s[32];
      char* txt = "Texte reçu";
      int param = 12;
      //Contruit une chaine s en tenant compte de de sa taille (évite buffer overflow)
      snprintf(s, sizeof(s), "%s - p = %i °C", txt, param);
      Serial.println(s);
     
      char* txt2 = "Texte vraiment beaucoup trop long";
      snprintf(s, sizeof(s), "%s - p = %i °C", txt2, param);
      Serial.println(s);
     
      //Exemple de formattage d'heure - pour avoir le temps sur deux caractères
      int tempsH,tempsM,tempsS;
      tempsH=6;
      tempsM=50;
      tempsS=9;
      snprintf(s, sizeof(s), "%02dh%02d:%02d", tempsH, tempsM, tempsS);
      Serial.println(s);
     
      //Exemple de formattage de texte à longueur contante (voir http://www.cplusplus.com/reference/cstdio/printf/)
      // Longueur constante - alignement à droite
      for (int i=0;i<3;i++) {
        snprintf(s, sizeof(s), "|%25s|", tab_srom_erreurs[i]);
        Serial.println(s);
      }
      // Longueur constante - alignement à gauche
      for (int i=0;i<3;i++) {
        snprintf(s, sizeof(s), "|%-25s|", tab_srom_erreurs[i]);
        Serial.println(s);
      }
     
      // Construction d'une chaine String quand on ne peut pas faire autrement
      String path = String("/api/") + RESOURCE + "?key=" + API_KEY; // réalise 6 allocations dans la RAM !
      // Il faut le faire de façon optimisée : 
      // - opérateur +=
      // - Reserve
      // - null string au constructeur
      // Le code suivant ne réalise qu'une seule allocation dans la RAM :
      /*
      String path((char *)0);
      path.reserve(50);
      path += "/api/";
      path += RESOURCE;
      path += "?key=";
      path += API_KEY;
      */
      Serial.println(path);
     
      duree = micros() - duree;
      snprintf_P(s, sizeof(s), PSTR("Durée %ld µs"), duree);
      Serial.println(s);
    }
     
    void loop() // run over and over
    {
    }
     
    void printErrorN (int n) {
        Serial.println(tab_srom_erreurs[n]);
    }
     
    void printError(String s) {
      Serial.print("Erreur : ");
      Serial.println(s);
    }
    - Bonnes pratiques :

    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
    /*
    Software Serial Examples.
    No change necessary.
     */
    #include <SoftwareSerial.h>
     
    // SoftwareSerial esp8266(11, 12);
     
    #include <string.h>
    #include <avr/pgmspace.h>
    #define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
     
    #define RESOURCE "qflknqjlsgkbzkjfbkj"
    #define API_KEY "216513213515335"
     
    // Le code suivant réalise 6 allocations mémoires :
    String path = String("/api/") + RESOURCE + "?key=" + API_KEY;
     
     
    // Une chaine constante en ROM utilisable dans tout le programme
    const char srom_1[] PROGMEM = "Chaine de caractères globale en ROM";
     
    // Un tableau de chaines constantes en ROM utilisables dans tout le programme
    const char srom_err1[] PROGMEM = "Plus de papier";
    const char srom_err2[] PROGMEM = "Plus d'encre";
    const char srom_err3[] PROGMEM = "Bourrage papier";
    const char* const PROGMEM tab_srom_erreurs[] = {
      srom_err1,
      srom_err2,
      srom_err3 
    };
     
    // Un tableau de données en ROM utilisable dans tout le programme :
    const byte PROGMEM tab_octets[] = {
      0,
      12,
      255,
      28,
      128,
      60
    };
     
    void setup()
    {
      long duree;
     
      // Open serial communications and wait for port to open:
      Serial.begin(19200);
      duree = micros();
     
      Serial.println(F("===================== TEST BONNES PRATIQUES ====================="));
     
      char s2[]="Chaine de caractères locale en RAM";
     
      Serial.println(FPSTR(srom_1));
      Serial.println(s2);
     
      Serial.println(F("texte en rom dans une fonction locale"));
     
      printError(F("autre texte en rom dans une fonction locale"));
     
      printErrorN(0);
      printErrorN(1);
      printErrorN(2);
     
      for (int i=0;i<6;i++) {
        Serial.print(pgm_read_byte(tab_octets + i));
        Serial.print(F(" ; "));
      }
      Serial.println();
     
      char s[32];
      char* txt = "Texte reçu";
      int param = 12;
      //Contruit une chaine s en tenant compte de de sa taille (évite buffer overflow)
      //Bien mieux que la fonction String() et permet de faire plus de choses comme du formattage
      snprintf_P(s, sizeof(s), PSTR("%s - p = %i °C"), txt, param);
      Serial.println(s);
     
      char* txt2 = "Texte vraiment beaucoup trop long";
      snprintf_P(s, sizeof(s), PSTR("%s - p = %i °C"), txt2, param);
      Serial.println(s);
     
      //Exemple de formattage d'heure - pour avoir le temps sur deux caractères
      int tempsH,tempsM,tempsS;
      tempsH=6;
      tempsM=50;
      tempsS=9;
      snprintf_P(s, sizeof(s), PSTR("%02dh%02d:%02d"), tempsH, tempsM, tempsS);
      Serial.println(s);
     
      //Exemple de formattage de texte à longueur contante (voir http://www.cplusplus.com/reference/cstdio/printf/)
      char stmp[32];
      // Longueur constante - alignement à droite
      for (int i=0;i<3;i++) {
        strcpy_P(stmp, (char*) pgm_read_word(&(tab_srom_erreurs[i])));
        snprintf_P(s, sizeof(s), PSTR("|%25s|"), stmp);
        Serial.println(s);
      }
      // Longueur constante - alignement à gauche
      for (int i=0;i<3;i++) {
        strcpy_P(stmp, (char*) pgm_read_word(&(tab_srom_erreurs[i])));
        snprintf_P(s, sizeof(s), PSTR("|%-25s|"), stmp);
        Serial.println(s);
      }
     
      // Construction d'une chaine String quand on ne peut pas faire autrement
      // String path = String("/api/") + RESOURCE + "?key=" + API_KEY; // réalise 6 allocations dans la RAM !
      // Il faut le faire de façon optimisée : 
      // - opérateur +=
      // - Reserve
      // - null string au constructeur
      // Le code suivant ne réalise qu'une seule allocation dans la RAM :
      String path((char *)0);
      path.reserve(50);
      path += "/api/";
      path += RESOURCE;
      path += "?key=";
      path += API_KEY;
      //Encore mieux : quand c'est possible on peut concatenner des chaines à la compilation :
      //String path = "/api/" RESOURCE "?key=" API_KEY;
     
      Serial.println(path);
     
     
     
      duree = micros() - duree;
      snprintf_P(s, sizeof(s), PSTR("Durée %ld µs"), duree);
      Serial.println(s);
    }
     
    void loop() // run over and over
    {
    }
     
    void printErrorN (int n) {
        Serial.println(FPSTR(tab_srom_erreurs[n]));
    }
     
    void printError(const __FlashStringHelper* s) {
      Serial.print(F("Erreur : "));
      Serial.println(s);
    }


    La sortie sur le terminal série :

    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
    16:35:02.658 -> ==================== TEST MAUVAISES PRATIQUES ====================
    16:35:02.692 -> Chaine de caractères globale en ROM
    16:35:02.726 -> Chaine de caractères locale en RAM
    16:35:02.726 -> texte en rom dans une fonction locale
    16:35:02.760 -> Erreur : autre texte en rom dans une fonction locale
    16:35:02.794 -> Plus de papier
    16:35:02.794 -> Plus d'encre
    16:35:02.794 -> Bourrage papier
    16:35:02.794 -> 0 ; 12 ; 255 ; 28 ; 128 ; 60 ; 
    16:35:02.828 -> Texte reçu - p = 12 °C
    16:35:02.828 -> Texte vraiment beaucoup trop lo
    16:35:02.862 -> 06h50:09
    16:35:02.862 -> |           Plus de papier|
    16:35:02.862 -> |             Plus d'encre|
    16:35:02.896 -> |          Bourrage papier|
    16:35:02.896 -> |Plus de papier           |
    16:35:02.930 -> |Plus d'encre             |
    16:35:02.930 -> |Bourrage papier          |
    16:35:02.964 -> /api/qflknqjlsgkbzkjfbkj?key=216513213515335
    16:35:02.964 -> Durée 280824 µs
    16:35:22.579 -> ===================== TEST BONNES PRATIQUES =====================
    16:35:22.613 -> Chaine de caractères globale en ROM
    16:35:22.647 -> Chaine de caractères locale en RAM
    16:35:22.647 -> texte en rom dans une fonction locale
    16:35:22.681 -> Erreur : autre texte en rom dans une fonction locale
    16:35:22.715 -> Plus de papier
    16:35:22.715 -> Plus d'encre
    16:35:22.715 -> Bourrage papier
    16:35:22.715 -> 0 ; 12 ; 255 ; 28 ; 128 ; 60 ; 
    16:35:22.749 -> Texte reçu - p = 12 °C
    16:35:22.749 -> Texte vraiment beaucoup trop lo
    16:35:22.787 -> 06h50:09
    16:35:22.787 -> |           Plus de papier|
    16:35:22.787 -> |             Plus d'encre|
    16:35:22.819 -> |          Bourrage papier|
    16:35:22.819 -> |Plus de papier           |
    16:35:22.854 -> |Plus d'encre             |
    16:35:22.854 -> |Bourrage papier          |
    16:35:22.886 -> /api/qflknqjlsgkbzkjfbkj?key=216513213515335
    16:35:22.886 -> Durée 280304 µs
    Maintenant je vais mettre ça en pratique dans mon programme d'horloge

    Mon ambition est d'utiliser des Arduino pour un système domotique maison.
    Dans chaque pièce un Arduino UNO devra gérer un écran TFT tactile et une liaison ethernet avec un module TCP SPI.
    Un Arduino Mega fera office d'unité centrale, il n'aura pas d'écran mais devra piloter des relais et gérer les échanges de données avec un module TCP SPI ; de plus il devra envoyer des ordres à un Raspberry Pi utilisé en lecteur MP3.

    Dans mon projet domotique les Arduinos devront manipuler beaucoup de texte (affichage sur l'écran, échanges TCP IP)
    Maitriser l'usage efficace et fiable des chaines de caractères est essentiel.

    A bientôt

  16. #16
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 817
    Points : 5 674
    Points
    5 674
    Par défaut
    oui et si vous enlevez les String et sprintf() pour utiliser les fonctions dont je parlais, vous verrez que vous gagnez sans doute plus d'1Ko de mémoire flash

    par exemple comparez leur version "optimisée des Strings quand on n'a pas le choix"
    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
    #define RESOURCE "qflknqjlsgkbzkjfbkj"
    #define API_KEY "216513213515335"
     
    void setup() {
      Serial.begin(115200);
     
      String path((char *)0);
      path.reserve(50);
      path += "/api/";
      path += RESOURCE;
      path += "?key=";
      path += API_KEY;
      Serial.println(path);
    }
     
    void loop() {}
    sur un UNO (comme votre Nano):
    Le croquis utilise 2914 octets (9%) de l'espace de stockage de programmes. Le maximum est de 32256 octets.
    Les variables globales utilisent 246 octets (12%) de mémoire dynamique, ce qui laisse 1802 octets pour les variables locales. Le maximum est de 2048 octets.



    maintenant un programme qui fait la même chose en utilisant les librairies en C:
    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
    #define RESOURCE "qflknqjlsgkbzkjfbkj"
    #define API_KEY "216513213515335"
     
    void setup() {
      Serial.begin(115200);
     
      char path[50];
      path[0] = '\0';
      strcat(path, "/api/");
      strcat(path, RESOURCE);
      strcat(path, "?key=");
      strcat(path, API_KEY);
      Serial.println(path);
    }
     
    void loop() {}
    sur le même UNO (comme votre Nano):
    Le croquis utilise 1624 octets (5%) de l'espace de stockage de programmes. Le maximum est de 32256 octets.
    Les variables globales utilisent 236 octets (11%) de mémoire dynamique, ce qui laisse 1812 octets pour les variables locales. Le maximum est de 2048 octets.

    ==> on a donc gagné 2914-1624 =1290 octets de mémoire flash et 10 octets de mémoire vive

    Bien sûr, la bonne méthode pour ce path puisque tout est connu à l'avance serait la concaténation au niveau d'une Macro
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #define RESOURCE "qflknqjlsgkbzkjfbkj"
    #define API_KEY "216513213515335"
    #define path ("/api/" RESOURCE "?key=" API_KEY)
     
    void setup() {
      Serial.begin(115200);
      Serial.println(path);
    }
     
    void loop() {}
    et là sur un UNO on gagne encore 1624 - 1518 = 106 octets de flash et 4 octets de SRAM!
    Le croquis utilise 1518 octets (4%) de l'espace de stockage de programmes. Le maximum est de 32256 octets.
    Les variables globales utilisent 232 octets (11%) de mémoire dynamique, ce qui laisse 1816 octets pour les variables locales. Le maximum est de 2048 octets.


    Et bien sûr on pourrait tout mettre en PROGMEM pour gagner un max de SRAM

  17. #17
    Membre expérimenté Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    952
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 952
    Points : 1 309
    Points
    1 309
    Par défaut
    Bonjour,

    alors j'ai appliqué ces bonnes pratiques à mon horloge

    Ca fonctionne bien mieux :
    - plus aucun plantage
    - code plus court, plus propre et plus lisible
    - 11214 octets de code au lieu de 14810
    - 412 octets de RAM (20%) au lieu de 1491 (72%)

    Voici le code de mon horloge Internet :

    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
     
    #define DEBUG true
    #define LED_WLAN 13
     
    #include <SoftwareSerial.h>
    #include <TimeLib.h>
    #include <LiquidCrystal.h>
     
    LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
    SoftwareSerial esp8266(11, 12); // RX, TX
     
    const char srom_jour1[] PROGMEM = "Dimanch";
    const char srom_jour2[] PROGMEM = "Lundi";
    const char srom_jour3[] PROGMEM = "Mardi";
    const char srom_jour4[] PROGMEM = "Mercred";
    const char srom_jour5[] PROGMEM = "Jeudi";
    const char srom_jour6[] PROGMEM = "Vendred";
    const char srom_jour7[] PROGMEM = "Samedi";
    const char* const PROGMEM tab_srom_jours[] = {
      srom_jour1,srom_jour2,srom_jour3,srom_jour4,srom_jour5,srom_jour6,srom_jour7
    };
     
    const char srom_mois1[] PROGMEM = "janvier";
    const char srom_mois2[] PROGMEM = "fevrier";
    const char srom_mois3[] PROGMEM = "mars";
    const char srom_mois4[] PROGMEM = "avril";
    const char srom_mois5[] PROGMEM = "mai";
    const char srom_mois6[] PROGMEM = "juin";
    const char srom_mois7[] PROGMEM = "juillet";
    const char srom_mois8[] PROGMEM = "aout";
    const char srom_mois9[] PROGMEM = "septembr";
    const char srom_mois10[] PROGMEM = "octobre";
    const char srom_mois11[] PROGMEM = "novembre";
    const char srom_mois12[] PROGMEM = "decembre";
    const char* const PROGMEM tab_srom_mois[] = {
      srom_mois1,srom_mois2,srom_mois3,srom_mois4,srom_mois5,srom_mois6,srom_mois7,srom_mois8,srom_mois9,srom_mois10,srom_mois11,srom_mois12
    };
     
    void setup() {
      Serial.begin(19200);
      esp8266.begin(19200);
     
      lcd.begin(16, 2);
      lcd.setCursor(0, 0);
      lcd.print(F("Horloge Web"));
     
      if (!espConfig()) serialDebug();
      else digitalWrite(LED_WLAN, HIGH);
     
      lcd.setCursor(0, 1);
      lcd.print(F("Liaison WIFI OK"));
     
      getTime();
    }
     
    void loop() {
      delay(1000);
     
      char jour[8];
      strcpy_P(jour, (char*) pgm_read_word(&(tab_srom_jours[weekday()-1])));
     
      char Time[17];
      snprintf_P(Time, sizeof(Time), PSTR("%02dh%02d:%02d %7s"), hour(), minute(), second(), jour);
     
      char mois[8];
      strcpy_P(mois, (char*) pgm_read_word(&(tab_srom_mois[month()-1])));
     
      char Date[17];
      // Problème du mois de septembre qui a trop de lettres si le jour est sur deux caractères :
      if ((month()==9)&&(day()<10)) {
        snprintf_P(Date, sizeof(Date), PSTR("%d %se %d    "), day(), mois, year());
      } else {
        snprintf_P(Date, sizeof(Date), PSTR("%d %s %d    "), day(), mois, year());
      }
     
      debug(Date);
      debug(Time);
     
      lcd.setCursor(0, 0);
      lcd.print(Time);
      lcd.setCursor(0, 1);
      lcd.print(Date);
    }
     
    boolean getTime() {   //getTime(F("chronic.herokuapp.com"), F("/utc/in+two+hours"));
      boolean success = true;
      int xyear, xmonth, xday, xhour, xminute, xsecond;  //lokal variables
      success &= sendCom(F("AT+CIPSTART=\"TCP\",\"chronic.herokuapp.com\",80"), "OK");
    /*
      String getRequest = "GET /utc/in+two+hours HTTP/1.1\r\nHost:chronic.herokuapp.com\r\n";
      success &= sendCom("AT+CIPSEND=" + String(getRequest.length() + 2), ">");
      esp8266.println(getRequest);
    */
      success &= sendCom(F("AT+CIPSEND=62"), ">"); //62 = longueur de la chaine en enlevant les '\'  +  2
      esp8266.println(F("GET /utc/in+two+hours HTTP/1.1\r\nHost:chronic.herokuapp.com\r\n"));
     
      if (esp8266.find("+IPD")) {
        if (esp8266.find("\r\n\r\n")) {
          xyear = esp8266.parseInt();
          xmonth = esp8266.parseInt();
          xday = esp8266.parseInt();
          xhour = esp8266.parseInt();
          xminute = esp8266.parseInt();
          xsecond = esp8266.parseInt();
     
          if (xday < 0) xday *= -1;          //Because of date seperator - parseInt detects negativ integer
          if (xmonth < 0) xmonth *= -1;    //Because of date seperator - parseInt detects negativ integer
     
     
          setTime(xhour, xminute, xsecond, xday, xmonth, xyear);
          sendCom(F("AT+CIPCLOSE"), "OK");
          return true;
        } else return false;
      } else return false;
    }
     
    //-----------------------------------------Config ESP8266------------------------------------
     
    boolean espConfig() {
      boolean success = true;
      esp8266.setTimeout(5000);
      success &= sendCom(F("AT+RST"), "ready");
      esp8266.setTimeout(1000);
      if (configStation()) {
        success &= true;
        debug(F("WLAN Connected"));
        debug(F("My IP is:"));
        debug(sendCom(F("AT+CIFSR")));
      }  else  {
        success &= false;
      }
      success &= sendCom(F("AT+CIPMODE=0"), "OK");  //So rum scheit wichtig!
      success &= sendCom(F("AT+CIPMUX=0"), "OK");
       return success;
    }
     
    boolean configStation() {
      boolean success = true;
      success &= (sendCom(F("AT+CWMODE=1"), "OK"));
      esp8266.setTimeout(20000);
      success &= (sendCom(F("AT+CWJAP=\"NOM_DU_RESEAU_WIFI\",\"CLEF_WEP_DU_RESEAU_WIFI\""), "OK"));
      esp8266.setTimeout(1000);
      return success;
    }
     
    //-----------------------------------------------Controll ESP-----------------------------------------------------
     
    boolean sendCom(const String& command, char respond[]) {
      esp8266.println(command);
      if (esp8266.findUntil(respond, "ERROR")) {
        return true;
      } else {
        debug(F("ESP SEND ERROR: "));
        debug(command);
        return false;
      }
    }
     
    String sendCom(const String& command) {
      esp8266.println(command);
      return esp8266.readString();
    }
     
    void serialDebug() {
      while (true) {
        if (esp8266.available())
          Serial.write(esp8266.read());
        if (Serial.available())
          esp8266.write(Serial.read());
      }
    }
     
    void debug(const String& Msg) {
      if (DEBUG) Serial.println(Msg);
    }
    Voilà un problème résolu !

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

Discussions similaires

  1. [Qt4] Bug bizarre avec QTableWidget
    Par Michaël dans le forum Qt
    Réponses: 12
    Dernier message: 26/04/2007, 16h48
  2. Bug bizarre (surement un virus)
    Par Muesko dans le forum Sécurité
    Réponses: 11
    Dernier message: 20/10/2006, 19h47
  3. Réponses: 1
    Dernier message: 04/10/2006, 19h49
  4. [CSS] Bug bizarre sous IE mais pas FF
    Par totofweb dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 13/09/2006, 20h40
  5. bug bizarre...
    Par gilux dans le forum Access
    Réponses: 7
    Dernier message: 15/05/2006, 15h01

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