Compter les temps d'activité d'une sortie

Bonjour à vous tous,

Sur mon arduino Uno :

Je voudrai compter le temps(plusieurs jours) qu'une sortie passe à l’état HIGH ou à l’état LOW

et que ces temps se cumulent .(somme des états hauts et somme des états bas)

Je cherche un comptage non bloquant.

Oui çà a l’air simple mais pas pour moi ,çà fait quelques jours que je galère avec millis , je ne m’en sort pas et je n’ai pas trouvé d’exemple sur le net ,qui ressemble à ce que je souhaite.

Merci de bien vouloir m’aider en utilisant : millis , timer ou easyRun , peu importe

merci d’avance pour votre aide.

Bonjour,

Tu veux mesurer le temps d'activité d'une sortie? Ce ne serait pas plutôt une entrée? Une sortie c'est toi qui la commandes, tu sais combien de temps tu l'as commandé.

Si c'est une entrée, pour mesurer le temps passé à l'état haut tu mémorises millis() quand le signal passe de l’état bas à l'état haut et ensuite tu lis millis() quand le signal repasse de l'état bas. Tu fais la différence et tu l'ajoute au temps total.

Bonjour

fait un relevé et accumulation de milis() sur un interrupt change
reste à gerer le rollover de milis() si > 49.7 jours

