LCD display

Guten Tag,
ich sitze seit circa 3 Tagen am Stecken und basteln für meine neue Maschine. Diese soll verschiedene funktionen haben wie z. B. Förederband Roboterarm etc. Übungs projekt..
In dem Code wollte ich für den Anfang 5 States machen (z. B. Start, Stopp...) die ich abfragen kann und schauen kann was passiert wenn das Systeme sich in dem und dem Status befindet

Folgendes Problem
In meinem Sketch kommt immer eine Fehlermeldung beim decompilen.
'state' was not declared in this scope

Falls ihr für den Code ansich Vorschläge hättet zum Verbessern etc. Bitte schreiben.

#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd(0x27, 20, 21);



//Control Unit 
enum StateSystem {Start, Stop, CostumerID, Login, Sleep};
int d[] {5000, 2000, 500, 500};
byte StateSystem = state;
enum StateMaschine {Start, Fehler, Temperatur, Sleep};
unsigned long int millisStart;
unsigned long int millisStop;
unsigned long int millisCostumerID;
unsigned long int millisLogin;
unsigned long int Fehler;
unsigned long int Temperatur;


byte StateSystem = Start
byte StateMaschine = Start

void setup() {
  Serial.begin(9600);
  lcd.begin();
  millisStart = millis();
}

void loop() {
  if(millis()- millisStart < d[0]){
    Serial.println("Das System ist nun Einsatzbereit!");
    state = CostumerID;
  }else{
    state = Start;
  }
  if(state == Start){
  lcd.setCursor(4,0);
  lcd.print("Das Systeme");
  lcd.setCursor(2,1);
  lcd.print("startet gerade..");
  }else if(state == CostumerID){
  lcd.setCursor(3,1);
  lcd.print("Costumer ID...");
  }else if(state == Login){
  lcd.setCursor(4,1);
  lcd.print("Checking...");
  }else if(state == Sleep){
  lcd.setCursor(5,1);
  lcd.print("Sleeping...");
  }else if(state == Stop){
  lcd.setCursor(3,1);
  lcd.print("Herunterfahren...");
  }
}

Danke im Voraus <3

Wieso willst Du decompilieren?

Oder meinst Du Komplieren (Sketch zu Maschienenkode)?

Was wolltest Du in Zeile 11 mit
byte StateSystem = state;
denn machen?

So hast Du state nicht definiert und das nörgelt der die IDE beim compilieren.

Grüße Uwe

Wenn ich byte weglasse kommt
expected unqualified-id before '=' token
MFG

byte StateSystem = state;

state ist ja auch nicht bekannt. Wurde vorher nie erwähnt. Natürlich sagt da der Compiler dass er das nicht kennt

Außerdem: die C enums sind nicht typsicher, aber man sollte es trotzdem so machen:

enum StateMachine : byte {Start, Fehler, Temperatur, Sleep};

StateMachine currentState = Start;

Der darunterliegende Typ ist ein Byte, ja, aber den Typ der Zustandsvariablen sollten von dem Typ der Aufzählung sein

Damit kann man aber immer noch allerlei Unsinn machen und es gibt auch Probleme, weil die Aufzählung keinen eigenen Gültigkeitsbereich hat. Daher besser:

enum class StateSystem : byte {Start, Stop, CostumerID, Login, Sleep};
enum class StateMaschine : byte {Start, Fehler, Temperatur, Sleep};

StateMachine currentState = StateMachine::Start;

Das geht seit C++11. Damit sind keine direkten Zuweisungen an Integer-Datentypen mehr erlaubt. Und man kann auch mehrere Aufzählungen mit den gleichen Konstanten haben. z.B. zwei Zustandsmaschinen mit "Start" und "Sleep". Bei dir kannst du diese Zustände zwischen den zwei enums im Moment nicht unterscheiden. Die überschneiden sich praktisch. Man kann die zwei enums z.B. untereinander zuweisen obwohl das womöglich semantisch keinen Sinn hat

Mit enum class (strongly typed enums) sind StateMachine::Start und StateSystem::Start klar zwei verschiedene Dinge

Ich glaube es hängt gerade ein wenig bei mir aber WARUM geht es nicht?
Ich verstehe es nicht :confused:
Meldung: use of enum 'StateSystem' without previous declaration

#include <LiquidCrystal_I2C.h>


LiquidCrystal_I2C lcd(0x27, 20, 21);



//Control Unit 
enum class StateSystem byte : {Start, Stop, CostumerID, Login, Sleep};
int d[] {5000, 2000, 500, 500};
StateSystem currentState = StateMachine::Start;
enum StateMaschine {Start, Fehler, Temperatur, Sleep};
unsigned long int millisStart;
unsigned long int millisStop;
unsigned long int millisCostumerID;
unsigned long int millisLogin;
unsigned long int Fehler;
unsigned long int Temperatur;


StateSystem = Start
StateMaschine = Start

void setup() {
  Serial.begin(9600);
  lcd.begin();
  millisStart = millis();
}

