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 :

Cherche expert arduino et écran 4D system pour projet mémoire d'ingénieur


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut Cherche expert arduino et écran 4D system pour projet mémoire d'ingénieur
    Bonjour, je suis en dernière année de mémoire d'ingénieur et je suis sur un projet où je développe un logiciel utilisant un Arduino mega2560 et un écran 4D system.
    Mon programme est terminé mais j'ai des soucis de vitesse d'exécution. Je cherche donc quelqu'un qui s'y connaisse pour examiner mon programme et me dire ce qui ne va pas.
    Je ne le met pas en ligne car il est long et que je ne souhaite pas le diffuser.
    Merci d'avance.

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 134
    Par défaut
    Et sur un Due, ce ne serait pas plus rapide ? (A moins que le Mega 2560 soit imposé)

    Attention toutefois aux périphériques, le Due fonctionne avec des entrées/sorties en 3.3V et non 5V comme le Mega2560, sinon il est compatible au niveau du brochage et les programmes écrits avec les bibliothèques Arduino (*) sont compatibles d'un processeur à l'autre. (* : donc sans accès direct aux registres et aux ports)
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 282
    Par défaut
    Bonsoir

    Ne pas oublier que le Mega tourne sur un cœur AVR qui n'est que du 8 bits à virgule fixe et qui est optimisé pour un accès en direct aux entrées/sorties. De ce fait certaines petites facilités de programmation bouffent du temps de manière énorme.

    Dans les points classiques:
    Il ne faut pas utiliser les types flottant. Par rapport à un int utilisé en virgule fixe, le facteur de vitesse est entre 50 et 200.
    Il faut limiter les divisions. Les multiplications ne devraient être réalisées que sur du INT. (Car l'ALU de l'AVR possède une multiplication 8 bits câblée en 2 cylces)

    Il faut éviter les pinMode, digitalWrite, digitalRead, analogWrite d’Arduino. Un digitalWrite c'est 48 cycles (pour un Uno, pour le 2560 il me semblait plus mais je ne retrouve pas l'info), l'équivalent PortX |= _BV(y) ou PortX &= ~_BV(y) avec l'état et l'adresse codée en dur, c'est 2 ou 3 cycles (assembleur SBI ou CBI). Le surcoût des fonctions Arduino vient de l'aspect paramétrique de la fonction et des tests pour s'assurer que l'E/S est dans le bon mode.
    Utiliser l'accès direct aux ports nécessaire de ne pas faire n'importe quoi, car tout doit être géré par son code.
    EDIT: on peut toujours programmer de manière paramétrique mais l'adresse des entrées-sortie doit être définie par un #define (codage C) ou un const int (codage C++) et non par une variable.

    Utiliser les strings de manière parcimonieuse. C'est des données de tailles importantes nécessitant beaucoup de calcul.

    Et j'ajouterais faire gaffe aux bibliothèques que l'on utilise. Certaines sont très bien faîtes, mais d'autre sont codées avec les pieds (et notamment un abus notoire de variables à virgule flottante pour quelques unes que j'ai vu passé par ici).

    Bonne suite

    Delias

  4. #4
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    Citation Envoyé par Delias Voir le message
    Bonsoir

    Ne pas oublier que le Mega tourne sur un cœur AVR qui n'est que du 8 bits à virgule fixe et qui est optimisé pour un accès en direct aux entrées/sorties. De ce fait certaines petites facilités de programmation bouffent du temps de manière énorme.

    Dans les points classiques:
    Il ne faut pas utiliser les types flottant. Par rapport à un int utilisé en virgule fixe, le facteur de vitesse est entre 50 et 200.
    Il faut limiter les divisions. Les multiplications ne devraient être réalisées que sur du INT. (Car l'ALU de l'AVR possède une multiplication 8 bits câblée en 2 cylces)

    Il faut éviter les pinMode, digitalWrite, digitalRead, analogWrite d’Arduino. Un digitalWrite c'est 48 cycles (pour un Uno, pour le 2560 il me semblait plus mais je ne retrouve pas l'info), l'équivalent PortX |= _BV(y) ou PortX &= ~_BV(y) avec l'état et l'adresse codée en dur, c'est 2 ou 3 cycles (assembleur SBI ou CBI). Le surcoût des fonctions Arduino vient de l'aspect paramétrique de la fonction et des tests pour s'assurer que l'E/S est dans le bon mode.
    Utiliser l'accès direct aux ports nécessaire de ne pas faire n'importe quoi, car tout doit être géré par son code.
    EDIT: on peut toujours programmer de manière paramétrique mais l'adresse des entrées-sortie doit être définie par un #define (codage C) ou un const int (codage C++) et non par une variable.

    Utiliser les strings de manière parcimonieuse. C'est des données de tailles importantes nécessitant beaucoup de calcul.

    Et j'ajouterais faire gaffe aux bibliothèques que l'on utilise. Certaines sont très bien faîtes, mais d'autre sont codées avec les pieds (et notamment un abus notoire de variables à virgule flottante pour quelques unes que j'ai vu passé par ici).

    Bonne suite

    Delias
    Merci pour toutes ces infos je verrais ce que je peux utiliser la dedans, sachant que ce n'est pas une manière de programmer que je maitrise (je crois que je n'en maitrise aucune d'ailleurs!). Je peux pas me passer de calculs avec des floats, j'ai des paramètres avec plusieurs chiffres après la virgules, alors même si le résultat à la fin peut être un int, je ne peux pas me permettre de tronquer autant les paramètres sans m'apporter de grosses erreurs à la fin. Je pense que le soucis vient de la communication avec l'écran car le programme est assez fluide si je ne lui demande pas d'afficher quelque chose à l'écran.

  5. #5
    Modérateur

    Homme Profil pro
    Ingénieur électricien
    Inscrit en
    Septembre 2008
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur électricien

    Informations forums :
    Inscription : Septembre 2008
    Messages : 1 282
    Par défaut
    Bonjour

    L'écran communique au moyen du port série, à une vitesse relativement élevée (c'est 200k, dans l'exemple joint à la bibliothèque). Pour arriver à un problème il doit y avoir trop de communication.
    Lors de mon travail de diplôme j'avais eu le problème avec un convertisseurs DAC en i2C qui prenait trop de temps pour la mise jour dans la boucle de régulation. La solution fut de fractionner la mise à jour en n'envoyant qu'un canal à chaque tour de calcul. C'est éventuellement ce qu'il faut prévoir ici, car le serial n'est pas complètement asynchrone sur Arduino. Si c'est réellement l'écran qui ralenti trop le calcul c'est la piste d'optimisation.

    Pour changer les float en entiers, il faut décomposer le calcul et déterminer à chaque étape les valeurs min, max et la précision nécessaire (c'est du travail de réflexion papier - crayon). Une première optimisation est l'ordre du calcul, généralement c'est d’abord les multiplications puis les divisions sauf a exploser la limite de stockage du type entier que l'on utilise (8, 16 ou 32 bits).
    Pour travailler en virgule fixe sans bibliothèque, il faut multiplier par un 2n les nombres en entrée et diviser par ce même nombres en fin de calcul. Pour la sortie, si on veut arrondir au lieu de tronquer, il faut au préalable ajouter la moitié de la division. (par exemple val_réelle = (valeur_décalée + 32) / 64;). Ces calculs sont très rapide car ce ne sont que de simple décalage de bits.

    Bonne suite

    Delias

  6. #6
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    on m'a conseillé d'assouplir les writeObject ou les writeStr dans ma boucle loop, ce que j'ai fait et en effet le programme tourne plus vite. j'ai eu recours à des variables de mémorisation et je met à jour mon affichage que si quelque chose change plutôt qu'a chaque boucle. Cependant j'ai d'autres problèmes. Il n'y a pas de méga calculs dans mon programme donc cela ne vient vraiment pas du traitement mais vraiment l'échange avec l'écran qui ralentit l'ensemble. Ce que j'ai réglé. Maintenant ce sont des soucis de fonctionnement. En fait le plus simple est que qqun qui s'y connaisse me donne son mail en mp pour que je lui passe le programme et qu'il jette un oeil pour me dire d'où pourrais venir le problème et que je lui décrive le fonctionnement du bouzin...

  7. #7
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Vous n'initialisez pas bien le parametres.nomAD. S'il n'yen a qu'un seul, il doit être en dehors de la boucle qui initialise les 20 valeurs. S'il y en a 20 différents, alors la variable n'est pas du bon type, il faudrait un tableau à 2 dimensions (pour le moment vous n'avez réservé que 20 octets. Je pense que le compilateur doit d'ailleurs se plaindre... activez dans les préférences toutes les alertes et éliminez les toutes, quand le compilateur dit quelque chose il faut le prendre en compte.)

    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
    void saveParametres() {
      EEPROM.put(keywordAddress, keyword);
      EEPROM.put(paramAddress, parametres);
    }
    
    void getParametres() {
      uint32_t tmpKey;
    
      EEPROM.get(keywordAddress, tmpKey);
      if (tmpKey == keyword) {
        EEPROM.get(paramAddress, parametres);    // EEPROM was already initialized OK to read
      } else {
        // First run on this arduino, memory was never initialized. so establish default values
        strcpy(parametres.nomAD, "sans nom"); //nom des AD
        for (int i = 0; i < 20; i++) {
          parametres.talMeF[i]    = 0; //talon mise en froid auto
          parametres.talStop[i]   = 0; //talon pause auto
          parametres.talMaint[i]  = 0; //talon maintien froid auto
          parametres.tpsMeFM[i]   = 0; //tps de mise en froid manu
          parametres.tpsStopM[i]  = 0; //tps pause manu
          parametres.tpsMaintM[i] = 0; //tps maintien
        }
        saveParametres();
      }
    }

    Sinon simplifiez le setup avec des boucles:
    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
    void setup() 
    {
      Serial1.begin(200000);
      genie.Begin(Serial1);//écran sur le Serial 1
      genie.AttachEventHandler(myGenieEventHandler);//cde vérifiant ce qui se passe sur l'écran
      genie.WriteContrast(15);
     
      for (int i = 0; i < 8; i++) {
        pinMode(CEV[i], INPUT);
        pinMode(EV[i], OUTPUT); digitalWrite(EV[i], LOW);
      }
     
      for (int i = 0; i < 4; i++) {
        pinMode(PEV[i], INPUT);
        pinMode(led[i], INPUT);
      }
     
      pinMode(temp, INPUT);
      pinMode(Hr, INPUT);
      pinMode(alim, INPUT);
     
      pinMode(A, OUTPUT);   digitalWrite(A, LOW);
      pinMode(B, OUTPUT);   digitalWrite(B, LOW);
      pinMode(C, OUTPUT);   digitalWrite(C, LOW);
      pinMode(INH, OUTPUT); digitalWrite(INH, HIGH);
     
      getParametres();
    }
    tous les noms de pins ne sont pas super et ne sont pas déclarés du bon type (déclarez les en const uint8_t) Je vous suggère de mettre le mot pin quand une variable représente une pin, par exemple pinTemperature sera plus lisible que temp. A, B et C sont des noms vraiment très mal choisis. Hr n'est pas terrible non plus...

    idem pour t, ce n'est pas un nom génial... ça ne vous coute pas plus cher de l'appeler temperatureActuelle ou un truc comme cela...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float t = 0; //variable de température

    Si etatCev et etatLed doivent contenir HIGH ou LOW, il ne faut pas les déclarer comme des booléens. utilisez plutôt uint8_t

  8. #8
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    Citation Envoyé par Jay M Voir le message
    Vous n'initialisez pas bien le parametres.nomAD. S'il n'yen a qu'un seul, il doit être en dehors de la boucle qui initialise les 20 valeurs. S'il y en a 20 différents, alors la variable n'est pas du bon type, il faudrait un tableau à 2 dimensions (pour le moment vous n'avez réservé que 20 octets. Je pense que le compilateur doit d'ailleurs se plaindre... activez dans les préférences toutes les alertes et éliminez les toutes, quand le compilateur dit quelque chose il faut le prendre en compte.)

    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
    void saveParametres() {
      EEPROM.put(keywordAddress, keyword);
      EEPROM.put(paramAddress, parametres);
    }
    
    void getParametres() {
      uint32_t tmpKey;
    
      EEPROM.get(keywordAddress, tmpKey);
      if (tmpKey == keyword) {
        EEPROM.get(paramAddress, parametres);    // EEPROM was already initialized OK to read
      } else {
        // First run on this arduino, memory was never initialized. so establish default values
        strcpy(parametres.nomAD, "sans nom"); //nom des AD
        for (int i = 0; i < 20; i++) {
          parametres.talMeF[i]    = 0; //talon mise en froid auto
          parametres.talStop[i]   = 0; //talon pause auto
          parametres.talMaint[i]  = 0; //talon maintien froid auto
          parametres.tpsMeFM[i]   = 0; //tps de mise en froid manu
          parametres.tpsStopM[i]  = 0; //tps pause manu
          parametres.tpsMaintM[i] = 0; //tps maintien
        }
        saveParametres();
      }
    }
    Il y a un nom pour chacun des 20 profiles mais c'est un nom de 4-5 caractères maximum.

    Citation Envoyé par Jay M Voir le message
    Sinon simplifiez le setup avec des boucles:
    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
    void setup() 
    {
      Serial1.begin(200000);
      genie.Begin(Serial1);//écran sur le Serial 1
      genie.AttachEventHandler(myGenieEventHandler);//cde vérifiant ce qui se passe sur l'écran
      genie.WriteContrast(15);
     
      for (int i = 0; i < 8; i++) {
        pinMode(CEV[i], INPUT);
        pinMode(EV[i], OUTPUT); digitalWrite(EV[i], LOW);
      }
     
      for (int i = 0; i < 4; i++) {
        pinMode(PEV[i], INPUT);
        pinMode(led[i], INPUT);
      }
     
      pinMode(temp, INPUT);
      pinMode(Hr, INPUT);
      pinMode(alim, INPUT);
     
      pinMode(A, OUTPUT);   digitalWrite(A, LOW);
      pinMode(B, OUTPUT);   digitalWrite(B, LOW);
      pinMode(C, OUTPUT);   digitalWrite(C, LOW);
      pinMode(INH, OUTPUT); digitalWrite(INH, HIGH);
     
      getParametres();
    }
    Je prend note!

    Citation Envoyé par Jay M Voir le message
    tous les noms de pins ne sont pas super et ne sont pas déclarés du bon type (déclarez les en const uint8_t) Je vous suggère de mettre le mot pin quand une variable représente une pin, par exemple pinTemperature sera plus lisible que temp. A, B et C sont des noms vraiment très mal choisis. Hr n'est pas terrible non plus...

    idem pour t, ce n'est pas un nom génial... ça ne vous coute pas plus cher de l'appeler temperatureActuelle ou un truc comme cela...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float t = 0; //variable de température

    Si etatCev et etatLed doivent contenir HIGH ou LOW, il ne faut pas les déclarer comme des booléens. utilisez plutôt uint8_t
    Pourquoi pas en booléens? ce n'est pas justement le principe?

  9. #9
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    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
     
    #include <genieArduino.h>
    #include <OneWire.h>
    #include <EEPROM.h>
    //initialisation sliders:
    int slider0_val = 0;
    int slider1_val = 0;
    int slider2_val = 0;
    int slider3_val = 0;
    int slider4_val = 0;
    int slider5_val = 0;
    uint8_t neg1 = 0;
    uint8_t neg2 = 0;
    uint8_t neg3 = 0;
     
    //initialisation des variables temps et talons:
    struct __attribute__((packed)) _paramS {
      char nomAD[20]; //nom des AD
      unsigned long talMeF[20]; //talon mise en froid auto
      unsigned long talStop[20]; //talon pause auto
      unsigned long talMaint[20]; //talon maintien froid auto
      unsigned long tpsMeFM[20]; //tps de mise en froid manu
      unsigned long tpsStopM[20]; //tps pause manu
      unsigned long tpsMaintM[20]; //tps maintien
    } parametres;
     
    const uint32_t keyword = 0xDEADBEEF;
    const uint16_t keywordAddress = 0x00;
    const uint16_t paramAddress = keywordAddress + sizeof(keyword);
     
    unsigned long tpsUP[4] = {0}; //tps d'ouverture EV1 à 4
    unsigned long tpsDN[4] = {0};
    unsigned long tpsMeF[4] = {0};
    unsigned long tpsStop[4] = {0};
    unsigned long tpsMaint[4] = {0};
    unsigned long tpsMeFA[20] = {0}; //tps mise en froid auto (calcul+talon)
    unsigned long tpsStopA[20] = {0}; //tps pause auto(calcul+talon)
    unsigned long tpsMaintA[20] = {0}; //tps de maintien froid auto (calcul+talon)
    //initialisation variable de travail programme:
    int Param = 0; //récupération du numéro de profil.
    int Dem[4] = {0}; // variable de sélection profil circuit 1 à 4
    uint8_t Mode[4] = {0}; //variable pour le circuit 1 à 4
    uint8_t FEV[4] = {0}; //récupère la demande de mise en marche des 4 circuits
     
    //variable calcul pression:
    int pression2[4] = {0}; //2eme pression pour les 4 circuits
    int resultat[4] = {0}; //resultat du calcul pression4 - pression42 pour le circuit 4
    int resultatAT = 0; //resultat de l'autotest BMO
     
    //init pin commande EV:
    const char EV[8] = {5, 12, 6, 11, 7, 10, 8, 9}; //pin cde EV8
     
    //variables de mesure:
    const uint8_t temp = 13; //capteur de temperature branché sur pin 13
    OneWire Capt_temp(temp);
    int pression1[4] = {0}; //première pression azote 4 circuits
    int Hr = A0; //pin mesure humidité
     
    //init capteur pression:
    const uint8_t PEV[4] = {A1, A2, A3, A4}; //pin mesure pression circuit 4
     
    //init commande déportée EV:
    const uint8_t CEV[8] = {48, 50, 52, 38, 40, 42, 44, 46}; //pin cde déportée EV8
     
    //init variable état cde EV:
    uint8_t etatCev[8] = {0};
     
    //variable calcul tps mise en froid auto:
    float tempCalcul = 0; //variable de température
    float PressionCalcul[4] = {0}; //variable de pression 4
     
    //init pin mesure tension LED 1à4:
    const uint8_t led[4] = {A5, A6, A7, A8};
    uint8_t etatLed[4] = {0};
     
    //init pin mesure tension des alim de la BMO:
    const float alim = A13;
     
    //init multiplexeur mesure alim:
    const uint8_t A = 47;
    const uint8_t B = 49;
    const uint8_t C = 51;
    const uint8_t INH = 53;
     
    //init variable de travail:
    int i = 0;
    int j = 0;
    unsigned long temps = 0; //variable de cadencement de loop
    uint8_t D[4] = {0}; //idem circuit 4
    long T[4] = {0}; //idem circuit 4
    uint8_t Val = 0; //variable autorisant la mémorisation des valeurs entrée pour les temps de fonctionnement
    uint8_t AT = 0; //compteur servant à l'autotest.
    int tempMem = 0; //mémoire température
    unsigned long talMeFMem = 0; //mémoire talon mise en froid
    unsigned long talStopMem = 0; //mémoire talon stop
    unsigned long talMaintMem = 0; //mémoire talon maintien froid
    unsigned long tpsMeFMMem = 0; //mémoire mise en froid manuelle
    unsigned long tpsStopMMem = 0; //mémoire stop manuel
    unsigned long tpsMaintMMem = 0; //mémoire maintien froid manuel
    int pression1Mem[4] = {0}; //mémoire pression1
    int affPression[4] = {9, 14, 19, 24};
    int affCr[24] = {31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54};
    int HrMem = 0; //mémoire taux d'humidité
     
    Genie genie;
     
    void setup() {
      Serial1.begin(200000);
      genie.Begin(Serial1);//écran sur le Serial 1
      genie.AttachEventHandler(myGenieEventHandler);//cde vérifiant ce qui se passe sur l'écran
      genie.WriteContrast(15);
     
      for(int i=0;i<8;i++){
        pinMode(CEV[i],INPUT);
        pinMode(EV[i], OUTPUT);  digitalWrite(EV[i], LOW);
      }
     
      for (int i=0;i<4;i++){
        pinMode(PEV[i], INPUT);
        pinMode(led[i], INPUT);
      }
      pinMode(temp, INPUT);
      pinMode(Hr, INPUT);
      pinMode(alim, INPUT);
      pinMode(A, OUTPUT);  digitalWrite(A, LOW);
      pinMode(B, OUTPUT);  digitalWrite(B, LOW);
      pinMode(C, OUTPUT);  digitalWrite(C, LOW);
      pinMode(INH, OUTPUT);  digitalWrite(INH, HIGH);
     
      getParametres();
    }
     
    void saveParametres() {
      EEPROM.put(keywordAddress, keyword);
      EEPROM.put(paramAddress, parametres);
    }
     
    void getParametres() {
      uint32_t tmpKey;
     
      EEPROM.get(keywordAddress, tmpKey);
      if (tmpKey == keyword) {
        EEPROM.get(paramAddress, parametres);    // EEPROM was already initialized OK to read
      } else {
        // First run on this arduino, memory was never initialized. so establish default values
        for(int i=0;i<20;i++){
          strcpy(parametres.nomAD[i],"sans nom"); //nom des AD
          parametres.talMeF[i] = 0; //talon mise en froid auto
          parametres.talStop[i] = 0; //talon pause auto
          parametres.talMaint[i] = 0; //talon maintien froid auto
          parametres.tpsMeFM[i] = 0; //tps de mise en froid manu
          parametres.tpsStopM[i] = 0; //tps pause manu
          parametres.tpsMaintM[i] = 0; //tps maintien
        }
       saveParametres();
      }
    }
     
    void loop() {
      //log("Debut loop");
      if (millis() - temps >= 30000) {
        //log("Debut mesure météo");
        //mesure pressions:
        for (int i = 0; i < 4; i++) {
          pression1[i] = ((analogRead(PEV[i]) * 5) / 1024) * 0.0125;
          PressionCalcul[i] = 0.097085 * pression1[i];
          if (pression1[i] != pression1Mem[i]) {
            genie.WriteStr(affPression[i], pression1[i]);
            genie.WriteObject(GENIE_OBJ_COOL_GAUGE, i, pression1[i]);
          }
          pression1Mem[i] = pression1[i];
        }
        //mesure température:
        int temp = getTemp();
        if (temp != tempMem) {
          genie.WriteObject(GENIE_OBJ_THERMOMETER, 0, temp + 30); //affichage t°sur thermomètre avec offset de 30
          tempCalcul = 196 + temp + 10;
        }
        tempMem = temp;
        //mesure humidité:
        Hr = getHr();
        //if(Hr!=HrMem ){
        //genie.WriteObject(GENIE_OBJ_LED_DIGITS,0,Hr);
        //}
        HrMem = Hr;
        temps = millis();
        //log("Fin mesure météo");
      }
      genie.DoEvents();  //TEMPO
     
     
      //demarrage de l'autotest de la BMO:
      if (AT == 1) {
        Autotest();//déclenchement de l'autotest de la BMO
        if (resultatAT >= 34) {
          genie.WriteStr(28, "OK");
        } else {
          genie.WriteStr(28, "NOK");
        }
      }
      //memorisation des talons et temps dans le paramétrage:
      if (Param != 0) {
        if (Val == 1) {
          if (neg1 == 1) {
            parametres.talMeF[Param] = -slider0_val;
          } else {
            parametres.talMeF[Param] = slider0_val;
          }
          if (neg2 == 1) {
            parametres.talStop[Param] = -slider1_val;
          } else {
            parametres.talStop[Param] = slider1_val;
          }
          if (neg3 == 1) {
            parametres.talMaint[Param] = -slider2_val;
          } else {
            parametres.talMaint[Param] = slider2_val;
          }
          parametres.tpsMeFM[Param] = slider3_val;
          parametres.tpsStopM[Param] = slider4_val;
          parametres.tpsMaintM[Param] = slider5_val;
          saveParametres();
        }
     
        if (parametres.talMeF[Param] != talMeFMem) {
          if (parametres.talMeF[Param] < 0) {
            genie.WriteObject(GENIE_OBJ_LED, 12, 1);
            genie.WriteObject(GENIE_OBJ_LED_DIGITS, 7, -parametres.talMeF[Param]);
          } else {
            genie.WriteObject(GENIE_OBJ_LED, 12, 0);
            genie.WriteObject(GENIE_OBJ_LED_DIGITS, 7, parametres.talMeF[Param]);
          }
        }
        if (parametres.talStop[Param] != talStopMem) {
          if (parametres.talStop[Param] < 0) {
            genie.WriteObject(GENIE_OBJ_LED, 13, 1);
            genie.WriteObject(GENIE_OBJ_LED_DIGITS, 8, -parametres.talStop[Param]);
          } else {
            genie.WriteObject(GENIE_OBJ_LED, 13, 0);
            genie.WriteObject(GENIE_OBJ_LED_DIGITS, 8, parametres.talStop[Param]);
          }
        }
        if (parametres.talMaint[Param] != talMaintMem) {
          if (parametres.talMaint[Param] < 0) {
            genie.WriteObject(GENIE_OBJ_LED, 14, 1);
            genie.WriteObject(GENIE_OBJ_LED_DIGITS, 9, -parametres.talMaint[Param]);
          } else {
            genie.WriteObject(GENIE_OBJ_LED, 14, 0);
            genie.WriteObject(GENIE_OBJ_LED_DIGITS, 9, parametres.talMaint[Param]);
          }
        }
        if (parametres.tpsMeFM[Param] != tpsMeFMMem) {
          genie.WriteObject(GENIE_OBJ_LED_DIGITS, 10, parametres.tpsMeFM[Param]);
        }
        if (parametres.tpsStopM[Param] != tpsStopMMem) {
          genie.WriteObject(GENIE_OBJ_LED_DIGITS, 11, parametres.tpsStopM[Param]);
        }
        if (parametres.tpsMaintM[Param] != tpsMaintMMem) {
          genie.WriteObject(GENIE_OBJ_LED_DIGITS, 12, parametres.tpsMaintM[Param]);
        }
        talMeFMem = parametres.talMeF[Param];
        talStopMem = parametres.talStop[Param];
        talMaintMem = parametres.talMaint[Param];
        tpsMeFMMem = parametres.tpsMeFM[Param];
        tpsStopMMem = parametres.tpsStopM[Param];
        tpsMaintMMem = parametres.tpsMaintM[Param];
      }
      //calcul des tps de mise en froid en auto:
      for (int j = 1; j < 6; j++) {
        tpsMeFA[j] = (-tempCalcul / (-PressionCalcul[0] + 12.59815)) + parametres.talMeF[j];
      }
      for (int j = 6; j < 11; j++) {
        tpsMeFA[j] = (-tempCalcul / (-PressionCalcul[1] + 12.59815)) + parametres.talMeF[j];
      }
      for (int j = 11; j < 16; j++) {
        tpsMeFA[j] = (-tempCalcul / (-PressionCalcul[2] + 12.59815)) + parametres.talMeF[j];
      }
      for (int j = 16; j < 21; j++) {
        tpsMeFA[j] = (-tempCalcul / (-PressionCalcul[3] + 12.59815)) + parametres.talMeF[j];
      }
      //définition des temps de travail des EV:
      for (int i = 0; i < 4; i++) {
        if (Mode[i] == 1) { //si le mode auto est sélectionné pour les 4 EV.
          tpsMeF[i] = tpsMeFA[Dem[i]];
          tpsStop[i] = tpsStopA[Dem[i]];
          tpsMaint[i] = tpsMaintA[Dem[i]];
        } else {
          tpsMeF[i] = parametres.tpsMeFM[Dem[i]];
          tpsStop[i] = parametres.tpsStopM[Dem[i]];
          tpsMaint[i] = parametres.tpsMaintM[Dem[i]];
        }
        //fonctionnement EV:
        if (FEV[i] == 1) { //si EV 1 à 4 à démarré
          if (((Mode[i] == 1) && (pression1[i] >= 135) && (Dem[i] != 0)) || ((Mode[i] == 0) && (Dem[i] != 0))) { //si mode auto ET pression >=135 bars ET profile sélectionné OU mode manu et profil sélectionné
            if (D[i] == 0) { //si la mise en froid n'est pas réalisée
              tpsUP[i] = tpsMeF[i] * 1000; // on utilise le temps de mise en froid
            } else {
              tpsUP[i] = tpsMaint[i] * 1000; //sinon on utilise le temps de maintien froid
            }
            tpsDN[i] = tpsStop[i] * 1000;
            etatCev[i] = HIGH;
            digitalWrite(EV[i], etatCev[i]);
            if (millis() - T[i] > tpsUP[i]) {
              etatCev[i] = LOW;
              digitalWrite(EV[i], etatCev[i]);
              D[i] = 1;
            }
            if (millis() - T[i] > tpsUP[i] + tpsDN[i]) {
              etatCev[i] = HIGH;
              digitalWrite(EV[i], etatCev[i]);
              T[i] = millis();
     
            }
          }
        } else {
          etatCev[i] = LOW;
          digitalWrite(EV[i], etatCev[i]);
     
        }
      }
      /*
        //utilisation cde EV déportée:
        for(i=0;i<9;i++){
        if(digitalRead(CEV[i])==LOW){
        etatCev[i]=!etatCev[i];
        digitalWrite(EV[i],etatCev[i]);
        }
        }
      */
    }
    Voilà. Pour le nomAD je ne vois pas ce qu'il faut mettre pour initialiser les 20 noms.
    Pour les variables Hr (Humidité relative c'est la notation scientifique) et les PINS A,B et C (Pin A B et C du multiplexeur) Je ne vois pas comment choisir autre chose de plus explicite...

  10. #10
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    mais l'adresse des entrées-sortie doit être définie par un #define (codage C) ou un const int (codage C++) et non par une variable.
    si vous voulez parlez des ports il vaudrait mieux un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     constexpr volatile uint8_t *
    non ?

  11. #11
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    si vous ne pouvez pas optimiser la partie calculs, il faut donc vous concentrer sur l'optimisation de ce qui va à l'écran 4D system
    - quel écran ? quel mode de communication ? pouvez vous choisir un débit différent plus rapide ?
    - ne pas tout effacer pour rafraîchir l'écran. modifiez juste ce qui doit l'être
    - conservez en mémoire l'ancienne valeur affichée, et n'envoyez un ordre de mise à jour que si cette valeur a changé par exemple
    ...

    pour les calculs, passer sur un autre type de cartes (ESP32 ou autres MKR) avec une vraie unité de calculs en 32 bits et tournant à plus de 16Mhz vous fera aussi sans doute gagner du temps.

  12. #12
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    avez vous 20 noms "nomAD" ? ou un seul à sauvegarder.

    Si vous voulez 20 noms et qu'ils puissent faire chacun jusqu'à 19 caractères (plus le '\0' de fin de chaîne), il faut déclarer un tableau de tableaux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const uint8_t nombreDeNoms = 20;
    const uint8_t longeurMaxDuNom = 19;
    char nomAD[nombreDeNoms][longeurMaxDuNom+1];
    et là le code suivant va fonctionner:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy(parametres.nomAD[i],"sans nom"); //nom des AD
    car parametres.nomAD[i] est une zone mémoire de (longeurMaxDuNom+1) octets

    Notez cependant que 20 noms de 20 octets, c'est 400 octets de SRAM. Vous en avez 8192 au total sur votre MEGA, donc ça fait 5% de la mémoire juste pour les noms --> avez vous vraiment besoin de 20 caractères ?

    Pour Humidité relative --> vous pourriez l'appeler pinHR par exemple. juste pour pas confondre avec la mesure d'Humidité relative
    Pour les Pin A B et C du multiplexeur, moi j'aurais mis pinMultiplexeurA, pinMultiplexeurB, pinMultiplexeurC par exemple
    Au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const uint8_t temp = 13; //capteur de temperature branché sur pin 13
    j'aurais mis pinTemperature

    La preuve que c'est facile de se mélanger les pinceaux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //init pin mesure tension des alim de la BMO:
    const float alim = A13;
    --> Pourquoi le N° d'une pin serait rangée dans un nombre de type float ? -->
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    donc ce serait plutôt const uint8_t pinMesureAlimentation = A13; //N° de pin pour mesure tension des alim de la BMO:
    Ensuite bien souvent dans le code on oublie que c'est le N° de pin et vous allez confondre "alim" avec la valeur lue par un analogRead() mais sans faire la lecture...

    ce sont des petites habitudes qui ne coûtent pas cher à mettre en place mais qui évitent bien des soucis lors de la relecture et du debug (ou compréhension de votre code par des tiers, comme quand j'essaye de le lire).

  13. #13
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    Citation Envoyé par Jay M Voir le message
    avez vous 20 noms "nomAD" ? ou un seul à sauvegarder.

    Si vous voulez 20 noms et qu'ils puissent faire chacun jusqu'à 19 caractères (plus le '\0' de fin de chaîne), il faut déclarer un tableau de tableaux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    const uint8_t nombreDeNoms = 20;
    const uint8_t longeurMaxDuNom = 19;
    char nomAD[nombreDeNoms][longeurMaxDuNom+1];
    et là le code suivant va fonctionner:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy(parametres.nomAD[i],"sans nom"); //nom des AD
    car parametres.nomAD[i] est une zone mémoire de (longeurMaxDuNom+1) octets

    Notez cependant que 20 noms de 20 octets, c'est 400 octets de SRAM. Vous en avez 8192 au total sur votre MEGA, donc ça fait 5% de la mémoire juste pour les noms --> avez vous vraiment besoin de 20 caractères ?
    Non, juste 20 noms de 5 caractères chacun ...

  14. #14
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    Ca fonctionne je dois voir comment utiliser le keyboard de 4Dsystem pour entrer mes nomsAD maintenant.
    Merci encore. A plutard je pense !

  15. #15
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Joli !!!



    pour améliorer un peu les performances et la lisibilité, vous devriez créer une petite fonction qui met à jour les temps pour un circuit donné:

    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
    void calculTemps(int8_t indexCircuit)
    {
      if (Mode[indexCircuit] == 1) { //si le mode auto est sélectionné pour les cette EV.
        uint8_t indexProfil = 0; // profil par défaut
        if (Dem[indexCircuit] < 6)       indexProfil = 0; // si le profil correspond au circuit 1, on fait les calculs avec la pression 1
        else if (Dem[indexCircuit] < 11) indexProfil = 1; // si le profil correspond au circuit 2 , on fait les calculs avec la pression 2
        else if (Dem[indexCircuit] < 16) indexProfil = 2; // si le profil correspond au circuit 3 , on fait les calculs avec la pression 3
        else if (Dem[indexCircuit] < 21) indexProfil = 3; // si le profil correspond au circuit 4, on fait les calculs avec la pression 4
        tpsMeF[indexCircuit] = (-tempCalcul / (-PressionCalcul[indexProfil] + 12.59815)) + parametres.talMeF[Dem[indexCircuit]];
        tpsStop[indexCircuit] = ((-tempCalcul + chauffeCapteur) / (-PressionCalcul[indexProfil] + 12.59815)) + parametres.talStop[Dem[indexCircuit]];
        tpsMaint[indexCircuit] = ((-tempCalcul + chauffeCapteur) / (-PressionCalcul[indexProfil] + 12.59815)) + parametres.talMaint[Dem[indexCircuit]];
      } else {
        tpsMeF[indexCircuit] = parametres.tpsMeFM[Dem[indexCircuit]];
        tpsStop[indexCircuit] = parametres.tpsStopM[Dem[indexCircuit]];
        tpsMaint[indexCircuit] = parametres.tpsMaintM[Dem[indexCircuit]];
      }
    }
    et ensuite appeler cette fonction dans la machine à état uniquement quand c'est pertinent, la boucle sur les 4 circuits serait alors
    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
    for (uint8_t i = 0; i < 4; i++) {
    
      switch (etat[i]) {  //fonctionnement EV
    
        case etatStop:
          if (FEV[i] == 1) { // demande démarrage
            etatCev[i] = HIGH;
            digitalWrite(EV[i], etatCev[i]);
            chrono[i] = millis();
            etat[i] = etatMiseFroid;
          }
          break;
    
        case etatMiseFroid:
          if (FEV[i] == 0) { // demande arrêt
            etatCev[i] = LOW;
            digitalWrite(EV[i], etatCev[i]);
            etat[i] = etatStop;
          } else {
            calculTemps(i);
            if (millis() - chrono[i]  >= (tpsMeF[i] * 1000)) {
              etatCev[i] = LOW;
              digitalWrite(EV[i], etatCev[i]);
              chrono[i] = millis();
              etat[i] = etatPause;
            }
          }
          break;
    
        case etatPause:
          if (FEV[i] == 0) { // demande arrêt
            etatCev[i] = LOW;
            digitalWrite(EV[i], etatCev[i]);
            etat[i] = etatStop;
          } else {
            calculTemps(i);
            if (millis() - chrono[i]  >= (tpsStop[i] * 1000)) {
              etatCev[i] = HIGH;
              digitalWrite(EV[i], etatCev[i]);
              chrono[i] = millis();
              etat[i] = etatMaintienFroid;
            }
          }
          break;
    
        case etatMaintienFroid:
          if (FEV[i] == 0) { // demande arrêt
            etatCev[i] = LOW;
            digitalWrite(EV[i], etatCev[i]);
            etat[i] = etatStop;
          } else {
            calculTemps(i);
            if (millis() - chrono[i]  >= (tpsMaint[i] * 1000)) {
              etatCev[i] = LOW;
              digitalWrite(EV[i], etatCev[i]);
              chrono[i] = millis();
              etat[i] = etatPause;
            }
          }
          break;
      }
    }
    On pourrait affiner encore plus en séparant le calcul des 3 temps car seul un des temps est nécessaire dans un état donné. (les calculs en nombre flottant sont "lents").

    L'autre option serait d'avoir toujours à jour ces temps et de les modifier quand une des valeurs de la formule change. ça éviterait de faire le calcul à chaque tour de loop, vous le feriez uniquement quand c'est vraiment nécessaire.
    Vous pourriez aussi éviter le x 1000 à chaque test et stocker la valeur en ms directement dans la variable.


    ---

    enfin autre petites améliorations de la lisibilité:

    - utiliser partout des const uint8_t pour les N° de pins.

    - mettre le mot pin de manière uniforme dans toutes les constantes qui contiennent des pins (comme vous avez fait pour pinHr par exemple) on aurait donc par exemple au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const char EV[8] = {5, 12, 6, 11, 7, 10, 8, 9}; //pin cde EV8
    le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const uint8_t pinEV[8] = {5, 12, 6, 11, 7, 10, 8, 9}; //pins de commandes des groupes d'électro-vannes (EV)
    .
    De même
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const byte temp = 13; //capteur de temperature branché sur pin 13
    deviendrait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const uint8_t pinTemperature = 13; // capteur de temperature branché sur pin 13
    - vous n'êtes pas obligé de donner la dimension dans les tableaux à 1 dimension, comme ça si vous rajoutez des circuits vous n'avez rien à modifier. Par exemple au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //init capteur pression:
    const uint8_t PEV[4] = {A1, A2, A3, A4}; //pin mesure pression circuit 4
    vous pouvez écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //init capteur pression:
    const uint8_t pinPEV[] = {A1, A2, A3, A4}; //pin mesure pression circuit 4
    - mettre au début du code un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const uint8_t nombreDeCircuits = 4; // Nombre de circuits pilotés
    et ensuite partout où vous retrouvez ce 4 dans le code pour les 'boucles for' remplacer le 4 par nombreDeCircuits... Vous serez bien content d'avoir fait cela s'il faut passer à 5 circuits.

    - Une autre option serait de le calculer à la compilation en fonction d'un des tableau de pins, par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    //init capteur pression:
    const uint8_t pinPEV[] = {A1, A2, A3, A4}; //pin mesure pression circuit 4
    const uint8_t nombreDeCircuits = sizeof(pinPEV) / sizeof(pinPEV[0]); // Nombre de circuits pilotés
    bref - évitez tout ce qui est nombre magique dans le code, remplacez les par des constantes du bon type qui portent un nom parlant.

  16. #16
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    j'ai lu en diagonal, il y a tellement de répétition de code qu'on s'y perd...
    faudrait utiliser des tableaux et factoriser

    i faudrait aussi mettre des else entre les if quand ils sont mutuellement exclusifs (dans myGenieEventHandler)

    Je ne suis pas sûr de ce que vous faites que vous écrivez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     if (Mode1 == 1) { //si le mode auto est sélectionné pour l'EV1
        int i = Dem1; //les tps auto en mémoire sont placés dans les variables de temps
        tpsMeF1 = tpsMeFA[i];
        tpsStop1 = tpsStopA[i];
        tpsMaint1 = tpsMaintA[i];
      } else {
        tpsMeF1 = tpsMeFM[i];
        tpsStop1 = tpsStopM[i];
        tpsMaint1 = tpsMaintM[i];
      }
    dans la partie vraie du if vous avez un i en variable locale temporaire, mais qui du i qui est utilisé dans le else ?

    enchaîner des analogRead sur des pins différentes peut conduire à des mesures erronées
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        pression1 = ((analogRead(PEV1) * 5) / 1024) * 0.0125;
        pression2 = ((analogRead(PEV2) * 5) / 1024) * 0.0125;
        pression3 = ((analogRead(PEV3) * 5) / 1024) * 0.0125;
        pression4 = ((analogRead(PEV4) * 5) / 1024) * 0.0125;
    la recommendation est de lire une fois "à blanc" la pin, jeter la valeur et relire. ça permet à la tension de se stabiliser correctement s'il y a de grosses différences de potentiel d'une pin à l'autre

    ensuite comme il manque plein de code difficile de dire où le temps est passé. Il faudrait instrumenter tout cela. par exemple combien de temps dure Autotest()?

  17. #17
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    Citation Envoyé par Jay M Voir le message
    j'ai lu en diagonal, il y a tellement de répétition de code qu'on s'y perd...
    faudrait utiliser des tableaux et factoriser
    Je ne suis pas sur de comprendre...
    Citation Envoyé par Jay M Voir le message
    i faudrait aussi mettre des else entre les if quand ils sont mutuellement exclusifs (dans myGenieEventHandler)
    Je ne leur demande rien d'autre, je leur demande de faire quelque chose quand on appuie sur les boutons. Sinon que devrais-je mettre en else?

    Citation Envoyé par Jay M Voir le message
    Je ne suis pas sûr de ce que vous faites que vous écrivez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     if (Mode1 == 1) { //si le mode auto est sélectionné pour l'EV1
        int i = Dem1; //les tps auto en mémoire sont placés dans les variables de temps
        tpsMeF1 = tpsMeFA[i];
        tpsStop1 = tpsStopA[i];
        tpsMaint1 = tpsMaintA[i];
      } else {
        tpsMeF1 = tpsMeFM[i];
        tpsStop1 = tpsStopM[i];
        tpsMaint1 = tpsMaintM[i];
      }
    dans la partie vraie du if vous avez un i en variable locale temporaire, mais qui du i qui est utilisé dans le else ?
    En fait je défini 1 profil par circuit. Ce numéro de profil je le stock dans les variable Dem 1 à 4. Elles me servent à ressortir les valeurs de temps en auto et en manuel. Ces temps je les mets dans les tpsMeF1, tpsStop1 et tpsMaint1, 2, 3 et 4. Si le Mode(1 a 4) est sur 1 c'est que je suis en auto et 0 en manuel donc je charge les temps auto ou manuel dans ces variables.
    Le i dans la partie vrai n'est pas utilisé dans la partie fausse?
    Cela expliquerai pourquoi mes temps s'harmonisent quand je lance le programme avec les relais en manuel car je ne peux pas utiliser le mode auto pour l'instant faute de pression...
    Citation Envoyé par Jay M Voir le message
    enchaîner des analogRead sur des pins différentes peut conduire à des mesures erronées
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        pression1 = ((analogRead(PEV1) * 5) / 1024) * 0.0125;
        pression2 = ((analogRead(PEV2) * 5) / 1024) * 0.0125;
        pression3 = ((analogRead(PEV3) * 5) / 1024) * 0.0125;
        pression4 = ((analogRead(PEV4) * 5) / 1024) * 0.0125;
    la recommendation est de lire une fois "à blanc" la pin, jeter la valeur et relire. ça permet à la tension de se stabiliser correctement s'il y a de grosses différences de potentiel d'une pin à l'autre
    C'est un problème que je verrais plus tard, mais je prend note. Ce sont des capteurs PU5400 que j'utilise mais je ne les ai pas tous et je n'ai pas encore la possibilité de les tester.

    Citation Envoyé par Jay M Voir le message
    ensuite comme il manque plein de code difficile de dire où le temps est passé. Il faudrait instrumenter tout cela. par exemple combien de temps dure Autotest()?

    L'autotest se déroule qu'à la demande donc il n'entre pas en ligne de compte pour le coup. Et se déroule en une 30 aine de seconde.

    En fait mes temps de fonctionnement tpsMeF1, tpsStop1 et tpsMaint1 (et a fortiori les autres) ne sont pas respectés par le programme et bien souvent le relais reste à l'état HIGH. Je pense que cela doit venir de la gestion de millis(), mes temps sont en secondes mais je compare avec une valeur en milliseconde, mais en multipliant par 1000 ces temps la au moment du traitement (pas pendant l'élaboration sinon ca fout en l'air l'affichage des valeurs) ca ne fonctionne pas mieux…

    Je precise que j'ai appris à programmer par mes propres moyens mais que je ne suis pas un professionnel...

  18. #18
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Le i dans la partie vrai n'est pas utilisé dans la partie fausse?
    Cela expliquerai pourquoi mes temps s'harmonisent quand je lance le programme avec les relais en manuel car je ne peux pas utiliser le mode auto pour l'instant faute de pression
    Non il est même inconnu à cet endroit... vous devez avoir un i en variable globale sans doute, c'est celui qui est pris...

    Sinon que devrais-je mettre en else?
    Si je regarde vos tests pour les événements il ressemblent à cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
      if (Event.reportObject.index == 3) {  }
      if (Event.reportObject.index == 4) {  }
      if (Event.reportObject.index == 5) {  }
      if (Event.reportObject.index == 6) {  }
      if (Event.reportObject.index == 7) {  }
      if (Event.reportObject.index == 8) {  }
      if (Event.reportObject.index == 9) {  }
      ...
    }
    on voit bien que si vous avez trouvé que 4 était la bonne réponse ce n'est plus la peine de tester 5,6,7,....
    donc i faut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
      if (Event.reportObject.index == 3) {  }
      else if (Event.reportObject.index == 4) {  }
      else if (Event.reportObject.index == 5) {  }
      else if  (Event.reportObject.index == 6) {  }
      else if  (Event.reportObject.index == 7) {  }
      else if  (Event.reportObject.index == 8) {  }
      else if  (Event.reportObject.index == 9) {  }
      ...
    }
    ou alors mettre un switch sur Event.reportObject.index.
    Il semble aussi que vous ayez un nombre conséquent d'éléments d'interface.... pourriez vous simplifier ?

    Pour les tableaux c'est quand je vois par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (a = 1; a < 5; a++) {
        if (FEV[a] == 1) { //si EV 1 à 4 à démarré
          switch (a) {
            case 1:... break;
            case 2:... break;
            case 3:... break;
            case 4:... break;
         } // fin du switch
      } // fin du if 
    } // fin du for
    Dans votre boucle for vous faites un truc spécial par valeur de a mais le code dans les switch se ressemble bcp, il semblerait donc qu'au lieu d'avoir des variables distinctes pour Dem1, Dem2, Dem3, Dem4 on gagnerait à les avoir dans un tableau par exemple et l'index serait directement la variable a de votre boucle.


    PS: je ne connais pas ces écrans ni cette librairie, mais je me dis que réduire le bavardage entre les 2 composants vous fera sans doute gagner bcp de temps. Simplifiez l'UI au maximum, créez des sous écrans peut être de façon à limiter ce qui est disponible à l'affichage à un instant t....

    rajoutez aussi à certains endroit de quoi mesurer le temps passé dans certaines fonctions pour comprendre ce qui coûte cher et commencez par optimiser cette partie

  19. #19
    Membre averti
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2017
    Messages
    77
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Meuse (Lorraine)

    Informations professionnelles :
    Activité : Technicien maintenance

    Informations forums :
    Inscription : Février 2017
    Messages : 77
    Par défaut
    Citation Envoyé par Jay M Voir le message
    Non il est même inconnu à cet endroit... vous devez avoir un i en variable globale sans doute, c'est celui qui est pris...
    effectivement… du coup j'ai rajouté aussi dans le partie fausse de if.
    Citation Envoyé par Jay M Voir le message
    Si je regarde vos tests pour les événements il ressemblent à cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
      if (Event.reportObject.index == 3) {  }
      if (Event.reportObject.index == 4) {  }
      if (Event.reportObject.index == 5) {  }
      if (Event.reportObject.index == 6) {  }
      if (Event.reportObject.index == 7) {  }
      if (Event.reportObject.index == 8) {  }
      if (Event.reportObject.index == 9) {  }
      ...
    }
    on voit bien que si vous avez trouvé que 4 était la bonne réponse ce n'est plus la peine de tester 5,6,7,....
    donc i faut écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
      if (Event.reportObject.index == 3) {  }
      else if (Event.reportObject.index == 4) {  }
      else if (Event.reportObject.index == 5) {  }
      else if  (Event.reportObject.index == 6) {  }
      else if  (Event.reportObject.index == 7) {  }
      else if  (Event.reportObject.index == 8) {  }
      else if  (Event.reportObject.index == 9) {  }
      ...
    }
    ou alors mettre un switch sur Event.reportObject.index.
    Très bien je vais voir comment réagit le programme à cela, en fait à ce niveau, j'ai 2 écrans avec 20 boutons:
    - un écran qui me permet de paramétrer mes 20 profils, divisés en 4 groupes de 5,
    - un autre écran qui me permet d'en choisir un parmi les 5 de son groupe et de choisir le mode auto ou manuel.
    Ensuite j'ai un autre écran qui fait le rappel du profil choisi, le mode dans lequel il est, la pression de son circuit et les temps de Mise en froid, de pause et de maintien froid.
    Du coup le programme tournera probablement plus vite mais est ce qu'il detectera tous les appuis?

    Citation Envoyé par Jay M Voir le message
    Il semble aussi que vous ayez un nombre conséquent d'éléments d'interface.... pourriez vous simplifier ?
    Difficile… Peut être regrouper les écrans de paramétrage et de sélection... j'ai 8 pages d'interfaces en tout:
    -Une page de "présentation" qui redirige vers le paramétrage, le démarrage et l'autotest,
    -Une page de paramétrage qui redirige vers la page avec les sliders et les affichages et vers une autres page avec un clavier pour nommer le profil.
    -Une page démarrage et "récapitulatif des paramètres".
    -Une page autotest qui redirige vers une page compte rendu de test.
    Je ne vois pas beaucoup où je peux réduire l'interface sans compliquer les choses derrière...
    Citation Envoyé par Jay M Voir le message
    Pour les tableaux c'est quand je vois par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (a = 1; a < 5; a++) {
        if (FEV[a] == 1) { //si EV 1 à 4 à démarré
          switch (a) {
            case 1:... break;
            case 2:... break;
            case 3:... break;
            case 4:... break;
         } // fin du switch
      } // fin du if 
    } // fin du for
    Dans votre boucle for vous faites un truc spécial par valeur de a mais le code dans les switch se ressemble bcp, il semblerait donc qu'au lieu d'avoir des variables distinctes pour Dem1, Dem2, Dem3, Dem4 on gagnerait à les avoir dans un tableau par exemple et l'index serait directement la variable a de votre boucle.
    J'ai également tenté de mettre ça en tableau et ca devient compliqué on rentre dans des boucles dans des boucles et je m'y suis un peu perdu, j'ai donc réduit le nombre de boucle au profit d'un allongement du code...
    Ce qu'il faut savoir c'est que sur ma page récapitulatif des paramètres j'ai 4 boutons qui mettent en marche les 4 circuits, ils sont stockés dans les FEV1 à 4.
    Lorsque le circuit est mis en marche, je récupère le numéro de profil (Dem 1 à 4) qui me sert à extraire les paramètres de temps de mise en froid, pause et maintien froid du profil (auto ou manuel fonction de l'état de Mode 1à 4). Je commande ensuite le relais du circuit aux rythmes des différents temps.
    Je peux retenter de réduire la taille du code...
    Comment puis-je mettre en tableaux mes sorties EV 1 à 4 car c'est pour ça que j'ai programmer comme cela, je ne pense pas que je puisse les mettre en tableau... d'un point de vue déclaration également...

  20. #20
    Expert confirmé

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

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 908
    Par défaut
    Je ne connais pas ces écrans, donc je ne peux pas aider...

Discussions similaires

  1. Cherche un document management system pour s'inspirer
    Par randriano dans le forum Autres Solutions d'entreprise
    Réponses: 0
    Dernier message: 03/12/2014, 10h08
  2. Réponses: 0
    Dernier message: 05/11/2014, 21h11
  3. Trouver un poste pour un mémoire d'ingénieur CNAM
    Par AntoineGael dans le forum Emploi
    Réponses: 2
    Dernier message: 13/01/2014, 14h22
  4. disquette systéme pour windows xp
    Par gilleski2010 dans le forum Windows XP
    Réponses: 1
    Dernier message: 14/10/2005, 22h13

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