Mettre un capteur en pause sans bloquer les autres

Bonjour,
toujours autant novice je viens encore demander un peu d'aide.
Je suis en train de preparer Halloween (et oui deja), dans l'idée je voulais installer une ancienne tablette deriere un miroir sans tain qui déclancherait une video grace à un detecteur PIR en bleutooth.
Donc j'ai fait une petit appli avec Appinventor, un semblant de code Arduino et ça fonctionne plutot bien, mais du coup je me suis dit pour quoi pas un second capteur et une seconde video, et voilà là les choses se compliquent.
Mon code fonctionne mais trop simple et donc la fonction delay bloque, je voudrais faire mieux mais aprés je sais pas faire, j'ai beau lire et relire mais mon cerveau de mouche n'enregistre pas.
Donc la vision de l'utilisation:
un premier capteur (zone large) detecte et lance la video 1, aprés ça j'aimerais que celui ci ne déclenche plus pendant on va dire 10min mais laisse la possibilité au capteur 2 de déclencher qui lui et un capteur IR avec une zone de detection trés reduite de déclencher la video2.

je vous met mon bout de code actuel

const int motionPin = 2;
const int soundPin  = 4;
int motionState = 0;
int soundState  = 0;

void setup() {
  Serial.begin(9600);
  pinMode(motionPin, INPUT);
  pinMode(soundPin, INPUT);
}
 
void loop() {
  motionState = digitalRead(motionPin);
  soundState = digitalRead(soundPin);
  if (motionState == LOW) {
    Serial.println("1");
    delay(3000);
   }
   if (soundState == LOW) {
    Serial.println("2");
    delay(3000);
  }
}

merci

En effet, il faut que tu oublies les delay et que tu utilises millis.
millis est une fonction qui compte le temps passé depuis le lancement du code, comme un chrono que tu lances.
Voici le principe pour ton code :

  • Dans le setup tu initialises une variable booléenne à false.
  • Ensuite dans la loop :
  • Si la variable booléenne est à false tu lis ton premier capteur. Lorsqu'il est activé, tu stockes la valeur de millis car c'est "l'heure" à laquelle le capteur s'est déclenché (dans la variable tempsOn par exemple). Tu mets la variable booléenne à true pour indiquer que le capteur est ON. Tu lances la première vidéo.
  • Tu testes le temps passé depuis cet instant mémorisé (en calculant la différence millis() - tempsOn) et dès que cette différence est supérieure à 10 minutes, tu mets le booléen à false.
  • Si la variable booléenne est à true, tu lis le second capteur qui envoie la vidéo lorsqu'il est activé.

C'est l'idée, je pense que ça devrait fonctionner. Mets tes variables en global pour faciliter les choses.
Pense à déclarer tempsOn en unsigned long
A tester... ça ne prendra pas en compte le cas où le temps entre les activations des deux capteurs est plus long que 10 minutes, mais c'est déjà un premier jet.

Ca y est, tu m'as perdu :sweat_smile:?
deja merci de ta réponse, le probleme est bien millis, la derniere fois que j'ai testé de faire un truc avec ça, j'y ai passé des soirées et ça n'a jamais fonctionné...
Bon je vais retenter le coup...

Voici un essai :

bool state1 = false;
bool state2 = false;
unsigned long tempsON1 = 0;
unsigned long tempsON2 = 0;
const int motionPin = 2;
const int soundPin  = 4;
int motionState = 0;
int soundState  = 0;
const unsigned long attente1 = 10; // minutes
const unsigned long attente2 = 30; // secondes

void setup() {
  Serial.begin(115200);
  pinMode(motionPin, INPUT);
  pinMode(soundPin, INPUT);
}

void loop() {
  if (!state1) {
    motionState = digitalRead(motionPin);
    if (motionState == LOW) {
      tempsON1 = millis();
      state1 = true;
      // lancer la vidéo n°1
      Serial.println("vidéo 1");
    }
  } else {
    if (millis() - tempsON1 > attente1 * 60000ul) state1 = false;
    if (millis() - tempsON2 > attente2 * 1000ul)  state2 = false;
    if (!state2) {
      soundState = digitalRead(soundPin);
      if (soundState == LOW) {
        state2 = true;
        tempsON2 = millis();
        // lancer la vidéo n°2
        Serial.println("vidéo 2");
      }
    }
  }
}

