Dans le cadre de mon projet, j'aimerai pouvoir lancer mon programme arduino à l'aide d'un bouton poussoir. Je m'explique, j'aimerai que le fonctionnement soit le suivant :
- Un appui sur le bouton jaune : Lancement du programme - Un 2ème appui sur le bouton jaune: Arrêt du programme - Un appui sur le bouton rouge : Réinitialisation du programme (l'horloge retourne à 00:00:00)
Seulement, malgré tous les tutos et les tentatives de bidouillages, je n'arrive pas à réaliser cela. Et je ne comprends pas pourquoi !
De plus, par soucis de place, je compte utiliser les pins analogiques pour brancher mes boutons. J'ai vu que cela ne posait pas de soucis si j'utilisais bien les fonctions digitalWrite() ou digitalRead().
Je ne sais pas quel est le but de ton montage, mais je ferais quelque chose dans ce genre :
- Créer une variable qui mémorise l'état du programme (déclenché ou arrêté).
- le bouton jaune change la valeur de cette variable
- Mettre le programme dans un If pour qu'il ne s’exécute que si le programme est a l'état déclenché
- En cas d'appui sur le bouton rouge, mettre la variable d'état à 'arrêté', et remettre les autres variables à 0
Pour les boutons sur les pin analogiques, pour 'économiser' au max le nombre de pins utilisées, je me suis déjà basé sur cette page, et ça fonctionne très bien : http://modelleisenbahn.triskell.org/spip.php?article59
int Bp = 0 ; //variable tampon
#define pinBouton A0
#define pinLedR A1
#define pinLedV A2
void setup(){
Serial.begin(9600);
pinMode(pinBouton, INPUT);
pinMode(pinLedR, OUTPUT);
pinMode(pinLedV, OUTPUT);
}
void loop(){
if (Bp=0 and digitalRead(pinBouton)=1){
Bp = 1;
Serial.println(Bp);
Serial.println("Le programme est en marche");
digitalWrite(pinLedV, HIGH);// on allume la lumière verte
digitalWrite(pinLedR, LOW); // la lumière rouge est éteinte
}
else if (Bp =1 and digitalRead(pinBouton)=1){
Bp = 0;
Serial.println(Bp);
Serial.println("Le programme est arrété!");
digitalWrite(pinLedR, HIGH);
digitalWrite(pinLedV, LOW);
}
delay(100);
}
Voici mon programme : le premier appui démarre le programme (représenté ici par l'allumage de la led verte) et le deuxième appui l'éteint (représenté par l'allumage de la led Rouge). Mais je n'arrive même pas à compiler...
J'ai cette erreur au niveau du else if : " exit status 1
J'ai modifié mon programme et cela fonctionnait, je vous remercie de votre aide.
En fait, j'aimerai que l'appui sur les boutons puisse "stopper mon programme". J'ai alors essayé de faire une sorte de code avec des fonctions non bloquantes mais le résultat reste vain...
Voici le programme que j'ai réalisé :
void loop(){
for (int compteur = 0; compteur <5, compteur ++){
if (etatAllumage){ //On teste si étatAllumage est à 1
//si c'est le cas, on allume la lampe verte
Serial.println("Je suis dans la LED verte");
digitalWrite(pinLedV, HIGH);
digitalWrite(pinLedR, LOW);
//Récupération de du temps
task_horloge();
delay(1000);
// Rotation du moteur
task_motor();
delay(1000);
//Récupération des données du cpateur de température
task_sensor_temperature();
delay(1000);
//Récupération des données de la balance
task_balance();
}
else{
//si ce n'est pas le cas, on allume la led rouge
digitalWrite(pinLedV, LOW);
digitalWrite(pinLedR, HIGH);
Serial.println("Je suis dans la led rouge");
}
// On lit l'état actuel du bouton et on le stocke dans une variable tampon
boolean etatPinBouton = digitalRead(pinBoutonM);
if(!etatPinBouton){ // si le bouton est enclenché, ie etatPinBouton=False
if (etatAllumage){ // Si on était en état de marche
//alors ce nouvel appui sur le bouton provoque l'arrêt du programme
etatAllumage = 0;
Serial.println("Le programme est arrété !");
}
else{ //On a apppuyé sur le bouton et le programme ne fonctionnait pas initialement
//Donc on met en route le programme
etatAllumage=1;
Serial.println("Le programme est en marche!");
}
}
/* Enregistrement des données sur la carte */
monFichier.flush();
delay(5000); // Pause entre les 2 mesures
}
//Fin de la boucle for, mon expérience est terminée, je ferme le programme
monFichier.close();
Serial.println("Fichier Clos");
}
Pendant que ton programme fait un delay, il ne fait rien d'autres, donc pas de détection des boutons, ni d'exécution de tes fonctions task.
Est-ce vraiment voulu d'avoir des delay aussi long ???
Si tu veux que ton programme soit assez réactif aux boutons, il faudrait tester leur état le plus souvent possible et donc limiter les appels de delay.
Une autre solution radicale pour faire en pause ton programme serait d'utiliser les interruptions.
Par exemple, tu pourrais connecter ton bouton à la pin 2 pour utiliser INT0.
Dans la fonction d'interruption, il te faudrait mettre une boucle pour attendre que le bouton soit enfoncé à nouveau pour quitter l'interruption.
Ce sera donc réactif instantanément (moins d'une milli seconde, peut importe que le programme soit en train de faire un delay, un print ou autre) et ultra efficace puisque bloquer le programme dans une interruption freeze tout le processeur.
Du coup, tu auras vraiment le programme en pause puisque tout sera bloqué.
Par exemple, si le programme était en train de faire un print "Fichier Clos" et que tu appuis sur le bouton à ce moment là, alors le print s'arrêtera là ou il en était (peut-être qu'il n'aura affiché que "Fichi") et ne reprendra qu'au rappui sur le bouton.
Pour cela, il faut que ton bouton soit relié à la pin 2 et qu'il donne l'état LOW quand il est enfoncé, ce qui implique que l'autre coté du bouton soit relié à la pin GND.
/*
Fonction de traitement de l'interruption INT0.
Attente active (blocage du CPU) jusqu'au rappuis sur le bouton
/!\ Pendant une interruption, toutes les fonctions basées elles
aussi sur les interruptions sont interdites !
Donc interdit d'utiliser "delay" ou "millis" par exemple.
*/
void INT0_callback(void) {
// Attente de 100 ms, histoire que le bouton soit stable
// Fonction "delay" interdite, on utilise "delayMicroseconds"
for ( int i = 0 ; i < 100 ; i++ ) {
delayMicroseconds(1000);
}
// Attente que le bouton repasse à HIGH (relaché)
while ( digitalRead(2) == LOW ) {
/* rien (on attend) */
}
// Attente de 100 ms, histoire que le bouton soit stable
// Fonction "delay" interdite, on utilise "delayMicroseconds"
for ( int i = 0 ; i < 100 ; i++ ) {
delayMicroseconds(1000);
}
// Attente que le bouton repasse à LOW (enfoncé à nouveau)
while ( digitalRead(2) == LOW ) {
/* rien (on attend) */
}
// Attente de 100 ms, histoire que le bouton soit stable
// Fonction "delay" interdite, on utilise "delayMicroseconds"
for ( int i = 0 ; i < 100 ; i++ ) {
delayMicroseconds(1000);
}
}
void setup(void) {
// Init serial
Serial.begin(9600);
// Init pin 2 en INPUT_PULLUP, bouton câblé sur GND
pinMode(2, INPUT_PULLUP);
// Activation de l'interruption INT0 (pin 2) en FALLING (passage à l'état LOW (enfoncé))
attachInterrupt(digitalPinToInterrupt(2), INT0_callback, FALLING);
}
void loop(void) {
Serial.println("AZERTYUIOPQSDFGHJKLMWXCVBN");
}
Le programme va spammer AZERTYUIOPQSDFGHJKLMWXCVBN en boucle dans la console.
Et quand tu enfoncera le bouton, tu verras que tout s'arrête.
Puis ça repart à nouveau quand tu re-appuis.
Par contre, je vois que tu parles "d'autonomie" donc j'en profite pour dire que ce n'est pas parce que le programme est stoppé que l'arduino consommera moins.
Pendant que le programme est stoppé, l'arduino est en réalité bloqué dans l'interruption donc il consomme tout autant d'énergie que si il était en train d'exécuter le programme.
Je vous remercie de votre aide. J'ai bien étudié votre code, mais il y a quelque chose que je ne comprends pas, la fonction INTO_callback n'est pas appelée dans le programme principal? Elle se déclenche automatiquement quand j'appui sur le bouton ?
Ah oui oui, j'étais consciente de cela ! Le bouton marche/arrêt me permet juste d'avoir une instrumentation "autonome" dans le sens complètement indépendant d'un PC (une fois le programme téléversé!).
Je ne comprends pas pourquoi dans la fonction INTO_callback, la condition digitalRead(2) == LOW est la même dans les 2 cas ?
On ne devrait pas faire plutôt :
//Attente que le bouton repasse à HIGH ( = soit relaché)
while (digitalRead(pinBouton) == LOW ){
/* on attend */
}
//On attend encore 100ms pour être sûr que le bouton soit stable
for (int i =0; i<100; i++){
delayMicroseconds(1000);
}
//Attente que le bouton repasse à LOW (soit enfoncé de nouveau)
while (digitalRead(pinBouton) == HIGH){
/* on attend */
}
Bon après, quand je teste cela, le programme s'arrête quand j'appuie sur le bouton mais ne redémarre pas quand j'appuie une seconde fois et je ne comprends pas pourquoi ...
- Edité par MathildeHochedel 18 juillet 2018 à 9:25:19
Effectivement, la fonction INT0_Callback n'est pas appelée dans le programme, c'est normale.
La fonction est enregistrée comme étant une interruption dans le setup à l'aide de attachInterrupt.
Elle est paramétrée en mode FALLING (front descendant passant de HIGH à LOW) donc à chaque fois que le bouton passera de l'état HIGH à l'état LOW, le processeur va temporairement stopper ce qu'il était en train d’exécuter pour aller exécuter la fonction INT0_Callback.
C'est donc un appel automatique et instantané dès que tu enfonces le bouton.
-
Sinon, il y a une petite erreur dans mon code ligne 29, le LOW devrait être un HIGH.
Ce qui nous donne :
/*
Fonction de traitement de l'interruption INT0.
Attente active (blocage du CPU) jusqu'au rappuis sur le bouton
/!\ Pendant une interruption, toutes les fonctions basées elles
aussi sur les interruptions sont interdites !
Donc interdit d'utiliser "delay" ou "millis" par exemple.
*/
void INT0_callback(void) {
// Attente de 100 ms, histoire que le bouton soit stable
// Fonction "delay" interdite, on utilise "delayMicroseconds"
for ( int i = 0 ; i < 100 ; i++ ) {
delayMicroseconds(1000);
}
// Attente que le bouton repasse à HIGH (relaché)
while ( digitalRead(2) == LOW ) {
/* rien (on attend) */
}
// Attente de 100 ms, histoire que le bouton soit stable
// Fonction "delay" interdite, on utilise "delayMicroseconds"
for ( int i = 0 ; i < 100 ; i++ ) {
delayMicroseconds(1000);
}
// Attente que le bouton repasse à LOW (enfoncé à nouveau)
while ( digitalRead(2) == HIGH ) {
/* rien (on attend) */
}
// Attente de 100 ms, histoire que le bouton soit stable
// Fonction "delay" interdite, on utilise "delayMicroseconds"
for ( int i = 0 ; i < 100 ; i++ ) {
delayMicroseconds(1000);
}
}
void setup(void) {
// Init serial
Serial.begin(9600);
// Init pin 2 en INPUT_PULLUP, bouton câblé sur GND
pinMode(2, INPUT_PULLUP);
// Activation de l'interruption INT0 (pin 2) en FALLING (passage à l'état LOW (enfoncé))
attachInterrupt(digitalPinToInterrupt(2), INT0_callback, FALLING);
}
void loop(void) {
Serial.println("AZERTYUIOPQSDFGHJKLMWXCVBN");
}
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Voici mon programme : le premier appui démarre le programme (représenté ici par l'allumage de la led verte) et le deuxième appui l'éteint (représenté par l'allumage de la led Rouge). Mais je n'arrive même pas à compiler...