Relais mit Taster Schalten und LCD Lauftext

Hallo,

Ich bin Neuling und habe leider bisher kaum Ahnung oder Erfahrung mit Arduino oder dem Programmieren von solchen.

Mein Projekt ist eigentlich recht einfach - dachte ich.

Ich habe eine 16x2 LCD anzeige (kein I2C) auf welcher ein Lauftext zu sehen ist. Zusätzlich möchte ich mit einem Taster ein Relais ansteuern, welches dann eine definierte zeit geschaltet bleiben soll.

Wenn ich das Relais alleine mit dem Taster betreibe, funktioniert es Wunderbar. Hier der Code den ich verwende:

int rel = 31;
int taster = 30;
int tasterstatus = 0;

void setup()
{
  pinMode(rel, OUTPUT);
  pinMode(taster, INPUT);
}

void loop() {

  tasterstatus = digitalRead(taster);
  if (tasterstatus == HIGH)
  {
    digitalWrite(rel, HIGH);
    delay (2000);
    digitalWrite(rel, LOW);
  }
  else
  {
    digitalWrite(rel, LOW);
  }

}

Das LCD betreibe ich mit folgendem Code:

#include <LiquidCrystal.h>

int Contrast = 75;
LiquidCrystal lcd(41, 42, 43, 40, 45, 46);

//SETUP           SETUP             SETUP

void setup() {

  analogWrite(44, Contrast);
  lcd.begin(16, 2);
  lcd.print("   Lauftext");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("      Zeile2");

}

///LOOP               LOOP             LOOP

void loop() {

  //LCD Anzeige

  {

    for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
      lcd.scrollDisplayLeft();
      delay(400);
    }

    for (int positionCounter = 0; positionCounter < 28; positionCounter++) {
      lcd.scrollDisplayRight();
      delay(400);
    }

    for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
      lcd.scrollDisplayLeft();
      delay(400);
    }

    delay(3000);
  }

Beides für sich funktioniert wunderbar. Also dachte ich mir ich könnte die beiden Codes einfach zusammenfügen:

#include <LiquidCrystal.h>

int Contrast = 75;
LiquidCrystal lcd(41, 42, 43, 40, 45, 46);

int rel = 31;                                                               //Relais
int taster = 30;                                                            //Taster
int tasterstatus = 0;

//SETUP           SETUP             SETUP

void setup() {

  analogWrite(44, Contrast);
  lcd.begin(16, 2);
  lcd.print("   Lauftext");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("      Zeile2");

  pinMode(rel, OUTPUT);                                                   //Relais
  pinMode(taster, INPUT);                                                 //Taster

}

///LOOP               LOOP             LOOP

void loop() {

  //LCD Anzeige

  {

    for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
      lcd.scrollDisplayLeft();
      delay(400);
    }

    for (int positionCounter = 0; positionCounter < 28; positionCounter++) {
      lcd.scrollDisplayRight();
      delay(400);
    }

    for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
      lcd.scrollDisplayLeft();
      delay(400);
    }

    delay(3000);
  }

  //Relais Steuerung

  {
    tasterstatus = digitalRead(taster);
    if (tasterstatus == HIGH)
    {
      digitalWrite(rel, HIGH);
      delay (2000);
      digitalWrite(rel, LOW);
    }
    else
    {
      digitalWrite(rel, LOW);
    }
  }

}

Lesestoff: BlinkwithoutDelay - Die Nachtwächtererklärung

1 Like

Dir fällt das delay() auf die Füße. In der Zeit macht der Prozessor Kaffeepause.
Den Ausweg hat Dir Moko bereits gezeigt.

Gruß Tommy

1 Like

Danke Für eure Antworten und den Verweis auf den "Wachmann". Leider blicke ich da trotz der Erklärung nicht durch bzw ich verstehe nicht wie ich meinen Code auf "millis" umändere.. Also wie und worauf ich das anwenden muss. Ich weiß einem wird schnell Faulheit unterstellt, aber ich steige da wirklich nicht hinter. Wäre jemand so nett und könnte mir genauere Anweisungen geben? Ich habe absolut keinen Plan wie ich

{

    for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
      lcd.scrollDisplayLeft();
      delay(400);
    }

umändern soll.

Evtl. hilft Dir der erste Teil dieses Tutorials von Rentner weiter.
Es ist wichtig, dass Du diese Zusammenhänge verstehst und nicht nur kopierst.

Gruß Tommy

Das sehe ich genauso :wink: Da das "kleine Tutorial" ein wenig mehr zu lesen/testen ist, bedanke ich mich schon mal und arbeite mich jetzt da durch. Ich hoffe das dann der Groschen fällt :sweat_smile:

Ich weiß ja nicht, was du genau machen willst, aber dein Code aus Post 4
könnte so aussehen:

unsigned long scrolltimer;
bool tasterstatus;
int positionCounter = 0;
const int taster = 30;

void setup() {
  pinMode(taster, INPUT_PULLUP);
}

