Interrupt am analogen Eingang

Hallo Gemeinde,
Mein Projekt ist eine Anzeige für meine CNC Steuerung.
Dabei fiel meine Wahl auf einen ESP32 38PIN.
Dieser soll den Status der Endschalter und sonst einiger Funktionen auswerten und auf ein 2,5Zoll Display zaubern. Des Weiteren ist er für die Ansteuerung eines BL Motors zuständig und das Einschalten eben diesen.
Das Programm läuft zur Zeit ordentlich ab.
Das Einschalten per interrupt funktioniert einwandfrei.
Für die Steuerung des BL Motors hängt am A0 ein Eingangssignal von 0-1V zur Steuerung der Drehzahl.
Nun zur Frage:
Kann man am A0 einen interrupt auslösen, der auf Änderung des Eingangswertes reagiert?
Im loop läuft die Anzeige mit einigen delays danach die Abfrage des A0 also immer um die delays verzögert.
Das möchte ich ändern.
Oder kann man das viellecht anders lösen?
Ich bin Anfänger auf diesem Gebiet und bitte nicht gleich in schallendes Gelächter auszubrechen, wenn ihr den anschließenden sketch lest.

#include <Arduino.h>
#include <Adafruit_GFX.h>      // Core graphics library
#include <Adafruit_I2CDevice.h>
#include <Adafruit_ST7789.h>   // Hardware-specific library for ST7789
#include <SPI.h>               // Arduino SPI library
#include <ESP32Servo.h>        // Servobibliothek.

#define BLACK 0x0000    //Farbe Schwarz
#define BLUE 0x001F     //Farbe Blau
#define RED 0xF800      //Farbe Rot
#define GREEN 0x07E0    //Farbe Grün
#define CYAN 0x07FF     //Farbe Cyan
#define MAGENTA 0xF81F  //Farbe Magenta
#define YELLOW 0xFFE0   //Farbe Gelb
#define WHITE 0xFFFF    //Farbe Weiß

#define TFT_MOSI 23     // SDA Pin on ESP32
#define TFT_SCLK 18     // SCL Pin on ESP32
#define TFT_CS 17       // Chip select control pin
#define TFT_DC 2        // Data Command control pin
#define TFT_RST -1      // Reset pin (could connect to RST pin)
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

String Status_Stg;       //Status Enable
String Status_ES_X;      //Status Endschalter X
String Status_ES_Y;      //Status Endschalter Y
String Status_ES_Z;      //Status Endschalter Z
String Status_3D;        //Status 3D-Taster
String Status_Z_Laenge;  //Status WKZ-Länge
String Status_Spindel;   //Status Spindel
String Achse;            //Var. für Achse

unsigned long Farbe;         // Farbe= Schriftfarbe
int Dz_in = A0;              // Eingang Drehzahl-Spindel 0-10V
int Spindel_in = 12;         // Eingang Spindel_an Eingang
int Es_X_in = 39;            // Eingang Endschalter X
int Es_Y_in = 34;            // Eingang Endschalter Y
int Es_Z_in = 35;            // Eingang Endschalter Z
int Taster_in = 26;          // Eingang 3D Taster
int Wkz_in = 27;             // Eingang WKZ-Länge
int EStop_in = 32;           // Eingang Notaus
int Ena_in = 14;             // Eingang Enable
int Reserve_in = 33;         // Eingang Reserve Relais
int Spindel_out = 16;        // Ausgang Spindel_an
int Reserve_Relais_out = 4;  // Ausgang Reserve Relais
int Reserve_out = 4;         // Ausgang Reserve 
int ESC_out = 13;            // Ausgang PWM ESC
int TFT_BL = 15;             // Ausgang Beleuchtung TFT
int Drehzahl = 0;            // Var. Drehzahl (Drehzahl 0)
int DZ = 0;                  // War. Drehzahl in Anzeige(0-25000)
Servo ESC;                   // Der ESC-Controller wird als Objekt mit dem Namen "ESC" festgelegt
//void ICACHE_RAM_ATTR ISR();

