Comment afficher le temps en sec, mn et h

Bonjour,

J'aimerais bien affiché le temps que tourne mon programme.

Pour cela. je fais ceci:

uint32_t timers = (millis() - timer)/1000; // sec

timer est mis à 0, dans à la fin de mon setup().

Le truc c'est qu'il me retorune toujours le résultat en seconde.
Alors dans un sens, ca ne me dérange pas trop, mais apèrs un temps il est dure de donner un notion en mnute ou heure, quand les secondes dépassent les centaines.

Aussi, la taille de timers à une limite..

Si par exemple, mon programme tourne depuis 80 secondes, je sais qu'il tourne depuis une minute et 20 seconde. Facile.

Mais s'il tourne depuis 800 secondes, c'est plus compliqué.

Je peux aussi diviser par 60, pour avoir le résultat en minute, mais un chiffre à virgule ne m'indiquerai rien en seconde.

Alors peut etre que je suis nul en math, ou je me demandais s'il y avait un truc de simple, que je ne connaisse pas, qui pourrais m'afficher,
les secondes
les minutes et secondes (sans décimal, pour les minutes)
et ainsi de suite pour les heures, minutes, seconde.

Ya pas un truc du genre modulo qui pourrais m'aider?

Voyez-vous mon objectifs?

Le programmes tourne depuis:
1h 20mn, 45sec

Milles mercis

Comme c'est un nombre entier si vous divisez par un nombre entier, vous obtenez un nombre entier arrondi. (100/3 = 33 par exemple)

Donc si vous divisez par 1000 vous avez des secondes, si vous divisez par 3600000ul vous avez le nombre entier d'heures, si vous divisez par (24ul * 3600ul * 1000ul) vous avez le nombre de jours

