Abfrage mehrerer Eingänge, z.B. mittels Drehschalter

Serenifly:
Mhh, das ist interessant. In VisualMicro geht das. Die Arduino IDE kommt anscheinend wieder mal mit den Funktionsprototypen durcheinander. Normal muss man Funktionen deklarieren bevor man sie verwendet. Die IDE schreibt dann wahrscheinlich das Array vor die Prototypen. Ich dachte das hätte man inzwischen behoben. Und auch VisualMicro verwendet eigentlich die normalen Arduino Tools im Hintergrund.

Einfach das oben hinschreiben:

void funktion_1();

void funktion_2();
void funktion_3();

Ahja, jetzt funktioniert´s! :wink:

Serenifly:
Ansonsten wenn du etwas nicht verstehst: Google nach den Begriffen. Da gibt es sehr viele Anleitungen.
Deshalb ist es auch sehr wichtig die richtigen Namen für Dinge zu verwenden

Mache ich ja schon fleißig, hilft nur nichts. Aber das soll nicht weiter Thema hier sein, weil ich auch (noch) nicht sagen kann, was mir an Information eigentlich zum Verständnis zu Funktionen und Zeigern fehlt. Und ich kann und werde nicht erwarten, dass sich jemand erbarmt mir das beizubiegen - da muss ich selber erstmal irgendwie einen Zugang finden.

Also in diesem Sinne nochmals vielen Dank! :slight_smile:

Marcus

Schau dir wie gesagt lieber mal Funktionsparameter an. Damit hantierst du sowieso schon ständig

void funktion(byte nummer)
{
   if (nummer == ...)
      ...
}

Aufruf:

funktion(1);
funktion(2);

Ansonsten ist nicht ganz klar wie sich deine verschiedenen Funktionen wirklich unterscheiden. Ich nehme mal an die sehen zwar grob ähnlich aus, aber sind im Detail anders. Dann ist es schwer da Code zusammenzufasssen

Serenifly:
Schau dir wie gesagt lieber mal Funktionsparameter an. Damit hantierst du sowieso schon ständig

void funktion(byte nummer)

{
  if (nummer == …)
      …
}



Aufruf:


funktion(1);
funktion(2);




Ansonsten ist nicht ganz klar wie sich deine verschiedenen Funktionen wirklich unterscheiden. Ich nehme mal an die sehen zwar grob ähnlich aus, aber sind im Detail anders. Dann ist es schwer da Code zusammenzufasssen

Hmm… jetzt wo du es so geschrieben hast, kommt doch evtl. langsam Licht ins Dunkel …

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);                                                 // Adresse 0x3F oder 0x27 (Arduino Uno I2C Pins sind: A4==SDA, A5==SCL; MEGA 20 = SDA, 21 = SCL)

// Pinbelegungen
const byte Stellung[] = {3, 4, 5, 6, 7, 8, 9, 10 ,11 ,12};                          // Drehschalter mit den jeweiligen Pins verbunden
bool Pruefungsmarker[10];                                                           // Marker true/false der aktuellen Prüfung --> Aufruf in der Loop()
#define Relais_N   22                                                               // Signalleitungen der Relais mit den jeweiligen Pins verbunden
#define Relais_L   23
#define Relais_1   24
#define Relais_2   25
#define Relais_1B  26
#define Relais_12B 27
#define Relais_3   28
#define Relais_3B  29
#define Relais_4   30
#define Relais_5   31
#define Relais_6   32
#define Relais_7   33
#define Relais_8   34