Bonjour Kamill,
c'est bien d'une sortie (pinMode (led, OUTPUT); qu'il s'agit mais je m'embrouille pour utiliser millis
et faire la somme des temps

bonjour Artouste,
tu penses que je dois faire une interruption , je n'e me souviens pas d'avoir touché à çà
si ce n'ait pas trop chronophage pourrais-tu me mettre un bout de code avec millis en plus ?
oui je sais n' être pas très doué mais je m'accroche!
merci d'avance

Tu n'as pas besoin d'une interruption. Si c'est une sortie c'est toi qui la commandes et tu sais à quel moment tu la commandes.

Comme une sortie ne peut avoir que deux états, LOW et HIGH, il suffit de compter le temps cumulé d'un de ces deux états et de l'ôter du temps total pour obtenir l'autre.

Par exemple pour mesurer le temps de l'état HIGH, il faut détecter les changements d'états.
Le passage de LOW à HIGH lance le chrono, le passage dans l'autre sens l'arrête.
Pour ça, il faut conserver en mémoire l'état à l'instant de mesure précédent. Puis comparer l'état courant à cet état précédent. S'ils sont différents, on détecte un changement.

Donc tu as besoin de quelques variables globales

unsigned long tempsTotal, tempsEtat, chronoEtat;
byte etat, etatprec;

A la fin du setup tu initialises la mesure du temps total
tempsTotal = millis();
Et tu choisis l'état que tu vas surveiller

etat = digitalRead (pin);
etatprec = etat ;
chronoEtat = millis();

Enfin dans la loop, tu surveilles ta pin

  byte etatCourant = digitalRead (pin);
  if (etatCourant != etatprec) { // changement d'état détecté
    if (etatCourant == etat) { // passage à l'état surveillé : on lance le chrono
      chronoEtat = millis();
    } else { // fin d'état surveillé, on cumule le temps
      tempsEtat += (millis() - chronoEtat);
    }
  }
  etatprec = etatCourant;

Tu peux afficher les temps de chaque Etat : tempsEtat pour l'état 'etat' et (millis()-tempsTotal-tempsEtat) pour l'autre état.

À tester, j'ai juste écrit ça sur mon smartphone...

Bonjour à tous ,

merci aux aimables et compétents contributeurs qui apportent leur aide ;

Merci en particulier à lesept pour son bout de code qui m’a bien débloqué

je l’ai transcrit dans ce petit sketch ,et j’ai fait un petit montage avec un interrupteur, il fonctionne en partie mais il reste quelques problèmes :

-tempsEtatOFF et tempsEtatON j’ai une chance sur deux que se soit inversé ,à la mise en service

on compter toujours sur TemsEtatON même si l’interrupteur est sur OFF

-sur le moniteur série la mise à jour de l’état OFF ne se fait pas avant le basculement suivant de l’interrupteur. je mets le sketch ci-desous ,merci d'avance

unsigned long tempsTotal, tempsEtat, chronoEtat;
bool etat, etatprec;

const int ledPin=13;
const int interrupteur=3;
void setup() {
 
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  pinMode(interrupteur,INPUT);
  etat = digitalRead (ledPin);
  etatprec = etat ;
  chronoEtat = millis();

}

void loop() {
  int test=digitalRead(interrupteur);
  if (test==HIGH){digitalWrite (ledPin,HIGH);}
  else{digitalWrite(ledPin,LOW);}
  bool etatCourant = digitalRead (ledPin);
  if (etatCourant != etatprec) { // changement d'état détecté
    if (etatCourant == etat) { // passage à l'état surveillé : on lance le chrono
      chronoEtat = millis();
    } else { // fin d'état surveillé, on cumule le temps
      tempsEtat += (millis() - chronoEtat);
    }
  }
  etatprec = etatCourant;

  Serial.print("tempsEtatOFF = ");
  Serial.println(tempsEtat);
  Serial.print("tempsEtatON = ");
  Serial.println(millis()-tempsTotal-tempsEtat);
delay(2000);
}

Tu t'emmêles avec les deux pins
Moi je croyais qu'il n'y en avait qu'une, donc dans mon code le mot 'pin' doit devenir 'interrupteur' partout.
Vérifie que tu as bien fait ça et teste encore

Je n'ai qu "un seul pin en sortie: la Led , l'autre pin est une entrée : l'interrupteur que j'ai
ajouté pour modifie à volonté l'état de la led

enregistrez les durées quand vous faites les changements d'état de la LED. étudiez un truc comme cela: (tapé ici, non compilé, non testé)

const uint8_t ledPin = LED_BUILTIN;
uint32_t dureeON, dureeOFF;
uint32_t dernierChangement;

void rapport() {
  Serial.print(F("ON : ")); Serial.print(dureeON);
  Serial.print(F("\tOFF : ")); Serial.println(dureeOFF);
}

void allumer() {
  if (digitalRead(ledPin) == LOW) { // si elle est vraiment éteinte
    dureeOFF += millis() - dernierChangement;
    dernierChangement = millis();
    digitalWrite(ledPin, HIGH);
    rapport();
  }
}

void eteindre() {
  if (digitalRead(ledPin) == HIGH) { // si elle est vraiment allumée
    dureeON += millis() - dernierChangement;
    dernierChangement = millis();
    digitalWrite(ledPin, LOW);
    rapport();
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  rapport();
}

void loop() {
  delay(1000);
  if (random(2) == 0) allumer(); else eteindre(); // on demande aléatoirement
}

merci J-M-L çà fonctionne , il me reste à l'adapter à l'utilisation de l'interrupteur qui pilote la led,
je suis bloqué pour l'instant je ne sais plus téléverser de sketch
la console du moniteur série bizarrement ne trouve pas le port et j'ai un message d'erreur
je continuerai à regarder demain
bonsoir à vous

rebonjour , mon arduino uno Wavgat me joue des tours pour téléverser , parfois çà fonctionne
mais souvent pas , en jonglant avec le bouton reset au début du téléversement çà passe mais pas toujours , j'ai réinstallé le driver CH340 c'est pareil .
dans le sketch de J-M-L j'ai apporté une toute petite modif dans la loop pour traiter l'interrupteur
void loop() {
delay(1000);
//if (random(2) == 0) allumer(); else eteindre(); // on demande aléatoirement ,remplacé par;
int test = digitalRead(interrupteur);
if (test ==HIGH)allumer(); else eteindre();
}
çà marche à peu près , quelques problèmes d'affichage , peut-être les rebonds ?

oui les rebonds sont un souci
mais comment avez vous connecté le bouton?

bonjour J-M-L,
une borne de l'interrupteur est relié au +5v , l'autre à l'entrée digital (D3) et aussi via une résistance de 56k au gnd.
j'ai ajouté un condensateur de 47 nF aux bornes du contact , çà va nettement mieux !
je vais intégrer ce code dans un projet qui consiste à surveiller la consommation et les périodes de marche et d'arret d'un appareil électrique quelconque ,ce sera un boitier sur une rallonge , dans quelques temps il sera prêt , j 'en ferai part dans le forum.
A bientôt .
Avant de le mettre en réalisation finie , il serait sans doute bon que je le soumette à votre expertise .

ce n'est pas 100% clair... un petit schéma pour s'assurer que c'est correct serait mieux...

1 Like