Brauche Hilfe bei meinem Programm zur Vorschubsteuerung

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