Interruptions dans les déclarations critiques

Sep 12 2020

J'ai refait un croquis Arduino précédent que j'ai publié dans lequel j'avais du mal à capturer le nombre d'encodeurs dans les déclarations critiques, n'ayant pas la chance d'attacher et de détacher correctement les interruptions. J'ai étudié différents croquis ISR mais je n'ai rien pu produire qui réponde à mes besoins.

J'ai maintenant un boîtier de commutation dans lequel un moteur à courant continu avec encodeur CPR tourne correctement dans les deux sens entre les limites spécifiées s'il est seul dans la boucle vide. Cependant, une fois inclus dans une déclaration critique (je veux que cette action se produise uniquement si un bouton est enfoncé), le moteur à courant continu continue de tourner dans un seul sens.

J'ai besoin d'aide pour savoir où attacher et détacher correctement ces interruptions et comment passer correctement la valeur de l'encodeur à l'action suivante. Voici ce que j'ai fait jusqu'à présent et toute aide serait grandement appréciée.

#define enA 9
#define in1 6
#define in2 7

const int button1Pin = 8;

int button1State = 0;     

volatile long temp, counter = 0;

long local_counter=counter;

enum {IdleState, ForwardState, BackwardState} State;

void setup() {
  
  Serial.begin(9600);
  
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  Serial.begin (9600);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  
  attachInterrupt(0, ai0, RISING);
  attachInterrupt(1, ai1, RISING);

  pinMode(button1Pin, INPUT);

  State = IdleState;
}

void loop() {

  button1State = digitalRead(button1Pin);

   if( counter != temp ){
   Serial.print("counter = ");
   Serial.print (counter);
   Serial.print("     local counter = ");
   Serial.println(local_counter);
   temp = counter;
   }

   //if (button1State == HIGH) {

          switch (State) {
            
              case IdleState:
                halt ();
        
              if (counter<2000)
                State = ForwardState;
              break;
        
              case ForwardState:
                clockwise();
                         
              if (counter>=2000)
                State = BackwardState;
              break;
        
              case BackwardState:
                counterclockwise();

              if (counter <=0)
                State = ForwardState;
              break;   
           
          } // end switch
   //  }

}

void ai0() {
  if(digitalRead(3)==LOW) {
  counter++;
  }else{
  counter--;
  }
  }
   
void ai1() {
  if(digitalRead(2)==LOW) {
  counter--; 
  }else{
  counter++;
  }
  }

void clockwise (){
    analogWrite(enA, 255);
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  }

void counterclockwise () {
    analogWrite(enA, 255);
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }

void halt () {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
}

Une explication de ma configuration est la suivante:

Mon bouton est un bouton tactile sur la maquette (connecté à la broche 8 d'un Arduino Uno), avec une alimentation 5V d'Arduino. Les broches 6 de l'Arduino sont connectées à l'entrée 1 du pilote de moteur L298N , la broche 7 d'Arduino connectée à l'entrée 2 du pilote de moteur et la broche 9 de l'Adruino connectée à l'activation du pilote de moteur. Le pilote de moteur est alimenté par une alimentation externe 12V qui alimente également le motoréducteur 12V DC avec encodeur . Les sorties du codeur sont connectées aux broches 2 et 3 de l'Arduino.

Réponses

Gerben Sep 12 2020 at 22:50

À mon avis, l'état devrait revenir à IdleState si le bouton n'est pas enfoncé. Le simple fait de mettre le boîtier de l'interrupteur à l'intérieur de l'instruction if aura pour effet que le moteur continue de tourner comme il tournait lorsque le bouton est relâché.

if (button1State == LOW ) {
  State = IdleState;
  counter=2000;
}
else if(button1State==HIGH && State==IdleState ) {
  counter = 0;
}

switch(State) {
  ...

En fonction de ce que vous voulez faire, vous voudrez peut-être ajouter un autre état (par exemple StoppedState), où les moteurs sont arrêtés, tout comme IdleState, mais vous n'obtenez pas de changement d'état si counter<2000. Ensuite, vous n'avez pas à modifier la countervariable.

if (button1State == LOW ) {
  State = StoppedState;
}
else if(button1State==HIGH && State==StoppedState ) {
  State = IdleState;
}

switch(State) {
  case StoppedState:
    halt ();
    break;
  case IdleState:
    ...

PS s'il vous plaît indentez les déclarations if à l'intérieur de vous cases.