4 Taster 4 Relais An/Aus schalten

Erstmal ein nettes Hallo an die Comunity,

Ich bin absolut neu auf dem Gebiet des Ardruino und wollte damit nur 3 kleine Projekte zusammenbasteln.

Nun stecke ich schon im Ersten projekt fest :frowning: und hoffe, dass mir hier einer helfen kann.

Ich habe hier 4 Taster und möchte damit gerne 4 Relais schalten.

Taster 1 zum ersten Mal gedrückt = einschalten; Taster 1 erneut drücken = aus
Taster 2 zum ersten Mal gedrückt = einschalten; Taster 2 erneut drücken = aus
.
.
.

Nun habe ich das für den ersten Taster hinbekommen und weiss nicht, wie ich in das Programm die 3 noch fehlenden Taster einbinden muss.

const int buttonPin = 4;
const int RE1 = 6;
int merker=0;

int buttonState = 0;

void setup()
{
pinMode(RE1, OUTPUT);
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}

void loop()
{
buttonState = digitalRead(buttonPin);

if ((buttonState == HIGH)&&(merker==0))
{
digitalWrite(RE1, HIGH);
merker=1;
}

if ((buttonState == LOW)&&(merker==1))
{
merker=2;
}

if ((buttonState == HIGH)&&(merker==2))
{
digitalWrite(RE1, LOW);
merker=3;
}
if ((buttonState == LOW)&&(merker==3))
{
merker=0;
}

Serial.print("Merker= ");
Serial.println(merker);
}

Hallo und willkommen im Forum!

Deinen Sketch packst Du bitte in code-Tags, das ist der Button </>, damit er besser lesbar ist.

Da Du es geschafft hast, nicht blockierenden Code zu schreiben, kannst Du den Inhalt von loop vervielfältigen. Die Konstanten und Variablen brauchen natürlich für jeden Taster und jedes Relais eindeutige Namen, also buttonPin1 und merker1 usw.

Ebenfalls möglich sind Felder (arrays), also const byte buttonPin[] = {4, 5, 6, 7};

Den Inhalt von loop kannst Du auch in eine Funktion verlagern, um dann diese Funktion vier mal aufzurufen.

hast du an deinen Tastern Pulldown Widerstände?
Wenn nein, wäre es besser mit pinMode (x,INPUT_PULLUP) zu arbeiten und die Taster auf LOW abzufragen.

Danke für deine Antwort :slight_smile:

Also ich beschreib am besten mal den Aufbau:

ein UNO

da dran hängt ein Boort mit 4 Relais und die Taster sind keine direkten Taster, sondern ein Funkempfänger für eine 4 Tasten Fehrnbedinung.

Wie gesagt ich hab da leider noch keine Ahnung von ...ich weis nur wie ich den pin den namen zuortne und in/output definire
Hatte beim schreiben einen Bekanten hir der mir den weg für den Ersten Taster geschriben hat.

Es wer super wenn mir eine in den bestehenden code den 2 Taster schreiben könne ( so könnt ich es dan warscheinlich besser nachvolzihen und die weiteren Taster selbst ein binden )

( taster 2 wer dan z.B. buttonPin2 = 2; RE2 = 7; )

Evt. Hat jemand auch einen besseren weg wie man das schreiben könnte .

const int buttonPin1 = 4;
const int RE1 =  6;
int merker=0;

int buttonState = 0;       

void setup()
  {
    pinMode(RE1, OUTPUT);     
    pinMode(buttonPin1, INPUT);
    Serial.begin(9600);
  }

void loop()
{
   buttonState = digitalRead(buttonPin1);

  if ((buttonState == HIGH)&&(merker==0))
    {   
      digitalWrite(RE1, HIGH);
      merker=1;
    }
   
  if ((buttonState == LOW)&&(merker==1))
    {   
      merker=2;
    }
   
  if ((buttonState == HIGH)&&(merker==2))
    {
       digitalWrite(RE1, LOW);
       merker=3;
    }
   if ((buttonState == LOW)&&(merker==3))
    {   
       merker=0;
    }
       
    Serial.print("Merker= ");
    Serial.println(merker);
}

Hast du das denn schon gebaut und ausprobiert?
Prima. Dann ist in deinem Fall ein Funkempfänger einfacher als echte Taster, Glückwunsch

Trau dich doch einfach, es so zu machen:

const int buttonPin1 = 4;
const int RE1 =  6;
const int buttonPin2 = 5;
const int RE2 =  7;
int merker1=0;
int merker2=0;
 

void setup()
  {
    pinMode(RE1, OUTPUT);     
    pinMode(RE2, OUTPUT);     
    pinMode(buttonPin1, INPUT);    
    pinMode(buttonPin2, INPUT);
    Serial.begin(9600);
  }