// Variablen
byte Stellung_Drehknopf = 11;                                                       // absichtlich Wert > 10, damit die Abfrage des Drehknopfes startet
byte Stellung_Drehknopf_alt = 10;                                                   // absichtlich Wert > 9, damit die Abfrage des Drehknopfes startet
byte aktuelle_pruefung = 0;                                                         // Status zum Vergleich der aktuellen Prüfung mit der Vorherigen; absichtlich "0", damit der Startbildschirm stehen bleibt
byte Relais[] = {Relais_N, Relais_L, Relais_1, Relais_2, Relais_1B, Relais_12B,     // Array "Relais[]" mit den Relais-Benennungen in den einzelnen Feldern
                 Relais_3, Relais_3B, Relais_4, Relais_5, Relais_6, Relais_7, 
                 Relais_8};
                        //Relais_N  Relais_L  Relais_1  Relais_2  Relais_1B   Relais_12B  Relais_3  Relais_3B   Relais_4  Relais_5  Relais_6  Relais_7  Relais_8
byte schaltzustand_0[] = {0,        0,        0,        0,        0,          0,          0,        0,          0,        0,        0,        0,        0};
byte schaltzustand_1[] = {0,        0,        1,        0,        0,          0,          1,        0,          0,        0,        0,        0,        0};
byte schaltzustand_2[] = {0,        0,        1,        0,        0,          0,          0,        0,          1,        0,        0,        0,        0};
byte schaltzustand_3[] = {0,        0,        0,        1,        0,          0,          1,        0,          0,        0,        0,        0,        0};
byte schaltzustand_4[] = {0,        0,        1,        1,        1,          1,          1,        1,          1,        0,        0,        0,        0};
byte schaltzustand_5[] = {0,        0,        1,        1,        1,          0,          1,        1,          1,        1,        0,        0,        0};
byte schaltzustand_6[] = {1,        1,        1,        1,        1,          1,          1,        1,          1,        0,        0,        0,        0};
byte schaltzustand_7[] = {1,        1,        1,        1,        1,          0,          1,        1,          1,        1,        0,        0,        0};
byte schaltzustand_8[] = {0,        0,        1,        1,        1,          1,          1,        1,          1,        0,        0,        0,        1};
byte schaltzustand_9[] = {0,        0,        0,        0,        0,          0,          1,        0,          1,        0,        0,        1,        0};
unsigned long startzeit;                                                            // größtmöglicher Wertebereich f. Zeitstempel (ca. 4,29*10^10)
unsigned long schaltzeit;                                                           // Zeitstempel zur Verzögerung beim Durchschalten des Drehreglers
volatile bool status500ms = false;                                                  // Statusvariable, Bedingung f. Prüfungsstart. " volatile", da die Variable durch Interrupt geändert wird
float spannungswert = 0;

void setup() {
  pinMode(2, INPUT_PULLUP);                                                         // interner Pullup-Widerstand aktiviert, hilft gg. Störeinflüsse
  pinMode(A0, INPUT_PULLUP);                                                        // interner Pullup-Widerstand aktiviert, hilft gg. Störeinflüsse
  for (byte i = 0; i < sizeof(Stellung); i++) {                                     // Stellungen werden als INPUT_PULLUP deklariert 
    pinMode(Stellung[i], INPUT_PULLUP);}                         
  for (byte i = 0; i < sizeof(Relais); i++) {                                       // Relais werden als OUTPUT definiert und alle AUS gestellt
    pinMode(Relais[i], OUTPUT); digitalWrite(Relais[i], LOW);}   
  
  attachInterrupt(0, statusinterrupt, LOW);                                         // "Interrupt 0" ist Pin 2! void Statusinterrupt() wird aufgerufen

  lcd.init();                                                                       // Initialisierung LCD
  lcd.backlight();                                                                  // Hintergrundbeleuchtung an
}

void statusinterrupt() {                                                            // hier wird der Status auf "true" gesetzt (wenn der Interrupt auslöst)
  status500ms = true;
}

