/*
Forum: https://forum.arduino.cc/t/millis-mit-if-bedingung/1290488/5
Wokwi: https://wokwi.com/projects/405851025462290433
*/
#include <Keypad.h>
#include <AccelStepper.h>
#include <PololuMaestro.h>
// Größe des Keypads definieren
const byte COLS = 4; // 4 Spalten
const byte ROWS = 4; // 4 Zeilen
// Die Ziffern und Zeichen des Keypads
char hexaKeys[ROWS][COLS] = {
{ '1', '2', '3', 'A' },
{ '4', '5', '6', 'B' },
{ '7', '8', '9', 'C' },
{ '*', '0', '#', 'D' }
};
byte colPins[COLS] = { 11, 12, 4, 5 }; // Pins für die 4 Spalten
byte rowPins[ROWS] = { 7, 6, 8, 9 }; // Pins für die 4 Zeilen
char Taste; // Variable für die jeweils gedrückte Taste
Keypad Tastenfeld = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
const int relayPins[] = { A0, A1, A2, A3, A4, A5, A6 };
const int numRelays = sizeof(relayPins) / sizeof(relayPins[0]);
unsigned long previousMillis = 0;
int currentPatternIndex = 0;
bool patternActive = false;
int patternLength = 0;
// Die folgende Struktur beinhaltet
// die Nummer des zu schaltenden Relais und
// die Dauer des Einschaltens (Schaltintervall) in [ms]
struct relayType {
int relay;
unsigned long interval;
};
relayType *currentPattern = nullptr;
// Beispielmuster
// linker Wert = Relaisnummer
// rechter Wert = Schaltintervall
const relayType pattern0[] =
{ {0, 4000},
{1, 4000},
{3, 4000}
};
const relayType pattern1[] =
{ {2, 2000},
{3, 3000}
};
const relayType pattern2[] =
{
{0, 4000},
{1, 4000},
{3, 4000}
};
// Das folgende Macro ergibt die Anzahl der Einträge in den Arrays vom Typ "relayType"
#define ANZAHL(x) sizeof(x)/sizeof(relayType)
#ifdef SERIAL_PORT_HARDWARE_OPEN
#define maestroSerial SERIAL_PORT_HARDWARE_OPEN
#else
#include <SoftwareSerial.h>
SoftwareSerial maestroSerial(18, 19);
#endif
MicroMaestro maestro(maestroSerial);
const int open = 8000;
const int close = 6000;
AccelStepper stepper(1, 2, 3);
int endstop_1 = A14;
int endstop_2 = A15;
void setup() {
Serial.begin(9600);
maestroSerial.begin(9600);
//Endstop
pinMode(endstop_1, INPUT);
pinMode(endstop_2, INPUT);
stepper.setMaxSpeed(1000);
stepper.setAcceleration(1000);
stepper.setSpeed(100);
for (int i = 0; i < numRelays; i++) {
pinMode(relayPins[i], OUTPUT);
digitalWrite(relayPins[i], HIGH); // Relais anfangs ausschalten (HIGH bedeutet ausgeschaltet für ein Relaismodul)
}
}
void loop() {
Taste = Tastenfeld.getKey();
if (Taste) { // Wenn eine Taste gedrückt wurde
Serial.print("Die Taste ");
Serial.print(Taste);
Serial.println(" wurde gedrückt");
switch (Taste) {
case '0': if (digitalRead(endstop_1) != LOW) break; // Wenn endstop_1 ungleich LOW, geht's nicht weiter
prepare(); // Hier wird alles abgerufen, was bei der Taste '0' vor dem Schalten der Relais erfolgt
startPattern(pattern0, ANZAHL(pattern0));
break;
case '1' : startPattern(pattern1, ANZAHL(pattern1));
break;
case '2': startPattern(pattern2, ANZAHL(pattern2));
break;
}
}
if (patternActive) {
if (millis() - previousMillis >= currentPattern[currentPatternIndex].interval) {
switchRelay(HIGH);
currentPatternIndex++;
if (currentPatternIndex < patternLength) {
switchRelay(LOW);
} else {
patternActive = false; // Muster ist beendet
Serial.println("Muster abgeschlossen");
}
}
}
}
// Vorgeplänkel im Fall der Taste '0'
void prepare() {
maestro.setSpeed(50, 50);
maestro.setAcceleration(10, 10);
setStepperAndMaestro(800, -3730, true);
setStepperAndMaestro(400, -3250, true);
setStepperAndMaestro(400, -2680, true);
setStepperAndMaestro(400, -1800, false);
}
// Diese Funktion wird an mehreren Stellen aufgerufen, um Relais ein- und auszuschalten
void switchRelay (byte state) {
previousMillis = millis(); // Hier wird die Schaltzeit für das Intervall gesetzt
digitalWrite(relayPins[currentPattern[currentPatternIndex].relay], LOW); // Nächstes Relais einschalten
Serial.print("Relais ");
Serial.print(currentPattern[currentPatternIndex].relay + 1);
Serial.println((state == LOW) ? " eingeschaltet" : " ausgeschaltet");
}
void startPattern(const struct relayType pattern[], int length) {
currentPattern = pattern;
patternLength = length;
currentPatternIndex = 0;
patternActive = true;
switchRelay(LOW);
}
// Wird bei prepare() mehrfach aufgerufen
void setStepperAndMaestro(int maxSpeed, int newPos, boolean setMaestro) {
stepper.setMaxSpeed(maxSpeed);
stepper.runToNewPosition(newPos);
if (setMaestro) {
maestro.setTarget(0, open);
delay(3000);
maestro.setTarget(0, close);
}
}