(Le ul à la fin c'est pour bien dire au compilateur de travailler en unsigned long - il faut au moins un nombre qui le mentionne)

// t est le nombre de millisecondes en unsigned long
J = t / (24ul * 3600ul * 1000ul); // Nombre de jours. ça,donne 0 si on n'a pas encore passé un jour
H = (t - (J*24ul * 3600ul * 1000ul)) / 3600000ul; // on soustrait à t le nb de jours en ms (ou 0 si J valait 0), donc reste moins d'un jour qu'on divise par Le nombre de ms dans 1h (3600 secondes * 1000ms par secondes)
M =  (t - (J*24ul * 3600ul * 1000ul + H*3600000ul)) / 60000ul; // nb de minutes (1 min = 60s = 60000ms)
// etc
...

Vous pouvez bien sûr utiliser directement 86400000ul au lieu de (24ul * 3600ul * 1000ul)

En utilisant millis vous pouvez représenter environ 49 jours ensuite ça revient zéro

Salut J-M-L,

C'est super, merci, ca semble fonctionner.
J'ai ajouté les secondes et voici mon code pour d'autre (s'il y a pas d'erreurs :slight_smile: )

void running_since(void)
{
  sprint(F("\nRunning since: "),2);
  unsigned long t = (millis() - timer);  // milsec
  unsigned long j;
  unsigned long h;
  unsigned long m;
  unsigned long s;
  
  Serial.print("t: "); Serial.print(t/1000ul); Serial.print(", "); // DEBUG
  
  j = t / (24ul * 3600ul * 1000ul); // Nombre de jours. ça,donne 0 si on n'a pas encore passé un jour
  h = (t - (j*24ul * 3600ul * 1000ul)) / 3600000ul; // on soustrait à t le nb de jours en ms (ou 0 si J valait 0), donc reste moins d'un jour qu'on divise par Le nombre de ms dans 1h (3600 secondes * 1000ms par secondes)
  m = (t - (j*24ul * 3600ul * 1000ul + h*3600000ul)) / 60000ul; // nb de minutes (1 min = 60s = 60000ms)
  s = (t - (j*24ul * 3600ul * 1000ul + h*3600000ul + m*60000ul)) / 1000ul; // 


// Vous pouvez remplacer sprint() par Serial.print()
  sprint(j,2); sprint(F("j. "),2);
  sprint(h,2); sprint(F("h. "),2);
  sprint(m,2); sprint(F("mn. "),2);
  sprint(s,2); sprintln(F("sec.\n"),2);
}

Ca ne fais que 20mn qu ca toure, mais ca semble bien fonctionner.

Merci!!!

très bien

Vous pouvez optimiser un peu les maths en utilisant un modulo, je vous avais donné ces formules pour que ce soit plus facile à comprendre (et dans l'absolu des soustraction ou multiplications sur des long c'est beaucoup plus rapide qu'une division ou un modulo, mais dans ce cas il y a une petite optimisation possible)

  unsigned long t = (millis() - timer);  // milsec
  unsigned long j;
  unsigned long h;
  unsigned long m;
  unsigned long s;
  
  Serial.print("t: "); Serial.print(t/1000ul); Serial.print(", "); // DEBUG
  
  j = t / 86400000ul; t = t % 86400000ul;
  h = t / 3600000ul; t = t % 3600000ul;
  m = t / 60000ul; t = t % 60000ul;
  s = t / 1000ul;

parce que les bons compilateurs, quand on fait une division, ils obtiennent en même temps le modulo (le reste de la division) et donc ne le recalculent pas si on le demande juste ensuite ==> quand on a fait   j = t / 86400000ul; alors le t = t % 86400000ul; est "gratuit" en terme de coût de calcul, le compilo a déjà la valeur dans un registre et c'est la même chose que t - (j*24ul * 3600ul * 1000ul)

J'ai jamais vérifié cela dit si l'assembleur généré par avr-gcc Le faisait.

(mais attention le code modifie t au fur et à mesure)

Hello @J-M-L,

i try your code but for the second and minutes, after 59, its continue to 60, 61, 62, ....it doesnt stop to 59 and after restart to 00, 01, ...

An idea please?

Thanks

Popol974:
i try your code ...

Quel code ?? (which code - French forum here?)

Merci pour la réponse, désolé, trop l'habitude de parler anglais sur les forums :wink:

le code ci dessous :

  unsigned long t = (millis() - timer);  // milsec
  unsigned long j;
  unsigned long h;
  unsigned long m;
  unsigned long s;
  
  Serial.print("t: "); Serial.print(t/1000ul); Serial.print(", "); // DEBUG
  
  j = t / 86400000ul; t = t % 86400000ul;
  h = t / 3600000ul; t = t % 3600000ul;
  m = t / 60000ul; t = t % 60000ul;
  s = t / 1000ul;

en fait les secondes et minutes continuent au dela de 59...: 2mn et 31 secondes s'affiche comme ceci : 2 ' 151''...pas le résultat escompté dans le format standard,

merci par avance,

Olivier

hum je ne comprends pas ce que vous dites. Que voyez vous dans le moniteur série à 115200 bauds si vous faites tourner cela

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

}

void loop() {
  unsigned long t = millis();  // milsec
  unsigned long j;
  unsigned long h;
  unsigned long m;
  unsigned long s;

  j = t / 86400000ul; t = t % 86400000ul;
  h = t / 3600000ul; t = t % 3600000ul;
  m = t / 60000ul; t = t % 60000ul;
  s = t / 1000ul;

  Serial.print(j); Serial.write(" ");
  Serial.print(h); Serial.write(" ");
  Serial.print(m); Serial.write(" ");
  Serial.println(s);

  delay(1000);
}

ça devrait compter correctement

ou si vous voulez voir le temps défiler plus rapidement et ne pas attendre 24h pour voir les jours changer, on peut tricher un peu

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

}

void loop() {
  static unsigned long t1, t = 0; // millis();  // milsec
  unsigned long j;
  unsigned long h;
  unsigned long m;
  unsigned long s;

  t1 += 1000;
  t = t1;
  j = t / 86400000ul; t = t % 86400000ul;
  h = t / 3600000ul; t = t % 3600000ul;
  m = t / 60000ul; t = t % 60000ul;
  s = t / 1000ul;

  Serial.print(j); Serial.write(" ");
  Serial.print(h); Serial.write(" ");
  Serial.print(m); Serial.write(" ");
  Serial.println(s);

  //delay(10); // si vous voulez ralentir
}

et vous devriez voir le temps avancer correctement.

postez un code complet de votre souci, avec juste un extrait je ne sais pas quoi regarder pour vous aider

Merci!!

ca fonctionne nickel chrome!

Désolé c'est moi qui avait interprété le code, pas l'habitude de voir 2 codes sur une même ligne séparé par des ";", je ne savais même pas que l'IDE d'arduino acceptait ca sans broncher :wink:

Merci pour votre patience et votre temps et bon courage pour le Covid-19 ! >:(

Pas de pb. Le C ou le C++ se fichent du passage à la ligne ou de l’Indentation. On les utilise pour essayer de grouper les choses. Ici les 2 éléments (division et modulo) vont bien ensemble, c’est pour cela que j’ai écrit cela comme ça

Bonne soirée