Ausgang bei Ereignis kurzzeitig schalten

Hallo zusammen,

ich habe ein kleines Problem ( so einen ähnlichen Fall hatte ich schonmal, kann aber mit dem alten Code irgendwie nichts anfangen, komme da nicht weiter).

An einen Nano wird an Pin 10 eine externe Lichtschranke angeschlossen. Wenn jemand vor der Lichtschranke steht fällt das Signal an Pin 10 auf LOW ab, ansonsten HIGH. Das funktioniert schon einmal.

Nun möchte ich dass, sobald das Input Signal an Pin 10 auf LOW abfällt, ein OUTPUT an Pin 2 ebenfalls auf LOW abfällt, aber nur für ca. 500 millisekunden. Danach soll Pin 2 wieder auf HIGH gesetzt werden.

Erst wenn das Eingangssignal an Pin 10 wieder auf HIGH wechselt darf der Prozess wieder von vorne beginnen.

Im Prinzip so > Jemand steht vor die Lichtschranke > jetzt wird nur ein kurzes Signal ausgegeben, also nicht so lange wie tatsächlich jemand vor der Lichtschranke steht.
Das Signal soll erst erneut ausgegeben werden,wenn die Person den Bereich der Lichtschranke wieder verlassen hat, und dann wieder betritt.

Ich habe mal angefangen, komme aber nicht wirklich weiter.

int hupePin = 2;
int lichtschrankePin = 10;
int bewegungsstatus = 0;

bool merker = false;
unsigned long startTime; // Merker Wann hat hupen angefangen
unsigned long hupeTime = 100; // Zeit in ms!


void setup()
{
  pinMode (hupePin, OUTPUT);
  pinMode (lichtschrankePin, INPUT);
}

void loop()
{

.....????

Vielleicht kann mir wieder jemand auf die Sprünge helfen dieses Problem zu lösen,
ich würde mich sehr darüber freuen!

Herzlichen Dank!

Hallo
probier mal:

digitalWrite (hupePin,digitalRead(lichtschrankePin));
// Forensketch - Bei Ereignis ein weiteres einmalig auslösen und beenden
// basiert auf https://forum.arduino.cc/t/ausgang-bei-ereignis-kurzzeitig-schalten/1008177

const byte hupePin = 2;
const byte lichtschrankePin = 10;
//int bewegungsstatus = 0;

bool merker = false;
unsigned long startTime; // Merker Wann hat hupen angefangen
unsigned long hupeTime = 1100; // Zeit in ms!


void setup()
{
  pinMode (hupePin, OUTPUT);
  pinMode (lichtschrankePin, INPUT);
}

void loop()
{
  if (digitalRead(lichtschrankePin) == LOW)
  {
    if (merker == false)
    {
      merker = true;
      startTime = millis();
      digitalWrite(hupePin, HIGH);
    }
  }
  else
  {
    merker = false;
  }
  if (millis() - startTime > hupeTime)
    digitalWrite(hupePin, LOW);
}

Hallo paulpaulson,

vielen Dank, damit hatte ich es schon versucht, kam aber nicht wirklich weiter.. Aber vielen Dank!

Hallo my_xy_projekt,

wow, das passt! Herzlichen Dank für Deine Hilfe, ich bin begeistert!!
Ich hatte igrendwie zu kompliziert gedacht :slight_smile:

Ich wünsche euch allen einen schönen Abend!

Dann hier die berichtigte kürzerFassung.
Und dann stell das auf gelöst :wink:

// Forensketch - Bei Ereignis ein weiteres einmalig auslösen und beenden
// basiert auf https://forum.arduino.cc/t/ausgang-bei-ereignis-kurzzeitig-schalten/1008177

const byte hupePin = 2;
const byte lichtschrankePin = 10;
//int bewegungsstatus = 0;

bool merker = false;
unsigned long startTime; // Merker Wann hat hupen angefangen
const unsigned long hupeTime = 1100; // Zeit in ms!

void setup()
{
  pinMode (hupePin, OUTPUT);
  pinMode (lichtschrankePin, INPUT);
}

void loop()
{
  if (!digitalRead(lichtschrankePin))
  {
    if (!merker)
    {
      merker = true;
      startTime = millis();
      digitalWrite(hupePin, HIGH);
    }
  }
  else
    merker = false;
  if (millis() - startTime > hupeTime)
    digitalWrite(hupePin, LOW);
}

Kleine Ergänzung:

Falls das Lichtschrankensignal innerhalb hupeTime wechselt, verlängert sich die Schaltzeit entsprechend.

Ggf. wäre es sinnvoll, das noch zu "debouncen"? Also das Schalten von hupePin erst nach Ablauf einer Zeit größer als hupeTime zuzulassen...

Ich würde gerne etwas ganz bestimmtes herausfinden.
Ich möchte herausfinden ob ich mit meiner Vermutung falsch oder richtig liege.

Meine Vermutung: Wenn im Programm zwei Dinge gemacht werden:

  1. konsequent möglichst spezifische und selbsterklärende Namen wählen
  2. zusätzlich viele Kommentare hinzufügen

Diese Kombination aus 1.) und 2.) führt möglicherweise zu mehr Verwirrung als zu Erklärung. Und das ist das was ich herausfinden will.