void loop()
{
   int buttonState = digitalRead(buttonPin1);   // braucht nicht global gemerkt zu werden

  if ((buttonState == HIGH)&&(merker1==0))
    {   
      digitalWrite(RE1, HIGH);
      merker1=1;
    }
   
  if ((buttonState == LOW)&&(merker1==1))
    {   
      merker1=2;
    }
   
  if ((buttonState == HIGH)&&(merker1==2))
    {
       digitalWrite(RE1, LOW);
       merker1=3;
    }
   if ((buttonState == LOW)&&(merker1==3))
    {   
       merker1=0;
    }
       
    Serial.print("Merker1= ");
    Serial.println(merker1);
// Taster 2 -------------------------------------
   buttonState = digitalRead(buttonPin2);   // buttonstate ist frei für den nächsten Taster

  if ((buttonState == HIGH)&&(merker2==0))
    {   
      digitalWrite(RE2, HIGH);
      merker2=1;
    }
   
  if ((buttonState == LOW)&&(merker2==1))
    {   
      merker2=2;
    }
   
  if ((buttonState == HIGH)&&(merker2==2))
    {
       digitalWrite(RE2, LOW);
       merker2=3;
    }
   if ((buttonState == LOW)&&(merker2==3))
    {   
       merker2=0;
    }
       
    Serial.print("Merker2= ");
    Serial.println(merker2);

}

Wenn es dir blöd vorkommt, das nochmal zu verdoppeln, hast du natürlich recht.
Vor allem, weil du dich leicht vertippen kannst und das ganz schwer zu findende Fehler werden.

Entweder du machst es trotzdem und hat dein Projekt fertig,

oder du lernst was über Funktionen in C,
und schreibst dann das ganze in eine Funktion um,
die 4 mal aufgerufen wird.

Aber das mach mal selber und melde dich erst, wenn es klemmt.

Ich würde so eine Funktion erfinden:

byte TRelais ( byte PinTaster, byte PinRelais, byte Merker )
{
// liest Taster Zustand und schaltet je nach Merker das Relais
// gibt den neuen Merker-Zustand zurück
// ... und jetzt du ...
}

Du kannst übrigens auch int statt byte nehmen. Da gewöhnst du dir nur ein bisschen Schlamperei an, geht aber eigentlich genauso gut.

Dann wird dich wohl stören, dass Serial.print viel zu viel ausgibt.
Nun wird es knifflig: Nur wenn das Ergebnis von TRelais etwas anderes ist als der alte Merker, ausschreiben. Beim nächsten loop - Durchlauf muss natürlich der neue Merker-Wert mitgegeben werden. ( ... und jetzt du ... )

ich habe einen etwas anderen Weg als Michael, schau ihn dir mal an:

const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int Rel1 =  6;
const int Rel2 =  7;
const int Rel3 =  8;
const int Rel4 =  9;
boolean last_state_1;
boolean last_state_2;
boolean last_state_3;
boolean last_state_4;

void setup()
  {
    pinMode(Rel1, OUTPUT); 
    pinMode(Rel2, OUTPUT); 
    pinMode(Rel3, OUTPUT); 
    pinMode(Rel4, OUTPUT); 
        
    Serial.begin(9600);
  }

void loop()
{
  boolean button1=(digitalRead (buttonPin1));
   if (!button1)
  {
  if (!last_state_1)
    {
    static boolean state;
    last_state_1 =1;
    digitalWrite (Rel1, state);
    state=!state;
    }
  }
  else last_state_1 =0;
  
 boolean button2=(digitalRead (buttonPin2));
   if (!button2)
  {
  if (!last_state_2)
    {
    static boolean state;
    last_state_2 =1;
    digitalWrite (Rel2, state);
    state=!state;
    }
  }
  else last_state_2 =0;
  

}

Man könnte auch die Pins in einem Array definieren und das einfach in eine for-Schleife packen.

const int ButtonPin[4] = {4,5,10,11};    // Pins an denen die Taster angeschlossen sind
const int RelaisPin[4] =   {6,7,8,9};       // Pins die die Relais treiben
boolean RelaisState[4] = {0,0,0,0};      // Array in dem der Status der Relais gespeichert wird
boolean ButtonStatelast[4] = {0,0,0,0}; 
     
void setup(){
    Serial.begin(9600);
    for (int i = 0; i<4; i++){            
      pinMode(RelaisPin[i], OUTPUT);     
      pinMode(ButtonPin[i], INPUT);
    }
}
    

