Einlesen eines 4 stufigen Drehschalters, je nach Schaltstellung anderes Relais schalten

Hallo Forum.

ich befinde mich noch in Kinderschuhen, was Programmieren mit Arduino angeht. Ich habe insgesamt eine Temperatursteuerung verschiedener Teilsegmente vor. Diese Teilsegmente sollen mittels einem 4 stufigen Drehschalter gewählt werden. Auf Stufe 0 sollen alle anzusteuernden Relais ausgeschalten sein. Stufe 1 am Drehschalter soll Relais 1 schalten usw.
Die Relais sind im Moment nur zum Probieren eingebaut. Später sollen in den jeweiligen IF Blöcken verschiedene Temperaturabfragen, Ventilsteuerungen usw. rein.

Ich versuche, nicht alles miteinander zu programmieren, sondern erstmal die einzelnen Blöcke und später dann eben zusammenfügen, das denke ich fürs Verständnis erstmal sinnvoll.

Nun zu meinem Problem:

benutzen tu ich einen Arduino UNO

Wenn ich von Schaltstufe 0 auf 1 schalte, schaltet Relais 1 und 2
von 1 auf 2 schalten Relais 1 und 2 aus
von 2 auf 3 schaltet nichts
von irgendetwas auf 0 zurück passiert ebenfalls nichts.

Nun meine Frage:

Liegts an meinem Code oder muss ich wo anders suchen.

Danke schon mal für Eure Hilfe.

LG

//Definition Ausgänge

int RELAIS1 = 5;
int RELAIS2 = 6;
int RELAIS3 = 7;

//Definition Eingänge
int TASTER1 = 8;
int TASTER2 = 9;
int TASTER3 = 10;

int Schalter1 ;
int Schalter2 ;
int Schalter3 ;



void setup()
{
  // Setzen der Ausgänge
  pinMode(RELAIS1, OUTPUT);
  pinMode(RELAIS2, OUTPUT);
  pinMode(RELAIS3, OUTPUT);

  // Setzen des entprellten Eingangs
  pinMode(TASTER1, INPUT_PULLUP);
  pinMode(TASTER2, INPUT_PULLUP);
  pinMode(TASTER3, INPUT_PULLUP);
}

void loop()
{
  //Abfragen des Status des Drehschalters mit 4 Schaltpositionen
  Schalter1 = digitalRead(TASTER1);
  Schalter2 = digitalRead(TASTER2);
  Schalter3 = digitalRead(TASTER3);

delay(1000);
  
 //Abfrage der ersten Schaltstufe des Drehschalters 
 if (Schalter1 == HIGH) {

  delay(200);
  //Schalten der Ausgänge, Relais 1 soll schalten, wenn Schaltstufe 1 des Schalters ein ist    
  digitalWrite(RELAIS1, HIGH);
  digitalWrite(RELAIS2, LOW);
  digitalWrite(RELAIS3, LOW);
    }

  else if (Schalter2 == HIGH) {
    
  delay(200);
   //Schalten der Ausgänge, Relais 2 soll schalten, wenn Schaltstufe 2 des Schalters ein ist   
  digitalWrite(RELAIS1, LOW);
  digitalWrite(RELAIS2, HIGH);
  digitalWrite(RELAIS3, LOW);
    }

  else if (Schalter3 == HIGH) {

  delay(200);
   //Schalten der Ausgänge, Relais 3 soll schalten, wenn Schaltstufe 3 des Schalters ein ist   
  digitalWrite(RELAIS1, LOW);
  digitalWrite(RELAIS2, LOW);
  digitalWrite(RELAIS3, HIGH);
    }
    
  else if (Schalter1 == LOW && Schalter2 == LOW && Schalter3 == LOW)
   {
      //Schalten der Ausgänge, Schaltstufe 0, alle Relais sollen aus sein  

      delay(200);
      digitalWrite (RELAIS1, LOW);
      digitalWrite (RELAIS2, LOW);
      digitalWrite (RELAIS3, LOW);
    }

}

Sie wollen die Zustandsänderungen erkennen, nicht den Zustand selbst. Außerdem müssen Sie die Prellungen Ihrer Taster berücksichtigen.

Eine Bibliothek, die Taster verwaltet, wird Ihnen das Leben erleichtern.