Welche Art der Programmierung ist für dich als Einsteiger leichter verständlich
Ich bin jetzt explizit auf eine vergleichende Bewertung aus.
Ein Stil kurze Variablennamen relativ wenig Kommentare im Vergleich zu
lange selbsterklärende Namen und zusätzliche Konstanten plus oben drauf viele Kommentare.

Das ist für mich eine wirklich offene Frage an user @zappzerapp4
Ich möchte daraus erfahren welcher Stil leichter verständlich ist.

hier meine Code-Version


const byte hupePin = 2;
const byte lichtschrankePin = 10;
byte LS_State;
byte LS_lastState;

bool LS_flanke_HIGH_LOW = false;

unsigned long startHupe; // Variable für ZeitStempel Wann hat hupen angefangen
unsigned long hupeEinschaltZeit = 500; // Zeit in ms!

#define LS_unterbrochen LOW
#define Einschalten HIGH
#define Ausschalten LOW

void setup() {
  pinMode (hupePin, OUTPUT);
  pinMode (lichtschrankePin, INPUT);
}


void loop() {

  LS_State = digitalRead(lichtschrankePin);// IO-pin status einlesen und speichern

  if (LS_lastState != LS_State) { // prüfe ob sich IO-pin status geändert hat
    // WENN sich IO-pin-Status geändert hat
    if (LS_State == LS_unterbrochen) { // prüfe ob NEUER Zustand Lichtschranke unterbrochen ist
      // WENN Lichtschranke unterbrochen ist
      LS_flanke_HIGH_LOW = true; // setze Flankenmerker
    }

    LS_lastState = LS_State; // nach dem Vergleich if (LS_lastState != LS_State) LS_lastState aktualisieren
  }

  if (LS_flanke_HIGH_LOW) { // prüfe ob es eine HIGH_LOW-FLANKE ist
    // WENN es eine HIGH-LOW-Flanke ist
    LS_flanke_HIGH_LOW = false; // flankenmerker zurücksetzen
    startHupe = millis();  // aktuellen Zeitstempel speichern
    digitalWrite(hupePin, Einschalten);
  }

  if (millis() - startHupe >= hupeEinschaltZeit) { // prüfe ob Hupe-Einschaltzeit vorbei ist
    // WENN Hupe-Einschaltzeit vorbei ist
    digitalWrite(hupePin, Ausschalten);
  }

}

Und hier die WOKWI Simulation dazu

Schon klar dass das für jeden user wieder anders ist.
Es geht darum - im Laufe der Zeit viele Einsteiger das zu Fragen um herauszufinden gibt es eine Tendenz.
vgs

Auch wenn du mich nicht explizit gefragt hast, lautet meine Antwort: "Clean Code"!
(google gibt gerne Auskunft)

Das ist mir völlig klar! Deswegen gibt es ja so wenig Programme die das im Ausführlich-Stil machen. Die für mich entscheidende Frage ist aber nicht wie gut gefällt der Code einem Experten sondern die entscheidende Frage für mich ist:

Wie leicht verständlich ist ein Programm das explizit für Einsteiger zum Lernen geschrieben ist.

"Beispiele" zum Code lesen lernen der nullkomma-garnicht kommentiert ist gibt es schon ganz viele.

Und wenn jetzt das Argument kommt damit "versaut" man Einsteigern "clean-coding"
dann antworte ich dazu:

"Ihr Super-Experten macht erst mal das dämliche delay() aus den ganzen Beispielen raus!
Das versaut richtig!
Wenn schon "Anspruch von Anfang an" dann in der Form, dass als erstes nicht-blockierendes timing und state-machine erklärt wird. Und zwar in einem für Einsteiger möglichst leicht verständlichen Tutorial. Nicht durch schnelles reinklatschen von "clean-code"
vgs

Aha und was ist mit kurzen Variablennamen und vielen Kommentaren? :wink: Das erscheint mir logischer. Wenn jemand nur einzelne Buchstaben verwendet, wie das mal vor 40 Jahren "Basic Style" war, dann dürften Kommentare eher hilfreich sein als bei selbsterklärenden Namen.

Es kann nicht der Sinn von Kommentaren sein, den Quellcode noch einmal mit anderen Worten aufzuschreiben.

Richtig!
Der Code sagt/zeigt was getan wird.
Der Kommentar, warum es so getan wird.

Es macht einen Unterschied, ob man "led1" schreibt oder "stoermelderLed". Schon hat man viele Kommentare eingespart.

Das ist ein anderes Kapitel!
Clean Code hat nichts mit dem Unterschied/Differenz verschiedener Algorithmen zu tun.
Das ist eine andere Baustelle.

Das ist eine der Fragen die ich gerne von den Einsteigern selbst beantwortet haben möchte. Ich selbst vermute dass das eine Fehleinschätzung ist. Und um zu klären ob diese Einschätzung zutrifft oder eine Fehleinschätzung ist Frage ich explizit diejenigen die es wirklich berifft: Die Einsteiger
vgs

Und dann macht der selbsterklärende Name Sinn und an der Stelle braucht man dann tatsächlich keinen weiteren Kommentar.

Mal eine andere Frage:

Verwirrt es die werten Experten wenn viele Kommentare drinstehen die den Code mit anderen Worten noch einmal wiedergeben?
Wenn ja, dann ist das mit dem Expertensein wohl noch nicht so richtig gelungen.
vgs

Katze - Maus - Bauer
Bei dem Dreieck ist nicht jedem gleich klar, wer gut und böse ist.
bzw. vom Standpunkt abhängig.

Nein, man fragt nicht den Anfänger, wenn man fortgeschrittene Techniken implementieren möchte.
Wie man auch nicht den Bock zum Gärtner macht.
Aber ok, ich halte mich ab jetzt hier raus!

Doppelte Information ist arg "irritierend"!
Wenn ich mich als Experte betrachte: JA! Mich stört das massiv!

Nicht.

Der LichtschrankePin geht LOW wenn eingetreten wird.
Nur wenn KEIN merker gesetzt ist, geht die Hupe AN
Kommt jetzt der Wechsel von LOW nach HIGH beim verlassen, wird zwar der merker gelöscht, aber es wird kein neues Timing ausgelöst.

Im Original waren 100ms Hupe als Anforderung.
Wenn man nun innerhalb der 100ms vermeiden möchte, das der Timer durch erneutes eintreten ausgelöst wird, müsste mit verlassen das Signal beendet werden.

  if (millis() - startTime > hupeTime || !merker)
    digitalWrite(hupePin, LOW);

Mein Beitrag heute.

Ob redundante Wiederholung dessen, was der Code bereits aussagt, sinnvoll ist oder nicht, ist m.E.

a) von der Qualität des Codes selbst,
b) dem Nutzwert des Kommentars
c) dessen Zweck und damit auch der Zielgruppe

abhängig.

Kommentare, die nur wiederholen, was im Quelltext nachzulesen ist, sind im besten Fall nur für absolute Anfänger hilfreich, in der Regel aber eher "Zeichenverschwendung" beim Erstellen und Lesen...

Umständlich bzw. schwer nachvollziehbar geschriebener Code wird durch Kommentare nicht besser.

Kommentare sollten das ergänzen, was dem Code nicht oder ggf. nur indirekt entnehmbar ist; im optimalen Fall braucht es diese höchstens zur Schnittstellenbeschreibung oder um Grenzen oder Beschränkungen zu beschreiben.

Anders kann dies bei einführenden Beispielen für Anfänger aussehen. Aber auch dort ist der fehlende Kenntnisse ergänzende Charakter von Bedeutung.

Das finde ich ein sehr gutes Kriterium.
vgs

Bin noch nicht überzeugt... Wenn die Lichtschranke "zappelt", wird mit Deinem Code ( wenn ich das im Trockendurchgang richtig interpretiere, kann mich natürlich irren) die startTime neu gesetzt ... Oder täusche ich mich?

Also ich spreche von mehrfachem Wechseln. Bei 100 ms ist das sicher weniger wahrscheinlich, bei den 1100 ms könnte es passieren.

Danke, allerdings ist das herausfordernder, als es zu formulieren ... Es braucht Disziplin, Übung und eine Auseinandersetzung mit der Zielgruppe, für die man kommentiert.

Übersichtlich und nachvollziehbar geschriebener Code ist das A&O.

Vorteilhaft sind i.d.R.

  • kürzere Funktionen, aus denen das Programm in setup() und loop() zusammen gesetzt wird
  • das Vermeiden von mehrfach kopierten Funktionen
  • die Verwendung von globalen Variablen auf das Notwendige beschränken

Damit kann man den Code besser nachvollziehen und in den meisten Fällen einzeln mit definierten Werten (z.B. in setup()) testen, bevor man sie im Verbund in loop() einsetzt.

Das ist sicher ein interessantes Thema ... Aber wir kapern hier gerade den Thread ... ;-(