[Résolu] Erreur d'assignation d'interruption

Bonjour,

Je voudrais utiliser une interruption... Pour cela, j'ai branché un interrupteur sur la broche d'interruption. Ce n'est pas l'interrupteur ni son branchement qui pose problème car ils fonctionnent si je les branche sur une autre interruption.

Voici ma commande pour initialiser l'interruption :

attachInterrupt(INT_CHANG_MODE, changerMode, RISING);

Avec INT_CHANG_MODE défini par :

#define INT_CHANG_MODE 0

Mon problème est que l'interruption ne marche pas... Enfin, je ne sais pas si ça vient de la ligne d'initialisation ou d'autre chose...

Pouvez-vous m'aider ? Merci d'avance

Aucun code et aucun hardware … On est pas devin !

Tu raccordes bien ton interrupteur sur la broche 2?

Quelle carte UNO, MEGA, autre ? Quel numéro de broche d'interruption ? Avec l'inter il y a bien une résistance de tirage soit au Vcc soit au GND ? ou sans résistance externe la pull-up interne du micro est bien activée ?

Bonjour,

On m'avait pas prévenu que c'était un club de divination ici :grin:

Allez je mise sur : 1) une résistance de pullup oubliée / mal cablée 2) une erreur de n° de broche côté Arduino

Excusez moi… Je reconnais que j’avais rien mis dans mon post… ^^

Donc, le schéma est en pièce jointe.
(par contre, l’interrupteur est un inter normalement fermé…)

La carte est une carte UNO.
Le numéro de l’interruption est le 0 (donc broche D2 de la carte Arduino).