Hallo,

mit dem Post ist ein verwandtes Thema aufgepflobbt und ich konnte das Problem lösen.

HIGH und LOW war komplett vertauscht.

Anbei nochmal der Code. Jetzt funktionierts ;-)

Danke

//Definition Ausgänge

int RELAIS1 = 5;
int RELAIS2 = 6;
int RELAIS3 = 7;

//Definition Eingänge
int TASTER1 = 8;
int TASTER2 = 9;
int TASTER3 = 10;

int Schalter1 ;
int Schalter2 ;
int Schalter3 ;



void setup()
{
  // Setzen der Ausgänge
  pinMode(RELAIS1, OUTPUT);
  pinMode(RELAIS2, OUTPUT);
  pinMode(RELAIS3, OUTPUT);

  // Setzen des entprellten Eingangs
  pinMode(TASTER1, INPUT_PULLUP);
  pinMode(TASTER2, INPUT_PULLUP);
  pinMode(TASTER3, INPUT_PULLUP);
}

void loop()
{
  //Abfragen des Status des Drehschalters mit 4 Schaltpositionen
  Schalter1 = digitalRead(TASTER1);
  Schalter2 = digitalRead(TASTER2);
  Schalter3 = digitalRead(TASTER3);


  
 //Abfrage der ersten Schaltstufe des Drehschalters 
 if (Schalter1 == LOW) {

  delay(200);
  //Schalten der Ausgänge, Relais 1 soll schalten, wenn Schaltstufe 1 des Schalters ein ist    
  digitalWrite(RELAIS1, LOW);
  digitalWrite(RELAIS2, HIGH);
  digitalWrite(RELAIS3, HIGH);
    }

  else if (Schalter2 == LOW) {
    
  delay(200);
   //Schalten der Ausgänge, Relais 2 soll schalten, wenn Schaltstufe 2 des Schalters ein ist   
  digitalWrite(RELAIS1, HIGH);
  digitalWrite(RELAIS2, LOW);
  digitalWrite(RELAIS3, HIGH);
    }

  else if (Schalter3 == LOW) {

  delay(200);
   //Schalten der Ausgänge, Relais 3 soll schalten, wenn Schaltstufe 3 des Schalters ein ist   
  digitalWrite(RELAIS1, HIGH);
  digitalWrite(RELAIS2, HIGH);
  digitalWrite(RELAIS3, LOW);
    }
    
  else if (Schalter1 == HIGH && Schalter2 == HIGH && Schalter3 == HIGH)
   {
      //Schalten der Ausgänge, Schaltstufe 0, alle Relais sollen aus sein  

      delay(200);
      digitalWrite (RELAIS1, HIGH);
      digitalWrite (RELAIS2, HIGH);
      digitalWrite (RELAIS3, HIGH);
    }

}

Ihr delay() ist wahrscheinlich lang genug, um das Prellen der Taster nicht zu sehen, und Sie wiederholen vermutlich mehrere tausend Mal pro Sekunde den Befehl für die Relais.

Intellektuell ist das nicht besonders befriedigend, da man in der Regel den Befehl nur einmal beim Zustandswechsel des Tasters ausgibt, aber wenn es für Sie so passt, ist das kein Problem. Es erfüllt seinen Zweck.

Willkommen im Club. Wenn du am Anfang bist, lerne es bitte gleich richtig.

Ein paar Sachen sind mir aufgefallen:

Der Datentype int ist zu groß. byte oder uint8_t reicht. Noch besser als Konstante:
constexpr uint8_t RELAIS1 { 5 };

Warum nennst du es Taster, wenn es ein Schalter ist.

Durchzählen von Variablen ist auch schlecht. Dafür wurden arrays erfunden.

ist eine nette Funktion. Bei ganz einfachen Programmen funktioniert es auch. Aber relativ schnell wirst du merken, das dein Programm hängt und nicht auf Eingaben reagiert. Schau dir mal die Programierung mit millis() an.

Ohne Schaltplan für uns nicht zu finden...

Ich nenn solche Varianten gerne PIN_xxx und constexpr dürfen die sein.

Ich würde noch den Code der die Schalterstellung bestimmt in eine Funktion rausziehen. Dann kann man das if-else Konstrukt mit einem switch-case ersetzen.

