Gestion des interruptions dans une bibliothèque

Bonjour à tous,

Actuellement je réalise une petite bibliothèque pour faciliter l’utilisation des boutons dans mes programmes sur plateforme Arduino. Pour la gestion de ces boutons, je veux utiliser les interruptions via la fonction attachInterrupt pour détecter les changements de fronts. Mon idée est donc « d’attacher » ma fonction de gestion des interruptions à la pin correspondante lors de l’appel du constructeur de l’objet.

Pour cela j’ai besoin de l’adresse de la méthode gestion_interruption_BT de mon objet instancié, je pense que je l’ai bien récupéré mais pas sûr à 100% …

Bref, j’ai le message d’erreur suivant :

\Bouton.cpp: In constructor ‘Bouton::Bouton(int)’:
\Bouton.cpp:36: error: invalid use of non-static member function

J’ai donc fait un essai avec une méthode « static » et cela fonctionne mais le problème est que la méthode « static » ne peut utiliser que des variables « static » qui sont donc communes aux instances de la classe bouton ce qui est problématique. Je voudrais que la méthode de gestion d’interruption accède uniquement aux variables de l’objet instancié.

Ma question est donc : est t’il possible de faire appel à une fonction «non static» pour la gestion des interruptions dans une bibliothèque ? Et si oui, comment procéder ?

Le code actuel est ci-dessous :

Bouton::Bouton(int pin){
	int pin_int ;
		
	Bouton *monpointeur(this);
	typedef void (Bouton::*ptr)();
	ptr a(&Bouton::gestion_interuption_BT);
	
	pin_bouton = pin ;
	pinMode(pin,INPUT);
	
	switch (pin) { 
        case 2  : pin_int = 0 ;
		     break;
        case 3  : pin_int = 1 ;
		    break;
	case 21 : pin_int = 2 ;
		     break;
	case 20 : pin_int = 3 ;
		     break;
	case 18 : pin_int = 4 ;
                     break;
	case 19 : pin_int = 5  ;
		     break;
        default : pin_int = -1 ;
  }
   if(pin_int > 0){
        attachInterrupt(pin_int,monpointeur->*a,CHANGE);	//Ligne problématique
   }
   back_edge = 0 ;
   front_edge = 0 ;
}

Merci d’avance pour vos réponses :slight_smile:

Bonjour,

Une interruption doit être une fonction C déclaré dans le scope global. Tu ne peut pas utiliser une fonction d'une classe car il faut une instance de cette classe pour appeler la fonction. J'ai jamais essayé mais tu doit pouvoir t'en sortir avec une lambda C++.

Merci pour la réponse, je vais essayer de construire ma bibliothèque autrement pour contourner le problème. Je posterai la solution trouvée si elle est propre :)

Abbie: Merci pour la réponse, je vais essayer de construire ma bibliothèque autrement pour contourner le problème. Je posterai la solution trouvée si elle est propre :)

Normalement quand tu utilises une interruption tu fait une classe singleton et tu fait un fonction C "cachée" hors de la classe pour gérer l'interruption.

Ici tu peut avoir plusieurs instances de ta classe donc c'est plus compliqué. La solution que j'ai utilisé dans ma librairie PCF8574 c'est de fournir une fonction de gestion d'interruption publique. Quand l'interruption ce fait j'appelle la fonction de l'utilisateur (qu'il me fourni par pointeur) qui doit (si il a fait les choses correctement) appeler ma fonction publique. C'est le principe des lambda C++ mais sans lambda :grin:

Hum... En d'autres mots : ->l'utilisateur doit associer l'interruption à l'une de ces fonctions via une méthode publique de la classe. L'utilisateur doit donc créer une fonction par bouton si je comprends bien... ->la fonction créé par l'utilisateur fait appel à la méthode de traitement de l'objet instancié.

En résumé, j'ai besoin de créer : Une méthode publique dans ma classe bouton qui associe les interruptions de mon bouton à une fonction. Une fonction par instance d'objet dans le fichier de mon main pour faire l'appel de la méthode de traitement associé au bon objet.

Je crois avoir bien compris ta solution mais pour aller plus loin...

Je voudrais ne pas avoir besoin de créer ces fonctions et donc associer l'interruption à l'une des méthodes de l'objet via une méthode publique de la classe. Est ce possible ? La question devient : Est t'il possible d'associer directement une interruption à une méthode d'un objet instancié ? :fearful:

Merci pour ton aide, et félicitation pour ton site il est vraiment intéressant :)

Abbie: Je voudrais ne pas avoir besoin de créer ces fonctions et donc associer l'interruption à l'une des méthodes de l'objet via une méthode publique de la classe. Est ce possible ? La question devient : Est t'il possible d'associer directement une interruption à une méthode d'un objet instancié ? :fearful:

Non pas directement, une interruption est appelé par le matériel sans arguments. Or une fonction de classe à toujours un argument : this (sauf les fonctions statiques).

La seule solution "transparente" que je vois c'est une lambda C++, ça revient à faire faire par le compilateur ce que je demande à l'utilisateur de faire. (dans mon cas laisser faire l'utilisateur avait des avantages technique, ici ce n'est pas franchement le cas)

Juste par curiosité essaye :

attachInterrupt(pin_int, [this](){ this->gestion_interuption_BT(); }, CHANGE);

(je sait même pas si le compilateur fourni de base avec l'ide arduino est assez récent pour avoir le support des lambda)

Parfait, je comprends beaucoup mieux maintenant je ne voyais pas l'objet comme un argument donc tout s'explique :)

J'ai essayé ta ligne et j'ai l'erreur suivante :

error: expected primary-expression before '[' token

Ce qui semble correspondre à ce que tu disais précédemment, le compilateur ne supporte pas le lambda C++. C'est la première fois que j'entends parler du lambda C++, je vais lire des docs à ce sujet ça a l'air puissant comme outil...

Merci encore !

Arf, pas de bol, la team arduino fourni la version 4.3.x de gcc et c'est dans la 4.5.x que c'est apparu : http://gcc.gnu.org/gcc-4.5/changes.html (la dernière version est 4.7.x)

Il serait bon qu'ils fasse le ménage dans le code source et qu'il passe à la version 4.7.x, 5 ans de retard ça commence à faire ...

Au moins si je dois faire des bibliothèques du genre pour un autre µC, je sais ce qu'il faut utiliser. Et vu que c'est des bibliothèques perso, ta solution convient très bien. Je pense pas qu'on va être beaucoup à demander une nouvelle version du compilateur parce les lambdas ne sont pas supportés :p

Abbie: Au moins si je dois faire des bibliothèques du genre pour un autre µC, je sais ce qu'il faut utiliser. Et vu que c'est des bibliothèques perso, ta solution convient très bien. Je pense pas qu'on va être beaucoup à demander une nouvelle version du compilateur parce les lambdas ne sont pas supportés :p

Les lambda c'est une chose mais tu te doute bien qu'en 5 ans le langage C++ à évoluer et que GCC c'est largement amélioré ;) Exemple de truc qui justifierait une màj : http://forum.arduino.cc/index.php?topic=163944.msg1232039#msg1232039 (et puis copier/coller un dossier n'est pas une màj bien compliqué :grin:)