Problem beim interrupt in Verbindung mit Tone

Moin Gemeinde,
Ich sehe wieder einmal den Wald vor lauter Bäume nicht. Vielleicht bekomme ich ja über diesen Weg ein Licht am Tunnel.

Ich Benutze den Tone Befehl als Rechteckgenerator um einen Schrittmotor anzusteuern. Klappt auch. Jetzt möchte ich aber wissen wieviele Schritte er gemacht hat während ich die Taste gedrückt hatte. Mein Idee war einfach den Ausgang des TonPins an den Interrupt Eingang zu legen. Klappt auch, aaaber der counter des interrupt zählt fleißig weiter obwohl der Tonausgang per notone abgeschalten wurde ?????

Ich benutze einen UNO

Ein Tip für die richtige Richtung zur Lösung wäre SUPI

Gruß Stefan

Bedenke dabei:
Der Interrupt unterbricht das laufende Programm. Damit wirst du also dein gewünschtes Ergebnis nicht erhalten

Der Fehler liegt in Zeile 42.

1 Like

Hallo,
das kann ja eigentlich nicht sein, mit notone() wird ja keine Frequenz mehr ausgegeben und der Motor bleibt ja auch stehen.
Zeig doch mal einen mini Sketch wie du das gemacht hast.

es funktioniert ja zu Programmstart. Soll heissen es wird nichts gezählt solange per Tone nichts generiert wird. Aktiviere ich den Tone, Zählt der Interrupt auch, allerding hört er nicht mehr auf wenn ich notone aufrufe. Das finde ich etwas verwirrend.

Und jetzt dürfen wir alle weiter raten ?


#define EnablePin_X 5                                     // HIGH => gesperrt
#define StepPin_X 6                                       // Schritte des X-Motors, generiert über "Tone"
#define DirPin_X 7                                        // Drehrichtung

int MotorRechts_Taster_Pin_X = 8;                         // Schalter Pin für X-Motor Rechtslauf
int Taster_Wert_Rechts_X = 0;                             // 0 oder 1, dreht oder dreht sich nicht (Enable)

int MotorLinks_Taster_Pin_X = 9;                          // Schalter PIN für X-Motor Linkslauf
int Taster_Wert_Links_X = 0;                              // 0 oder 1, dreht oder dreht sich nicht (Enable)

int Motorrichtung_X = 0;                                  // Motorrichtung_X Links / Rechts ??

int REGLER_Pin_X = A0;                                    // Potentiometer am Anschluss A0
int ReglerWert_X = 0;                                     // Poti gelesenen Werts

#define PIN_DOUT 2
volatile long count = 0;



void setup()
{
  Serial.begin(9600);
  
  pinMode(MotorLinks_Taster_Pin_X, INPUT_PULLUP);
  pinMode(MotorRechts_Taster_Pin_X, INPUT_PULLUP);
  pinMode(EnablePin_X, OUTPUT);
  pinMode(StepPin_X, OUTPUT);
  pinMode(DirPin_X, OUTPUT);

  pinMode(PIN_DOUT, INPUT);
  attachInterrupt(digitalPinToInterrupt(PIN_DOUT), isrCount, FALLING);
  ReglerWert_X = analogRead(REGLER_Pin_X);                  // Wert des Potentiometers lesen
  Motor_AUS_X();
}



void loop()
{
  Taster_Wert_Links_X = digitalRead(MotorLinks_Taster_Pin_X);     // manueller Linkslauf
  Taster_Wert_Rechts_X = digitalRead(MotorRechts_Taster_Pin_X);   // manueller Rechtslauf
  ReglerWert_X = analogRead(REGLER_Pin_X);                        // Wert des Potentiometers lesen
//  Serial.println(ReglerWert_X);
  if ( Taster_Wert_Rechts_X == 1 && Taster_Wert_Links_X == 1 || Taster_Wert_Rechts_X == 0 && Taster_Wert_Links_X == 0)
      { 
        Motor_AUS_X();                   // Motor-X ausschalten
        Serial.print("counter = ");  
        Serial.println(count);
      }
  else if ( Taster_Wert_Rechts_X == 0 && ReglerWert_X > 10 )                        
     {
      count = 0;
      Motorrichtung_X = 1;                                        // Rechtslauf vorgewählt
      ReglerWert_X = (ReglerWert_X * 3) + 31;                     // 31 = mindest Frequenz für Tone
      Motor_AN_X();                                               // Motor-X einschalten  
     }
  else if ( Taster_Wert_Links_X == 0 && ReglerWert_X > 10 )                        
     {
      count = 0;
      Motorrichtung_X = 0;                                        // Linkslauf vorgewählt
      ReglerWert_X = (ReglerWert_X * 3) + 31;                     // 31 = mindest Frequenz für Tone
      Motor_AN_X();                                               // Motor-X einschalten  
     }
}                                                                 // Ende loop



void Motor_AUS_X()
{
  noTone;
  digitalWrite(EnablePin_X, HIGH);                                // Motor gesperrt 
}  



