#include <SPI.h> // Arduino SPI library
#include <ESP32Servo.h> // Servobibliothek.
#include <TFT_eSPI.h> // Hardware-specific library
#include "Free_Fonts.h"
constexpr const char *STATUS_TEXT[] {"Aus", "Ein", "Fehler", "o.k."};
constexpr const char *AXIS_TEXT[] {" X-Achse", " Y-Achse", " Z-Achse", " Taster", " Werkzeug"};
enum StatusTextIdx { aus, ein, fehler, ok };
namespace AxisTextIdx {
enum ATI { esX, esY, esZ, taster, werkzeug };
}
namespace AssemblyGroupIdx {
enum AGI { enaIn, esX, esY, esZ, taster, werkzeug, spindel };
}
using STI = StatusTextIdx;
using ATI = AxisTextIdx::ATI;
using AGI = AssemblyGroupIdx::AGI;
// Struktur definieren
struct TftStringData {
const char *text;
const int32_t xPos;
const int32_t yPos;
const uint8_t fontNr;
};
// Array aus obiger Strukturdefinition initialisieren
TftStringData statusScreen[] {
{"Status", 120, 0, 4},
{"Steuerung", 0, 26, 4},
{"Endsch. X", 0, 52, 4},
{"Endsch. Y", 0, 78, 4},
{"Endsch. Z", 0, 104, 4},
{"3D-Taster", 0, 130, 4},
{"WKZ-Laenge", 0, 156, 4},
{"Spindel", 0, 182, 4},
{"Drehzahl", 0, 208, 4}
};
struct AssemblyGroup {
uint8_t pin;
uint16_t color;
TftStringData tft;
};
AssemblyGroup asg[] {
{12, TFT_GREEN, {STATUS_TEXT[STI::ein], 200, statusScreen[1].yPos, statusScreen[1].fontNr}}, // enable Input
{14, TFT_GREEN, {STATUS_TEXT[STI::ein], 200, statusScreen[2].yPos, statusScreen[2].fontNr}}, // es X
{39, TFT_GREEN, {STATUS_TEXT[STI::ok], 200, statusScreen[3].yPos, statusScreen[3].fontNr} }, // es Y
{34, TFT_GREEN, {STATUS_TEXT[STI::ok], 200, statusScreen[4].yPos, statusScreen[4].fontNr} }, // es Z
{35, TFT_GREEN, {STATUS_TEXT[STI::ok], 200, statusScreen[5].yPos, statusScreen[5].fontNr} }, // taster
{26, TFT_GREEN, {STATUS_TEXT[STI::ok], 200, statusScreen[6].yPos, statusScreen[6].fontNr} }, // werkzeug
{27, TFT_GREEN, {STATUS_TEXT[STI::ok], 200, statusScreen[7].yPos, statusScreen[7].fontNr} }, // spindel
};
unsigned long intervall = 4000; // Länge der Anzeige Status
unsigned long intervall1 = 4000; // Länge der Pause für Bereitschaft Fahrtenregler
unsigned long altMillis = 0; // Speicher für alte Zeit
unsigned long neuMillis; // akt. Zeit übernehmen
int Status_Motor = 0; // Var. für Statuszustand Spindel_in
String DZ; // Var. für Drehzahl
unsigned long Farbe; // Farbe= Schriftfarbe
int Dz_in = A0; // Eingang Drehzahl-Spindel 0-10V
int EStop_in = 32; // Eingang Notaus
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)
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
Servo ESC; // Der ESC-Controller wird als Objekt mit dem Namen "ESC" festgelegt
// Achsen freifahren
void Freifahren(const char *const axis) {
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0);
tft.setFreeFont(FF19);
tft.println("");
tft.setTextColor(TFT_BLUE);
tft.println(" Aktion");
tft.println(" erforderlich!");
tft.println("");
tft.setTextColor(TFT_RED);
tft.println(axis);
tft.setTextColor(TFT_GREEN);
tft.println(" freifahren");
delay(2000);
tft.fillScreen(TFT_BLACK);
}
// Aktion bei Steuerung aus
void Steuerung_ein() {
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0);
tft.setFreeFont(FF19);
tft.println("");
tft.setTextColor(TFT_BLUE);
tft.println(" Aktion");
tft.println(" erforderlich!");
tft.println("");
tft.setTextColor(TFT_GREEN);
tft.println(" Steuerung");
tft.println(" einschalten!");
delay(2000);
tft.fillScreen(TFT_BLACK);
}
// UP Status anzeigen
void Anzeige() {
int index {0};
tft.setTextPadding(tft.textWidth("555555"));
tft.setTextColor(TFT_RED, TFT_BLACK);
for (const auto &sts : statusScreen) {
if (index == 1) { tft.setTextColor(TFT_BLUE, TFT_BLACK); }
tft.drawString(sts.text, sts.xPos, sts.yPos, sts.fontNr);
++index;
}
// tft.drawString("Drehzahl", 10, 208, 4);
for (const auto &part : asg) {
tft.setTextColor(part.color);
tft.drawString(part.tft.text, part.tft.xPos, part.tft.yPos, part.tft.fontNr);
}
tft.setTextColor(TFT_ORANGE, TFT_BLACK, true);
tft.drawString(DZ, 200, 208, 4);
}
// UP Satus Eingänge
void Status() {
if (digitalRead(asg[AGI::enaIn].pin) == LOW) { // Status Eingang Enable
asg[AGI::enaIn].color = TFT_RED;
asg[AGI::enaIn].tft.text = STATUS_TEXT[STI::aus];
Steuerung_ein();
} else {
asg[AGI::enaIn].color = TFT_GREEN;
asg[AGI::enaIn].tft.text = STATUS_TEXT[STI::ein];
}
if (digitalRead(asg[AGI::esX].pin) == HIGH) { // Status Eingang Endschalter X-
asg[AGI::esX].color = TFT_RED;
asg[AGI::esX].tft.text = STATUS_TEXT[STI::fehler];
Freifahren(AXIS_TEXT[ATI::esX]);
} else {
asg[AGI::esX].color = TFT_GREEN;
asg[AGI::esX].tft.text = STATUS_TEXT[STI::ok];
}
if (digitalRead(asg[AGI::esY].pin) == HIGH) { // Status Eingang Endschalter Y-
asg[AGI::esY].color = TFT_RED;
asg[AGI::esY].tft.text = STATUS_TEXT[STI::fehler];
Freifahren(AXIS_TEXT[ATI::esY]);
} else {
asg[AGI::esY].color = TFT_GREEN;
asg[AGI::esY].tft.text = STATUS_TEXT[STI::ok];
}
if (digitalRead(asg[AGI::esZ].pin) == HIGH) { // Status Eingang Endschalter Z-
asg[AGI::esZ].color = TFT_RED;
asg[AGI::esZ].tft.text = STATUS_TEXT[STI::fehler];
Freifahren(AXIS_TEXT[ATI::esZ]);
} else {
asg[AGI::esZ].color = TFT_GREEN;
asg[AGI::esZ].tft.text = STATUS_TEXT[STI::ok];
}
if (digitalRead(asg[AGI::taster].pin) == HIGH) { // Status Eingang 3D Taster
asg[AGI::taster].color = TFT_RED;
asg[AGI::taster].tft.text = STATUS_TEXT[STI::fehler];
Freifahren(AXIS_TEXT[ATI::taster]);
} else {
asg[AGI::taster].color = TFT_GREEN;
asg[AGI::taster].tft.text = STATUS_TEXT[STI::ok];
}
if (digitalRead(asg[AGI::werkzeug].pin) == LOW) { // Status Eingang Werkzeuglänge
asg[AGI::werkzeug].color = TFT_RED;
asg[AGI::werkzeug].tft.text = STATUS_TEXT[STI::fehler];
Freifahren(AXIS_TEXT[ATI::werkzeug]);
} else {
asg[AGI::werkzeug].color = TFT_GREEN;
asg[AGI::werkzeug].tft.text = STATUS_TEXT[STI::ok];
}
if (digitalRead(asg[AGI::spindel].pin) == HIGH) { // Status Eingang Spindel
asg[AGI::spindel].color = TFT_RED;
asg[AGI::spindel].tft.text = STATUS_TEXT[STI::aus];
} else {
asg[AGI::spindel].color = TFT_GREEN;
asg[AGI::spindel].tft.text = STATUS_TEXT[STI::ein];
}
}
// Motor an
void Motor() {
if (digitalRead(asg[AGI::spindel].pin == LOW)) { // Wenn Spindel_in LOW und Status_Motor 0
digitalWrite(Spindel_out, LOW); // ESC 5V einschalten
} else {
digitalWrite(Spindel_out, HIGH); // ESC 5V ausschalten
Status_Motor = 0; // Status_Motor 0
}
}
// Reserve
void Reserve() {
if (digitalRead(Reserve_in) == LOW) {
digitalWrite(Reserve_Relais_out, LOW); // Reserve Relais an
digitalWrite(Reserve_out, LOW); // Reserve Ausgang LOW
} else {
digitalWrite(Reserve_Relais_out, HIGH); // Reserve Relais aus
digitalWrite(Reserve_out, HIGH); // Reserve Ausgang HIGH
}
}
// Drehzahlreglung
void Umdrehungen() {
Drehzahl = map(analogRead(Dz_in), 0, 4094, 0, 180); // umwandeln 0 - 1V in 0 - 180 Grd.
DZ = map(analogRead(Dz_in), 0, 4049, 0, 25000); // umwandeln 0 - 1V in 0 - 25000 U/min
neuMillis = millis(); // akt. Zeit übernehmen
if ((neuMillis - altMillis) >= intervall1 && Status_Motor == 0) { // wenn x ms abgelaugfen
altMillis = neuMillis; // akt. Zeit in altMillis
ESC.write(Drehzahl); // Erzeugung PWM
Status_Motor = 1;
} else {
ESC.write(Drehzahl); // Erzeugung PWM
}
}
void setup() {
for (const auto &part : asg) { pinMode(part.pin, INPUT_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
Serial.begin(9600);
digitalWrite(TFT_BL, HIGH);
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.setFreeFont(FF24);
tft.drawString("Systemstart!", 10, 2);
tft.setFreeFont(FF19);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.drawString("Steuerung wird", 15, 60);
tft.drawString("aktiviert!", 15, 100);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
for (byte i = 0; i <= 4; i++) {
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.drawString("Bitte warten!", 60, 160);
delay(1000);
tft.fillRect(0, 159, 318, 30, TFT_BLACK);
delay(500);
}
tft.fillScreen(TFT_BLACK);
ESC.attach(ESC_out, 1000, 2000); // Pin, minimale, maximale Pulsweite in Mikrosekunden
// attachInterrupt(digitalPinToInterrupt(asg[AGI::spindel].pin), Motor, CHANGE); // Motor Interrupt aktiviert
// attachInterrupt(digitalPinToInterrupt(Reserve_in), Reserve, CHANGE); // Reserve Interrupt aktiviert
}
// Hauptschleife
void loop() {
neuMillis = millis(); // akt. Zeit übernehmen
if ((neuMillis - altMillis) >= intervall) { // wenn x ms abgelaugfen
altMillis = neuMillis; // akt. Zeit in altMillis
Status(); // Fehler und Aktion wird angezeigt
}
Anzeige(); // Anzeige wird aktualisiert
Umdrehungen(); // Aktualisierung Drehzahl
Motor(); // Motor ein aus schalten
}