Einsteiger braucht Programmierhilfe

Hallo, ich würde mir gern eine kleine Steuerung aufbauen. Die Hardware habe ich (Arduino Mega und eine 16 Kanal Relaiskarte) beide sind schon verbunden und funktionieren auch technisch. Mit dem Anfänger Sketch "Blink" alle Relais schon einmal ausprobiert. Nur das die Relais auf OUTPUT LOW anziehen und auf HIGH abfallen, das ist aber kein Problem denke ich, muss man halt umdenken.
Nur am programmieren haperts jetzt bei mir.
Ich bräuchte folgende eigentlich simple Funktionen:

1.Anforderung:
Taster 1 gedrückt - Relais 1 schaltet an und bleibt an bis man Taster 1 ein weiteres mal drückt Taster 1 erneut drücken - Relais 1 schaltet wieder an... usw, also Taster als Schalter sozusagen. Das kann man denn ja kopieren für Taster 2 -Relais 2 u.s.w.
Habe in den Beispielsketches immer nur Taster gedrückt LED an, Taster loslassen LED aus gefunden.

2.Anforderung
Taster Automatik soll einen Zeitlichen Ablauf starten.
Taster Automatik drücken Relais 2 schaltet,hält für ca 30s fällt dann ab, Relais 3 schaltet nach 5s
hält dann für 10s und fällt dann ab. Das ganze auf weitere Relais, wenn man das Grundprinzip weiss kann man es ja erweitern.
Wichtig wäre nur das der Ablauf immer bis zum Ende ausgeführt wird, egal ob man den Automatiktaster zwischendrin betätigt und das der Ablauf immer am Anfang startet.

Für eure Programmiertipps wäre ich sehr dankbar.

Mach Dich mal mit dem Thema "Debounce" oder "Entprellen" vertraut, z.B. hier.

Immer Schritt für Schritt vorgehen, daher erst einmal die Vorgehensweise für die erste Anforderung:
Um es möglichst übersichtlich und den Quellcode leicht verständlich zu gestalten, solltest ein sogenanntes Flag setzen, wenn der Taster gedrückt wird. Das ist eine einfache Variable, die den Zustand High bzw. Low annehmen kann, meinetwegen auch 1 oder 0. Dann ist die Abfolge (also die loop) in etwa so:

  • wenn Taster gedrückt und Flag ist 0 dann setze Flag auf 1
  • wenn Taster gedrückt und Flag ist 1 dann setze Flag auf 0
  • wenn Flag auf 1 steht: Relais anschalten
  • wenn Flag auf 0 steht: Relais ausschalten

Taster sollte man zusätzlich noch entprellen, wie Joghurt bereits anmerkte.

sth77:

  • wenn Taster gedrückt und Flag ist 0 dann setze Flag auf 1
  • wenn Taster gedrückt und Flag ist 1 dann setze Flag auf 0

...wobei darauf zu achten ist dass das Flag nur ein Mal pro Tastendruck umgesetzt wird, daher auch die Sache mit dem Debounce. :wink:

Das kannst Du realisieren, indem Du Dir am Ende der Schleife den Zustand des (entprellten) Tasters merkst, und das Flag nur umsetzt, wenn der Taster "an" ist und der Gemerkte Zustand "aus" anzeigt.

Was in der Richtung:

  if (lastButtonState == LOW && debouncedButton() == HIGH) {
    flag = !flag; // Umschalten
  }
  lastButtonState = debouncedButton();

wie schon die Vorgänger geschrieben haben must du dich mit entprellen beschäftigen.
Für den Anfang geht es so, das delay(100) ist im Moment für das Entprellen da, aber so kannst du das mal testen:

#define Taster 3 
#define Relais1 4  
boolean Letzter, Aktuell, onoff;
//---------------------------------------------------------------------------------
void setup(){
 pinMode(Taster, INPUT); 
 pinMode(Relais1, OUTPUT); 
}

//---------------------------------------------------------------------------------
void loop(){
 Letzter = Aktuell; 
 if (digitalRead(Taster) == HIGH ) Aktuell = true; else Aktuell = false; //auslesen des Tasters
  delay(100);
  if(!Letzter && Aktuell){ // reagiert auf Tasterwechsel von nicht gedrückt auf gedrückt
   if (onoff)
     digitalWrite(Relais1,HIGH);
    else  
     digitalWrite(Relais1,LOW);
  onoff = !onoff; 
 }
}