void loop() {
  tasterstatus = !digitalRead(taster);    // Taster einlesen
  if (millis() - scrolltimer > 400 ) {    //  ist die Wartezeit vorbei?
    scrolltimer = millis();                  // Zeit merken.
    if (tasterstatus == HIGH) {              // Wenn Taster gedrückt
      if (positionCounter++ < 14) {          // bis max 14 LCD scrollen
        lcd.scrollDisplayLeft();
      }
    }
  }
}// end loop

Hier wird alle 400ms dein LCD gescrollt, wenn ein Taster gedrückt wurden, aber begrenzt auf 14mal scrollen.

1 Like

Da Du schreibst, das das bisher funktioniert hat, ist mir nicht klar, was der else-Zweig macht.
Bisher ist das delay() nur eine Bremse.
Es gibt keine Initialisierung im setup, was der rel-Pin am Anfang machen soll.
Kann es sein, das Du mit dem else-Zweig das Versäumnis aus dem setup nachholen willst?

Da der Taster ein Relais steuert, würde das Relais nur anziehen, wenn die Wartezeit vorbei, bzw. die Taste nur abgefragt wenn der Umlauf durch ist.

Der Zusammenhang von Tastern und Relais ging für mich nicht aus dem Sketch hervor.
Aber egal. greez2k5 wollte wissen, wie er eine for-delay-Schleife im Zeitscheibenmodell umsetzt.
Nur das wollte ich demonstrieren.

1 Like

Danke für die ganze Hilfe!
Leider ist da wohl etwas durcheinander geraten. Das LCD soll ununterbrochen den Text hin und her scrollen, ganz von alleine, ohne einen Taster oder sonstige "Fremdeinwirkung". Das ist der Programmteil der problemlos funktioniert hat - warum ist mir inzwischen auch klar. (Eben weil das hin- und herscrollen des Textes plus die sonstigen delay ca 26 Sekunden beansprucht haben in denen ich natürlich so oft ich wollte den Taster betätigen konnte und nichts passiert). Unabhängig zu dem scrollenden Text möchte ich per Taster ein Relais schalten. Das LCD hat also nichts mit dem Taster oder dem Relais zu tun. Warum mein Sketch nicht funktioniert habe ich definitiv begriffen, doch die "millis" Funktion macht mir zu schaffen weil ich mir nicht ausmalen kann wie ich die 3 for-delay-Schleifen da reinbekomme und zusätzlich noch den Taster der das Relais für eine vorgegebene Zeit öffnet. Das erschließt sich mir aus den mir zur Verfügung gestellten Erklärungen noch nicht.

Das habe ich so aus einem Tutorial übernommen. Wenn ich das einfach ins Setup schreiben und mir dann sparen kann werde ich das gerne anwenden. Bei genauerer Überlegung ist das auch für mich absolut logisch.

Wie gesagt, es ist alles absolutes Neuland und ich versuche wirklich mein bestes um nachzuvollziehen was da warum passiert. Es ist nur krass viel Input und dann kommt "millis" mit Beispielen die ich nicht auf mein Problem anwenden kann. Warum wollen eigentlich immer alle nur LED´s leuchten lassen :joy:

Ok, dann hab ich das natürlich richtig verstanden.
Na mal schauen - ich versuch mal was.

1 Like

doch doch - das geht.
Ich hab mal was gebaut. Nur fürs relais.
Wichtig: Der Code macht genau das, was Du für das relais vorgibst. Aber: Du hast einen Pin als INPUT definiert. Wenn Du da keinen Widerstand dran hast, der den PIN auf ein definiertes Potenzial zieht, kann da alles mögliche passieren.

Möchtest Du Deinen Aufbau fotografieren oder ein Fritzing oder sonstwas machen, das ich weiss, das Du immer ein definiertes Potential auf den INPUT-Pins hast?

int rel = 31;
int taster = 30;
int tasterstatus = 0;
unsigned long lastmillis = 0;

void setup()
{
  pinMode(rel, OUTPUT);
  pinMode(taster, INPUT);
  digitalWrite(rel, LOW);
}

void loop()
{
  if (digitalRead(taster))
  {
    if (!digitalRead(rel))
    {
      digitalWrite(rel, HIGH);
      lastmillis = millis();
    }
  }
  else if (millis() - lastmillis > 2000)
  {
    digitalWrite(rel, LOW);
  }
}
1 Like

Ich habe den Taster mit einem 1k Ohm Widerstand angeschlossen - so wie es in den meisten Tutorials gezeigt wird.
Hier ein bild meines Aufbaus/meiner Schaltung:

Das ist dann vermutlich ein Widerstand nach GND. Ok, das geht.

Das Bild sehe ich nicht. Und vermutlich wird das da auch bald weg sein - dann sieht später niemand mehr, was Dein Aufbau war. Bitte editiere dden Post von Dir und nutze den Hochladen-Button im Editor, damit es einen Zusammenhang gibt - Danke.
Damit sollte der Sketch von mir gehen - Ändern geht später immer noch - Bitte einmal testen.

Und hier mal insgesamt aus der hohlen Hand.

#include <LiquidCrystal.h>

