Brauche Hilfe bei meinem Programm zur Vorschubsteuerung

Das mit dem selbst programmieren war ja leider nichts! :slight_smile:
Ich schaue mir mal das Beispiel bei MobaTools an.

Wie setzt man denn sowas um, hast du dazu zufällig ein Beispiel?

Danke und Grüße
Dan

Erstmal habe ich printDisplay() mit Hilfe von snprintf() reduziert. Leider ist die Verarbeitung von Fließkommazahlen bei kleinen Arduinos weggelassen, weshalb die Unterteilung in vor und nach dem Komma bestehen bleiben muß. Du kannst diese Änderung für Dich übernehmen.

Eine Aktualisierung der Anzeige erfolgt, wenn der Merker anzeigeMerker true und eine Wartezeit, hier 100 ms, abgelaufen ist.

Nö, aber habe eins gemacht. Dabei verwende ich einen globalen Merker.

Die Anzeige wird nur aktualisiert, wenn der Taster gedrückt wird. Dieses Beispiel ist bewußt simpel, damit Du es leicht übernehmen kannst.

#include <U8g2lib.h>
#include <Wire.h>

U8G2_SH1106_128X64_NONAME_1_HW_I2C OLED(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

bool anzeigeMerker = true;                          // für die erste Anzeige true
const byte tasterPin = 8;                           // Anzeige nur bei gedrücktem Taster
unsigned long currentSpeedA = 0;                    // Current speed in rpm.
unsigned long currentSpeedXYZ = 0;                  // Current speed in mm/min.

void setup() {
  pinMode(tasterPin, INPUT_PULLUP);
  OLED.begin();                                     // Init the OLED.
}

void loop() 
{
  if(!digitalRead(tasterPin)) anzeigeMerker = true;
  currentSpeedA = 123;
  currentSpeedXYZ = millis() / 10;
  printDisplay();
}

void printDisplay()
{
  uint32_t jetzt = millis();
  static uint32_t vorhin = jetzt;
  const uint32_t intervall = 100;
  if ((jetzt - vorhin >= intervall) && anzeigeMerker) {
    anzeigeMerker = false;
    vorhin = jetzt;
    char buf [7];
    OLED.setFont(u8g2_font_profont22_mr);
    OLED.firstPage();
    do {
      snprintf(buf, sizeof(buf), "%4lu.%lu", currentSpeedXYZ / 10, currentSpeedXYZ % 10);
      OLED.setCursor(3, 18);
      OLED.print("XYZ");
      OLED.setCursor(46, 18);
      OLED.print(buf);
      snprintf(buf, sizeof(buf), "%4lu.%lu", currentSpeedA / 10, currentSpeedA % 10);
      OLED.setCursor(3, 48);
      OLED.print("A");
      OLED.setCursor(46, 48);
      OLED.print(buf);
      OLED.drawFrame(0, 0, 128, 20);
      OLED.drawLine(39, 0, 39, 19);
      OLED.drawFrame(0, 30, 128, 20);
      OLED.drawLine(39, 30, 39, 49);
    } while ( OLED.nextPage() );
  }
}

Den Überlauf nach 99999 ms habe ich nicht berücksichtigt!

Hallo agmue,

vielen Dank für das Beispiel!
Die Funktion snprintf() war mir noch nicht bekannt.
Dann werde ich mal versuchen das auf mein Programm zu übertragen.

Warum muss die Variablendeklaration mit uint32_t ausgeführt werden, ist da ein Unterschied zu unsigned int?

Warum muss das innerhalb des if-Statements stehen?

Viele Grüße
Dan

Müssen mußt Du nicht, aber ich tue es.

In C++ oder der Arduino-IDE, das weiß ich nicht so genau, gibt es verwirrend viele Möglichkeiten, Variablentypen festzulegen. Ich springe zwischen verschiedenen µCs hin und her, da kann man leicht durcheinenderkommen. Mal ein Beispiel:

  • UNO: Typ int hat 16 Bit.
  • ESP32: Typ int hat 32 Bit.

Daher habe ich mir die Schreibweise int16_t, uint16_t, int32_t oder uint32_t angewöhnt, die hat die Anzahl der Bits ja explizit im Namen. Sie ist wohl nicht universell gebräuchlich, hat in der Arduino-IDE bislang bei mir aber immer funktioniert.

Möchtest Du eine Typprüfung, ist diese Schreibweise besser:

  uint32_t jetzt {millis()};
  static uint32_t vorhin {jetzt};
  const uint32_t intervall {100};

Müssen muß das nicht, aber ich möchte eine lokale Variable, die nur innerhalb der Funktion gültig ist und am Ende der Funktion wird der Speicher wieder freigegeben.

Deine Timer variables könnten lokal festgelegt werden, da sie nur innerhalb einer Funktion verwendet werden. Global mußt Du einen spezifischen Namen wie previousMillisRapidButtonA verwenden, lokal würde previousMillis genügen.

Grundsätzlich versucht man, globale Variablen auf ein notwendiges Minimum zu beschränken. Je größer ein Programm wird, desto wichtiger ist ein durchdachtes, auf Dich zugeschnittenes Programmdesign. Ich gebe nur Hinweise oder begründe meine Sichtweise.

Danke für die ausführliche Erklärung, hab schon wieder was dazugelernt! :slight_smile:

Das sich die Variable innerhalb der Funktion befinden soll kann ich nachvollziehen.
Ich habe mich nur gefragt ob es einen Grund gibt warum sie innerhalb der if-Bedingung steht und nicht zum Beispiel unter const uint32_t intervall = 100; und damit noch vor der if-Bedingung.

Viele Grüße
Dan

Dann wird sie nur angelegt, wenn sie auch benötigt wird.

Super danke, jetzt hab ich's verstanden! :slight_smile:

Hallo agmue,

ich habe mein Programm nun nochmals umgeschrieben und auch die while-Schleifen entfernt.
Es bleibt aber immer noch hängen, wenn man die Taster oft und lange betätigt.
Und wenn man beide Eilgangtaster betätigt bleibt das Programm immer noch hängen. :roll_eyes:

Das mit dem Aktualisieren des Displays (alle 100ms) habe ich noch nicht hinbekommen, deshalb ist es auskommentiert.
Ich habe es ein wenig anders gelöst als in deinem Beispiel, kannst du mir vielleicht trotzdem helfen und mal drüber schauen warum das nicht funktioniert?

Danke und Grüße
Dan

/*
  Manual Mill Controller v1.0
  written by Iron-Dan
  Creates stepper pulses to set speeds in mm/min and rpm and included rapid traverse mode.
  Implemented with the usage of the libraries which are included below.
*/

/*
  Universal 8bit Graphics Library (https://github.com/olikraus/OLED/)

  Copyright (c) 2016, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification,
  are permitted provided that the following conditions are met:

    Redistributions of source code must retain the above copyright notice, this list
    of conditions and the following disclaimer.

    Redistributions in binary form must reproduce the above copyright notice, this
    list of conditions and the following disclaimer in the documentation and/or other
    materials provided with the distribution.
*/

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

// Please UNCOMMENT one of the contructor lines below
// OLED Contructor List (Picture Loop Page Buffer)
// The complete list is available here: https://github.com/olikraus/OLED/wiki/OLEDsetupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected

U8G2_SH1106_128X64_NONAME_1_HW_I2C OLED(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

#include <Tone.h>

// Variables

bool stateDisplay = true;                           // Init with true for first display after startup.

const byte minusButtonA = 8;                        // Minus Button for speed value on A-Axis at Arduino Pin 10.
const byte plusButtonA = 7;                         // Plus Button for speed value on A-Axis at Arduino Pin 9.
bool stateMinusButtonA = false;                     // State of minusButtonA -> If button is pressed stateMinusButtonA = true.
bool statePlusButtonA = false;                      // State of plusButtonA -> If button is pressed statePlusButtonA = true.
const byte rapidButtonA = 2;                        // Button for rapid traverse mode on A-Axis at Arduino Pin 2.
const byte rapidLEDA = 11;                          // LED for indication of rapid traverse mode on A-Axis at Arduino Pin 11.
bool stateRapidModeA = false;                       // State of rapid traverse mode on A-Axis.
const unsigned long maxSpeedA = 136;                // Max. speed / 10 = speed in rpm. 136 = 65280Hz -> max. 65535Hz!
unsigned long currentSpeedA = 0;                    // Current speed in rpm.
unsigned long oldSpeedA = 0;                        // Old speed in rpm.

const byte minusButtonXYZ = 10;                     // Minus Button for speed value on XYZ-Axis at Arduino Pin 8.
const byte plusButtonXYZ = 9;                       // Plus Button for speed value on XYZ-Axis at Arduino Pin 7.
bool stateMinusButtonXYZ = false;                   // State of minusButtonXYZ -> If button is pressed stateMinusButtonXYZ = true.
bool statePlusButtonXYZ = false;                    // State of plusButtonXYZ -> If button is pressed statePlusButtonXYZ = true.
const byte rapidButtonXYZ = 3;                      // Button for rapid traverse mode on XYZ-Axis at Arduino Pin 3.
const byte rapidLEDXYZ = 12;                        // LED for indication of rapid traverse mode on XYZ-Axis at Arduino Pin 12.
bool stateRapidModeXYZ = false;                     // State of rapid traverse mode on XYZ-Axis.
const unsigned long maxSpeedXYZ = 20000;            // Max. speed / 10 = speed in mm/min.
unsigned long currentSpeedXYZ = 0;                  // Current speed in mm/min.
unsigned long oldSpeedXYZ = 0;                      // Old speed in mm/min.

// Timer variables

unsigned long previousMillisRapidButtonA = 0;       // Time value in ms when rapidButtonA was pressed last time.
unsigned long currentMillisRapidButtonA;            // New time value in ms when rapidButtonA was pressed.
unsigned long previousMillisMinusButtonA = 0;       // Store time in ms as MinusButtonA was clicked first time.
unsigned long currentMillisMinusButtonA = 0;        // Store time value as long as MinusButtonA is held.
unsigned long previousMillisPlusButtonA = 0;        // Store time in ms as PlusButtonA was clicked first time.
unsigned long currentMillisPlusButtonA = 0;         // Store time value as long as PlusButtonA is held.

unsigned long previousMillisRapidButtonXYZ = 0;     // Time value in ms when rapidButtonXYZ was pressed last time.
unsigned long currentMillisRapidButtonXYZ;          // New time value in ms when rapidButtonXYZ was pressed.
unsigned long previousMillisMinusButtonXYZ = 0;     // Store time in ms as MinusButtonXYZ was clicked first time.
unsigned long currentMillisMinusButtonXYZ = 0;      // Store time value as long as MinusButtonXYZ is held.
unsigned long previousMillisPlusButtonXYZ = 0;      // Store time in ms as PlusButtonXYZ was clicked first time.
unsigned long currentMillisPlusButtonXYZ = 0;       // Store time value as long as PlusButtonXYZ is held.

// Stepper variables

unsigned int microStepsA = 16;
unsigned int motorStepsA = 200;
unsigned int turnsPerRoundA = 90;
unsigned int microStepsXYZ = 16;
unsigned int motorStepsXYZ = 200;
unsigned int mmPerRoundXYZ = 5;
unsigned int frequencyA = 0;
unsigned int frequencyXYZ = 0;

Tone pulseA;                                        // Create Tone object pulseA.
Tone pulseXYZ;                                      // Create Tone object pulseXYZ.

// Setup

void setup() {
  pinMode(minusButtonA, INPUT_PULLUP);
  pinMode(plusButtonA, INPUT_PULLUP);
  pinMode(rapidButtonA, INPUT_PULLUP);
  pinMode(minusButtonXYZ, INPUT_PULLUP);
  pinMode(plusButtonXYZ, INPUT_PULLUP);
  pinMode(rapidButtonXYZ, INPUT_PULLUP);
  pinMode(rapidLEDA, OUTPUT);
  pinMode(rapidLEDXYZ, OUTPUT);

  pulseA.begin(5);                                  // Init stepper pulses for A-Axis at Arduino Pin 5.
  pulseXYZ.begin(6);                                // Init stepper pulses for XYZ-Axis at Arduino Pin 6.

  OLED.begin();                                     // Init the OLED.

  bootScreen();                                     // Show Boot Screen


}

void loop() {

  readRapidButtonA();
  readRapidButtonXYZ();
  readMinusButtonA();
  readPlusButtonA();
  readMinusButtonXYZ();
  readPlusButtonXYZ();

  printDisplay();

}

void bootScreen()
{
  OLED.firstPage();
  do {
    OLED.setFont(u8g2_font_profont22_tf);
    OLED.drawStr(0, 14, "MANUAL");
    OLED.drawStr(0, 29, "MILL");
    OLED.drawStr(0, 44, "CONTROLLER");
    OLED.setFont(u8g2_font_profont11_tf);
    OLED.drawStr(0, 54, "v1.0");
    OLED.drawStr(0, 64, "BY IRON-DAN");
  } while (OLED.nextPage());
  delay(4000);
}

void printDisplay()
{
  unsigned long speedA;
  unsigned long speedXYZ;
  unsigned long newTime;
  unsigned long oldTime;
  unsigned int intervalTime = 100;
  bool displayMarker = false;

  if (stateRapidModeA)
  {
    speedA = maxSpeedA;
  }
  else
  {
    speedA = currentSpeedA;
  }

  if (stateRapidModeXYZ)
  {
    speedXYZ = maxSpeedXYZ;
  }
  else
  {
    speedXYZ = currentSpeedXYZ;
  }

  if (stateDisplay && !displayMarker)
  {
    displayMarker = true;
    newTime = millis();
    oldTime = newTime;
  }

  if (stateDisplay && displayMarker)
  {
    newTime = millis();

    //if (newTime - oldTime >= intervalTime)
    //{
      stateDisplay = false;
      displayMarker = false;      
      char buf[7];

      OLED.setFont(u8g2_font_profont22_tf);
      OLED.firstPage();
      do {
        snprintf(buf, sizeof(buf), "%4lu.%lu", speedXYZ / 10, speedXYZ % 10);
        OLED.setCursor(3, 18);
        OLED.print("XYZ");
        OLED.setCursor(46, 18);
        OLED.print(buf);
        snprintf(buf, sizeof(buf), "%4lu.%lu", speedA / 10, speedA % 10);
        OLED.setCursor(3, 48);
        OLED.print("A");
        OLED.setCursor(46, 48);
        OLED.print(buf);
        OLED.drawFrame(0, 0, 128, 20);
        OLED.drawLine(39, 0, 39, 19);
        OLED.drawBox(96, 15, 2, 2);
        OLED.drawFrame(0, 30, 128, 20);
        OLED.drawLine(39, 30, 39, 49);
        OLED.drawBox(96, 45, 2, 2);
      } while (OLED.nextPage());
    //}
  }
}

void readRapidButtonA()
{
  if (!digitalRead(rapidButtonA))
  {
    currentMillisRapidButtonA = millis();
    if (currentMillisRapidButtonA - previousMillisRapidButtonA > 150)             // Push button debouncing.
    {
      stateRapidModeA = !stateRapidModeA;             // Toggle stateRapidModeA when rapidButtonA was pressed.
      if (stateRapidModeA)
      {
        digitalWrite(rapidLEDA, HIGH);
        //oldSpeedA = currentSpeedA;                  // Store previous speed for A-Axis.
        //currentSpeedA = maxSpeedA;                  // Set max speed for A-Axis.
        stateDisplay = true;
        setSpeedA();
      }
      else
      {
        digitalWrite(rapidLEDA, LOW);
        //currentSpeedA = oldSpeedA;                  // Restore speed value before rapid traverse mode was entered.
        stateDisplay = true;
        setSpeedA();
      }
    }
    previousMillisRapidButtonA = currentMillisRapidButtonA;
  }
}

void readRapidButtonXYZ()
{
  if (!digitalRead(rapidButtonXYZ))
  {
    currentMillisRapidButtonXYZ = millis();
    if (currentMillisRapidButtonXYZ - previousMillisRapidButtonXYZ > 150)         // Push button debouncing.
    {
      stateRapidModeXYZ = !stateRapidModeXYZ;         // Toggle stateRapidModeXYZ when rapidButtonXYZ was pressed.
      if (stateRapidModeXYZ)
      {
        digitalWrite(rapidLEDXYZ, HIGH);
        //oldSpeedXYZ = currentSpeedXYZ;              // Store previous speed for XYZ-Axis.
        //currentSpeedXYZ = maxSpeedXYZ;              // Set max speed for XYZ-Axis.
        stateDisplay = true;
        setSpeedXYZ();
      }
      else
      {
        digitalWrite(rapidLEDXYZ, LOW);
        //currentSpeedXYZ = oldSpeedXYZ;              // Restore speed value before rapid traverse mode was entered.
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    previousMillisRapidButtonXYZ = currentMillisRapidButtonXYZ;
  }
}

void readMinusButtonA()
{
  if (!digitalRead(minusButtonA) && !stateMinusButtonA)
  {
    stateMinusButtonA = true;
    currentMillisMinusButtonA = millis();                       // Store first time value when minusButtonA was pressed.
    previousMillisMinusButtonA = currentMillisMinusButtonA;
  }
  if (!digitalRead(minusButtonA) && stateMinusButtonA)          // Start counting as long as minusButtonA is held.
  {
    currentMillisMinusButtonA = millis();                       // Update time value as long as minusButtonA is held.

    if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 50) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 1000))
    {
      if (currentSpeedA >= 1)
      {
        currentSpeedA -= 1;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 1000) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 4000))
    {
      if (currentSpeedA >= 2)
      {
        currentSpeedA -= 2;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 4000) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 7000))
    {
      if (currentSpeedA >= 5)
      {
        currentSpeedA -= 5;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisMinusButtonA - previousMillisMinusButtonA > 7000)
    {
      if (currentSpeedA >= 10)
      {
        currentSpeedA -= 10;
        stateDisplay = true;
        setSpeedA();
      }
    }
  }
  else if (digitalRead(minusButtonA) && stateMinusButtonA)      // Stop counting when minusButtonA is released.
  {
    stateMinusButtonA = false;
  }
}