void setup() {
  pinMode(Es_X_in, INPUT_PULLUP);         // PIN Es_X_in Eingang Pullup
  pinMode(Es_Y_in, INPUT_PULLUP);         // PIN Es_Y_in Eingang Pullup
  pinMode(Es_Z_in, INPUT_PULLUP);         // PIN Es_Z_in Eingang Pullup
  pinMode(Spindel_in, INPUT_PULLUP);      // PIN Spindel_in Eingang Pullup
  pinMode(Ena_in, INPUT_PULLUP);          // Pin Enable_in Eingang Pullup
  pinMode(Taster_in, INPUT_PULLUP);       // Pin 3D-Taster Eingang Pullup
  pinMode(Wkz_in, INPUT_PULLUP);          // Pin WKZ-Laenge-Taster Eingang Pullup
  pinMode(EStop_in, INPUT_PULLUP);        // Pin EStop Eingang Pullup
  pinMode(ESC_out, OUTPUT);               // PIN ESC_out Ausgang
  pinMode(TFT_BL, OUTPUT);                // PIN TFT_BL Beleuchtung TFT Display
  pinMode(Spindel_out, OUTPUT);           // PIN Spindel Relais out (Relaisausgang)
  pinMode(Reserve_Relais_out, OUTPUT);    // PIN Reserve Relais out (Relaisausgang)
  pinMode(Reserve_out, OUTPUT);           // PIN Reserve out 
  digitalWrite(Spindel_out, HIGH);        // Spindel_out auf High
  digitalWrite(Reserve_Relais_out, HIGH); // Reserve_Relais auf High
  
  ESC.attach(ESC_out, 1000, 2000);  // Pin, minimale, maximale Pulsweite in Mikrosekunden
  attachInterrupt(digitalPinToInterrupt(Spindel_in), Motor, CHANGE);  // Motor Interrupt aktiviert
  attachInterrupt(digitalPinToInterrupt(Reserve_in), Reserve, CHANGE); // Reserve Interrupt aktiviert
  
  Serial.begin(115200);
  digitalWrite(TFT_BL, HIGH);
  tft.init(240, 320, SPI_MODE2);
  tft.setRotation(3);
  tft.fillScreen(BLACK);
  tft.setCursor(0, 0);
  tft.setTextSize(4);
  tft.setTextColor(RED);
  tft.println("Systemstart!");
  tft.println("");
  tft.println("");
  tft.setTextSize(3);
  tft.setTextColor(GREEN);
  tft.println("Steuerung wird");
  tft.println("aktiviert! ");
  tft.println("");
  tft.println("Bitte warten! ");
  delay(10000);
  tft.fillScreen(BLACK);
}


//Hauptschleife
void loop() {
  Status();
  Umdrehungen();
}

//UP Satus Eingänge
void Status() {
  if (digitalRead(Ena_in) == HIGH) {  //Status Eingang Enable
    Farbe = RED;
    Status_Stg = "Aus";
    Steuerung_ein();
  } else Status_Stg = "Ein";

  if (digitalRead(Es_X_in) == HIGH) {  //Status Eingang Endschalter X-
    Farbe = RED;
    Status_ES_X = "Fehler";
    Achse = "   X-Achse";
    Freifahren();
  } else Status_ES_X = "o.k.";

  if (digitalRead(Es_Y_in) == HIGH) {  //Status Eingang Endschalter Y-
    Farbe = RED;
    Status_ES_Y = "Fehler";
    Achse = "   Y-Achse";
    Freifahren();
  } else Status_ES_Y = "o.k";

  if (digitalRead(Es_Z_in) == HIGH) {  //Status Eingang Endschalter Z-
    Farbe = RED;
    Status_ES_Z = "Fehler";
    Achse = "   Z-Achse";
    Freifahren();
  } else Status_ES_Z = "o.k.";

  if (digitalRead(Taster_in) == LOW) {  //Status Eingang 3D Taster
    Farbe = RED;
    Status_3D = "Fehler";
    Achse = "   Taster";
    Freifahren();
  } else Status_3D = "o.k.";

  if (digitalRead(Wkz_in) == LOW) {  //Status Eingang Werkzeuglänge
    Farbe = RED;
    Status_Z_Laenge = "Fehler";
    Achse = "   Werkzeug";
    Freifahren();
  } else Status_Z_Laenge = "o.k.";

  if (digitalRead(Spindel_in) == HIGH) {  //Status Eingang Spindel
    Status_Spindel = "Aus";
  } else Status_Spindel = "Ein";

  tft.setCursor(0, 0);
  tft.setTextSize(3);
  tft.setTextColor(RED);
  tft.println("STATUS");
  tft.println("");
  tft.setTextSize(3);
  tft.setTextColor(BLUE);
  tft.print("Steuerung  ");
  tft.setTextColor(Farbe);
  tft.println(Status_Stg);
  tft.setTextColor(BLUE);
  tft.print("Endsch. X  ");
  tft.setTextColor(Farbe);
  tft.println(Status_ES_X);
  tft.setTextColor(BLUE);
  tft.print("Endsch. Y  ");
  tft.setTextColor(Farbe);
  tft.println(Status_ES_Y);
  tft.setTextColor(BLUE);
  tft.print("Endsch. Z  ");
  tft.setTextColor(Farbe);
  tft.println(Status_ES_Z);
  tft.setTextColor(BLUE);
  tft.print("3D-Taster  ");
  tft.setTextColor(Farbe);
  tft.println(Status_3D);
  tft.setTextColor(BLUE);
  tft.print("WKZ-Laenge ");
  tft.setTextColor(Farbe);
  tft.println(Status_Z_Laenge);
  tft.setTextColor(BLUE);
  tft.print("Spindel    ");
  tft.setTextColor(Farbe);
  tft.println(Status_Spindel);
  tft.setTextColor(BLUE);
  tft.print("Drehzahl   ");
  tft.setTextColor(Farbe);
  tft.println(DZ);
  delay(4000);
}

