[Problème] Bouton simple..

Bonjour,
sur arduino j'ai branché plusieurs boutons et j'ai fais une fonction pour récupérer l'état d'un bouton.
Cependant, ça ne fonctionne pas! Je ne comprends vraiment pas pourquoi, tout à l'air bon pourtant...

#include <VirtualWire.h>

const int bt1 = 2;
const int bt2 = 3;
const int bt3 = 4;
const int bt4 = 5;
const int bt5 = 6;

int etat = 0;

void setup()
{
   vw_setup(2000);
   pinMode(bt1,INPUT);
   pinMode(bt2,INPUT);
   pinMode(bt3,INPUT);
   pinMode(bt4,INPUT);
   pinMode(bt5,INPUT);
}
 
void loop()
{
   
   if (bouton(bt1))
   {
      radio_envoie("a");
   }
}

void radio_envoie(char *msg)
{
   vw_send((uint8_t *)msg, strlen(msg));
   vw_wait_tx();
}

int bouton(int const bt)
{
   int val = digitalRead(bt);
   
   if((val != etat) && (val == LOW))
   {
      return 1;
   }
   else
   {
      return 0;
   }
   
   etat = val;
}

Voyez vous même...
Par contre, si à la place de "return 1;" je met "radio_envoie("a");" et bien ça fonctionne! Pourquoi le return 1 ne m'envoye pas "1" ?
Merci de m'éclairer... :slight_smile:

Ta fonction bouton() est buggée par conception

Je ne sais pas ce qu'elle doit faire, mais elle ne peut pas le faire proprement.
Tu as 3 chemin de code dont 2 seulement ont une instruction return
Donc quand tu passes par etat = val; tu ne sait pas qu'elle valeur est retournée

Le "etat = val;" et là pour stoquer en mémoire l'état du bouton..Je ne vois pas en quoi il y a un problème =(
La variable etat est bien déclaré aussi..

Pourtant sans le return, si je met autre chose ça fonctionne parfaitement bien.

Relis ton code
Tu as un if avec son else
Dans chacun des cas tu as un return donc tu sort de la fonction
Donc tu ne va jamais sur la ligne etat = val;

C'est cette fonction qui ne va pas :

int bouton(int const bt)
{
   int val = digitalRead(bt);
   
   if((val != etat) && (val == LOW))
   {
      return 1;
   }
   else
   {
      return 0;
   }
   
   etat = val;
}

D'une part la ligne etat=val n'est JAMAIS atteinte ! car soit le if est vrai soit il est faux, donc soit il return 1 ou soit il retourne 0.

De plus etat est une variable globale. Donc elle garde un état de tous les boutons. Est ce que c'est ce que tu veux ?

Que doit réaliser ton programme ? decrit ce que tu veux qu'il se passe quand on appuie sur un bouton, c'est à dire que font les autres.

Si tu dois garder un état pour chaque bouton, il faut utiliser un tableau pour les conserver.

Dis nous en plus.

A+

en dehors du code qui n'est pas bon, il faut aussi être sur que tu as cablé correctement.

L'état 0 ne se lit pas en branchant directement ton bouton entre le 0 et la broche de l'arduino. Il faut soit utiliser le pullup interne, ou alors ajouter une resistance de 10k qui relie le bouton au 5v

vohu:
en dehors du code qui n'est pas bon, il faut aussi être sur que tu as cablé correctement.

L'état 0 ne se lit pas en branchant directement ton bouton entre le 0 et la broche de l'arduino. Il faut soit utiliser le pullup interne, ou alors ajouter une resistance de 10k qui relie le bouton au 5v

Il est souvent plus sûre en effet d'activer les pull up est de lire en logique inverse de plus c'est moins sensible aux parasites et ne consomme aucune resistance. Le pied en sorte !

un peu de lecture pour cette version: http://www.instructables.com/id/Arduino-Button-Tutorial/

Hmm d'accord, je vois ! J'ai bien compris mon erreur, merci!
De plus comme tu dis Grag38, il me faut un tableau pour conserver l'état de chaque bouton, je m'y prend assez mal, je vais rectifier tous celà! :grin:

Je poste ma petite correction si des personnes ont eu le même soucis que moi ...

#include <VirtualWire.h>

const int bt1 = 2;
const int bt2 = 3;
const int bt3 = 4;
const int bt4 = 5;
const int bt5 = 6;

int etat[5] = {0,0,0,0,0};

void setup()
{
   vw_setup(2000);
   pinMode(bt1,INPUT);
   pinMode(bt2,INPUT);
   pinMode(bt3,INPUT);
   pinMode(bt4,INPUT);
   pinMode(bt5,INPUT);
}
 
void loop()
{
   
   if (bouton(bt1,1))
   {
      radio_envoie("a");
   }
   
   if (bouton(bt2,2))
   {
      radio_envoie("c");
   }
}

void radio_envoie(char *msg)
{
   vw_send((uint8_t *)msg, strlen(msg));
   vw_wait_tx();
}

int bouton(int const bt, int i)
{
   int val = digitalRead(bt);
   int state = 0;
   
   if((val != etat[i]) && (val == LOW))
   {
      state = 1;
   }
   else
   {
      state = 0;
   }
   
   etat[i] = val;
   
   return state;
}