Du denkst zu kompliziert.
Das ist ein typischer Fall, wo in einer Schleife alle Deine Codewiederholungen wegfallen können.

Wenn nur das Relais ausgelöst werden soll, welches der Schalterstellung entspricht, dann kannst Du das direkt ohne Zwischenvariable umsetzen.

Auf das delay kannst Du verzichten, da die Relais entschieden langsamer sind, als das prellen der Tasten.

Was sich nicht ändern kann, mach zu Konstanten,
Und Du hast gemerkt, dass Du mehrmals in Deinem Code die Umstellung von HIGH auf LOW händisch machen musst.
In der folgenden Variante gibt es eine Konstante, die geändert wird und dmit im gesamten Code alles erledigt.
Es gibt keine Kommentare. Die Variablen und Konstanten sowie die Funktionen sind eigentlich selbsterklärend.

// Forensketch
// https://forum.arduino.cc/

const bool relaisEin = LOW;
const bool tasteGedrueckt = LOW;

const uint8_t switchNums = 3;

const bool relaisAus = !relaisEin;
const uint8_t relaisPin[switchNums] = {5, 6, 7};
const uint8_t switchPin[switchNums] = {8, 9, 10};

void setup()
{
  for (uint8_t b = 0; b < switchNums; b++)
  {
    pinMode(switchPin[b], INPUT_PULLUP);
    pinMode(relaisPin[b], OUTPUT);
    digitalWrite(relaisPin[b], relaisAus);
  }
}

void loop()
{
  for (byte b = 0; b < switchNums; b++)
  {
    if (digitalRead(switchPin[b]) == tasteGedrueckt)       
    { digitalWrite(relaisPin[b], relaisEin); }             
    else
    { digitalWrite(relaisPin[b], relaisAus); }
  }
}

Die Konstante switchNums kann man sich auch sparen und das noch ein wenig verfeinern.

Dann sähe das u.a. wie folgt aus:

// Forensketch
// https://forum.arduino.cc/

constexpr bool relaisEin {LOW};
constexpr bool tasteGedrueckt {LOW};

constexpr bool relaisAus {!relaisEin};

struct SW2REL
{
  const uint8_t relaisPin;
  const uint8_t switchPin;
};

SW2REL swrelais[]
{{5, 8,}, {6, 9,}, {7, 10,},};

void setup()
{
  Serial.begin(115200);
  Serial.println(F("\r\nStart...\r\n"));

  for (SW2REL &sr : swrelais)
  {
    pinMode(sr.relaisPin, OUTPUT);
    digitalWrite(sr.relaisPin, relaisAus);
    pinMode(sr.switchPin, INPUT_PULLUP);
  }
}

void loop()
{
  for (SW2REL &sr : swrelais)
  {
    if (digitalRead(sr.switchPin) == tasteGedrueckt)
    { digitalWrite(sr.relaisPin, relaisEin); }
    else
    { digitalWrite(sr.relaisPin, relaisAus); }
  }
}

Hallo,

danke dir für die tolle Erklärung. Mal schauen ob ich das alles nachvollziehen kann, aber ich werds versuchen, alles so umzubauen, dass es ordentlich programmiert ist. Parallel bau ich meine einzelnen Bausteine weiter. Wenn ich weiter bin, schick ich den Code mal wieder zur Kontrolle rein.

Danke euch

Gruß

1 Like

Man kann das stärker kapseln, indem man die Funktionen direkt in die Struct integriert.

constexpr bool relaisEin {LOW};
constexpr bool tasteGedrueckt {LOW};
constexpr bool relaisAus {!relaisEin};

struct SW2REL {
  const uint8_t relaisPin;
  const uint8_t switchPin;

  void begin() const  {
    pinMode(relaisPin, OUTPUT);
    digitalWrite(relaisPin, relaisAus);
    pinMode(switchPin, INPUT_PULLUP);
  }

  void update() const {
    digitalWrite(relaisPin, digitalRead(switchPin) == tasteGedrueckt ? relaisEin : relaisAus );
  }
};

SW2REL swrelais[] { {5, 8},  {6, 9},  {7, 10}};

void setup() {
  for (const SW2REL &sr : swrelais)  sr.begin();
}

void loop() {
  for (const SW2REL &sr : swrelais) sr.update();
}

1 Like