Voici mon programme (j’ai enlevé tout ce que je pensais inutile :

/*
 * Numéros des interruptions
 */
#define INT_CHANG_MODE  0

/*
 * Mode :
 *   0 - arrêt
 *   1 - manuel
 *   2 - automatique
 */
int mode = 0;

/*
 * Variable contenant les noms de modes pour afficher le menu
 */
static const char modesAff[3][17] = {
  "  1. Arret      ",
  "  2. Manuel     ",
  "  3. Auto       " };

void setup() {
  /*
   * Choix du mode
   */
  mode = 0;
  changerMode();
  attachInterrupt(INT_CHANG_MODE, changerMode, RISING);
}

void loop() {
  // Boucle principale
}


/**
 * Interruption permettant de changer le mode
 */
void changerMode () {
  // Menu de sélection du mode (pas de problème ici)
  
  // On initialise les interruptions en fonction du mode choisi
  switch (mode) {
    // Arrêt de la machine
    case 0:
      detachInterrupt(INT_PAS);
      break;
    
    // Mode manuel => aucune interruption
    case 1:
      detachInterrupt(INT_PAS);
      break;
    
    // Mode automatique => interruption des pas
    case 2:
      attachInterrupt(INT_PAS, MA_addPas, RISING);
      break;
    
    default:
      detachInterrupt(INT_PAS);
      break;
  }
}

Mon problème est que l’interruption ne marche pas… J’ai l’impression que le fait d’appuyer sur le bouton (et donc d’ouvrir le contact) fait planter entièrement le programme…

N’est-il pas possible d’avoir 2 interruptions ?

Merci d’avance

Y a du mic mac dans l'air :

Tu déclenche une interruption. Tu fais un gros traitement dans l'interruption, déjà ce n'est pas bien : dans une interruption on fait le strict minimum, par exemple juste positionner une variable "drapeau" . Le vrai traitement se faisant dans loop() en fonction de la valeur du "drapeau". Mais en plus dans la fonction appelée par l'interruption tu désactive l'interruption alors que tu n'es pas encore sorti de l'interruption. Ce n'est peut être pas étonnant que ça plante.

Si tu fais le traitement dans loop() tu sera déjà sorti de l'interruption donc il sera possible de la désactiver.

D'accord, je vais retravailler mon programme...

Par contre, je désactive une autre interruption... Celle dont je vous parle reste active tout le temps !

sawok:
Par contre, je désactive une autre interruption… Celle dont je vous parle reste active tout le temps !

Il y a peut-être autre chose, mais plus ce sera clair plus cela aura de chance de fonctionner.
A ta place, n’étant pas un grand programmeur moi-même, je découperais le programme en tout petit tests.
D’abord une interruption qui ne fait qu’afficher un message par un SerialPrint() , puis 2 interruptions et si cela fonctionne je ferais faire un traitement plus conséquent par les interruptions. La méthode des petits pas est souvent, au final, la plus rapide.

Effectivement, c’est la meilleure solution et c’est celle que j’utilise depuis le début :
tester petit morceau par petit morceau

Donc, alors, le problème est résolu pour l’interruption de changement de mode…
C’était bien le problème du ‘trop de choses à faire’.
Cependant, je viens de me rendre compte que j’ai le même pour l’autre interruption (celle qui me permet de compter les pas)…

En fait, au début, avec cette seconde interruption (celle qui marchait, je n’avais pas le problème
car l’interruption ne faisait qu’incrémenter un int…
Maintenant, il me faut pouvoir mesurer l’angle (à partir d’une boussole) dans cette interruption de mesure du nombre de pas…
Mais ça ne marche pas (trop de choses à faire)…

Voici l’interrruption qui ne marche plus (car ajout de fonctionnalité) :

/**
 * Interruption permettant d'incrémenter le nombre de pas
 */
void MA_addPas () {
    // Si on ne peut plus enregistrer de pas, on arrête la fonction d'ajout de pas
  if (MA_nbPas > MA_NB_PAS_MAX)
    return;
  
    // Sinon, on ajoute un pas au nombre de pas
  MA_nbPas++;
  
    // Et on enregistre la direction actuelle
  MA_angles[ MA_nbPas - 1 ] = COMPASS_lire();
  
  Serial.println(MA_nbPas);
  Serial.println(MA_angles[ MA_nbPas - 1 ]);
}

Et voici ma fonction de lecture de la boussole :

//-----------------------------------------
//  Préfixe pour la boussole : "COMPASS_"
//-----------------------------------------

/*
 * Offsets sur les différents axes
 */
#define COMPASS_xOffSet       -29.5
#define COMPASS_yOffSet       110
#define COMPASS_zOffSet       0

/*
 * Variable de vérification d'erreur de la boussole
 */
int COMPASS_error = 0;

/*
 * Variables contenant les valeurs sur les différents axes
 */
int16_t COMPASS_x, COMPASS_y, COMPASS_z;


/**
 * Fonction de lecture de la direction
 * @return dir		Retourne la direction actuelle de la boussole en degré
 */
int COMPASS_lire () {
    // On lit les valeurs sur les différents axes
  boussole.getHeading(&COMPASS_x, &COMPASS_y, &COMPASS_z);
  
    // Ajout des offsets
  COMPASS_x += COMPASS_xOffSet;
  COMPASS_y += COMPASS_yOffSet;
  COMPASS_z += COMPASS_zOffSet;
  
    // On calcule l'angle
  float heading = atan2(COMPASS_y, COMPASS_x);
  
    // On rectifie si c'est inférieur à 0
  if(heading < 0)
    heading += 2 * M_PI;
  
    // On retourne la valeur en degré
  return (int) (heading * 180 / M_PI);
}

D’après vous, comment puis-je faire, sachant qu’il faut que je mesure l’angle à chaque fois que le nombre de pas est incrémenté de 1 ?

Merci d’avance

La seule chose que je sais faire c'est d'activer un drapeau dans l'interruption et de gérer dans loop()

void fonction_appellée_par_atach_interupt()
{
drapeau_1 = 1 ;
}

loop()
{
  If (drapeau_1)
    {
     /* traitement*/
       drapeau_1 =0;
   }

   If (drapeau_2)
   {
     /* traitement */
    drapeau_2 =0;
   }

}

Ya rien de pire que des brides de code hors contexte ... Le code complet ou rien, pour le moment je vois uniquement un problème de code spaghetti ;)

Bonjour :)

Alors, finalement, ce que j'ai fais, c'est que quand on fait un pas, on change le nombre de pas. Ce nombre de pas est aussi enregistré dans une variable ancienNbPas.

Lorsque les 2 valeurs sont différentes, en début du loop, je fais la mesure de la direction.

Merci pour votre aide précieuse sur cette erreur de conception des interuptions. :)