Arduino + millis

Bonjour,
Je travaille sur une installation avec un senseur de battement cardiaque + Arduino. Lorsque le spectateur pose les deux mains sur une plaque de métal, le senseur reçoit l’info et envoie “1” dans le moniteur série. Il demeure inactif ensuite durant 8 secondes avant de se mettre à lire le battement (à renvoyer “1” à chaque battement cardiaque…il alterne donc entre HIGH et LOW jusqu’à ce qu’on retire les mains).

Je voulais faire clignoter une première série de LED en fonction du battement (cette partie fonctionne très bien avec une simple fonction “if”), mais je trouvais un peu emmerdant qu’il y ait 8 secondes d’inactivité avant la lecture. Je voudrais donc faire clignoter une autre série de LED indépendante pendant cette période, soit 6 secondes suivi par un fade-out progressif sur 2 secondes. Autrement dit, lorsque le spectateur pose ses mains une première fois, une routine blink + fade est envoyée pendant 8 secondes sur la 2e série de LED, puis c’est la lecture du battement qui enchaîne, avec la 1ere série de LED.

Pour être en mesure de détecter quand est-ce qu’il faut envoyer la routine “blink”, j’ai essayé la chose suivante:

-chaque fois que la lecture de la carte tombe à “0”, un startTime est mémorisé.
-lorsque la carte détecte une valeur de “1” (>0), la série de LED “led_coeur” suit les impulsions en tout temps.
-si, lorsque la valeur passe à “1”, il y a eu plus de 2 secondes (mais pas exactement 8 secondes) d’écoulées entre le temps présent et le startTime lancé lorsque la valeur était à “0”, la série de LED “led_attente” se met à clignoter pour 6 secondes puis fait un fade-out sur 2 secondes.

Je pensais avoir sorti quelque chose de potable, mais la routine de “blink” ne part jamais, pas plus que le fade-out. Je ne suis pas très familière avec la logique de programmation, alors je me doute qu’il s’agit d’un problème de logique d’exécution dans le code, même s’il ne me donne aucun message d’erreur. Tout semble fonctionner au niveau hardware, alors le problème n’est pas là.

J’apprécierais vraiment que quelqu’un d’un peu plus expérimenté regarde mon code rapidement et puisse me dire ce qui ne va pas selon lui/elle.

Merci!

polar_last_last.ino (1.24 KB)

Bonjour

Tu cherches a tout faire en même temps ce qui t'amène à des situations compliquées. La solution s'appelle machine d'état.

En gros tu as 3 phases principales : - Attente : rien ne se passe - Préparation : attente des 6 secondes en blink - Fade-out durant 2 secondes - Démarrage : attente pendant au plus 2 secondes - Pulsation cardiaque : pendant les pulsations

Ensuite il faut que tu te poses les questions sur : - Que dois tu faire dans chaque état - Quelles conditions te font sortir de cet état

A la louche je pondrais quelque chose du genre (non testé, non compilé, tapé en vitesse du boulot) :

// Déclarer les états possibles et la variable qui va mémoriser l'état courant
enum { ATTENTE, PREPAR, PULSE } Etat = ATTENTE;
// ATTENTE : on attent la 1ere impulsion
// PREPAR : Pendant 8 secondes on gère le clignotement de la 2eme série de leds puis le fade
// PULSE : pulse suivant les impulsions entrante

// Mémoriser la "date" du dernier changement d'état
unsigned long LastMillis;

void setup()
{
  .... Blah blah toute l'initialisation

  // On démarre la machine dans l'état ATTENTE et on garde la date
  LastMillis = millis();
  Etat = ATTENTE;
}

loop()
{
  impulsion = digitalRead( entree impulsion )

  switch ( Etat )
  {
  case ATTENTE:
    if ( impulsion == HIGH )
    {
      Etat = PREPAR;
      LastMillis = millis();
    }
    break;
  case PREPAR:
    .. ici mettre le code pour gerer le clignotement
  case PULSE:
    .. ici le code pour gerer le 2eme clignotement
  }
}

C'est juste un code de principe. Peut être faut-il un état supplémentaire pour distinguer les 6 premières secondes puis le fade out Il te faudra aussi gérer des sous-états pour le clignotement et le fade Mais c'est l'idée générale

Tout doit tourner avec le principe non bloquant de : - prendre une date - vérifier si le temps est écoulé

Une comparaison de temps s'effectue toujoours de la façon suivant :

unsigned long DatePrecedanteAction;

.....

if ( (millis() - DatePrecedanteAction) > DUREE )
{
}

La comparaison par soustraction est obligatoire car la date retournée par millis() reboucle tous les 42 jours. Il faut faire une différence entre des entiers non signés pour que la différence représente le temps écoulé entre 2 dates.