void loop() {
  if(millis()- millisStart < d[0]){
    Serial.println("Das System ist nun Einsatzbereit!");
    state = CostumerID;
  }else{
    state = Start;
  }
  if(state == Start){
  lcd.setCursor(4,0);
  lcd.print("Das Systeme");
  lcd.setCursor(2,1);
  lcd.print("startet gerade..");
  }else if(state == CostumerID){
  lcd.setCursor(3,1);
  lcd.print("Costumer ID...");
  }else if(state == Login){
  lcd.setCursor(4,1);
  lcd.print("Checking...");
  }else if(state == Sleep){
  lcd.setCursor(5,1);
  lcd.print("Sleeping...");
  }else if(state == Stop){
  lcd.setCursor(3,1);
  lcd.print("Herunterfahren...");
  }
}
StateSystem = Start
StateMaschine = Start

Die Sache mit strongly typed enums ist das deren Gültigkeitsbereich eingeschränkt ist. Du musst immer mit dem Scope Operator :: angeben welches gemeint ist

Diese zwei Zeilen sind aber auch völlig sinnfrei. Du musst eine Variablen diesen Typs anlegen!
Zum Beispiel

enum class StateSystem : byte {Start, Stop, CostumerID, Login, Sleep};
enum class StateMaschine : byte {Start, Fehler, Temperatur, Sleep};

...

StateSystem systemState = StateSystem::Start;
StateMachine state = StateMachine::Start;

systemState ist vom Typ StateSystem und hat den Wert StateSystem::Start

Denke dir vielleicht mal bessere Namen aus. "StateMaschine" ist etwas zu allgemein wenn zwei Zustandsmaschinen existieren

Außerdem denke bitte etwas nach. Ich mag das in meinem Beispiel currentState genannt haben. Bei dir heißen die Zustandsvariablen anders. Das muss schon konsistent sein

Ja genau so..
Es kommt aber:

use of enum 'StateSystem' without previous declaration

enum class StateSystem byte : {Start, Stop, CostumerID, Login, Sleep};
int d[] {5000, 2000, 500, 500};
enum class StateMaschine byte: {Start, Fehler, Temperatur, Sleep};

StateSystem systemState = StateSystem::Start;
StateMachine state = StateMachine::Start;
enum class StateSystem : byte {Start, Stop, CostumerID, Login, Sleep};

Der darunterliegende Datentyp wird mit : byte angegeben. Nicht mit "byte :". Das ist auch optional. Wenn man das weglässt ist es halt int. Da man mit enum class aber anders als mit den klassischen C enums keine direkte Kompatibilität mit Integern hat, ist das auch nicht so wichtig.

War vielleicht mein Fehler. Ich hatte das einmal falsch hingeschrieben und dann ausgebessert

Siehe auch:
https://en.cppreference.com/w/cpp/language/enum

Ich komm nicht mit sry...

Wie soll ich das Problem lösen?
Wenn du mir ein bisschen diskreter erklären könntest was ich zu tun habe.

enum class StateSystem byte : {Start, Stop, CostumerID, Login, Sleep};
enum class StateMaschine byte : {Start, Fehler, Temperatur, Sleep};
int d[] {5000, 2000, 500, 500};
int d1[] {5000, 500, 500, 500};


byte StateSystem systemState = StateSystem::Start;
byte StateMachine state = StateMachine::Start;

Serenifly schreibt

enum class StateSystem : byte {Start, Stop, CostumerID, Login, Sleep};

bei dir steht

enum class StateSystem byte : {Start, Stop, CostumerID, Login, Sleep};

siehst du den Unterschied?

Dominik1313:
Ich komm nicht mit sry...

Wie soll ich das Problem lösen?
Wenn du mir ein bisschen diskreter erklären könntest was ich zu tun habe.

Ich übernehme das einfach mal.

Grundlagen lernen ist hier angesagt.
Du solltest einfach mal die Basics lernen die zur Programmierung wichtig sind.

Und auch ganz wichtig, auch mal auf frühere Threads antworten bzw. mal mitteilen, ob dir unsere Antworten weiter geholfen haben.

Wie gesagt das ist optional. Wenn man nicht angibt wird wie sonst auch immer int verwendet. Das sind dann halt zwei Bytes statt eins. Also erst mal egal

Das hier reicht:

enum class StateSystem {Start, Stop, CostumerID, Login, Sleep};

Auf der Seite die ich verlinkt habe steht doch die allgemeine Definition:

enum struct|class name { enumerator = constexpr , enumerator = constexpr , ... }

Oder

enum struct|class name : type { enumerator = constexpr , enumerator = constexpr , ... }

Achte auf die Position des Doppelpunkts. Das ist das gleiche wie bei anderen Verwendungen des Doppelpunkts in C++, auch wenn du diese vielleicht nicht kennst

Und dann baust du hier den nächsten Fehler ein:

byte StateSystem systemState = StateSystem::Start;
byte StateMachine state = StateMachine::Start;

Was soll das "byte" da? Tippst du da willkürlich Code ein?