J'ai ajouté une temporisation de 30 secondes pour le second capteur afin d'éviter qu'il lance la seconde vidéo de manière répétitive.
A tester...

ce serait plus modulable avec

const unsigned long attente1 = 10ul * 60ul * 1000ul; // 10 minutes en ms
const unsigned long attente2 = 30ul * 1000ul;        // 30 secondes en ms
...
    if (millis() - tempsON1 > attente1) state1 = false;
    if (millis() - tempsON2 > attente2)  state2 = false;

on ne câble pas en dur dans le code que attente1 est forcément en minutes de cette façon

c'est la qu'on voit les experts, j'en suis à peine à ma première tentative (qui d’ailleurs ne fonctionne pas :sweat_smile:) que vous vous en sortez déjà 2...
Du coup je vais comparer les votre avec mon truc pour voir ce qui cloche.

édit: je viens de tester en rapide ton code, il fonctionne mais il me bloque la seconde vidéo.
En version simple, la vidéo 2 doit être indépendante de la première car le capteur à un champ très réduit et ton idée des 30 secondes est parfaite, donc si je comprend bien pour la rendre indépendante je dois déplacer cette partie:

if (!state2) {
      soundState = digitalRead(soundPin);
      if (soundState == LOW) {
        state2 = true;
        tempsON2 = millis();
        // lancer la vidéo n°2
        Serial.println("vidéo 2");
      }

au dessus de "else"?

je n'ai pas eu le temps de faire le test, la pause déjeuné est courte...
mais déjà un grand merci car je vais pouvoir comprendre un peut plus le fonctionnement de "millis"

Très juste J-M-L, avec une petite coquille "attente2" au lieu de "attente2l"

Peux-tu m'expliquer ce que tu veux dire ?

oops - c'est le reste de votre 1000ul :slight_smile: que j'avais pas vu!

vous pouvez expliquer comment une vidéo est lancé?

Capteur 1 pour la vidéo 1, c'est un PIR qui couvre une zone de 3 à 4 m
Capteur 2 pour la vidéo 2, c'est un IR pour un déclenchement dans les 40 cm.

En fait le mot "bloqué" n'est pas forcément représentatif, lors de mon test le PIR lance bien la vidéo 1 et si je déclanche le second capteur dans la foulé la vidéo 2 démarre bien, mais si j'attend un peu trop le capteur 2 n'est pas pris en compte et il me faut attendre de pouvoir redémarré le capteur 1 pour lancer le 2 alors que le capteur 2 devrait pouvoir être démarré n'importe quand.
J'ai vérifié avec moniteur pour être sûr que cela ne soit pas mon appli qui pose problème.

Comme j'ai précisé cela a été des tests rapide pendant la pose repas donc je n'ai pas eu le temps de contrôler la durée avant de pouvoir relancer.

Tu as changé les valeurs des temporisations ?
Le capteur 2 n'est pris en compte que si le 1 a déclenché avant, mais cet état "déclenché" est remis à zéro au bout de la temporisation du capteur 1. Si c'est resté à 10 minutes, il y a peu de chances que cette RAZ arrive avant que le capteur 2 ne soit déclenché, mais si tu l'as fortement diminué alors oui, ça pourrait arriver.

Si je comprends bien, tu veux que le capteur 2 puisse être déclenché même si le 1 ne l'a pas été ?
Dans ce cas, les capteurs sont indépendants et la loop devient :

void loop() {
  if (!state1) {
    motionState = digitalRead(motionPin);
    if (motionState == LOW) {
      tempsON1 = millis();
      state1 = true;
      // lancer la vidéo n°1
      Serial.println("vidéo 1");
    }
  }
  if (millis() - tempsON1 > attente1) state1 = false;

  if (!state2) {
    soundState = digitalRead(soundPin);
    if (soundState == LOW) {
      tempsON2 = millis();
      state2 = true;
      // lancer la vidéo n°2
      Serial.println("vidéo 2");
    }
  }
  if (millis() - tempsON2 > attente2) state2 = false;
}

En effet j'ai fortement diminué car pour tester je ne pouvais pas le faire avec un temps de 10 min,
donc j'avais mis le timer 1 à 1minute et le 2 à 3 secondes, je voulais reprendre ce soir avec plus de temps...
Oui le second capteur lui peut déclencher n'importe quand, je teste ça ce soir, encore merci.

Dans l'idée la vidéo 1 est pour attirer le regard et la curiosités donc faire approcher la personne, la seconde et plus pour un effet de surprise.
j'avais réalisé quelque chose de similaire avec un pc :

C'est génial ! :stuck_out_tongue: Ca sera fun aussi avec un miroir ! Tu feras un Instructables ou une vidéo pour montrer quand ça sera fini ?

Oui ça a un peu d'effet quand les gens rentre chez moi, tu pense à un faux tableaux mal fait et la surprise arrive d'un coup.

Un grand merci, ça fonctionne exactement comme je le souhaitais, il faut vraiment que je potasse plus pour y arriver seul, maitenant j'ai un code que je pourrais examiner plus facilement.
Pour la video y a pas de probleme dès que le montage est terminé je donnerais le lien, par contre ça va encore prendre un certain temps car j'attend le materiel, pour l'instant mon montage est fait avec un vieux PIR d'une alarme et un inter qui simule l'IR, a la base je voulais faire avec un capteur ultrason pour gerer les distance mais j'ai eu peur de la complexité...
Maintenant reste plus qu'a mettre mes talents d'acteur en route pour les videos :joy:.
Encore merci.

Ne t'en fais pas pour le capteur ultrason, c'est assez simple à utiliser. Avec ou sans bibliothèque, ça se gère facilement.

simple, simple... parle pour toi :grinning_face_with_smiling_eyes:

La semaine derniere j'ai reçu mes capteurs, à y être j'avais commandé un HC04, un Ky032, un SR602 et un A02yK0f au moins j'avais le choix.

Donc je me suis mis au code pour l'ultrason en pensant que vu la base que j'avais ça irait vite, et bien non... j'avais des réactions bizarre, pour la même distance il déclanchait les deux videos, mon delay du ping ne fonctionnait pas enfin la galère pour un truc si simple.

Une fois bien posé les demandes sur une feuille pour comprendre les problemes, j'ai remis ça au propre et bam ça a fonctionné...

Truc étrange, sur le PC de la maison j'ai la version 1.8.10 et sur le PC que je prends au bureau c'est la version 1.8.5, sur ce dernier mon "delay "du ping fonctionne bien sur l'autre c'est comme s'il n'existait pas, pourtant le fichier est identique, donc si vous avez une idée je suis preneur, il me reste quelque déclenchement bizarre mais je pense qu'il faut filtrer l'alim.
Donc voici ce que j'ai pondu enfin si on peut dire ça :wink:

#include <NewPing.h>

#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
bool state1 = false;
bool state2 = false;
unsigned long tempsON1 = 0;
unsigned long tempsON2 = 0;
unsigned long tempsON3 = 0;
const unsigned long attente1 = 10ul * 60ul * 1000ul; // temps de latence pour la video 1 en minutes
const unsigned long attente2 = 30ul * 1000ul; // temps de latence pour la video 2 en secondes
const unsigned long attente3 = 2ul * 1000ul;//temps entre chaque demande de ping en secondes

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
Serial.begin(9600); // Open serial monitor at 9600 baud to see ping results.
}