void readPlusButtonA()
{
  if (!digitalRead(plusButtonA) && !statePlusButtonA)
  {
    statePlusButtonA = true;
    currentMillisPlusButtonA = millis();                        // Store first time value when plusButtonA was pressed.
    previousMillisPlusButtonA = currentMillisPlusButtonA;
  }
  if (!digitalRead(plusButtonA) && statePlusButtonA)            // Start counting as long as plusButtonA is held.
  {
    currentMillisPlusButtonA = millis();                        // Update time value as long as plusButtonA is held.

    if (currentMillisPlusButtonA - previousMillisPlusButtonA > 50 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 1000)
    {
      if (currentSpeedA <= (maxSpeedA - 1))
      {
        currentSpeedA += 1;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 1000 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 4000)
    {
      if (currentSpeedA <= (maxSpeedA - 2))
      {
        currentSpeedA += 2;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 4000 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 7000)
    {
      if (currentSpeedA <= (maxSpeedA - 5))
      {
        currentSpeedA += 5;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 7000)
    {
      if (currentSpeedA <= (maxSpeedA - 10))
      {
        currentSpeedA += 10;
        stateDisplay = true;
        setSpeedA();
      }
    }
  }
  else if (digitalRead(plusButtonA) && statePlusButtonA)        // Stop counting when plusButtonA is released.
  {
    statePlusButtonA = false;
  }
}

void readMinusButtonXYZ()
{
  if (!digitalRead(minusButtonXYZ) && !stateMinusButtonXYZ)
  {
    stateMinusButtonXYZ = true;
    currentMillisMinusButtonXYZ = millis();                     // Store time value when minusButtonXYZ was pressed.
    previousMillisMinusButtonXYZ = currentMillisMinusButtonXYZ;
  }
  if (!digitalRead(minusButtonXYZ) && stateMinusButtonXYZ)      // Start counting as long as minusButtonXYZ is held.
  {
    currentMillisMinusButtonXYZ = millis();                     // Update time value as long as minusButtonXYZ is held.

    if ((currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 50) && (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 1000))
    {
      if (currentSpeedXYZ >= 1)
      {
        currentSpeedXYZ -= 1;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if ((currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 1000) && (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 4000))
    {
      if (currentSpeedXYZ >= 5)
      {
        currentSpeedXYZ -= 5;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 4000 && currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 7000)
    {
      if (currentSpeedXYZ >= 10)
      {
        currentSpeedXYZ -= 10;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 7000 && currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 10000)
    {
      if (currentSpeedXYZ >= 100)
      {
        currentSpeedXYZ -= 100;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 10000)
    {
      if (currentSpeedXYZ >= 1000)
      {
        currentSpeedXYZ -= 1000;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
  }
  else if (digitalRead(minusButtonXYZ) && stateMinusButtonXYZ)  // Stop counting when minusButtonXYZ is released.
  {
    stateMinusButtonXYZ = false;
  }
}

void readPlusButtonXYZ()
{
  if (!digitalRead(plusButtonXYZ) && !statePlusButtonXYZ)
  {
    statePlusButtonXYZ = true;
    currentMillisPlusButtonXYZ = millis();                      // Store time value when PlusButtonXYZ was clicked.
    previousMillisPlusButtonXYZ = currentMillisPlusButtonXYZ;
  }
  if (!digitalRead(plusButtonXYZ) && statePlusButtonXYZ)        // Start counting as long as plusButtonXYZ is held.
  {
    currentMillisPlusButtonXYZ = millis();                      // Update time value as long as PlusButtonXYZ is held.

    if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 50 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 1000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 1))
      {
        currentSpeedXYZ += 1;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 1000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 4000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 5))
      {
        currentSpeedXYZ += 5;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 4000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 7000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 10))
      {
        currentSpeedXYZ += 10;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 7000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 10000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 100))
      {
        currentSpeedXYZ += 100;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 10000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 1000))
      {
        currentSpeedXYZ += 1000;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
  }
  else if (digitalRead(plusButtonXYZ) && statePlusButtonXYZ)    // Stop counting when plusButtonXYZ is released.
  {
    statePlusButtonXYZ = false;
  }
}

void setSpeedA()
{
  if (stateRapidModeA)
  {
    frequencyA = (maxSpeedA * microStepsA * motorStepsA * turnsPerRoundA) / (60 * 10);
    pulseA.play(frequencyA);
  }
  else
  {
    if (currentSpeedA >= 1)
    {
      frequencyA = (currentSpeedA * microStepsA * motorStepsA * turnsPerRoundA) / (60 * 10);
      pulseA.play(frequencyA);
    }
    else
    {
      pulseA.stop();
    }
  }
}

void setSpeedXYZ()
{
  if (stateRapidModeXYZ)
  {
    frequencyXYZ = (maxSpeedXYZ * microStepsXYZ * motorStepsXYZ) / (60 * mmPerRoundXYZ * 10);
    pulseXYZ.play(frequencyXYZ);
  }
  else
  {
    if (currentSpeedXYZ >= 10)
    {
      frequencyXYZ = (currentSpeedXYZ * microStepsXYZ * motorStepsXYZ) / (60 * mmPerRoundXYZ * 10);
      pulseXYZ.play(frequencyXYZ);
    }
    else
    {
      pulseXYZ.stop();
    }
  }
}

Da ich ein eigenes Projekt abschließen möchte, schaue ich derzeit nur sporadisch ins Forum.

Meine Änderungen:

  • Einige globale Variablen habe ich lokalisiert.
  • printDisplay() auf Anzeige maximal alle 100 ms umgestellt.
  • readRapidButtonA() Entprellen verbessert.
#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SH1106_128X64_NONAME_1_HW_I2C OLED(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

#include <Tone.h>

// Variables

bool stateDisplay = true;                           // Init with true for first display after startup.

const byte minusButtonA = 8;                        // Minus Button for speed value on A-Axis at Arduino Pin 10.
const byte plusButtonA = 7;                         // Plus Button for speed value on A-Axis at Arduino Pin 9.
bool stateMinusButtonA = false;                     // State of minusButtonA -> If button is pressed stateMinusButtonA = true.
bool statePlusButtonA = false;                      // State of plusButtonA -> If button is pressed statePlusButtonA = true.
const byte rapidButtonA = 2;                        // Button for rapid traverse mode on A-Axis at Arduino Pin 2.
const byte rapidLEDA = 11;                          // LED for indication of rapid traverse mode on A-Axis at Arduino Pin 11.
bool stateRapidModeA = false;                       // State of rapid traverse mode on A-Axis.
const unsigned long maxSpeedA = 136;                // Max. speed / 10 = speed in rpm. 136 = 65280Hz -> max. 65535Hz!
unsigned long currentSpeedA = 0;                    // Current speed in rpm.
unsigned long oldSpeedA = 0;                        // Old speed in rpm.

const byte minusButtonXYZ = 10;                     // Minus Button for speed value on XYZ-Axis at Arduino Pin 8.
const byte plusButtonXYZ = 9;                       // Plus Button for speed value on XYZ-Axis at Arduino Pin 7.
bool stateMinusButtonXYZ = false;                   // State of minusButtonXYZ -> If button is pressed stateMinusButtonXYZ = true.
bool statePlusButtonXYZ = false;                    // State of plusButtonXYZ -> If button is pressed statePlusButtonXYZ = true.
const byte rapidButtonXYZ = 3;                      // Button for rapid traverse mode on XYZ-Axis at Arduino Pin 3.
const byte rapidLEDXYZ = 12;                        // LED for indication of rapid traverse mode on XYZ-Axis at Arduino Pin 12.
bool stateRapidModeXYZ = false;                     // State of rapid traverse mode on XYZ-Axis.
const unsigned long maxSpeedXYZ = 20000;            // Max. speed / 10 = speed in mm/min.
unsigned long currentSpeedXYZ = 0;                  // Current speed in mm/min.
unsigned long oldSpeedXYZ = 0;                      // Old speed in mm/min.

// Timer variables

unsigned long previousMillisMinusButtonA = 0;       // Store time in ms as MinusButtonA was clicked first time.
unsigned long currentMillisMinusButtonA = 0;        // Store time value as long as MinusButtonA is held.
unsigned long previousMillisPlusButtonA = 0;        // Store time in ms as PlusButtonA was clicked first time.
unsigned long currentMillisPlusButtonA = 0;         // Store time value as long as PlusButtonA is held.

unsigned long previousMillisRapidButtonXYZ = 0;     // Time value in ms when rapidButtonXYZ was pressed last time.
unsigned long currentMillisRapidButtonXYZ;          // New time value in ms when rapidButtonXYZ was pressed.
unsigned long previousMillisMinusButtonXYZ = 0;     // Store time in ms as MinusButtonXYZ was clicked first time.
unsigned long currentMillisMinusButtonXYZ = 0;      // Store time value as long as MinusButtonXYZ is held.
unsigned long previousMillisPlusButtonXYZ = 0;      // Store time in ms as PlusButtonXYZ was clicked first time.
unsigned long currentMillisPlusButtonXYZ = 0;       // Store time value as long as PlusButtonXYZ is held.

// Stepper variables

unsigned int microStepsA = 16;
unsigned int motorStepsA = 200;
unsigned int turnsPerRoundA = 90;
unsigned int microStepsXYZ = 16;
unsigned int motorStepsXYZ = 200;
unsigned int mmPerRoundXYZ = 5;
unsigned int frequencyA = 0;
unsigned int frequencyXYZ = 0;

Tone pulseA;                                        // Create Tone object pulseA.
Tone pulseXYZ;                                      // Create Tone object pulseXYZ.

// Setup

void setup() {
  pinMode(minusButtonA, INPUT_PULLUP);
  pinMode(plusButtonA, INPUT_PULLUP);
  pinMode(rapidButtonA, INPUT_PULLUP);
  pinMode(minusButtonXYZ, INPUT_PULLUP);
  pinMode(plusButtonXYZ, INPUT_PULLUP);
  pinMode(rapidButtonXYZ, INPUT_PULLUP);
  pinMode(rapidLEDA, OUTPUT);
  pinMode(rapidLEDXYZ, OUTPUT);

  pulseA.begin(5);                                  // Init stepper pulses for A-Axis at Arduino Pin 5.
  pulseXYZ.begin(6);                                // Init stepper pulses for XYZ-Axis at Arduino Pin 6.

  OLED.begin();                                     // Init the OLED.

  bootScreen();                                     // Show Boot Screen
}

void loop() {
  readRapidButtonA();
  readRapidButtonXYZ();
  readMinusButtonA();
  readPlusButtonA();
  readMinusButtonXYZ();
  readPlusButtonXYZ();

  printDisplay();
}

void bootScreen()
{
  OLED.firstPage();
  do {
    OLED.setFont(u8g2_font_profont22_tf);
    OLED.drawStr(0, 14, "MANUAL");
    OLED.drawStr(0, 29, "MILL");
    OLED.drawStr(0, 44, "CONTROLLER");
    OLED.setFont(u8g2_font_profont11_tf);
    OLED.drawStr(0, 54, "v1.0");
    OLED.drawStr(0, 64, "BY IRON-DAN");
  } while (OLED.nextPage());
  delay(400);
}

void printDisplay()
{
  unsigned long newTime = millis();
  static unsigned long oldTime;
  const unsigned int intervalTime = 100;

  if (stateDisplay)
  {
    if (newTime - oldTime >= intervalTime)
    {
      oldTime = newTime;
      stateDisplay = false;
      char buf[7];

      OLED.setFont(u8g2_font_profont22_tf);
      OLED.firstPage();
      do {
        snprintf(buf, sizeof(buf), "%4lu.%lu", currentSpeedXYZ / 10, currentSpeedXYZ % 10);
        OLED.setCursor(3, 18);
        OLED.print("XYZ");
        OLED.setCursor(46, 18);
        OLED.print(buf);
        snprintf(buf, sizeof(buf), "%4lu.%lu", currentSpeedA / 10, currentSpeedA % 10);
        OLED.setCursor(3, 48);
        OLED.print("A");
        OLED.setCursor(46, 48);
        OLED.print(buf);
        OLED.drawFrame(0, 0, 128, 20);
        OLED.drawLine(39, 0, 39, 19);
        OLED.drawFrame(0, 30, 128, 20);
        OLED.drawLine(39, 30, 39, 49);
      } while (OLED.nextPage());
    }
  }
}

void readRapidButtonA()
{
  unsigned long currentMillis = millis();                                         // New time value in ms when rapidButtonA was pressed.
  static unsigned long previousMillis = 0;                                        // Time value in ms when rapidButtonA was pressed last time.
  bool newStateButton = !digitalRead(rapidButtonA);                               // new state of rapidButtonA -> If button is pressed newStateButton = true.
  static bool oldStateButton = newStateButton;                                    // old state of rapidButtonA

  if ( (currentMillis - previousMillis > 150) & (oldStateButton != newStateButton) )           // Push button debouncing.
  {
    previousMillis = currentMillis;
    oldStateButton = newStateButton;
    if (newStateButton)                               // Taste gedrückt
    {
      stateRapidModeA = !stateRapidModeA;             // Toggle stateRapidModeA when rapidButtonA was pressed.
      if (stateRapidModeA)
      {
        digitalWrite(rapidLEDA, HIGH);
        oldSpeedA = currentSpeedA;                    // Store previous speed for A-Axis.
        currentSpeedA = maxSpeedA;                    // Set max speed for A-Axis.
      }
      else
      {
        digitalWrite(rapidLEDA, LOW);
        currentSpeedA = oldSpeedA;                    // Restore speed value before rapid traverse mode was entered.
      }
      stateDisplay = true;
      setSpeedA();
    }
  }
}

void readRapidButtonXYZ()
{
  if (!digitalRead(rapidButtonXYZ))
  {
    currentMillisRapidButtonXYZ = millis();
    if (currentMillisRapidButtonXYZ - previousMillisRapidButtonXYZ > 150)         // Push button debouncing.
    {
      stateRapidModeXYZ = !stateRapidModeXYZ;         // Toggle stateRapidModeXYZ when rapidButtonXYZ was pressed.
      if (stateRapidModeXYZ)
      {
        digitalWrite(rapidLEDXYZ, HIGH);
        //oldSpeedXYZ = currentSpeedXYZ;              // Store previous speed for XYZ-Axis.
        //currentSpeedXYZ = maxSpeedXYZ;              // Set max speed for XYZ-Axis.
        stateDisplay = true;
        setSpeedXYZ();
      }
      else
      {
        digitalWrite(rapidLEDXYZ, LOW);
        //currentSpeedXYZ = oldSpeedXYZ;              // Restore speed value before rapid traverse mode was entered.
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    previousMillisRapidButtonXYZ = currentMillisRapidButtonXYZ;
  }
}

void readMinusButtonA()
{
  if (!digitalRead(minusButtonA) && !stateMinusButtonA)
  {
    stateMinusButtonA = true;
    currentMillisMinusButtonA = millis();                       // Store first time value when minusButtonA was pressed.
    previousMillisMinusButtonA = currentMillisMinusButtonA;
  }
  if (!digitalRead(minusButtonA) && stateMinusButtonA)          // Start counting as long as minusButtonA is held.
  {
    currentMillisMinusButtonA = millis();                       // Update time value as long as minusButtonA is held.

    if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 50) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 1000))
    {
      if (currentSpeedA >= 1)
      {
        currentSpeedA -= 1;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 1000) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 4000))
    {
      if (currentSpeedA >= 2)
      {
        currentSpeedA -= 2;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 4000) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 7000))
    {
      if (currentSpeedA >= 5)
      {
        currentSpeedA -= 5;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisMinusButtonA - previousMillisMinusButtonA > 7000)
    {
      if (currentSpeedA >= 10)
      {
        currentSpeedA -= 10;
        stateDisplay = true;
        setSpeedA();
      }
    }
  }
  else if (digitalRead(minusButtonA) && stateMinusButtonA)      // Stop counting when minusButtonA is released.
  {
    stateMinusButtonA = false;
  }
}

void readPlusButtonA()
{
  if (!digitalRead(plusButtonA) && !statePlusButtonA)
  {
    statePlusButtonA = true;
    currentMillisPlusButtonA = millis();                        // Store first time value when plusButtonA was pressed.
    previousMillisPlusButtonA = currentMillisPlusButtonA;
  }
  if (!digitalRead(plusButtonA) && statePlusButtonA)            // Start counting as long as plusButtonA is held.
  {
    currentMillisPlusButtonA = millis();                        // Update time value as long as plusButtonA is held.

    if (currentMillisPlusButtonA - previousMillisPlusButtonA > 50 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 1000)
    {
      if (currentSpeedA <= (maxSpeedA - 1))
      {
        currentSpeedA += 1;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 1000 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 4000)
    {
      if (currentSpeedA <= (maxSpeedA - 2))
      {
        currentSpeedA += 2;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 4000 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 7000)
    {
      if (currentSpeedA <= (maxSpeedA - 5))
      {
        currentSpeedA += 5;
        stateDisplay = true;
        setSpeedA();
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 7000)
    {
      if (currentSpeedA <= (maxSpeedA - 10))
      {
        currentSpeedA += 10;
        stateDisplay = true;
        setSpeedA();
      }
    }
  }
  else if (digitalRead(plusButtonA) && statePlusButtonA)        // Stop counting when plusButtonA is released.
  {
    statePlusButtonA = false;
  }
}

void readMinusButtonXYZ()
{
  if (!digitalRead(minusButtonXYZ) && !stateMinusButtonXYZ)
  {
    stateMinusButtonXYZ = true;
    currentMillisMinusButtonXYZ = millis();                     // Store time value when minusButtonXYZ was pressed.
    previousMillisMinusButtonXYZ = currentMillisMinusButtonXYZ;
  }
  if (!digitalRead(minusButtonXYZ) && stateMinusButtonXYZ)      // Start counting as long as minusButtonXYZ is held.
  {
    currentMillisMinusButtonXYZ = millis();                     // Update time value as long as minusButtonXYZ is held.

    if ((currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 50) && (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 1000))
    {
      if (currentSpeedXYZ >= 1)
      {
        currentSpeedXYZ -= 1;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if ((currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 1000) && (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 4000))
    {
      if (currentSpeedXYZ >= 5)
      {
        currentSpeedXYZ -= 5;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 4000 && currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 7000)
    {
      if (currentSpeedXYZ >= 10)
      {
        currentSpeedXYZ -= 10;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 7000 && currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 10000)
    {
      if (currentSpeedXYZ >= 100)
      {
        currentSpeedXYZ -= 100;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 10000)
    {
      if (currentSpeedXYZ >= 1000)
      {
        currentSpeedXYZ -= 1000;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
  }
  else if (digitalRead(minusButtonXYZ) && stateMinusButtonXYZ)  // Stop counting when minusButtonXYZ is released.
  {
    stateMinusButtonXYZ = false;
  }
}

void readPlusButtonXYZ()
{
  if (!digitalRead(plusButtonXYZ) && !statePlusButtonXYZ)
  {
    statePlusButtonXYZ = true;
    currentMillisPlusButtonXYZ = millis();                      // Store time value when PlusButtonXYZ was clicked.
    previousMillisPlusButtonXYZ = currentMillisPlusButtonXYZ;
  }
  if (!digitalRead(plusButtonXYZ) && statePlusButtonXYZ)        // Start counting as long as plusButtonXYZ is held.
  {
    currentMillisPlusButtonXYZ = millis();                      // Update time value as long as PlusButtonXYZ is held.

    if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 50 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 1000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 1))
      {
        currentSpeedXYZ += 1;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 1000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 4000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 5))
      {
        currentSpeedXYZ += 5;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 4000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 7000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 10))
      {
        currentSpeedXYZ += 10;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 7000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 10000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 100))
      {
        currentSpeedXYZ += 100;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 10000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 1000))
      {
        currentSpeedXYZ += 1000;
        stateDisplay = true;
        setSpeedXYZ();
      }
    }
  }
  else if (digitalRead(plusButtonXYZ) && statePlusButtonXYZ)    // Stop counting when plusButtonXYZ is released.
  {
    statePlusButtonXYZ = false;
  }
}

void setSpeedA()
{
  if (stateRapidModeA)
  {
    frequencyA = (maxSpeedA * microStepsA * motorStepsA * turnsPerRoundA) / (60 * 10);
    pulseA.play(frequencyA);
  }
  else
  {
    if (currentSpeedA >= 1)
    {
      frequencyA = (currentSpeedA * microStepsA * motorStepsA * turnsPerRoundA) / (60 * 10);
      pulseA.play(frequencyA);
    }
    else
    {
      pulseA.stop();
    }
  }
}

void setSpeedXYZ()
{
  if (stateRapidModeXYZ)
  {
    frequencyXYZ = (maxSpeedXYZ * microStepsXYZ * motorStepsXYZ) / (60 * mmPerRoundXYZ * 10);
    pulseXYZ.play(frequencyXYZ);
  }
  else
  {
    if (currentSpeedXYZ >= 10)
    {
      frequencyXYZ = (currentSpeedXYZ * microStepsXYZ * motorStepsXYZ) / (60 * mmPerRoundXYZ * 10);
      pulseXYZ.play(frequencyXYZ);
    }
    else
    {
      pulseXYZ.stop();
    }
  }
}

Ist es jetzt besser?

Hallo agmue,

vielen Dank für deine Unterstützung.

Ich wollte dir keine Arbeit aufhalsen, mach so wie du Zeit hast.

Leider nein, beim Betätigen beider Eilgangtaster bleibt das Programm immer noch hängen.
Ich habe aber jetzt eine Lösung dafür erarbeitet.
Anstatt die Funktionen setSpeedA() und setSpeedXYZ() in den Funktionen zur Tasterabfrage, verwende ich nun die globalen Merker stateSpeedA und stateSpeedXYZ.
Jetzt bleibt das Programm nicht mehr hängen, aber das Problem, dass die Anzeige nachläuft, wenn die Taster zur Geschwindigkeitseinstellung lange und häufig betätigt werden besteht nach wie vor.
Ursache hierfür scheint die Tone Library zu sein, denn wenn ich pulseA.play(frequencyA) und pulseXYZ.play(frequencyXYZ) kommentiere, läuft alles tadellos.
Ich schätze ich benötige eine andere Möglichkeit zur Takterzeugung.
Kann man das auch ohne Timer Interrupts z.B. mit millis() und micros() lösen?

Viele Grüße
Dan

Schade :thinking:

Welchen Arduino verwendest Du eigentlich?

Einen Nano-Klon, also den Atmega 328P.

Bitte zeige den aktuellen Stand Deines Programms, ob da noch ein Fehler schlummert.

Die Displayabfrage alle 100 Millisekunden musste ich wieder entfernen, da sich die Geschwindigkeitswerte bei gehaltenem Taster zu schnell erhöht hatten.
So funktioniert das Programm, bis auf die Einschränkung, dass das Programm bei zu viel Rumspielen an den Tastern hakt oder sich ganz aufhängt. :frowning:

Die folgenden globalen Variablen werde ich noch in lokale umwandeln:

unsigned long previousMillisMinusButtonA = 0;       // Store time in ms as MinusButtonA was clicked first time.
unsigned long currentMillisMinusButtonA = 0;        // Store time value as long as MinusButtonA is held.
unsigned long previousMillisPlusButtonA = 0;        // Store time in ms as PlusButtonA was clicked first time.
unsigned long currentMillisPlusButtonA = 0;         // Store time value as long as PlusButtonA is held.

unsigned long previousMillisMinusButtonXYZ = 0;     // Store time in ms as MinusButtonXYZ was clicked first time.
unsigned long currentMillisMinusButtonXYZ = 0;      // Store time value as long as MinusButtonXYZ is held.
unsigned long previousMillisPlusButtonXYZ = 0;      // Store time in ms as PlusButtonXYZ was clicked first time.
unsigned long currentMillisPlusButtonXYZ = 0;       // Store time value as long as PlusButtonXYZ is held.

Das ist der aktuelle Stand:

/*
  Manual Mill Controller v1.0
  written by Iron-Dan
  Creates stepper pulses to set speeds in mm/min and rpm and included rapid traverse mode.
  Implemented with the usage of the libraries which are included below.
*/

/*
  Universal 8bit Graphics Library (https://github.com/olikraus/OLED/)

  Copyright (c) 2016, olikraus@gmail.com
  All rights reserved.

  Redistribution and use in source and binary forms, with or without modification,
  are permitted provided that the following conditions are met:

    Redistributions of source code must retain the above copyright notice, this list
    of conditions and the following disclaimer.

    Redistributions in binary form must reproduce the above copyright notice, this
    list of conditions and the following disclaimer in the documentation and/or other
    materials provided with the distribution.
*/

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

// Please UNCOMMENT one of the contructor lines below
// OLED Contructor List (Picture Loop Page Buffer)
// The complete list is available here: https://github.com/olikraus/OLED/wiki/OLEDsetupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected

U8G2_SH1106_128X64_NONAME_1_HW_I2C OLED(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

#include <Tone.h>


//Flags

bool stateDisplay = true;                           // Init with true for first display after startup.
bool stateSpeedA = true;                            // State of speed setting for speedA -> if speedA has changed stateSpeedA = true.
bool stateSpeedXYZ = true;                          // State of speed setting for speedXYZ -> if speedXYZ has changed stateSpeedXYZ = true.

bool stateMinusButtonA = false;                     // State of minusButtonA -> If button is pressed stateMinusButtonA = true.
bool statePlusButtonA = false;                      // State of plusButtonA -> If button is pressed statePlusButtonA = true.
bool stateRapidModeA = false;                       // State of rapid traverse mode on A-Axis.
bool stateMinusButtonXYZ = false;                   // State of minusButtonXYZ -> If button is pressed stateMinusButtonXYZ = true.
bool statePlusButtonXYZ = false;                    // State of plusButtonXYZ -> If button is pressed statePlusButtonXYZ = true.
bool stateRapidModeXYZ = false;                     // State of rapid traverse mode on XYZ-Axis.

// Miscellaneous variables

const byte minusButtonA = 8;                        // Minus Button for speed value on A-Axis at Arduino Pin 10.
const byte plusButtonA = 7;                         // Plus Button for speed value on A-Axis at Arduino Pin 9.
const byte rapidButtonA = 2;                        // Button for rapid traverse mode on A-Axis at Arduino Pin 2.
const byte rapidLEDA = 11;                          // LED for indication of rapid traverse mode on A-Axis at Arduino Pin 11.
const unsigned long maxSpeedA = 136;                // Max. speed / 10 = speed in rpm. 136 = 65280Hz -> max. 65535Hz!
unsigned long currentSpeedA = 0;                    // Current speed / 10 = speed in rpm.
unsigned long speedA = 0;                           // Speed / 10 = speed in rpm.

const byte minusButtonXYZ = 10;                     // Minus Button for speed value on XYZ-Axis at Arduino Pin 8.
const byte plusButtonXYZ = 9;                       // Plus Button for speed value on XYZ-Axis at Arduino Pin 7.
const byte rapidButtonXYZ = 3;                      // Button for rapid traverse mode on XYZ-Axis at Arduino Pin 3.
const byte rapidLEDXYZ = 12;                        // LED for indication of rapid traverse mode on XYZ-Axis at Arduino Pin 12.
const unsigned long maxSpeedXYZ = 20000;            // Max. speed / 10 = speed in mm/min.
unsigned long currentSpeedXYZ = 0;                  // Current speed / 10 = speed in mm/min.
unsigned long speedXYZ = 0;                         // Speed / 10 = speed in mm/min.

// Timer variables

unsigned long previousMillisMinusButtonA = 0;       // Store time in ms as MinusButtonA was clicked first time.
unsigned long currentMillisMinusButtonA = 0;        // Store time value as long as MinusButtonA is held.
unsigned long previousMillisPlusButtonA = 0;        // Store time in ms as PlusButtonA was clicked first time.
unsigned long currentMillisPlusButtonA = 0;         // Store time value as long as PlusButtonA is held.

unsigned long previousMillisMinusButtonXYZ = 0;     // Store time in ms as MinusButtonXYZ was clicked first time.
unsigned long currentMillisMinusButtonXYZ = 0;      // Store time value as long as MinusButtonXYZ is held.
unsigned long previousMillisPlusButtonXYZ = 0;      // Store time in ms as PlusButtonXYZ was clicked first time.
unsigned long currentMillisPlusButtonXYZ = 0;       // Store time value as long as PlusButtonXYZ is held.

// Stepper variables

unsigned int microStepsA = 16;
unsigned int motorStepsA = 200;
unsigned int turnsPerRoundA = 90;
unsigned int microStepsXYZ = 16;
unsigned int motorStepsXYZ = 200;
unsigned int mmPerRoundXYZ = 5;
unsigned int frequencyA = 0;
unsigned int frequencyXYZ = 0;

Tone pulseA;                                        // Create Tone object pulseA.
Tone pulseXYZ;                                      // Create Tone object pulseXYZ.

// Setup

void setup() {
  pinMode(minusButtonA, INPUT_PULLUP);
  pinMode(plusButtonA, INPUT_PULLUP);
  pinMode(rapidButtonA, INPUT_PULLUP);
  pinMode(minusButtonXYZ, INPUT_PULLUP);
  pinMode(plusButtonXYZ, INPUT_PULLUP);
  pinMode(rapidButtonXYZ, INPUT_PULLUP);
  pinMode(rapidLEDA, OUTPUT);
  pinMode(rapidLEDXYZ, OUTPUT);

  pulseA.begin(5);                                  // Init stepper pulses for A-Axis at Arduino Pin 5.
  pulseXYZ.begin(6);                                // Init stepper pulses for XYZ-Axis at Arduino Pin 6.

  OLED.begin();                                     // Init the OLED.

  bootScreen();                                     // Show Boot Screen


}

void loop() {

  readRapidButtonA();
  readRapidButtonXYZ();
  readMinusButtonA();
  readPlusButtonA();
  readMinusButtonXYZ();
  readPlusButtonXYZ();

  printDisplay();

  setSpeedA();
  setSpeedXYZ();

}

void bootScreen()
{
  OLED.firstPage();
  do {
    OLED.setFont(u8g2_font_profont22_tf);
    OLED.drawStr(0, 14, "MANUAL");
    OLED.drawStr(0, 29, "MILL");
    OLED.drawStr(0, 44, "CONTROLLER");
    OLED.setFont(u8g2_font_profont11_tf);
    OLED.drawStr(0, 54, "v1.0");
    OLED.drawStr(0, 64, "BY IRON-DAN");
  } while (OLED.nextPage());
  delay(4000);
}

void printDisplay()
{
  if (stateDisplay)
  {
      stateDisplay = false;
      char buf[7];

      if (stateRapidModeA)
      {
        speedA = maxSpeedA;
      }
      else
      {
        speedA = currentSpeedA;
      }

      if (stateRapidModeXYZ)
      {
        speedXYZ = maxSpeedXYZ;
      }
      else
      {
        speedXYZ = currentSpeedXYZ;
      }

      OLED.setFont(u8g2_font_profont22_tf);
      OLED.firstPage();
      do {
        snprintf(buf, sizeof(buf), "%4lu.%lu", speedXYZ / 10, speedXYZ % 10);
        OLED.setCursor(3, 18);
        OLED.print("XYZ");
        OLED.setCursor(46, 18);
        OLED.print(buf);
        snprintf(buf, sizeof(buf), "%4lu.%lu", speedA / 10, speedA % 10);
        OLED.setCursor(3, 48);
        OLED.print("A");
        OLED.setCursor(46, 48);
        OLED.print(buf);
        OLED.drawFrame(0, 0, 128, 20);
        OLED.drawLine(39, 0, 39, 19);
        OLED.drawFrame(0, 30, 128, 20);
        OLED.drawLine(39, 30, 39, 49);
      } while (OLED.nextPage());
    }
  }

void readRapidButtonA()
{
  unsigned long newMillis = 0;                        // New time value in ms when rapidButtonA was pressed.
  static unsigned long oldMillis = 0;                 // Old time value in ms when rapidButtonA was pressed last time.

  if (!digitalRead(rapidButtonA))
  {
    newMillis = millis();

    if (newMillis - oldMillis >= 200)                  // Push button debouncing.
    {
      stateRapidModeA = !stateRapidModeA;             // Toggle stateRapidModeA when rapidButtonA was pressed.
      if (stateRapidModeA)
      {
        digitalWrite(rapidLEDA, HIGH);
        stateDisplay = true;
        stateSpeedA = true;
      }
      else
      {
        digitalWrite(rapidLEDA, LOW);
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    oldMillis = newMillis;
  }
}

void readRapidButtonXYZ()
{
  unsigned long newMillis = 0;                        // New time value in ms when rapidButtonXYZ was pressed.
  static unsigned long oldMillis = 0;                 // Old time value in ms when rapidButtonXYZ was pressed last time.


  if (!digitalRead(rapidButtonXYZ))
  {
    newMillis = millis();

    if (newMillis - oldMillis >= 200)                  // Push button debouncing.
    {
      stateRapidModeXYZ = !stateRapidModeXYZ;         // Toggle stateRapidModeXYZ when rapidButtonXYZ was pressed.
      if (stateRapidModeXYZ)
      {
        digitalWrite(rapidLEDXYZ, HIGH);
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
      else
      {
        digitalWrite(rapidLEDXYZ, LOW);
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    oldMillis = newMillis;
  }
}

void readMinusButtonA()
{
  if (!digitalRead(minusButtonA) && !stateMinusButtonA)
  {
    stateMinusButtonA = true;
    currentMillisMinusButtonA = millis();                       // Store first time value when minusButtonA was pressed.
    previousMillisMinusButtonA = currentMillisMinusButtonA;
  }
  if (!digitalRead(minusButtonA) && stateMinusButtonA)          // Start counting as long as minusButtonA is held.
  {
    currentMillisMinusButtonA = millis();                       // Update time value as long as minusButtonA is held.

    if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 50) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 1000))
    {
      if (currentSpeedA >= 1)
      {
        currentSpeedA -= 1;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    else if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 1000) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 4000))
    {
      if (currentSpeedA >= 2)
      {
        currentSpeedA -= 2;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    else if ((currentMillisMinusButtonA - previousMillisMinusButtonA > 4000) && (currentMillisMinusButtonA - previousMillisMinusButtonA <= 7000))
    {
      if (currentSpeedA >= 5)
      {
        currentSpeedA -= 5;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    else if (currentMillisMinusButtonA - previousMillisMinusButtonA > 7000)
    {
      if (currentSpeedA >= 10)
      {
        currentSpeedA -= 10;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
  }
  else if (digitalRead(minusButtonA) && stateMinusButtonA)      // Stop counting when minusButtonA is released.
  {
    stateMinusButtonA = false;
  }
}

void readPlusButtonA()
{
  if (!digitalRead(plusButtonA) && !statePlusButtonA)
  {
    statePlusButtonA = true;
    currentMillisPlusButtonA = millis();                        // Store first time value when plusButtonA was pressed.
    previousMillisPlusButtonA = currentMillisPlusButtonA;
  }
  if (!digitalRead(plusButtonA) && statePlusButtonA)            // Start counting as long as plusButtonA is held.
  {
    currentMillisPlusButtonA = millis();                        // Update time value as long as plusButtonA is held.

    if (currentMillisPlusButtonA - previousMillisPlusButtonA > 50 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 1000)
    {
      if (currentSpeedA <= (maxSpeedA - 1))
      {
        currentSpeedA += 1;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 1000 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 4000)
    {
      if (currentSpeedA <= (maxSpeedA - 2))
      {
        currentSpeedA += 2;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 4000 && currentMillisPlusButtonA - previousMillisPlusButtonA <= 7000)
    {
      if (currentSpeedA <= (maxSpeedA - 5))
      {
        currentSpeedA += 5;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
    else if (currentMillisPlusButtonA - previousMillisPlusButtonA > 7000)
    {
      if (currentSpeedA <= (maxSpeedA - 10))
      {
        currentSpeedA += 10;
        stateDisplay = true;
        stateSpeedA = true;
      }
    }
  }
  else if (digitalRead(plusButtonA) && statePlusButtonA)        // Stop counting when plusButtonA is released.
  {
    statePlusButtonA = false;
  }
}

void readMinusButtonXYZ()
{
  if (!digitalRead(minusButtonXYZ) && !stateMinusButtonXYZ)
  {
    stateMinusButtonXYZ = true;
    currentMillisMinusButtonXYZ = millis();                     // Store time value when minusButtonXYZ was pressed.
    previousMillisMinusButtonXYZ = currentMillisMinusButtonXYZ;
  }
  if (!digitalRead(minusButtonXYZ) && stateMinusButtonXYZ)      // Start counting as long as minusButtonXYZ is held.
  {
    currentMillisMinusButtonXYZ = millis();                     // Update time value as long as minusButtonXYZ is held.

    if ((currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 50) && (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 1000))
    {
      if (currentSpeedXYZ >= 1)
      {
        currentSpeedXYZ -= 1;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if ((currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 1000) && (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 4000))
    {
      if (currentSpeedXYZ >= 5)
      {
        currentSpeedXYZ -= 5;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 4000 && currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 7000)
    {
      if (currentSpeedXYZ >= 10)
      {
        currentSpeedXYZ -= 10;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 7000 && currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ <= 10000)
    {
      if (currentSpeedXYZ >= 100)
      {
        currentSpeedXYZ -= 100;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisMinusButtonXYZ - previousMillisMinusButtonXYZ > 10000)
    {
      if (currentSpeedXYZ >= 1000)
      {
        currentSpeedXYZ -= 1000;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
  }
  else if (digitalRead(minusButtonXYZ) && stateMinusButtonXYZ)  // Stop counting when minusButtonXYZ is released.
  {
    stateMinusButtonXYZ = false;
  }
}

void readPlusButtonXYZ()
{
  if (!digitalRead(plusButtonXYZ) && !statePlusButtonXYZ)
  {
    statePlusButtonXYZ = true;
    currentMillisPlusButtonXYZ = millis();                      // Store time value when PlusButtonXYZ was clicked.
    previousMillisPlusButtonXYZ = currentMillisPlusButtonXYZ;
  }
  if (!digitalRead(plusButtonXYZ) && statePlusButtonXYZ)        // Start counting as long as plusButtonXYZ is held.
  {
    currentMillisPlusButtonXYZ = millis();                      // Update time value as long as PlusButtonXYZ is held.

    if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 50 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 1000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 1))
      {
        currentSpeedXYZ += 1;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 1000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 4000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 5))
      {
        currentSpeedXYZ += 5;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 4000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 7000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 10))
      {
        currentSpeedXYZ += 10;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 7000 && currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ <= 10000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 100))
      {
        currentSpeedXYZ += 100;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
    else if (currentMillisPlusButtonXYZ - previousMillisPlusButtonXYZ > 10000)
    {
      if (currentSpeedXYZ <= (maxSpeedXYZ - 1000))
      {
        currentSpeedXYZ += 1000;
        stateDisplay = true;
        stateSpeedXYZ = true;
      }
    }
  }
  else if (digitalRead(plusButtonXYZ) && statePlusButtonXYZ)    // Stop counting when plusButtonXYZ is released.
  {
    statePlusButtonXYZ = false;
  }
}

void setSpeedA()
{
  if (stateSpeedA)
  {
    stateSpeedA = false;

    if (stateRapidModeA)
    {
      speedA = maxSpeedA;
    }
    else
    {
      speedA = currentSpeedA;
    }

    if (speedA >= 1)
    {
      frequencyA = (speedA * microStepsA * motorStepsA * turnsPerRoundA) / (60 * 10);
      pulseA.play(frequencyA);
    }
    else
    {
      pulseA.stop();
    }
  }
}

void setSpeedXYZ()
{
  if (stateSpeedXYZ)
  {
    stateSpeedXYZ = false;

    if (stateRapidModeXYZ)
    {
      speedXYZ = maxSpeedXYZ;
    }
    else
    {
      speedXYZ = currentSpeedXYZ;
    }

    if (speedXYZ >= 1)
    {
      frequencyXYZ = (speedXYZ * microStepsXYZ * motorStepsXYZ * mmPerRoundXYZ) / (60 * 10);
      pulseXYZ.play(frequencyXYZ);
    }
    else
    {
      pulseXYZ.stop();
    }
  }
}

Was ist mit 'Displayabfrage' gemeint? Am Display wird üblicherweise was ausgegeben und nichts abgefragt ( es sei denn Du hast einen Touchscreen, der aber programmtechnisch vom eigentlichen Display getrennt sein sollte.
Insgesamt deutet dieses Problem sehr darauf hin, dass in deinem Programm die einzelnen Funktionalitäten nicht sauber getrennt sind. Das Display darf nichts damit zu tun haben, was beim Drücken der Tasten passiert.

Wundert mich jetzt auch nicht allzusehr. Auch da ist das meiner Meinung nach vielzusehr verschachtelt. Z.B. sollte debouncing der Tasten und die Tastenfunktion streng getrennt werden.
Du solltest dich konsequent an das EVA-Prinzip halten: Einlesen - Verarbeiten - Ausgeben.
Debouncing gehört zum EInlesen der Tasten. Danach hast Du den Status der Tastenbedienung ( ist gedrückt, wurde gerade gedrückt, ist bereits seit x ms gedrückt usw ... je nachdem was Du brauchst. ) Das hat mit der Funktionalität dahinter noch gar nichts zu tun.
Erst wenn dies Info ermittelt wurde, werden aufgrund der Ergebnisse Funktionalitäten angestoßen. Das kann sich dann auch gegenseitig ausschließen: Wenn der Eilgang aktiv ist, werden die +/- Tasten garnicht ausgewertet, denn das hat dann keinen Sinn. So macht dann auch das 'Rumspielen' an den Tasten nichts. Tasten die im momentanen Betriebsstatus keine Sinn machen, werden einfach ignoriert.
Erst wenn alles ausgewertet ist, werden dann die entsprechenden Ausgaben gemacht ( Display aktualisieren, falls sich da was geändert hat, Schritterzeugung ( tone ) entsprechend ändern ).
Danach geht's wieder von vorn los ( loop ).
Nur so bekommst Du Ordnung in dein Programm, und bekonnst auch das Verhalten beim 'Rumspielen ' in den Griff.

Hallo MicroBahner,

danke für deinen Beitrag.

Da habe ich mich etwas unglücklich ausgedrückt, das Display gibt natürlich nur aus, es wird nicht abgefragt.

Das Display hat auch nichts damit zu tun, aber durch das Display lässt sich erkennen wenn das Programm beginnt sich aufzuhängen. Zum Beispiel wenn sich die Anzeige nur noch verzögert nach dem Tastendruck aktualisiert.

Viele Grüße
Dan

Wie muss ich dann diese Aussage verstehen?

Ich hatte es so verstanden, dass sich die Werte durch die Display'abfrage' zu schnell erhöht hätten.

Aber zu dem Problem mit dem 'Rumspielen' hatte ich ja auch schon was geschrieben, und das hat wohl eher mit der Art deiner Tasterabfragen zu tun.

Da habe ich mich wohl leider auch etwas unglücklich ausgedrückt. :slightly_smiling_face:
Ich meinte damit, dass die Schritte beim Drücken und halten der Taster nicht direkt nach jeder Änderung angezeigt werden, dadurch sieht es so aus als wäre die Schrittweite zu hoch.