Einfaches Beispiel:

int var = 5;

Eine Variable var vom Typ int wird deklarliert und mit 5 initialisiert

Analog hier:

StateMachine state = StateMachine::Start;

Eine Variable state vom Typ StateMaschine wird deklariert und mit StateMachine::Start initialisiert

Du hast einen eigenen Datentyp erzeugt. Daher gelten die gleichen Regeln wie für andere Datentypen.

Du solltest Programmstrukturen nur benutzen wenn Du weiß wie damit umzugehen ist.
Grüße Uwe

Ganz ehrlich halte ich es nicht für zielführend, jemandem, der offensichtlich noch so am Anfang steht, derartige Konstrukte zu empfehlen.
Das ist so ähnlich, als wenn Du ihm ein Einführungsbuch zu C++ vorschlägst, aber ihm empfiehlst es von hinten nach vorn zu lesen.

Er hat schon enums verwendet und will Zustandsmaschinen. Man muss aber enum class nehmen, damit die Zustände sauber getrennt sind, sonst gibt es Probleme. Das zu umgehen ist nicht sicher und erfordert noch mehr Wissen was da eigentlich dahinter steht. Enum class dagegen ist viel freundlicher, gerade weil man eher Fehler bekommt wenn man was falsch macht.

Der Unterschied ist minimalst. Einmal steht "class" dort und wenn man die Zustande verwendet muss man mit :: angeben auf welche Aufzählung man sich bezieht. Das ist alles.

uwefed:
Du solltest Programmstrukturen nur benutzen wenn Du weiß wie dami umzugehen ist.
Grüße Uwe

Hallo Uwe, da muß ich widersprechen, denn wenn ich nur tun würde, was ich schon gut kann, würde ich nie etwas dazulernen. Aber unsere Spezies möchte lernen, entdecken, hingehen, wo noch nie ein Mensch zuvor gewesen ist.

Wir fangen als Baby damit an und sollten nie aufhören! Das weltweite Netz ist eine der vielen Möglichkeiten dazu. Ist doch toll, wie einfach ich mit jemanden, der in Italien wohnt, kommunizieren kann.

Serenifly:
Er hat schon enums verwendet

Ich glaube, dass das ein großes Problem vieler Einsteiger ist, dass sie durch Copy/Paste vielfach Dinge nutzen, die sie noch nicht wirklich verstehen. Die Fehler, die er nach deinem Vorschlag gemacht hat, deuten eher darauf hin, dass ihm das ganze Thema der selbstdefinierten Datentypen noch nicht wirklich klar ist.
Insofern stimme ich auch Uwe zu, und ich denke so hat er das auch gemeint: Nicht einfach Copy/Paste, sondern lernen was das ist und dann bewusst einsetzen.

Serenifly:
Der Unterschied ist minimalst.

Wenn man sich auskennt, und die Hintergründe kennt schon :wink:

Abgeschlosse Millis anstatt delay - Deutsch - Arduino Forum

uwefed:
Du solltest Programmstrukturen nur benutzen wenn Du weiß wie damit umzugehen ist.
Grüße Uwe

MicroBahner:
Ganz ehrlich halte ich es nicht für zielführend, jemandem, der offensichtlich noch so am Anfang steht, derartige Konstrukte zu empfehlen.
Das ist so ähnlich, als wenn Du ihm ein Einführungsbuch zu C++ vorschlägst, aber ihm empfiehlst es von hinten nach vorn zu lesen.

Ja, sehe ich genauso. Diese Erklärungen zu den Fehlern kann man nicht kapieren wenn man noch keine Berührungen mit diese Strukturen hatte. Ich habe auch kein Wort von diesen Erklärungen kapiert, gebe ich offen zu, weil ich noch nichts derartiges bearbeiten musste.

Aber ich mache eben das, was ich immer mache wenn ich was hier nicht kapiere. Ich versuche es in meinen Büchern nachzuvollziehen, dass ich das nächste mal weiß worum es hierbei geht.

Franz

Mal ein einfaches Beispiel:

enum Test1 { Start, Warten, Stop };
enum Test2 { Start, Stop };

Start ist 0, Warten ist 1. Aber welchen Wert hat Stop? Einmal ist es 1 und einmal 2

Die klassischen C enums sind nicht viel anders als das:

#define Start 0
#define Stop 1

Wenn du eine Konstante neu definierst sollte der Compiler eigentlich eine Warnung ausspucken. Die musst in den IDE Einstellungen auch aktivieren.

EDIT:
Mal getestet und kommt sogar ein Fehler. Auch für Konstanten die eigentlich den gleichen Wert haben. Das konnte also nie so funktionieren

Das ganze nennt sich "Scope" oder Gültigkeitsbereich. Der ist in dem Fall global. Genau deshalb wurde mit den C++11 Standard enum class eingeführt. Damit haben die Konstanten nur noch den Gültigkeitsbereich der Aufzählung zu der sie gehören. Man kann so Stop zweimal haben, mit zwei verschiedenen Werten.