Für Buttons benutze ich diese Bibliothek:

http://arduino.cc/playground/Code/Buttons

Funktioniert bei mir hervorragend!

Bin ja echt begeistert wie schnell man hier Hilfe bekommt, komme ja kaum mit dem Probieren nach XD, DANKE erstmal dafür.
Der oder das Sketch (wie heisst es eigentlich richtig?) von Jr.Member funktioniert Klasse.
Da meine Relais ja förmlich negiert schalten, bei OUTPUT LOW sind die auf HIGH, war nach dem übertragen des Codes das Relais immer gleich auf HIGH, habe das gelöst indem ich den Taster jetzt gegen GND schalte statt an 5V nun ist es beim Start oder nach Reset zuerst auf LOW. Werde gleich mal auf 3Relais erweitern und probieren und dann hätte ich ja schon meine erste Anforderung erfüllt.
Danke für die Lösung der 1. Anforderung

Meinte natürlich Scetch von maverick1509

beim zweiten könnte ich dir auch helfen wenn ichs denn verstehe.
Ein Taster für 2 Relais, welche zeitversetzt an und ausgeschaltet werden sollen?

Ja bei der 2.Anforderung soll ein zeitlicher Ablauf wie oben beschrieben stattfinden aber eigentlich mit 4-5 Relais. Nochmal zu Deinem 1. Sketch, bin zu blöd den auf weitere Taster und Rlais zu erweitern, habs so probiert

#define Taster1 10
#define Taster2 9
#define Taster3 8
#define Relais1 23
#define Relais2 22
#define Relais3 25
boolean Letzter, Aktuell, onoff;
//---------------------------------------------------------------------------------
void setup(){
 pinMode(Taster1, INPUT);
 pinMode(Taster2, INPUT);
 pinMode(Taster3, INPUT);
 pinMode(Relais1, OUTPUT);
 pinMode(Relais2, OUTPUT);
 pinMode(Relais3, OUTPUT);
}