void loop() {
unsigned long Distance;
if (millis() - tempsON3 > attente3){
tempsON3 = millis();
Distance = sonar.ping_cm();}

if (!state1){
Distance = sonar.ping_cm ();
if ((Distance >=80) && (Distance <=150)){ // distance de detection video 1
tempsON1 = millis();
state1 = true;
// lancer la vidéo n°1
Serial.println("1");
}
}
if (millis() - tempsON1 > attente1) state1 = false;

if (!state2){
Distance = sonar.ping_cm ();
if ((Distance >=20) && (Distance <=50)){ //distance de detection video 2
tempsON2 = millis();
state2 = true;
// lancer la vidéo n°2
Serial.println("2");
}
}
if (millis() - tempsON2 > attente2) state2 = false;
}

Commence par tester la bibliothèque et faire un code qui fait la mesure et déclenche par exemple une LED lorsque la distance est supérieure (ou inférieure) à un seuil.

Lorsque tu auras réussi à faire ça, tu auras fait la moitié du chemin : il te restera à inclure certaines lignes dans ton code. Mais au passage tu auras compris comment fonctionnent le capteur et la bibliothèque...

Lorsqu'on découvre quelque chose (un capteur, un afficheur, ou autre), il vaut mieux apprendre à s'en servir en dehors de tout contexte avant de l'appliquer à son besoin. On gagne du temps et de la sueur. :smiley: