Appeler millis() pour enregistrer l'heure d'interruption

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je travaille avec une Arduino (plus précisément, une Controllino MAXI Automation) et j’ai un code de ce genre :

unsigned long MAX_DELAY_BETWEEN_INT = 3600000; // 1h
unsigned long lastIntTime = 0;

void sendAlert() {
  Serial.println("Alert!");
}

void interrupt() {
  lastIntTime = millis();
}

void setup() {
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(0), interrupt, RISING);
}

void loop() {
  if (millis() - lastIntTime > MAX_DELAY_BETWEEN_INT) {
    sendAlert();
  }
  delay(200);
}

Or je reçois des alertes dont je suis certain qu’elles ne devraient pas avoir lieu (parce que je peux m’assurer que le délai entre deux interruptions n’a pas pu dépasser une heure). Elles ne semblent pas suivre de motif particulier.

Je me demande alors si le problème ne viendrait pas de la ligne 9 (lastIntTime = millis();), avec une valeur de millis() plus faible que la réalité parce que les bits de poids fort n’ont pas eu le temps d’être écrits, comme expliqué ici.

Quand je cherche arduino millis interrupt, je ne tombe que sur des questions au sujet des calculs de durée et non pas au sujet de l’heure à laquelle l’interruption a eu lieu.

Merci.

+0 -0

@Eskimon oui, c’est ce que j’ai lu. Mais dans mon cas ce n’est pas gênant puisque je ne suis qu’à une heure près (MAX_DELAY_BETWEEN_INT). Le delay() dans loop() n’est là que pour illustrer des traitements supplémentaires, sa valeur est arbitraire.

@unidan quel est le problème avec le code que je présente ?

Merci pour vos réponses.

+0 -0

Merci ! Dernière petite question, une interruption peut-elle en interrompre une autre ? Autrement dit, ai-je besoin du ATOMIC_BLOCK(ATOMIC_RESTORESTATE) dans le code suivant ?

volatile unsigned long lastIntTime = 0;

void sendAlert() {
  Serial.println("Alert!");
}

void interrupt() {
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    lastIntTime = millis();
  }
}

Sachant que je le mets dans tous les cas dans le loop() :

void loop() {
  unsigned long lastIntTimeTmp;
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    lastIntTimeTmp = lastIntTime;
  }
  if (millis() - lastIntTimeTmp > MAX_DELAY_BETWEEN_INT) {
    sendAlert();
  }
  delay(200);
}
+0 -0

Dernière petite question, une interruption peut-elle en interrompre une autre ?

Oui. Tout dépend de comment sont réglées les priorités de ces dernières. Mais dans un code comme le tiens pas sur que ca ai de l’importance.

Pour ton autre question, aucune sorte d’idée, je vais donc répondre "non pas besoin je pense"

+0 -0

@Eskimon oui, c’est ce que j’ai lu. Mais dans mon cas ce n’est pas gênant puisque je ne suis qu’à une heure près (MAX_DELAY_BETWEEN_INT). Le delay() dans loop() n’est là que pour illustrer des traitements supplémentaires, sa valeur est arbitraire.

@unidan quel est le problème avec le code que je présente ?

Merci pour vos réponses.

Vayel

Dans le modèle mémoire du C, si une variable n’est pas marquée volatile, ça veut grossomodo dire qu’elle n’est "modifié que dans le contexte/scope courant", ou de façon plus juste et plus précise, que les variables non volatiles ne sont pas modifiées en dehors du code en cours par une interruption. Si tu as une interruption qui modifie l’état d’une variable, il faut donc marquer cette variable comme volatile.

Si tu ne le fais pas, le code généré ne va pas partir du principe qu’il doit resynchroniser sur l’accès à la valeur, et par exemple réutiliser la dernière valeur récupérée voire remplacer la valeur par une constante.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte