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.