while ((millis() - previousMillis) : améliorations à un code fonctionnel

Bonjour à tous,

Y aurait-il une amélioration à apporter pour ce code?
La pause pourrait durer 60 minutes.

byte pinToRead = 36;    //input

int whileFunction() {
  unsigned long long  previousMillis, thisMillis;
  int totVal = 0, val = 0;
  uint8_t  once = 0;
  uint8_t mean = 3, turns = 0;

  while (turns < mean) {
  if (once < 1) {
    Serial.println("dummy reading");
    analogRead(pinToRead);
    previousMillis = millis();
    while ((millis() - previousMillis) < (5E3)) { //lets the device warm up after opening it
      ;
    }
    once = 1;
  }
  
    val = analogRead(pinToRead);
    previousMillis = millis();
    while ((millis() - previousMillis) < 2000) {
      ; //2 seconds to read
    }
 
    if (isnan(val)) {
      Serial.println("Failed to read from probe.");
      return 0;
    }
    val = map(val, 3265, 1630, 0, 100);
    totVal += val;
    printf("%d %d\n", val, totVal);
  turns++;
  }
  return (totVal / mean);
}

void setup() {
  Serial.begin(115200);

  int a = whileFunction();
  printf("whileFunction() %d \n", a);
}

void loop() {
}

OUTPUT:

dummy reading
77 77
79 156
78 234
whileFunction() 78

Merci pour vos suggestions.

JPDaviau

Bonsoir Jean
pour pinToRead tu peux utiliser #define
la variable once et if (once < 1) sont inutiles
la variable mean tu peux la déclarer comme une constante.

  unsigned long long  previousMillis, thisMillis;

il y a 2 "long"

améliorer ? selon quel critère ?

si tu ne fait rien d'autre qu'attendre pendant tes phases d'attente (tu ne surveilles rien d'autre que le temps), tu peux remplacer ta boucle

while ( millis() - prevMillis < X ) {}

par delay ( X );

Bonjour Jean24816,

thisMillis n'est pas utilisé.

Quel genre d'amélioration ?

A quoi sert :

    if (isnan(val)) {
      Serial.println("Failed to read from probe.");
      return 0;
    }

Cordialement,
bidouilleelec

savoriano:
pour pinToRead tu peux utiliser #define

En pratique non, ce n'est pas une bonne idée d'utiliser un define pour les N° de pin.
l'idéal c'est de les déclarer comme constante et leur donner le bon type, on écrira doncconst byte pinToRead = 36;    //inputou si on veut faire savant et utiliser les types officiels du C/C++ faireconst uint8_t pinToRead = 36;    //input

Pourquoi me direz vous ?

pour plusieurs raisons: la première c'est que plus vous donnez d'information au compilateur sur le type des données, plus il peut optimiser le code. ici en déclarant la variable comme constante et tenant sur un seul octet le compilateur (et l'optimisateur) ont une information stratégique: ils peuvent remplacer dans le binaire généré directement l'appel à la variable par un octet ce qui tient souvent bien dans les instructions d'une machine 8 bit. donc pas d'allocation mémoire pour la variable et optimisation binaire.

avec un #define, vous remplacez toutes les mentions du nom par sa représentation et vous compilez. Pour un nombre, le type par défaut du langage est un int, qui tient sur 2 ou 4 octets suivant la plateforme. ça peut conduire à des coûts cachés du fait que le compilateur n'avait pas la bonne information de type.

Par exemple, compilez cela (je le fais sur un MEGA):

#define numeroPin 2

void setup() {
  Serial.begin(115200);
  Serial.print(F("Numero de pin = "));
  Serial.println(numeroPin);
}

void loop() {}

l'IDE va me dire:

[color=blue]Le croquis utilise [b]2024[/b] octets (0%) de l'espace de stockage de programmes. Le maximum est de 253952 octets.
Les variables globales utilisent [b]188[/b] octets (2%) de mémoire dynamique, ce qui laisse 8004 octets pour les variables locales. Le maximum est de 8192 octets.[/color]

Maintenant compilez ce code qui est exactement le même mais où on a dit au compilateur que numeroPin était une constante sur un octet:

const uint8_t numeroPin = 2;

void setup() {
  Serial.begin(115200);
  Serial.print(F("Numero de pin = "));
  Serial.println(numeroPin);
}

void loop() {}

l'IDE va me dire:

[color=blue]Le croquis utilise [b]1848[/b] octets (0%) de l'espace de stockage de programmes. Le maximum est de 253952 octets.
Les variables globales utilisent [b]188[/b] octets (2%) de mémoire dynamique, ce qui laisse 8004 octets pour les variables locales. Le maximum est de 8192 octets.[/color]

on voit bien que les variables utilisent la même place, 188 octets -> le fait de déclarer en const uint8_t n'a pas alloué plus de mémoire mais regardez la taille du binaire: on passe de 2024 octets avec le #define à 1848 octets. On gagne 176 octets de mémoire flash !! c'est parce que le compilateur a su qu'il avait à gérer l'impression d'un seul octet et pas d'un entier sur 2 ou 4 octets et donc la fonction print a été optimisée !

conclusion: plus vous donnez d'info au compilateur, mieux vous vous portez. Evitez les #define pour autre chose que de la compilation conditionnelle.


quelle plateforme utilisez vous ? (cf l'usage de printf() )

analogRead() retourne une valeur entre 0 et 1023 donc aucune chance que vous ayez "not a number" et le map     val = map(val, 3265, 1630, 0, 100);est bizarre puisqu'il n'y a aucune chance pour que val soit entre 1630 et 3265. ça va bien faire une fonction affine mais vous n'aurez pas un résultat entre 0 et 100 comme vous semblez l'espérer.


votre usage de millis() ou de 5E3 complexifie la lecture du code, autant faire delay(5000UL); ou delay(2000UL); (avec UL pour signifier qu'on veut une représentation en unsigned long)