void Motor_AN_X()
{
  digitalWrite(DirPin_X, Motorrichtung_X);                        // Richtung
  digitalWrite(EnablePin_X, LOW);                                 // Motor läuft / freigegeben
  tone(StepPin_X, ReglerWert_X );                                 // Pin, Frequenz, Dauer ms

//tone(StepPin_X, 3547);                                 // Pin, Frequenz, Dauer ms  
// Spindel 133 U/min / Leitspindel 3547 Hz bei 1600 Schritte pro Umdrehung

}



void isrCount()
  {
      count++;
  }


Die Übersetzung von "der Fehler liegt in Zeile 42" ist dass wir deinen Code brauchen. Und auch am besten noch einen Schaltplan

Taster_Wert_Links_X = digitalRead(MotorLinks_Taster_Pin_X); ???? das ist Zeile 42, aber ich sehe keinen Fehler.

Schaltplan hab ich keinen , Fehlermeldung bekomme ich auch keine

Schaltplan könnte ich als Skizze kurz malen, nicht zeichnen, denke aber die bringt nix, aber egal

pinMode(MotorRechts_Taster_Pin_X, INPUT_PULLUP);

Nein, da fehlt nix, es funktioniert ja auch

pinMode(PIN_DOUT, INPUT);

Wieso das?
Macht es nicht mehr Sinn, den Pin zum Output zu machen und damit den Treiber treiben?
Anstatt einen 2ten Pin dafür zu opfern

da hab ich Verständnis Probleme. Ich möchte die Anzahl der generierten Rechteecke am Tone Ausgang Zählen. Vielleicht kannst du das etwas ausführlicher erklären

Ich weiß!

Den Output auf 6 möchtest du zählen.
Wenn du den auf Pin 2 legst, sparst du einen Pin ein

Zusätzlich:
Dein counter muss im Hauptprogramm immer Atomic, zwischen Memory Barrieren, verarbeitet werden,
Das volatile ist da nicht nötig.

Ja, das mit dem Pin umlegen hat funktioniert, aaaber es ändertt nichts am Problem. Der Interrupt Zähler zählt weiter unbeirrt weiter obwohl der Motor abschaltet, sprich es kein Rechtecksignal mehr an Pin 2 generiert wird.

Hallo
ich hab das mal auf das Wesentliche gekürzt , und hatte das Problem ebenfalls. Allerdings ist es so das die Frequenz nicht ausgeschaltet wird. Dein Motor stopt sicher weil die Richtung ebenfalls aus geschaltet wird.

Nachdem ich bei noTone den pin angegeben habe geht es.
https://docs.arduino.cc/language-reference/de/funktionen/advanced-io/noTone/

allerdings solltest du den Atomic nutzten. zum auslesen der Variablen count werden mehrere ASM Befehle benötigt. Wenn während der Zeit ein Interrupt rein kommt dann kann die Variable falsch sein.

/*
   zum Testen eine Brücke zwischen pin 2 und 6 einlegen
*/
#include<util/atomic.h>
const byte tasterPin = 8;
const byte freqPin = 6;
const byte IntrPin = 2;

bool tasterState;
volatile long i_count;
long count;

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  pinMode(tasterPin, INPUT_PULLUP);
  pinMode(freqPin, OUTPUT);
  pinMode(IntrPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(IntrPin), isrCount, FALLING);

}

void loop() {
  // put your main code here, to run repeatedly:
  if (digitalRead(tasterPin) == 0) {
    tone(freqPin, 100);
    if (tasterState == false) { // flanke bilden
      Serial.println("start messen");
      i_count = 0; // reset
      tasterState = true;
    }

  }

  else {
    noTone(freqPin);
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
      count = i_count; // umladen
    }

    Serial.println(count); // Ergebniss anzeigen
    tasterState = false;
  }
}

void isrCount()
{
  i_count++;
}

Da würde ich

noTone();

erwarten.
Edit: Hatte Rentners Beitrag übersehen; vielleicht braucht es wirklich den Pin. Der Nicht-Funktionsaufruf aus #7 ist aber in jedem Fall falsch.

1 Like

erst mal danke für die Antworten und Anregungen. Ich muss für heute Schluss machen, mir raucht der Kopf. Morgen ist auch noch ein Tag

Habe ich doch glatt übersehen....

Sie haben 1000 Gummipunkte gewonnen!

E:\Programme\arduino\portable\sketchbook\Combie\AssemblerTest002_schlank\AssemblerTest002_schlank.ino: In function 'void Motor_AUS_X()':
E:\Programme\arduino\portable\sketchbook\Combie\AssemblerTest002_schlank\AssemblerTest002_schlank.ino:7:3: warning: statement is a reference, not call, to function 'noTone' [-Waddress]
    7 |   noTone;
      |   ^~~~~~
E:\Programme\arduino\portable\sketchbook\Combie\AssemblerTest002_schlank\AssemblerTest002_schlank.ino:7:3: warning: statement has no effect [-Wunused-value]

So, neuer Tag , neues Glück. Den Tone(6) Fehler habe ich nicht gesehen und das der Motor stehen bleibt wenn ich ihn Disable habe ich auch nicht berücksichtigt. Nach mehreren Stunden am Stück eigene Fehler suchen sieht man halt bald nix mehr.

Die Welt ist zumindest bei mir wieder rund.

Nochmal Dankeschön

Stefan