Bravo mais il reste un bug !

Quand tu vas faire la même chose avec le bouton5 il va y avoir un problème. Trouveras-tu la raison de ce problème ?

Un bug?
Mon bouton 5 fonctionne à merveille pourtant :astonished:

Tous les boutons fonctionne très bien je viens de tous les tester. :slight_smile:

EDIT: je vais faire un autre test en traitant tous les boutons pour voir

Non il y a un bug !

tu declares :

int etat[5] =  {0,0,0,0,0};

or le dernier indice accessible est : etat[4] car en C on indice à partir de 0.

Donc tu as un dépassement de buffer. Il ne cause pas de problèmes pour le moment. Mais si tu ajoutes d'autres variable et code, certaines seront écrasées par ce dépassement de buffer.

Si tu veux corriger :

-soit tu augmente de 1 la taille du tableau etat.

-soit tu indices tes variables etat avec un indeice de moins dans ta fonction bouton.

encore une petite chose.

Tu utilises un int pour l'état de ton bouton...

plutot que de tester l'état et le changer pourquoi ne pas directement envoyer la valeur du int ? :slight_smile:

Ca te permet d'enlever la moitier du code de ta fonction..
Le problème, c'est si par erreur, tu envoies autre chose... ce qui se règlerai par une seule condition...
ou si non, tu utilises plutôt un booléen ? il n'y a plus le moindre problème.

(à savoir qu'en C, les booléens n'existent pas... mais vu qu'on compile en C++, pas de soucis non plus :))

grab, il s'agit de la décraration, cette ligne est juste.

par contre , on peut écrire juste : int etat[5] = {0};
Ce qui initialisera toutes les autres valeurs à 0.

(En C, lorsqu'on donne la valeur d'une case d'un tableau, toutes celles qui n'ont pas étés spécifiées sont mise à la valeur 0)

int etat[5] = {3}; aurait donc donné un tableau contenant : 3, 0, 0, 0 et 0

Hmm je vois. :~

Donc ma fonction serait

boolean bouton(int const bt, int i)
{
   int val = digitalRead(bt);
   int state = 0;
   i--;
   
   if((val != etat[i]) && (val == LOW))
   {
      state = 1;
   }
   else
   {
      state = 0;
   }
   
   etat[i] = val;
   
   return state;
}

Code complet :

#include <VirtualWire.h>

const int bt1 = 2;
const int bt2 = 3;
const int bt3 = 4;
const int bt4 = 5;
const int bt5 = 6;

int etat[5] =  {0};

void setup()
{
   vw_setup(2000);
   pinMode(bt1,INPUT);
   pinMode(bt2,INPUT);
   pinMode(bt3,INPUT);
   pinMode(bt4,INPUT);
   pinMode(bt5,INPUT);
}
 
void loop()
{
   
   if (bouton(bt1,1))
   {
      radio_envoie("a");
   }
   
   if (bouton(bt2,2))
   {
      radio_envoie("b");
   }
   
   if (bouton(bt3,3))
   {
      radio_envoie("c");
   }
   
   if (bouton(bt4,4))
   {
      radio_envoie("d");
   }
   
   if (bouton(bt5,5))
   {
      radio_envoie("e");
   }
}

void radio_envoie(char *msg)
{
   vw_send((uint8_t *)msg, strlen(msg));
   vw_wait_tx();
}

boolean bouton(int const bt, int i)
{
   int val = digitalRead(bt);
   int state = 0;
   i--;
   
   if((val != etat[i]) && (val == LOW))
   {
      state = 1;
   }
   else
   {
      state = 0;
   }
   
   etat[i] = val;
   
   return state;
}

Si je teste mes boutons, 2 ne fonctionne pas. (bouton 2 et bouton 5) Je vais regarder mon cablage, à première vue il a l'air correct.. =(

vohu --> J'ai du mal à te suivre, envoyer directement la valeur du int ? ça voudrait dire que je testerai l'état du bouton dans ma fonction principale?

heu... oui, j'avais oublié que le but était de lire... pas d'écrire l'état du bouton.

Si tu veux lire l'état d'un bouton, tu n'as besoin que d'un seul paramètre dans ta fonction... le bouton à lire.

du coup, ta fonction se limite à

boolean bouton(int const bt)
{
   boolean state = digitalRead(bt);

   
   return state;
}

par contre j'ai pas d'arduino sous la main, donc je peux pas tester tout ça. Ce code fonctionne à condition qu'un LOW soit égal à false, et que HIGHT à true

Ah oui je vois, mais dans ce cas là, cette fonction très petite ne stoque pas la valeur mais la retourne, mais dans ma fonction principale je vais devoir tester à chaque fois la valeur et ça me prendrait plus de place non?

effectivement,

tu pourrais mettre directement dans le main()

void loop()
{
   
   if (digitalRead(bt1))
   {
      radio_envoie("a");
   }
}

Enfaite mes deux boutons marchaient très bien..C'est le radio_envoie("b"); et radio_envoie("e"); qui fonctionne pas :astonished: mais si je remplace le "b" et le "e" ça marche :roll_eyes:
Bref, je vais voir un peu ça..

vohu--> Oui je vois bien, mais quand on appuie sur le bouton en question, il execute radio_envoie("a"); des tonnes de fois à chaque appuie ^^