Interrupts innerhalb kritischer Aussagen

Sep 12 2020

Ich habe eine frühere Arduino-Skizze überarbeitet, in der ich Probleme hatte, die Anzahl der Encoder in kritischen Anweisungen zu erfassen. Ich hatte kein Glück, Interrupts richtig anzuhängen und zu entfernen. Ich habe verschiedene ISR-Skizzen studiert, konnte aber nichts produzieren, was meinen Bedürfnissen entspricht.

Ich habe jetzt ein Schaltgehäuse, in dem sich ein Gleichstrommotor mit CPR-Encoder korrekt zwischen festgelegten Grenzen hin und her dreht, wenn er sich allein in der Hohlraumschleife befindet. Sobald der Gleichstrommotor jedoch in einer kritischen Anweisung enthalten ist (ich möchte, dass diese Aktion nur ausgeführt wird, wenn eine Taste gedrückt wird), dreht er sich weiterhin nur in eine Richtung.

Ich benötige Unterstützung beim richtigen Anbringen und Trennen dieser Interrupts und beim korrekten Übergeben des Encoderwerts an die nächste Aktion. Im Folgenden ist aufgeführt, was ich bisher getan habe, und jede Hilfe wäre sehr dankbar.

#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);
}

Eine Erklärung meines Setups lautet wie folgt:

Mein Knopf ist ein taktiler Knopf auf dem Steckbrett (verbunden mit Pin 8 eines Arduino Uno) mit 5-V-Versorgung von Arduino. Die Pins 6 des Arduino sind mit Eingang 1 des L298N-Motortreibers verbunden , Pin 7 von Arduino mit Eingang 2 des Motortreibers und Pin 9 des Adruino mit der Freigabe des Motortreibers. Der Motortreiber wird von einer externen 12-V-Versorgung versorgt, die auch den 12-V-DC-Getriebemotor mit Encoder versorgt . Die Encoderausgänge sind mit Pin 2 und 3 des Arduino verbunden.

Antworten

Gerben Sep 12 2020 at 22:50

So wie ich es sehe, sollte der Status zu IdleState zurückkehren, wenn die Taste nicht gedrückt wird. Wenn Sie nur den Schalter in die if-Anweisung einfügen, dreht sich der Motor weiter so, wie er sich gedreht hat, als der Knopf losgelassen wurde.

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

switch(State) {
  ...

Je nachdem, was Sie tun möchten, möchten Sie möglicherweise einen anderen Status hinzufügen (z. B. StoppedState), in dem die Motoren angehalten werden, genau wie bei IdleState, aber Sie erhalten keine Statusänderung, wenn counter<2000. Dann müssen Sie die counterVariable nicht ändern .

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

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

PS Bitte rücken Sie die if-Anweisungen in Ihnen ein case.