Go Down

Topic: Temporiser une sortie (Read 904 times) previous topic - next topic

MANUPAT

Aug 21, 2017, 10:54 pm Last Edit: Aug 22, 2017, 10:06 pm by MANUPAT
Bonjour à tous,

J'ai besoin d'aide pour temporiser une sortie. ça ne doit pas être très compliqué pour quelqu'un d'aguerri mais pour un débutant comme moi...
Voila le problème:
Je souhaite réalise une alarme (basique) pour mon cabanon de jardin qui a déjà été visité 2 fois !!! :(

Le principe:
Un contact à clé pour mettre en fonction l'alarme,
Un contact détection choc.
Une sortie relais pour enclencher une sirène
Une sortie relais pour visualiser l'état de l'alarme (ON ou OFF)
une sortie relais pour visualiser si l'alarme a été déclenchée (gyrophare).

Tout est déjà codé (déclaration des entrées/sorties, condition...)

Ce qui me pose problème c'est que je souhaite, sur déclenchement de l'alarme, que la sirène se déclenche pendant 4 minutes pas plus (réglementation sur les nuisances sonores oblige).

J'ai réaliser la condition "si contact choc ON": Sirène = ON, gyrophare = ON
mais je ne vois vraiment pas comment temporiser l'enclenchement de l'alarme pendant 4 min dans ma condition sans que la sirène se remette en route à chaque début de la boucle.
delay ne peut fonctionner dans ce cas
Dois-je utiliser millis?

Mon code:
Code: [Select]

// Alarme
int alarmeON = 2; // entrée marche/arrêt alarme
int ILS_NO = 3;   // entrée ILS contact NO
int ILS_NF = 4;   // entrée ILS contact NF
int sirene = 6;   // Sortie sirène
int gyrophare = 7; // Sortie témoin alarme déclenchée
int temoin_alarme = 8; // Sortie témoin alarme en fonctionnement

void setup() {
  pinMode(alarmeON,INPUT);    //entrée contact NF mise en marche alarme
  pinMode(ILS_NO,INPUT);      //entrée contact NO détecteur choc
  pinMode(ILS_NF,INPUT);      //entrée contact NF détecteur choc
  pinMode(sirene,OUTPUT);     // sortie relais sirène
  pinMode(gyrophare,OUTPUT);  // sortie relais témoin alarme déclenchée
  pinMode(temoin_alarme,OUTPUT);  //sortie relais témoin alarme en fonction
  digitalWrite(sirene,LOW);        //initialisation à l'état bas relais sirène
  digitalWrite(gyrophare,LOW);     //initialisation à l'état bas relais témoin alarme déclenchée
  digitalWrite(temoin_alarme,LOW); //initialisation à l'état bas relais témoin alarme en fonction
 
}

void loop()
{
  if(alarmeON == LOW)        //si contact enclenchement alarme fermé
       { if(ILS_NO == LOW || ILS_NF == HIGH)                 //si contact ILS_NO ou si contact ILS_NF enclenché
                        {digitalWrite(sirene,HIGH);          //déclenchement sirène (à temporiser)
                         digitalWrite(gyrophare,HIGH);       //déclenchement gyrophare
                         digitalWrite(temoin_alarme,HIGH);}  //déclenchement témoin alarme ON
          else {}                                            //si ILS_NO ou si ILS_NF non déclenché, on ne fait rien
       }
  else                                //sinon si Contact enclenchement alarme ouvert, on ne passe toutes les sorties à OFF
  {digitalWrite(sirene,LOW);          //initialisation à l'état bas relais sirène
   digitalWrite(gyrophare,LOW);       //initialisation à l'état bas relais témoin alarme déclenchée
   digitalWrite(temoin_alarme,LOW);}  //initialisation à l'état bas relais témoin alarme en fonction
  }
[code]
 
 Merci de votre aide et de votre indulgence, je débute

J-M-L

#1
Aug 21, 2017, 10:59 pm Last Edit: Aug 21, 2017, 11:13 pm by J-M-L
Bonsoir

Quote
Merci de votre aide et de votre indulgence, je débute
oui mais quand même faut lire les bases de l'usage du forum...

corrigez votre post ci dessus et rajoutez les code tags autour du code:
[code] // votre code ici [/code].

ça doit ressembler à cela:
Code: [Select]
// votre code ici
(faites aussi ctrl-T (PC) or cmd-T (Mac) dans l'IDE avant de copier le code pour qu'il soit indenté correctement)




Quote
Tout est déjà codé (déclaration des entrées/sorties, condition...)
des trucs du genre
Code: [Select]
  if (alarmeON == LOW)       //si contact enclenchement alarme fermé
(alarmeON ça vaudra toujours 2, c'est vous qui l'avez défini en début de votre code, ça ne vaudra donc jamais LOW, c'est un N° de pin...)
ou encore
Code: [Select]
if (ILS_NO == LOW || ILS_NF == HIGH) ne vont pas marcher si vous ne faites pas un digitalRead() sur votre pin avant... avez vous mis des résistances de pullup externe ? sinon il faut déclarer les pins en INPUT_PULLUP...

bref - je ne pense pas du tout que votre code soit fonctionnel tel quel... (et aucune gestion du temps dans le code... )

pour faire correctement ce que vous voulez faire, une petite machine à états semble le plus approprié  et si vous regardez le post #26 de ce fil de discussion j'ai posté une petite machine à état et son code qui gère un délai sur déclenchement d'un bouton



Mais cela semble au delà de votre niveau actuel - si vous ne voulez pas que le code soit de la magie noire pour vous et tout comprendre, il serait bon de commencer par effectuer quelques tutos de base sans doute (cf tutos d'eskimon). Ce n'est pas négatif - on a tous commencé comme cela... il faut apprendre les bases et qu'elles soient solides pour bien progresser ensuite
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

MANUPAT

Bonjour J-M-L
Merci pour votre aide et désolé pour le format de mon message, je ne savais pas et ferai attention pour les prochains.

Je n'avais pas connaissances des "machines à états", je vais me documenter et voir comment je peux adapter pour mon code. Je demanderai probablement des conseils car adapter des exemples à ce que l'on veux faire n'est pas toujours évident. je suis autodidacte, je n'ai jamais eu de cour de programmation!

Effectivement j'ai oublié les digitalRead(), je vais corriger.

Pour l'instant je n'en suis qu'au stade de développement du code, mais je ne vais pas tarder à faire chauffer le fer a souder!
j'avais prévu de mettre des résistances externes mais c'est peut-être plus simple d'utiliser les internes de l'arduino! merci pour le rappel.

Encore merci pour vos conseils

J-M-L

 Bonjour

Pas de soucis - le lien ci dessus est un petit tuto mais si vous n'avez pas fait quelques tutos avant cela va être compliqué;

N'hésitez pas à poser des questions après avoir fait vos recherches le forum est dynamique et supportif de ceux qui s'impliquent dans leur projet (mais pas là pour écrire leur projet à  leur place)

Ps:
(Si vous clickez sur le bouton "Quick Édit" en dessous de votre premier post tout en haut vous pourrez rajouter les tags de code)
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

MANUPAT

Merci J-M-L

J'ai 47 ballais ! le but pour moi est d'apprendre, pas que qq'un me fasse mon code !
Et je n'ai plus de projet d'examen en vue ! A part peut-être la prostate !  lol
j'ai un BTS électrotech qui remonte à 92, à l'époque y'avais pas d'arduino ! Et la programmation c'était pour les F2
mais c'est fou les tucs que l'ont peut faire avec un si petit machin.

J'ai ajouté les tags de code, c'est vrai que c'est plus lisible.
cdlt

MANUPAT

#5
Aug 22, 2017, 09:59 pm Last Edit: Aug 22, 2017, 10:07 pm by MANUPAT
Re bonsoir,
j'ai fait quelques corrections à mon code initial.
Après avoir relu le B a Ba du langage, je me suis rendu compte que j'avais effectivement pris quelques raccourcis!

j'ai un peu confondu "int" et "const int" pour déclarer mes entrées et oublié de passer par un variable pour lire l'état des entrées
C'est corrigé... enfin je crois!
Je n'ai pas intégré pour l'instant la suppression de l'effet rebond des contacts, une chose après l'autre.
Je vais potassé les machines à états, c'est la prochaine étape.
Pour le moment pouvez vous me dire si mes corrections permettent le fonctionnement de mon programme SVP
Avec mes remerciements
 
Code: [Select]

// Alarme
const int alarmeMA = 2;      // entrée Marche/Arrêt alarme sur pin2
const int ILS_NO = 3;        // entrée ILS contact Normalement ouvert (NO) sur pin3
const int ILS_NF = 4;        // entrée ILS contact Normalement fermé (NF) sur pin4
const int sirene = 6;        // Sortie sirène sur pin6
const int gyrophare = 7;     // Sortie témoin alarme déclenchée sur pin7
const int temoin_alarme = 8; // Sortie témoin alarme en fonctionnement sur pin8
int Etat_alarmeMA = 0;       // Variable conteneant l'état du switch alarme Marhe/arrêt
int Etat_ILS_NO = 0;         // Variable conteneant l'état de l'ILS_NO
int Etat_ILS_NF = 0;         // Variable conteneant l'état de l'ILS_NO

void setup() {
  pinMode(alarmeMA,INPUT);         // entrée contact NF mise en marche alarme
  pinMode(ILS_NO,INPUT);           // entrée contact NO détecteur choc
  pinMode(ILS_NF,INPUT);           // entrée contact NF détecteur choc
  pinMode(sirene,OUTPUT);          // sortie relais sirène
  pinMode(gyrophare,OUTPUT);       // sortie relais témoin alarme déclenchée
  pinMode(temoin_alarme,OUTPUT);   // sortie relais témoin alarme en fonction
  digitalWrite(sirene,LOW);        // initialisation à l'état bas relais sirène
  digitalWrite(gyrophare,LOW);     // initialisation à l'état bas relais témoin alarme déclenchée
  digitalWrite(temoin_alarme,LOW); // initialisation à l'état bas relais témoin alarme en fonction
 
}

void loop()
{
  Etat_alarmeMA = digitalRead(alarmeMA);
  Etat_ILS_NO = digitalRead(ILS_NO);
  Etat_ILS_NF = digitalRead(ILS_NF);
   
  if(Etat_alarmeMA == LOW)        //si contact enclenchement Marche/Arrêt alarme fermé
       { if(Etat_ILS_NO == LOW || Etat_ILS_NF == HIGH)       //si contact ILS_NO ou si contact ILS_NF enclenché
                        {digitalWrite(sirene,HIGH);          //déclenchement sirène
                         digitalWrite(gyrophare,HIGH);       //déclenchement gyrophare
                         digitalWrite(temoin_alarme,HIGH);}  //déclenchement témoin alarme ON
          else {}    //si ILS_NO ou si ILS_NF non déclenché, on ne fait rien
       }
  else                                //sinon si Contact enclenchement alarme ouvert, on ne passe toutes les sorties à OFF
  {digitalWrite(sirene,LOW);          //initialisation à l'état bas relais sirène
   digitalWrite(gyrophare,LOW);       //initialisation à l'état bas relais témoin alarme déclenchée
   digitalWrite(temoin_alarme,LOW);}  //initialisation à l'état bas relais témoin alarme en fonction
  }
[code]

J-M-L

#6
Aug 22, 2017, 10:16 pm Last Edit: Aug 22, 2017, 10:17 pm by J-M-L
Quote
Et je n'ai plus de projet d'examen en vue ! A part peut-être la prostate !  lol
Lol :)

j'suis encore plus vieux :) - oui dans le temps y'avait pas tout ça

merci pour les tags - je lis le code et reviens vers vous
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

J-M-L

#7
Aug 22, 2017, 10:30 pm Last Edit: Aug 22, 2017, 10:32 pm by J-M-L
bravo pour le niveau des commentaires - c'est un bon début

Quelques suggestions

appuyez sur cmd-t sur Mac ou ctrl-t sur PC pour indenter bien le code (alignment des blocs)

pour les pins, const byte au lieu de const int ça suffit -> 1 octet au lieu de deux (bon le compilo va gérer ça pour vous mais c'est pas une raison). On a aussi tendance à mettre le mot Pin dans le nom de la variable pour que ce soit explicite.
Code: [Select]
const byte pinAlarmeMA = 2;      // entrée Marche/Arrêt alarme sur pin2

Généralement pour tout ce qui est bouton, on utilise un INPUT_PULLUP. ça évite de câbler une résistance de pull down ou de pull-up externe en plus dans le circuit, on utilise directement la résistance intégrée au micro.
On câble Pin --> bouton --> GND. la conséquence cependant c'est que la pin est HIGH quand le bouton n'est pas enfoncé et LOW quand on appuie, c'est un peu contre-intuitif mais on s'y fait (sinon on définit des contantes #define APPUI (LOW) et on teste if (digitalRead(pin) == APPUI) {...} comme ça c'est lisible


Code: [Select]
  if (Etat_alarmeMA == LOW)       //si contact enclenchement Marche/Arrêt alarme fermé
  { if (Etat...
généralement soit ont met l'accolade sur la même ligne que le premier if, soit toute seule sur sa ligne pour la lisibilité

Code: [Select]
    else {}    //si ILS_NO ou si ILS_NF non déclenché, on ne fait riensi on ne fait rien, pas besoin de mettre du code :) (bon le compilateur va virer cela pour vous)


Vous pourriez (ce sera utilisé plus tard dans la machine a état) définir des fonctions déclenchementAlarme(), arretAlarme() etc ça rendra votre boucle plus lisible






sinon pour introduire le temps, oui il va falloir regarder les machine à état pour bien faire; Vous pouvez éventuellement commencer par explorer l'exemple des tutos d'estimons [ Arduino 202] Introduire le temps


bon courage !!
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

bestel

#8
Aug 22, 2017, 10:53 pm Last Edit: Aug 22, 2017, 10:58 pm by bestel
Bonjour,

Pour ton problème de temporisation, tu peux essayer ce que j'avais utilisé une fois.

Tu créé une variable initialisée à 0 dans laquelle tu stocke "l'heure" de l'arduino avec millis() au moment du déclenchement, et ensuite il te suffit de vérifier si millis() est égal à ta valeur mémorisée + 4000.

En le plaçant au bon endroit, tu ne sera pas gêné par la boucle ... ça donnerait quelque chose dans ce genre :
Code: [Select]

if(Etat_alarmeMA == LOW)        //si contact enclenchement Marche/Arrêt alarme fermé
       {
          if(Etat_ILS_NO == LOW || Etat_ILS_NF == HIGH || Memo_declenchement == 0)       //si contact ILS_NO ou si contact ILS_NF enclenché
                          {digitalWrite(sirene,HIGH);          //déclenchement sirène
                           digitalWrite(gyrophare,HIGH);       //déclenchement gyrophare
                           digitalWrite(temoin_alarme,HIGH);  //déclenchement témoin alarme ON
                           Memo_declenchement = millis(); }
            else {
              if (millis() > Memo_declenchement + 4000) {
                digitalWrite(sirene,LOW);          //arrêt sirène
                digitalWrite(gyrophare,LOW);       //arrêt gyrophare
                digitalWrite(temoin_alarme,LOW);  //arrêt témoin alarme ON
                Memo_declenchement = 0;
              }   
       }
  else                                //sinon si Contact enclenchement alarme ouvert, on ne passe toutes les sorties à OFF
  {digitalWrite(sirene,LOW);          //initialisation à l'état bas relais sirène
   digitalWrite(gyrophare,LOW);       //initialisation à l'état bas relais témoin alarme déclenchée
   digitalWrite(temoin_alarme,LOW);}  //initialisation à l'état bas relais témoin alarme en fonction
  }

J-M-L

#9
Aug 22, 2017, 11:08 pm Last Edit: Aug 22, 2017, 11:12 pm by J-M-L
Attention ça ce n'est pas bon à cause des problèmes (bon c'est dans 50 jours) de débordement de la variable
Code: [Select]
if (millis() > Memo_declenchement + 4000) {si d'aventure Memo_declenchement + 4000 devient plus grand qu'un nombre représentable sur un unsigned long alors il retourne compter depuis zéro et votre condition sera vraie immédiatement sans attendre les 4 secondes


il faut en fait faire une soustraction
Code: [Select]
if (millis() - Memo_declenchement > 4000) {pour éviter tout soucis (et bien sur déclarer Memo_declenchement en unsigned long)

(merci d'indenter vos codes, ça pique les yeux !!!)

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

MANUPAT

Merci pour vos réponses,
Bon, je vois que j'ai encore du taf pour tout comprendre mais je vais intégrer vos remarque et modifier mon code pour que ce soit plus lisible (et pratique).
Je vais vraiment me pencher sérieusement sur les machines à états, mes projets (dans ma tête pour le moment) se rapprochement énormément du fonctionnement d'un automate programmable (ce que je sais et appris à faire lors de mes études d'électrotech) et c'est aussi ce que j'aime!
 J'ai déjà regardé les tutos que vous m'avez listés, j'ai compris le principe, reste à comprendre comment adapter à ce que je veux faire et apprendre le langage.
Je reviens vers vous dès que j'ai un doute ou une question.
Encore merci

 

J-M-L

#11
Aug 23, 2017, 10:26 pm Last Edit: Aug 23, 2017, 10:55 pm by J-M-L
OK - bon courage - une fois que c'est rentré, c'est tout bénéfice pour la suite

voilà une première idée de machine à état pour vous aider à réfléchir


(bien sûr dans l'état initial l'action de base c'est que tout est éteint)
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

MANUPAT

#12
Aug 24, 2017, 09:49 pm Last Edit: Aug 24, 2017, 09:56 pm by MANUPAT
Ouaouhhh, c'est beau et en plus exactement ce que je veux faire... Bravo et merci.
Avec quel logiciel fais-tu ça?


Quote
sinon on définit des contantes #define APPUI (LOW) et on teste if (digitalRead(pin) == APPUI) {...}
J'ai fouillé un peu sur le net pour comprendre ou tu voulais m'emmener!
Si j'ai bien compris le but est de déclarer mes sorties différemment pour que se soit plus compréhensible dans le programme.
Donc pour exemple dans mon code, "const int sirene = 6;" je peux le transformer en:

Code: [Select]
#define sirene 6                           //sirene branchée sur la Pin6
#define sireneOFF digitalWrite (sirene,1) // sirene OFF
#define sireneON digitalWrite (sirene,0)  // sirene ON


Après dans mon programme si je veux déclencher la sirène sur l'action de mon ILS_NO je pourrai écrire:
void loop () {
 if (Action ILS_NO)
   { sireneON;}
}
C'est bien ça?

Peut-on simplifier de la même façon pour les entrées?

Pour la machine à état je n'ai pas encore eu le temps d'approfondir. Gestion de la maison oblige (lessives, repassage, vaisselle, ménage...) non je déconne j'ai une femme !!! :)
Merci de votre aide

J-M-L

#13
Aug 24, 2017, 10:39 pm Last Edit: Aug 24, 2017, 10:44 pm by J-M-L
si vous voulez voir la structure de programmation par machine à états,  mon tuto éventuellement peut vous aider à y réfléchir

bien que techniquement ça peut marcher, j'éviterais les #define, déclarez juste des fonctions

Code: [Select]
const byte pinSirene = 6; // sirene branchée sur la Pin6
void sireneOFF()
{
    digitalWrite (pinSirene, HIGH) // sirene OFF
}

void sireneON()
{
    digitalWrite (pinSirene, LOW) // sirene ON
}


(le dessin est juste fait avec les outils d'édition fournis avec mon Mac ça a pris 5 minutes :) -> applis gratuites - dans ce cas c'est avec keynote que je l'ai fait)

 
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

MANUPAT

Super Merci,
Votre excellent tuto,  je l'ai lu, relu, re-relu, re-re-relu...
En parallèle j'ai aussi dû comprendre ce qu'était une fonction, comment la définir, comment l'appeler...
Et plein d'autres choses encore... Je ne partais pas de 0 mais pas loin!
Avec les conseils que vous m'avez donné, je commence à y voir plus clair.
Je vais profiter du WE approfondir et essayé d'adapter ces lignes de code à mon projet.

Go Up