void Drehknopf() {                                                                  // Abfrage des Drehknopfes
  while ((Stellung_Drehknopf_alt != Stellung_Drehknopf) &&                          // so lange der alte und neue Drehknopfwert ungleich sind ...
         (millis() - schaltzeit >= 2000)) {                                         // und die Schaltzeit zwischden den Stufen > 2 Sekunden (ermöglicht das Durchschalten, ohne dass direkt jede Schaltstellung des Drehschalters aktiv wird) ...
    for (byte i = 0; i < sizeof(Stellung); i++) {
      if ((digitalRead(Stellung[i]) == LOW) && (aktuelle_pruefung != i)) {          // ... lese nacheinander die digitalen Eingänge, sofern sie gg. GND geschaltet und nicht bereits ausgewählt sind
        Stellung_Drehknopf = i;
        Stellung_Drehknopf_alt = Stellung_Drehknopf;
        Pruefungsmarker[i] = true;                                                  // setze jeweiligen Prüfungsmarker auf true
        break;
      }
    }
  }
}

void Pruefung_0() {                                                               // 230V, Pin 6 auf +12V, Spannung zwischen Pin 7 & Pin 3/4 messen:
  schaltzeit = millis();                                                          // Zeitstempel für Verzögerung beim Durchschalten
  for (byte i = 0; i < sizeof(Relais); i++) {                                     // alle Relais aus                            
    digitalWrite(Relais[i], schaltzustand_0[i]);                     
  }
  lcd.setCursor (0, 0);
  lcd.print("Stellung 0: Neues   ");
  lcd.setCursor (0, 1);
  lcd.print("Ger\341t anschlie\342en...");
  lcd.setCursor (0, 2);
  lcd.print("                    ");
  lcd.setCursor (0, 3);
  lcd.print("& Pr\365fung w\341hlen... ");
  Stellung_Drehknopf_alt = 10;
  aktuelle_pruefung = 0;
  Pruefungsmarker[0] = false;
}
void loop() {
  Drehknopf();
  if (Pruefungsmarker[0] == true) {Pruefung_0();}
  if (Pruefungsmarker[1] == true) {Pruefung_1();}
  if (Pruefungsmarker[2] == true) {Pruefung_2();}
  if (Pruefungsmarker[3] == true) {Pruefung_3();}
  if (Pruefungsmarker[4] == true) {Pruefung_4();}
  if (Pruefungsmarker[5] == true) {Pruefung_5();}
  if (Pruefungsmarker[6] == true) {Pruefung_6();}
  if (Pruefungsmarker[7] == true) {Pruefung_7();}
  if (Pruefungsmarker[8] == true) {Pruefung_8();}
  if (Pruefungsmarker[9] == true) {Pruefung_9();}
}

Ich habe die Schaltzustände auch noch in Arrays gepackt - das gefällt mir jetzt nochmal wieder besser! ich habe dadurch insgesamt ca. 150 (!!) Zeilen zum Urspungscode eingespart :slight_smile:
Ich belasse es nun wirklich dabei, aber bei den Funktionen klemme ich mich noch hinter!

Was auch mit der Übersichtlichkeit hilft ist Variablen die zusammengehören in eine Struktur zusammenzufasssen. Und dann ein Array daraus zu machen:

struct Stellung
{
  const byte pin;
  const byte relaisZustand[3];
  bool marker = false;
};

Stellung drehknopf[] =
{
  { 3, { 0, 0, 1 } },
  { 4, { 1, 0, 1 } }
};

const byte ANZAHL_STELLUNGEN = sizeof(drehknopf) / sizeof(drehknopf[0]);

void setup()
{
  Serial.begin(9600);

  for (byte i = 0; i < ANZAHL_STELLUNGEN; i++)
  {
    Serial.print(drehknopf[i].pin);
    Serial.print(" -> ");
    for (byte j = 0; j < sizeof(drehknopf[0].relaisZustand); j++)
    {
      Serial.print(drehknopf[i].relaisZustand[j]); 
      Serial.print(" ");
    }
    Serial.println();
  }

  Serial.println();
  //Oder einfacher mit for each. Lese: für jedes Objekt stellung im Array drehknopf mach folgendes
  for (auto& stellung : drehknopf)   //Referenz da es sich um ein Objekt handelt. Dadurch wird keine Kopie angelegt
  {
    Serial.print(stellung.pin);
    Serial.print(" -> ");
    for (auto zustand : stellung.relaisZustand)
    {
      Serial.print(zustand);
      Serial.print(" ");
    }
    Serial.println();
  }

}