//UP Achsen freifahren
void Freifahren() {
  tft.fillScreen(BLACK);
  tft.setCursor(0, 0);
  tft.setTextSize(3);
  tft.println("");
  tft.setTextColor(BLUE);
  tft.println("     Aktion");
  tft.println("  erforderlich!");
  tft.println("");
  tft.setTextColor(RED);
  tft.println(Achse);
  tft.setTextColor(GREEN);
  tft.println("   freifahren");
  delay(2000);
  tft.fillScreen(BLACK);
}

//UP Aktion bei Steuerung aus
void Steuerung_ein() {
  tft.fillScreen(BLACK);
  tft.setCursor(0, 0);
  tft.setTextSize(3);
  tft.println("");
  tft.setTextColor(BLUE);
  tft.println("    Aktion");
  tft.println("  erforderlich!");
  tft.println("");
  tft.setTextColor(GREEN);
  tft.println("   Steuerung");
  tft.println("  einschalten!");
  delay(2000);
  tft.fillScreen(BLACK);
}

//ISR Motor an
void Motor() {
  if (digitalRead(Spindel_in) == LOW) {
    digitalWrite(Spindel_out, LOW);            // ESC 5V einschalten
    delayMicroseconds(3000);                   // Warten auf Fahrtenreglerbereitschaft
  }                      
  else {
    digitalWrite(Spindel_out, HIGH);           // ESC 5V ausschalten
  }
}

//ISR Reserve
void Reserve() {
  if (digitalRead(Reserve_in) == LOW) {
    digitalWrite(Reserve_Relais_out, LOW);            // Reserve Relais an
    digitalWrite(Reserve_out, LOW);                   // Reserve LOW
  }
  else {
    digitalWrite(Reserve_Relais_out, HIGH);           // Reserve Relais aus
    digitalWrite(Reserve_out, HIGH);                  // Reserve HIGH
  }
}

//Drehzahlreglung
void Umdrehungen() {
    Drehzahl = map(analogRead(Dz_in), 0, 1024, 0, 180);  // umwandeln 0 - 1V in 0 - 180 Grd.
    DZ = map(analogRead(Dz_in), 0, 1024, 0, 25000);      // umwandeln 0 - 1V in 0 - 25000 U/min
    ESC.write(Drehzahl);                                 // Erzeugung PWM
}

Bitte stellen Sie Ihre Frage auf Englisch im englischen Bereich des Forums.

Bitte posten Sie nicht in „Uncategorized“; lesen Sie bitte die Sticky Topics unter Uncategorized - Arduino Forum.

Thema in den deutschen Bereich verschoben.

Durchaus!
Siehe dazu das "Blink without delay" Beispiel.

Dazu:
Vermutlich möchtest du endliche Automaten bauen.

Moin @homerq ,

das delay(4000) kannst Du recht einfach loswerden. Lösche die Zeile "delay(4000);" und ersetzte sie durch eine Funktion, die "Status();" nur alle 4000 ms aufruft.

Das sähe z.B. so aus:

unsigned long lastStatusTime = 0;

//Hauptschleife
void loop() {
  if (millis()-lastStatusTime >= 4000 || lastStatusTime == 0){
    lastStatusTime = millis();
    Status();
  }
  Umdrehungen();
}

Ob das für den Rest verträglich ist, müsstest Du selbst ermitteln.

Generell wäre es vielleicht besser,

  • die Zustände der Eingänge regelmäßig und schnell zu ermitteln
  • die erneute Anzeige davon abhängig zu machen, ob sich an diesen Zuständen etwas geändert hat

es sei denn, dass bis zu vier Sekunden Verzug bei der Anzeige keine Rolle spielen ...

Gruß
ec2021

P.S.: Spielt die Verzögerung tatsächlich bei der Umsetzung auch keine Rolle????

Abgesehen davon wurde die TFT_eSPI für das Display nutzen, die ist sehr schnell wen es um Anzeige, du hast dir einer Art Menü gebaut das display wird neu gezeichnet mit