void loop(){

  for (int i=0; i<4; i++){                                   // nacheinander alle 4 Pins abfragen und auswerten.
   boolean ButtonState = digitalRead(ButtonPin[i]);                 // taster einlesen
   boolean Buttonpressed = ButtonState && !ButtonStatelast[i];      // Taste wurde gedrückt wenn letzter Status = 0 und neuer = 1
   ButtonStatelast[i] = ButtonState;                                // nach auswertung Taste Wert wieder merken.

    
   if (Buttonpressed == true) {                                        // wenn Taster gedrückt
     RelaisState[i] = !RelaisState[i];                               // Relaistate ändern
     digitalWrite(RelaisPin[i], RelaisState[i]);                     // und auf Relaispin auusgeben.

     for (int i=0; i<4; i++){                                       // Serielle Ausgabe der Relaisstati
      Serial.print("\tRE");Serial.print(i);Serial.print(": ");Serial.print(RelaisState[i]);
     }
     Serial.println();
   }
  }
}// end loop

Achtung, ungetesteter Code

@Lorks: du siehst: viele Wege führen nach Rom....

Hallo Gunther,
kleine Optimierungsvorschläge:

  1. Da loop schon eine Schleife ist, könnte die for-Schleife durch i++ und Rückführung auf 0 ersetzt werden.

  2. Die for-Schleife für Serial.print gibt zu viel aus und könnte entfallen. Nur die Schleife, nicht Serial.print.

Was meinst Du?

agmue:
Hallo Gunther,
kleine Optimierungsvorschläge:

  1. Da loop schon eine Schleife ist, könnte die for-Schleife durch i++ und Rückführung auf 0 ersetzt werden.

  2. Die for-Schleife für Serial.print gibt zu viel aus und könnte entfallen. Nur die Schleife, nicht Serial.print.

Was meinst Du?

ja, man hätte anstelle der for Schleife auch als erste Zeile in der loop den Befehl
if (++i >=4) i=0;
setzen können, aber ich finde, das macht das ganze eher kryptisch. for ist einfach leichter zu lesen und zu verstehen.

Aber die Serial.print for-Schleife macht genau das, was sie soll:
Bei jedem Tastendruck den Status aller Relais ausgeben.

Sieht dann so aus:

	RE0: 1	RE1: 1	RE2: 1	RE3: 1
	RE0: 0	RE1: 1	RE2: 1	RE3: 1
	RE0: 1	RE1: 1	RE2: 1	RE3: 1
	RE0: 0	RE1: 1	RE2: 1	RE3: 1

(Bei 4 mal Taste 1 drücken)
Letztlich ist die Serielle Ausgabe und deren Übersichtlichkeit immer Geschmacksache.

guntherb:

  1. Da loop schon eine Schleife ist, könnte die for-Schleife durch i++ und Rückführung auf 0 ersetzt werden.

Man sollte nicht ohne Grund zu viel optimieren. Den Fehler mache ich zugegebenermaßen auch öfters.

Das ist keine Anwendung bei der es auf Geschwindigkeit ankommt. Tastendrucke sind sehr langsam. Also kann man da ohne Probleme Code schreiben der einfacher verständlich ist.

Serenifly:
Man sollte nicht ohne Grund zu viel optimieren. Den Fehler mache ich zugegebenermaßen auch öfters.

Das hatte ich eigentlich nur wegen Dir geschrieben, weil for doch blockierend ist :wink:

guntherb:
Aber die Serial.print for-Schleife macht genau das, was sie soll:
Bei jedem Tastendruck den Status aller Relais ausgeben.

Wenn es so sein soll, dann ist es so gut. Ich bin wohl etwas sparsamer mit der Tinte auf dem Bildschirm ::slight_smile:

Erstmal ein großes Dankeschön an alle für die Hilfe :slight_smile:

Ich hab mir die ersten 2 Wege angepasst und sie laufen Fehler frei :slight_smile:

Bei dem 3. weg muss ich leider passen den kann ich "noch" nicht nach vollziehen aber natürlich auch ein dickes danke da für :slight_smile:

Ich muss woll erst mal befehle lernen :smiley: kennt jemand eine Deutsch sprachige Sammlung wo die befehle einfach für Einsteiger erläutert werden ( beim Google findet man zwar so einiges aber leider meist zu überfüllt ).

lg

Der Verzicht auf Groß- und Kleinschreibung kann zu bösen Missverständnissen führen.

Ich sage nur: "helft den armen vögeln!"

Lorks:
Ich muss woll erst mal befehle lernen :smiley: gibt es da zufällig ne sammlung wo die befehle einfach für einsteiger erlautert werden

Ich schaue in der Referenz, bei den Beispielen der IDE und der Programmbibliotheken. Außerdem lese ich hier im Forum, wodurch ich schon viele Denkanstöße erhalten habe. Aber die Wege zur "Erkenntnis" sind sehr unterschiedlich.