void loop()
{
}

EDIT: Arrays für Relais gleich in die Struktur gepackt und Dinge etwas sinnvoller benannt

Das sieht man auch wie viel schöner ein for each ist :slight_smile:

Ansonsten gibt es auch noch zwei-dimensionale Arrays. Damit lässt sich die Durchnummerierung der Zustände auch vermeiden

Und gewöhne dir an const für Konstanten zu verwenden. Auch deine Relais Pins sind besser so:

const byte Relais_3B = 29;

Moin,

Serenifly:
[…] Ich wollte dich nur nicht völlig verwirren. […]

also spätestens jetzt isses soweit :grinning:
Ich find das super als Denkanstoß, denn ich wusste ja nichtmal dass sowas hier möglich ist:

Serenifly:
Was auch mit der Übersichtlichkeit hilft ist Variablen die zusammengehören in eine Struktur zusammenzufasssen. Und dann ein Array daraus zu machen:

struct Stellung

{
  const byte pin;
  const byte relaisZustand[3];
  bool marker = false;
};

Stellung drehknopf =
{
  { 3, { 0, 0, 1 } },
  { 4, { 1, 0, 1 } }
};

const byte ANZAHL_STELLUNGEN = sizeof(drehknopf) / sizeof(drehknopf[0]);

void setup()
{
  Serial.begin(9600);

for (byte i = 0; i < ANZAHL_STELLUNGEN; i++)
  {
    Serial.print(drehknopf[i].pin);
    Serial.print(" → “);
    for (byte j = 0; j < sizeof(drehknopf[0].relaisZustand); j++)
    {
      Serial.print(drehknopf[i].relaisZustand[j]);
      Serial.print(” ");
    }
    Serial.println();
  }

Serial.println();
  //Oder einfacher mit for each. Lese: für jedes Objekt stellung im Array drehknopf mach folgendes
  for (auto& stellung : drehknopf)  //Referenz da es sich um ein Objekt handelt. Dadurch wird keine Kopie angelegt
  {
    Serial.print(stellung.pin);
    Serial.print(" → “);
    for (auto zustand : stellung.relaisZustand)
    {
      Serial.print(zustand);
      Serial.print(” ");
    }
    Serial.println();
  }

}

void loop()
{
}



EDIT: Arrays für Relais gleich in die Struktur gepackt und Dinge etwas sinnvoller benannt

Das sieht man auch wie viel schöner ein for each ist :)


Ansonsten gibt es auch noch zwei-dimensionale Arrays. Damit lässt sich die Durchnummerierung der Zustände auch vermeiden

Und gewöhne dir an const für Konstanten zu verwenden. Auch deine Relais Pins sind besser so:


const byte Relais_3B = 29;

Ich lasse mein “Progrämmchen” jetzt erstmal so, behalte deinen Vorschlag aber im Hinterkopf.

Vielen Dank für Deine Mühen!!!

Viele Grüße,
Marcus

Mir ist klar dass du Anfänger ist und nicht die Möglichkeiten, aber Datenstrukturen sind wirklich der absolute Kern jedes Programms. Über sowas sollte man nachdenken bevor man überhaupt die erste Zeile schreibt. Und nicht etwas was man nachträglich erledigt wenn schon alles geht

Strukturen zeigen dir sofort was zusammengehört. Alles in getrennten Variablen und Arrays zu haben geht bei so kleinen Programmen noch. Aber selbst da muss man unnötig überlegen wie es funktioniert wenn man sich das später nochmal anschaut

Ansonsten eben wenigstens ein zwei-dimensionales Array für die Relais-Zustände verwenden, damit du nicht wieder diese doofe Durchnummerierung hast. Das solltest du immer wenn möglich vermeiden Da