Wie kann man in der <void loop() > Methoden/Funktionen ein- und ausschalten.

  • Ich habe die untenstehende Version noch um eine Variante mit Button-Steuerung ergänzt. Um das Mainprogramm zu vereinfachen wurde eine Lauflichtklasse angelegt, die sich um die Steuerung des Lauflichtes kümmert:




    Die Lauflichtklasse (lauflicht.hpp):



    Der Link zum gesamten Programm: https://wokwi.com/projects/344617497327043154 inkl. Simulation.

  • Hallo Kai

    schön, Dein Beispiel. Für mich ist das C++ lange her und daher müsste ich ich es mir genauer ansehen um die Detail zu verstehen.

    Ein kleiner Hinweis:

    in der Zeile:


    constexpr byte LED_COUNT {sizeof(ledArray)/sizeof(ledArray[0])}; // Größe des Arrays speichern


    berechnest Du die Anzahl der Array members. Dies sieht man in dieser Art eher selten, ist aber genau der richtige Weg.

    Das zweite sizeof() in der Division entspricht der Grösse des Typs, daher würde ich sizeof( Led*) schreiben, was etwas deutlicher wirkt. Natürlich ist in diesem Fall beides identisch und daher richtig.


    Led *ledArray[] {&led3, &led4, &led5, &led6}; // LEDs für Lauflich in Array zusammenfassen
    constexpr byte LED_COUNT {sizeof(ledArray)/sizeof( Led* )}; // Anzahl Led im Array bestimmen


    herzliche Grüsse

    Pius

  • Um nochmal auf C++ zurück zu kommen. Basierend auf den sehr guten Videos von René beginnend mit "Der einfache Einstieg in Arduino & Co. 31 - Klassen und Objekte 1" und folgende, wurde bis zur Videonummer 34 die Programmierung von LED Objekten beschrieben, welche die Fähigkeit zu blinken vererbt bekommen.


    Basierend auf dem Code aus diesen Videos, habe ich die Klassen zu Übungszwecken etwas angepasst, sodass sie auch als Lauflicht und somit auch für @Beduinos Programmbeispiel zu nutzen sind.


    Im folgenden Beispiel wurde jedoch der Taster weggelassen. Es soll nur ums Lauflicht bzw. blinkende LEDs gehen. Es zeigt sich, dass durch C++ und die Objektorientierung sehr wenig Code benötigt wird, der unterschiedliche Anforderungen erfüllen kann. Unübersichtliche Kaskaden von IF-Verschachtelungen und sonstige komplizierte Konstrukte in loop() entfallen. Außerdem ist man nicht darauf angewiesen das die Pins, an denen die Lauflicht-LEDs angeschlossen sind, aufeinanderfolgend sein müssen. Es können im Prinzip beliebige Pins verwendet werden, was eine weitere Flexibilisierung bedeutet.


    Unten der Code als Beispiel für einen ersten Überblick. Es wird ein Lauflicht aus vier LEDs gesteuert. Die Leuchtdauer kann mit einem Potentiometer angepasst werden. Zusätzlich werden noch zwei LEDs (die eingebaute LED auf dem Controllerboard und eine weitere LED an Pin 12) angesteuert, die einfach nur mit individuellen Blinkzeiten vor sich "hinblinken". Dazu ist keinerlei besonderer Code mehr nötig. Es sind nur noch, neben dem Anlegen der Objekte, zwei Anweisungen pro LED notwendig.



    Die Simulation mit dem gesamten Code (mit den Klassen Led.hpp und Blink.hpp) sind hier zu sehen: https://wokwi.com/projects/344254666722247252


    Das nur nochmal zur Ergänzung zum Beitrag #25. Möglicherwiese interessiert es ja jemanden. Ansonsten... schön weiterschlafen.

  • Wenn man die Arduino IDE oder das Arduino Framework von PlatformIO verwendet, nutzt man einen C++ Compiler. Da bietet es sich an auch C++ Elemente zu verwenden. Darum kann ich nur empfehlen, die C++ Videos von René möglichst früh anzuschauen und sich die objektorientierten Prinzipien zueigen zu machen.


    Zumal nahezu alle Bibliotheken zu den verschiedensten Sensoren und Aktoren usw. in C++ geschrieben sind. Wenn man verstehen will was da passiert (z.B. weil die Dokumentation zu Bibliothek nicht gut ist), sind die Kenntnisse ebenfalls von Vorteil.

  • @ Kair

    = > Ob "Zaehler_now = 0; // Neu" in der IF-Anweisung vor oder hinter der FOR-Schleife steht, dürfte eigentlich ziemlich egal sein.


    Da hast du Recht. In meinem Fall ist das tatsächlich völlig egal.


    Ich hatte noch einProblem im Code welches ich glaubte mit dem versetzen gelöst zu haben. Was tatsächlich auch so zu funktionieren schien.

    Bis ich feststellte, dass wenn ich das Lauflicht auf dem Rückweg ausschaltete und wieder einschaltete mein Problem auf einmal wieder da war.

    Das hatte etwas mit dem Überlauf der byte - Variablen zu tun. Beim Rücklauf verwende ich in der Variablen <Lauf_Richtung> eine -1. Wenn ich nun

    <Zaehler_now> auf 0 setze und mit -1 gerechnet wird erscheint in < Zaehler_now> auf einmal die 255. Damit ist das Lauflicht erst einmal festgefahren .


    In >void steuern()< habe ich <Lauf_Richtung> auf 1 gesetzt und damit dies funktioniert wurde sie zudem global deklariert. Jetzt läuft`s erst einmal.


    Mit Objekten kann ich leider noch nicht umgehen, ich taste mich im Lehrgang von Rene aber weiter vor.


  • Beduino: Was willst Du sagen? Ich verstehe zumindest den letzten Beitrag nicht. Ob "Zaehler_now = 0; // Neu" in der IF-Anweisung vor oder hinter der FOR-Schleife steht, dürfte eigentlich ziemlich egal sein.


    Wie man das mit einer Datenstruktur lösen kann, habe ich ja schon im Beitrag #16 anhand der Wokwi Simulation gezeigt.


    Man kann auch ein Lauflicht Objekt (als Weiterentwicklung der Struktur aus #16) bauen. Das erlaubt die Steuerung von mehreren Lauflichtern, die man unabhängig voneinander ein- und ausschalten kann. Der dafür notwendige Quellcode ist identisch weil widerverwendbar (ohne Static Variablen) und das Hauptprogramm verkürzt sich auf:



    Das gesamte Beispiel mit Klassendefinition (button und lights.hpp) findet sich hier: https://wokwi.com/projects/341624134212518483

  • Mit Deiner Aussage hast Du recht. Ich habe nicht bedacht, dass die Datenrichtungsregister beim Start der µMCs mit 0 initialisiert sind, was dem INPUT Mode entspricht. Das entsprang meiner Gewohnheit, die Modi für PINs generell zu setzen. Dann kommen beim Lesen des Codes auch keine Zweifel auf.

  • Zitat

    Bei deinem letzen Code ist der Pin an dem der Taster hängt, immer noch nicht korrekt initialisiert. Auch wen Du auf active high abfragst, muss ein pinmode(taster_pin, INPUT); in setup() verwendet werden.

    Das Fehlen dieser Initialisierung könnte deine Problem mit den verschiedenen Entprellzeiten erklären.

    Ich habe es zwischenzeitlich getestet und den Taster im >setup()< modifiziert, aber die Entprellzeiten verhalten sich wie vorher.( Mein Test: Ich drücke 100x den Taster und beobachte die Reaktion und das 3x mit Abstand. 5min / gleiches Fehlerverhältnis 30ms/50ms/60ms/150ms)

    Ich war der Meinung das die Pins eines Arduino sofern sie nicht auf Output gestellt wurden immer Input sind. Ich habe gelesen, dass aus diesem Grund es nicht zwingend notwendig sei, den Pin für einen Eingabetaster auf Input zu modifizieren.

    Liege ich da falsch?


    Das andere schaffe ich heute nicht mehr. Vermutlich erst am Wochenende.


    MfG

    Beduino

  • Hallo Beduino,


    2. kannst Du lösen indem Du dir eigene Datentypen baust wie im Beispielcode. Diese werden an die jeweilige Funktion übergeben. Die Funktion ist dann im Zusammenhang mit diesem Datentyp universell und wiederverwendbar einsetzbar.


    5. kannst du mit einer sog. State Machine lösen. Die LED_State Variable ist ja schon ein Ansatz. Du bräuchtest nur drei Stati statt zwei. Der dritte ist dann fürs „nichts tun“.




    Bei deinem letzen Code ist der Pin an dem der Taster hängt, immer noch nicht korrekt initialisiert. Auch wen Du auf active high abfragst, muss ein pinmode(taster_pin, INPUT); in setup() verwendet werden.

    Das Fehlen dieser Initialisierung könnte deine Problem mit den verschiedenen Entprellzeiten erklären.

  • Guten Morgen KaiR,


    Ich habe meinen jetzigen Ausgangssketch unten nochmal beigefügt.

    Vorrangig ging es mir erst einmal darum, eine aktivierte Funktion wieder ausschalten zu können. ( Ich habe eine Weile nichts mehr tun können. Da ist einiges an Wissen, sofern es da war, wieder hinten heruntergefallen. Ich benutze das ganze, um eine winzige Modellbahn zu gestalten.)

    Das ausschalten der Funktion funktioniert jetzt, jedoch sind alle Deine Einwände berechtigt.

    zu 1.)Den Taster habe ich als Pull-Down angeschlossen und er hat damit ein definiertes Potential. (Das war aus meinem Geschreibsel nicht gut herauszulesen.)

    zu 3.)Das <delay()> wurde im entprellten <Taster1()> von mir wieder durch <millis()> ersetzt. 50-60 ms haben hier ein gutes Ergebnis erzeugt. (Bei hundert Drücken 2 Fehler) Größere oder Kleinere Zeiten ließen die Quote der Fehlschaltungen wieder ansteigen.

    für 2.) und 5.) habe ich noch keine Lösung, dass wird vermutlich auch etwas komplexer werden. Bei 5.) hatte ich mir das nämlich als einfach vorgestellt. Wars aber bis jetzt nicht!

    Danke für den beigefügten Vorschlag. Um den Code zu verstehen muß ich ihn erst einmal aufarbeiten.

    Ich melde mich bald.


    MfG

    Beduino



  • Der Code in #12 hat aber noch ein paar "Schwachpunkte".


    1. der Pinmode für den Taster pinmode(taster_pin, INPUT_PULLUP); wurde nicht gesetzt. Wenn der Taster funktioniert, ist das mehr oder weniger Zufall.

    2. Die static Definitionen in den Funktionen schränken die Nutzbarkeit ein. Bräuchte man einen zweiten Taster, müsste die Funktion kopiert werden, weil sonst der "taster_state_last" für zwei Taster verwendet würde, und das gäbe durcheinander. Das gleiche gilt im Prinzip auch für die Lauflichtfunktion.

    3. Der delay zum Entprellen hält die gesamte Programmausführung für 30ms an.


    4.

    Code
    1. if ( LED_State == LOW) {
    2. for ( int i = LED_StartPin; i < LED_StartPin + LED_Anzahl; i++) {
    3. digitalWrite(i, LOW);
    4. }
    5. }

    wird permanent ausgeführt wenn LED_State = Low ist. Das stört in dem Programm zwar nicht wirklich, ist aber unschön.


    5. Wurde die Animation abgeschaltet und dann wieder angeschaltet, läuft sich nicht vom Anfang an los, sondern dort wo sie gestoppt wurde. Es kann natürlich sein, dass das beabsichtigt ist.


    Hier ist mal eine Programmänderung als Vorschlag. Auch nicht optimal, aber das Programm enthält ein paar Konstrukte auf den Weg zur objektorientierten Programmierung ...


    https://wokwi.com/projects/340885657039667796

  • Guten Morgen Rene,

    danke für die Lorbeeren, ohne Deine Hilfe wäre ich sicher noch in meiner geistigen Schleife:) festgefahren.

    Dein vereinfachen der Tasterfunktion hat mich erst einmal darauf gestoßen den Test mit der LED zu umzusetzen.

    Die Aha-Effekte dann, sind genau dieses was Spaß macht.


    MfG

  • Jetzt habe ich eine Variante gefunden, so dass alle LED's ausgeschalten werden. Ich nehme meine Feststellung zurück, dass das Lauflicht in einer Endlosschleife gefangen war. Mit einer zusätzlichen LED konnte ich feststellen , dass der Taster auch ein LOW-Signal in die loop schickte.

    Damit ergab sich eine relativ einfache Lösung. Ich konnte alle LEDS durch eine for-Schleife ausschalten. Da gibt es bestimmt noch vornehmere Lösungen.

    Ab und an brauch man das schubsen.:) Jetzt probiere ich diese Lösung noch auf meinem entprellten Taster.

  • Guten Tag Rene,

    zunächst erst einmal vielen Dank für Deine Unterstützung.

    Ich habe mich gestern mit Deinem Vorschlag aus #9 beschäftigt.

    Etwas herumgeschraubt habe ich an Deinem Vorschlag auch , aber nichts wirklich verändert. (denke ich jedenfalls) Genau genommen habe ich taster_released in ein false versimpelt. Ich bin die Programmschritte händisch durchgegangen und habe festgestellt, dass sich bei taster_released nichts verändert. Diese Variable hängt nach dem einschalten in einem dieser Zustände LOW/0/false fest. Hoffentlich habe ich da nichts für sich später anschließende Programmschritte zerstört. Das läßt sich aber rasch wieder zurückdrehen.

    Das Lauflicht läuft, es kann mit dem Taster jedoch nur angehalten werden, aber nicht ausgeschalten werden, so dass eine LED stets weiterleuchtet.