tft.fillScreen();

was dauert bei Adafruit um die 0.8s bei deinem 2,5" Display mit der Genannter bist in 150ms fertig mit kompletter anzeige = Schriftzug und Werte .

Werd ich

Was ist ein endlicher Automat?

An der Stelle soll die Anzeige 4s stehen bleiben.

Wie gesagt, ich bin Anfänger. Die Verzögerung ist für die Anzeige kein Problem weil gewollt, aber für das Aktualisieren der Drehzahl des BL Motors schon, der muß dann auf sein Signal warten.

Du meinst tft.println durch tft.fillScreen ersetzen? Ist war, der Aufbau der Anzeige ist ziemlich lahm, aber einfach Ersetzen geht doch bestimmt nicht so einfach.

Naja, so würde ich es schon beschreiben. Ich will hier keine Rakete bauen, nur ein einfache Anzeige und mit gleichzeitiger Motorsteuerung.

Danke für das Umsetzen in die richtige Kategorie, werd es beim nächsten mal berücksichtigen.

Nahezu alle Arduino Programme sind im Endeffekt endliche Automaten.
Egal ob der Autor das beabsichtigt hat, oder ob man das sofort erkennt.

Mehr als dir den Lösungsweg zeigen kann ich nicht.

Hab gerade nachgesehen. Ich Depp, du meintest sicherlich fillScreen() anstatt fillScreen(Black)?

Doch du nutzt ja nur Printausgaben, sonst keine Mimik, also nur kleine Änderungen,
Werde morgen was bauen für die Anzeige für den Abschnit

void Steuerung_ein() {
  tft.fillScreen(BLACK);
  tft.setCursor(0, 0);
  tft.setTextSize(3);
  tft.println("");
  tft.setTextColor(BLUE);
  tft.println("    Aktion");
  tft.println("  erforderlich!");
  tft.println("");
  tft.setTextColor(GREEN);
  tft.println("   Steuerung");
  tft.println("  einschalten!");
  delay(2000);
  tft.fillScreen(BLACK);
}

dann kannst schauen ob das machst oder nicht.
Die Änderungen in den Funktionen betreffen eigentlich nur die Farben und die Schrift, ist nicht soooo kompliziert :wink: ist dein Display wirklich 2.5" gib mall link.

1 Like

Das muss schnell gehen... Eben deshalb ist das Delay Dein "Feind".

Die von mir dargestellte Lösung ruft Status() nur alle 4 Sekunden auf. Der Unterschied zum vorherigen Sketch ist, dass Umdrehungen() in jedem Loop() Durchgang aufgerufen wird.

Und das bedeutet, dass auch alle Reaktionen auf die dort abgefragten Sensoren/Taster nur alle 4 Sekunden abgefragt und berücksichtigt werden...

Nun ja, bei meinem Wissenstand verkompliziert es die Sache eher mehr, hier jetzt hochprofessionell an die Sache heranzugehen. Ich habe schon einige kleinere Projekte mit der Programmierplattform Arduino erfolgreich (mit Hilfe) umgesetzt. Aber niemals um die beste Lösung gerungen. Hier im Forum sind die meisten Experten und können auf ein umfangreiches Wissen zurückgreifen. Ich bin bemüht den guten Tipps zu folgen und natürlich auch interessiert, die Hintergründe zu erfahren. Aber ich weiß jetzt schon, in 1 Jahr, wenn das nächste Projekt anstehen könnte schaue ich wieder im Arduinowiki nach und die Überprüfung un der IDE weist mich darauf hin, dass ich das ; vergessen habe. Man möge mir verzeihen! Trotzdem bin ich für jeden Rat dankbar

Ja, das habe ich verstanden

Das bedeutet die Anzeige bleibt 4s stehen weil der loop einfach weitergeht. Aber die Abfrage alle 4s ist dann wiederum ein Problem.

Anders wiederum wird momentan ja auch 4s Pause gemacht. Ich sollte meine Struktur nochma überdenken.

Exakt.

Alles in der Funktion Umdrehungen() wird jetzt sehr häufig aufgerufen.

Die Aufrufe in Status() (wie im übrigen auch vorher!) nur alle vier Sekunden.

Daher meine Frage von oben...

Wenn Du das ändern willst, muss man die Datenerfassung und die Ausgabe trennen. Bei Änderung eines oder mehrerer Werte wird die Steuerung aufgerufen und die Anzeige erneuert ...

Nein, 2,4".
" 2,4 Zoll tft spi 65k Display 240*320 Smart Display 8p Laufwerk ic st7789 Laufwerk ic Modul"
link trau ich mir nicht.
aus China