unsigned int  Contrast = 75;
LiquidCrystal lcd(41, 42, 43, 40, 45, 46);

const byte contrastPin = 44;

const byte rel = 31;
const byte taster = 30;
byte posCounter = 0;
bool tasterstatus = LOW;
byte richtung = 0;
unsigned long relaisEinZeit = 0;

void setup()
{
  analogWrite(contrastPin, Contrast);
  lcd.begin(16, 2);
  lcd.print("   Lauftext");
  delay(1000);
  lcd.setCursor(0, 1);
  lcd.print("      Zeile2");
  pinMode(rel, OUTPUT);
  digitalWrite(rel, LOW);
  pinMode(taster, INPUT);
}


void loop()
{
  anzeige();
  relais();
}

bool tik(const uint32_t startmillis, const uint32_t pause)
{
  if (millis() - startmillis >= pause)
  {
    return true;
  }
  return false;
}

void relais()
{
  if (digitalRead(taster))             // Taster gedrückt? ...
  {
    if (!digitalRead(rel))             // ... und Relais ist aus? ...
    {
      digitalWrite(rel, HIGH);         // ... relais an ....
      relaisEinZeit = millis();        // ... merke zeit für delay (2000);
    }
  }
  if (!digitalRead(rel) && tik(relaisEinZeit, 2000))  // taste ist losgelassen UND Zeit abgelaufen?
  {
    digitalWrite(rel, LOW);            // mache relais aus
  }
}

void anzeige()
{
  static uint32_t myMillis = millis();
  switch (richtung)
  {
    case 0:
      if (posCounter < 14)
      {
        if (tik(myMillis, 400))
        {
          lcd.scrollDisplayLeft();
          posCounter++;
          myMillis = millis();
        }
      }
      else
      {
        richtung = 1;
        posCounter = 0;
        myMillis = millis();
      }
      break;
    case 1:
      if (posCounter < 28)
      {
        if (tik(myMillis, 400))
        {
          lcd.scrollDisplayRight();
          posCounter++;
          myMillis = millis();
        }
      }
      else
      {
        richtung = 2;
        posCounter = 0;
        myMillis = millis();
      }
      break;
    case 2:
      if (posCounter < 14)
      {
        if (tik(myMillis, 400))
        {
          lcd.scrollDisplayLeft();
          posCounter++;
          myMillis = millis();
        }
      }
      else
      {
        richtung = 3;
        posCounter = 0;
        myMillis = millis();
      }
      break;
    case 3:
      if (tik(myMillis, 3000))
      {
        posCounter = 0;
        richtung = 0;
      }
      break;
  }
}

ungetestet und unkommentiert.

Gute Nacht :wink:

1 Like

Also du bist der absolute burner :muscle:t2:
Geil das du dir so viel Arbeit machst :+1:t2:

Mit deinem Sketch läuft das LCD wunderbar und das Relais lässt sich auch schalten. Nur leider geht das Relais an wenn ich den Taster drücke und nicht wieder aus.

Ich werde mich erstmal mit dem Sketch beschäftigen und versuchen den Aufbau und die Funktion genauer zu verstehen. Das "delay(1000);" habe ich aber schon mal aus dem Setup entfernt - es ist eigentlich überflüssig und irritiert mich in dem "delay-freien-Sketch".

Auf jeden Fall noch mal 1000 Dank! Ich komme meinem Ziehl Stück für Stück näher und das nur dank dir/euch. Am ende wird es drei Taster und vier Relais geben - das will ich aber alleine schaffen wenn das Grundgerüst mit einem Relais erstmal so funktioniert wie es soll.

Wenn ich das soweit richtig verstehe, hast du eine Funktion für die Anzeige und eine für das Relais geschrieben welche dann im loop abgerufen werden. Dann ist da jedoch noch dieser Brocken:

bool tik(const uint32_t startmillis, const uint32_t pause)
{
  if (millis() - startmillis >= pause)
  {
    return true;
  }
  return false;
}

Warum steht das nicht im loop drin? Also für mich sieht es zumindest so aus als würde es frei im Raum schweben da es nirgends eingeklammert ist. Oder sehe ich das falsch?

Das sollte nach 2 Sekunden - und wenn die Taste losgelassen ist - wieder ausgehen.
Macht es das nicht, dann ist Dein Widerstand nicht nach GND. (PULLDOWN)

Du kannst das ganze auch ohne Widerstand betreiben und den internen PULLUP verwenden, dann ist nur die Tastenlogik umzuändern.

Logik PULLDOWN     Logik interner PULLUP
+5V -----+
         |
        / 
         |
         |
31  -----+          31 -----+
         |                  |
        | |                 |
        | |                /  
        | |                 |
         |                  |
GND -----+         GND -----+

Nach der Änderung der Verdrahtung
Änderungen in meinem Sketch von oben:
Zeile 25: pinMode(taster, INPUT_PULLUP);
Zeile 46: if (!digitalRead(taster))

1 Like

Habe die Schaltung auf INPUT_PULLUP geändert - leider das selbe Ergebnis.

Hier mal ein Video des ganzen. Vlt hilft das ja.

Video