//---------------------------------------------------------------------------------
void loop(){
 Letzter = Aktuell;
 if (digitalRead(Taster1) == HIGH ) Aktuell = true; else Aktuell = false; //auslesen des Tasters
  delay(10);
  if(!Letzter && Aktuell){ // reagiert auf Tasterwechsel von nicht gedrückt auf gedrückt
   if (onoff)
     digitalWrite(Relais1,LOW);
    else  
     digitalWrite(Relais1,HIGH);
  onoff = !onoff;
 }
{
 Letzter = Aktuell;
 if (digitalRead(Taster2) == HIGH ) Aktuell = true; else Aktuell = false; //auslesen des Tasters
  delay(10);
  if(!Letzter && Aktuell){// reagiert auf Tasterwechsel von nicht gedrückt auf gedrückt
   if (onoff)
     digitalWrite(Relais2,LOW);
    else  
     digitalWrite(Relais2,HIGH);
  onoff = !onoff;
 }
}

aber das will er nicht, bin halt neu und so einfach Copy Paste scheint es doch nicht zu sein, für ne kleine Hilfe wär ich dankbar

Das zweite kannst du auf die schnelle mal so testen:
Ist allerdings nicht die "feine englische Art" da das Programm für 30 Sek in eine Prozedur springt.

#define Taster 3 
#define Relais2 5  
#define Relais3 6  

long start;

//---------------------------------------------------------------------------------
void setup(){
 pinMode(Taster, INPUT); 
 pinMode(Relais2, OUTPUT); 
 pinMode(Relais3, OUTPUT); 
}
//---------------------------------------------------------------------------------
void automatik(){ 
 start=millis();
 while ((millis()-start) < 30000){
  digitalWrite(Relais2,HIGH);
  if (((millis()-start) > 5000) && ((millis()-start)) < 15000)
    digitalWrite(Relais3,HIGH);
   else
    digitalWrite(Relais3,LOW);
 }
 digitalWrite(Relais2,LOW);
}
//---------------------------------------------------------------------------------
void loop(){
 if (digitalRead(Taster) == HIGH ) {
  delay(100); 
 automatik();
}
}

als erstes ist eine geschweifte Klammer "falsch herum"
{
Letzter = Aktuell;

und dann mußt dufür jeden Taster die Variablen deklarieren,
(start1, start2,letzter1..., aktueller1...onoff1....)
dann sollte es gehen.

Das hat funktioniert der Code sieht jetz so aus

#define Taster1 10
#define Taster2 9
#define Taster3 8
#define Relais1 23
#define Relais2 22
#define Relais3 25
boolean Letzter, Aktuell, onoff;
boolean Letzter1, Aktuell1, onoff1;
boolean Letzter2, Aktuell2, onoff2;
//---------------------------------------------------------------------------------
void setup(){
 pinMode(Taster1, INPUT);
 pinMode(Taster2, INPUT);
 pinMode(Taster3, INPUT);
 pinMode(Relais1, OUTPUT);
 pinMode(Relais2, OUTPUT);
 pinMode(Relais3, OUTPUT);
}

//---------------------------------------------------------------------------------
void loop(){
 Letzter = Aktuell;
 if (digitalRead(Taster1) == HIGH ) Aktuell = true; else Aktuell = false; //auslesen des Tasters
  delay(10);
  if(!Letzter && Aktuell){ // reagiert auf Tasterwechsel von nicht gedrückt auf gedrückt
   if (onoff)
     digitalWrite(Relais1,LOW);
    else  
     digitalWrite(Relais1,HIGH);
  onoff = !onoff;
 }

 Letzter1 = Aktuell1;
 if (digitalRead(Taster2) == HIGH ) Aktuell1 = true; else Aktuell1 = false; //auslesen des Tasters
  delay(10);
  if(!Letzter1 && Aktuell1){ // reagiert auf Tasterwechsel von nicht gedrückt auf gedrückt
   if (onoff1)
     digitalWrite(Relais2,LOW);
    else  
     digitalWrite(Relais2,HIGH);
  onoff1 = !onoff1;
 }
 
  Letzter2 = Aktuell2;
 if (digitalRead(Taster3) == HIGH ) Aktuell2 = true; else Aktuell2 = false; //auslesen des Tasters
  delay(10);
  if(!Letzter2 && Aktuell2){ // reagiert auf Tasterwechsel von nicht gedrückt auf gedrückt
   if (onoff2)
     digitalWrite(Relais3,LOW);
    else  
     digitalWrite(Relais3,HIGH);
  onoff2 = !onoff2;
 }
}

und es klappt super mit 3Tastern und 3Relais, weiss jetzt wie ich das richtig erweitere.
DANKE :smiley:
Hab jetzt leider keine Zeit mehr um die Automatik zu probieren, erst am Montag wieder.
Wichtig wäre noch zur Automatik zu sagen das z.T. die gleichen Relais wie mit den Tastern geschaltet werden sollen.

noch was zu deiner Relaiskarte, so eine hatte ich auch mal.
Ich finde die äußerst "blöd", wie kann man eine Relaiskarte bauen, die ständig unter Strom steht,
alle Pins müssen immer auf "HIGH" sein und sind auf "LOW", wenn das Relais anzieht.
Vielleicht kann mir ja einer erklären, warum das so gemacht wird, ich versteh es nicht.

Um welche Relaisplatine handelt es sich denn? Viele Relais haben ja einen Umschaltkontakt, in diesem Produkt sind diese Umschalter als 3 poliger Anschluss (pro Relais) herausgeführt:
http://www.exp-tech.de/product_info.php?info=p201_12v-16-channel-relay-shield.html
Damit hat man also sowohl Öffner- als auch Schließerkontakt. Muss man eben immer schauen, was man denn braucht und was man bekommt... :wink:

hallo,
ich glaube das war so eines:
http://www.ebay.de/itm/2-Kanal-5V-Relay-Relais-Module-Modul-Arduino-ARM-MSP430-8051-AVR-/200718454506?pt=Elektromechanische_Bauelemente&hash=item2ebbc08eea#ht_3710wt_1139

aber trotz dreier Kontakte war das Relais ein Schließer und hatte keinen Umschaltkontakt.
Und der war stromlos geschlossen und das steht nicht in der Beschreibung.

Also das Ding aus dem eBay-Amgebot hat definitiv einen Umschltkontakt. Zum einen muss Relais-seitig das vorgegeben sein (und das ist beim SRD-05VDC-SL-C der Fall), zum anderen müssen die Leiterbahnen auch an die Kontakte geführt werden. In der Angebotsbeschreibung ist auch die Rückseite der Platine abgebildet, da kann man das auch erkennen. Zudem sind die Klemmen K1 und K2 auch entsprechend dargestellt.
Daher meine Frage nochmal, was für ein Produkt ist das denn vom Threadstarter? :wink:

Also die Relaiskarte ist auch von ebay
http://www.ebay.de/itm/DE-Lager-16-Kanal-5V-Relaismodul-Relay-Board-Module-Arduino-MSP430-TTL-Logik-/220959767873?pt=Elektromechanische_Bauelemente&hash=item33723a7d41

Ja das bringt wirklich Probleme musste ich nun feststellen. Glaubte ja die Sache zu überlisten indem ich den Taster gegen GND schalte anstatt gegen +5V, damit ist der Anfangsschaltzustand der Relais LOW. Vom Prinzip her klappt das auch, nur wenn der Arduino startet, man ihn Resetet oder ihm ein code raufläd, schalten die Relais für einen ganz kurzen Moment an und fallen dann ab. Das kann ich so nicht gebrauchen an den Relais sollen Magnetschalter angeschlossen werden und die dürfen natürlich nicht einfach mal "unkontrolliert in die Hände klatschen" :frowning:
Da nützt es auch nichts den Umschalt Kontakt zu benutzen, das würde wiederum bedeuten wenn die Relaiskarte Stromlos ist, ziehen die Magnetschalter an.
Ich verstehe das ohnehin nicht, alle anderen Relais der Karte denen ich noch kein Output vom Arduino zugewiesen hab sind ja auch auf LOW, wieso sind die Relais auf HIGH wenn Arduino LOW sendet und umgekehrt???

Also die Relaiskarte ist wirklich Mist, sie schaltet wenn GND an einem Eingangspin anliegt.
Werde mir jetzt selbst eine bauen nach diesem Vorbild http://www.loetstelle.net/projekte/relaiskarte/relaiskarte.php habe schon mit den Bauteilen auf dem Breadboard getestet. Es funktioniert wie es soll, wenn Arduino HIGH sendet schalten auch die Relais auf HIGH.
Vielen Dank nochmal an maverick1509 auch der Automatik Code

#define Taster 3 
#define Relais2 5  
#define Relais3 6  

long start;

//---------------------------------------------------------------------------------
void setup(){
 pinMode(Taster, INPUT); 
 pinMode(Relais2, OUTPUT); 
 pinMode(Relais3, OUTPUT); 
}
//---------------------------------------------------------------------------------
void automatik(){ 
 start=millis();
 while ((millis()-start) < 30000){
  digitalWrite(Relais2,HIGH);
  if (((millis()-start) > 5000) && ((millis()-start)) < 15000)
    digitalWrite(Relais3,HIGH);
   else
    digitalWrite(Relais3,LOW);
 }
 digitalWrite(Relais2,LOW);
}
//---------------------------------------------------------------------------------
void loop(){
 if (digitalRead(Taster) == HIGH ) {
  delay(100); 
 automatik();
}
}

funktioniert wie ich es mir vorgestellt habe, es wäre nett wenn Du mir noch sagen könntest wie man den Code richtig auf weitere Relais erweitern kann.
Oder falls es jemand anderes weiss kann er es gern mitteilen :slight_smile:

Hallo,
also Erweiterung bedarf schon noch einiger Infos, das ist nicht ganz so einfach. Ich hab ja geschrieben, das der Sketch so funktioniert,
ABER durch die "while" Schleife hängt sich das Programm ja für 30 Sek in der Prozedur "Automatik" auf.
In dieser Zeit sind keine weiteren Tastereingaben möglich. Wenn du mehrere Taster parallel betreiben willst, die verschiedene Relais
schalten sollen, dann wird es komplizierter. Soll das so sein? Da bedarf es noch näherer Infos.
Gruß
Bernward