Go Down

Topic: Lauflicht ohne delay mit Unterbrechung (Read 4680 times) previous topic - next topic

dimix100

Hallo Programmierfreunde,
ich habe folgendes Problem.

Zunächst bin ich hier im Forum neu und als Programmierer bin ich Anfänger. Falls ich den Beitrag in flasche Rubrik gestellt habe, entschuldige ich mich schon mal dafür!

Nun zum Problem:
Ich möchte mit einem Taster (oder einfach spannunseingang 5v) ein Lauflicht auslösen. Jede der 14 LED soll dazwischen 0,5s Pause haben. Wenn alle LED's an sind, dann bleiben für 10s alle an und dann sollen im selben Muster auch alle ausgehen mit 0,5 sek Verzögerung. Eingentlich einfach!

Ich habe schon ein Programm mit delay erstellt und es funktioniert auch alles. Doch ein Problem gibt es!:
Wenn die LED's im "Ausgeh-Modus" sind, kann ich die Schleife nicht vorzeitig starten, weil jedes mal im delay muss der mC warten und nichts tun!

Natürlich habe ich mir schon andere Lösungen angeguckt, wie z.B. currentMillis, oder Interrupt.
Aber ich bekommen nicht mal einen Plan wie ich das realisieren soll.

Ich brauche nicht unbediengt den kompletten Code für mein Problem, aber Leitfaden wäre nicht schlecht wie man so was realisieren kann.

ich hoffe ihr könnt mir helfen, danke
gruß

Tommy56

Schau Dir BlinkWitoutDelay und die Nachtwächtererklärung (kein Witz) an.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

michael_x

#2
Feb 16, 2017, 12:18 pm Last Edit: Feb 16, 2017, 12:20 pm by michael_x
Quote
Natürlich habe ich mir schon andere Lösungen angeguckt, wie z.B. currentMillis
Da bist du vermutlich schon richtig.

Damit es geht, brauchst du Variable, in der (denen) du dir merkst, wo du grade bist.
z.B. (als Vorschlag)   An / Aus Phase,  LED-Nummer .

Ich verstehe dich so, dass der Taster die Sequenz sofort wieder neu starten soll, egal ob sie schon fertig war oder noch nicht.

Das ist die klassische Aufgabe, wo delay() versagt.
Und wo das Schlagwort "BlinkWithoutDelay" nicht ganz ausreicht, wenn du nicht komplett verstehst, worin der wesentliche Unterschied besteht.

loop() braucht keine Zeit und kommt dafür sofort wieder dran, und du hast Variable, die dir sagen wo "Das Programm" grade ist. Bei BlinkWithoutDelay ist das previousMillis, bei dir wären wohl andere Merker interessant.


Obwohl: das geht auch nur mit
   unsigned long previousMillis; // Zeit des letzten Tasterdrucks
und etwas, das die ganze Lauflichtshow relativ dazu abdeckt.

Deine loop hätte dann eine ganze Serie von
- Wenn es x millis nach Show-Start ist, muss diese LED gerade an oder ausgeschaltet werden.
Anweisungen, und eine Tasterabfrage, die alles auf einen Anfangszustand setzt.
 

Zwei Hinweise, such dir einen davon aus und berichte. Viel Spass ;)

combie

#3
Feb 16, 2017, 12:27 pm Last Edit: Feb 16, 2017, 12:27 pm by combie
Quote
Ich brauche nicht unbediengt den kompletten Code für mein Problem, aber Leitfaden wäre nicht schlecht wie man so was realisieren kann.
Einen Leitfaden...?

Baue einen endlichen Automaten.
Alle sagen: Das geht nicht!
Einer wusste das nicht und probierte es aus.
Und: Es ging nicht.

Micha383

Code: [Select]



TimeLed1 = millis ();
If ((StartZeit - TimeLed1) >= deine zeit)
{
Led1 einschalten
}




Als code schnippsel wie sowas aussehen könnte.
Natürlich musst du in StartZeit die millis speichern damit es ein Vergleich gibt.

Würde zwar gerne ein besseres Bsp geben aber vom smartphone aus ist das einfach nix.

combie

If ((StartZeit - TimeLed1) >= deine zeit)

Code: [Select]
If ((millis() - StartZeit) >= deine zeit)
Alle sagen: Das geht nicht!
Einer wusste das nicht und probierte es aus.
Und: Es ging nicht.

jurs

Ich brauche nicht unbediengt den kompletten Code für mein Problem, aber Leitfaden wäre nicht schlecht wie man so was realisieren kann.
Dafür bietet sich eine Finite State Machine (SFM) mit vier Betriebszuständen an:
AUS,HOCHFAHREN,EIN,RUNTERFAHREN

Für jeden Betriebszustand brauchst Du eine "State Funktion" zum Agieren in diesem Zustand.
Dazu eine buttonPressed() Funktion mit boolschem Rückgabewert zum Feststellen eines Tastendrucks.

Ein Tastendruck würde dann jeweils den Betriebszustand HOCHFAHREN setzen.

Und alles andere würde zeitgesteuert bzw nach Anzahl der geschalteten LEDs ablaufen, im wesentlichen über die "vergangene Zeit seit ein Betriebszustand gesetzt wurde.

Den gewünschten Programmablauf hast Du ja sehr detailliert und verständlich beschrieben.

Wenn Du nicht weißt, wie Du eine FSM dafür programmtechnisch umsetzen kannst, verrate mir noch, an welchem Pin der Tastschalter und an welchen 14 Pins die LEDs hängen sollen, dann kann ich Dir ggf. ein Beispielprogramm machen.

Bei den LEDs mußt Du aufpassen, dass der Mikrocontroller vom Strombedarf her nicht überlastet wird. Also 14x 5mA wäre vermutlich OK, aber 14x20mA wäre vermutlich außerhalb der Spezifikation des Controllers, wenn Du die ganzen Milliamperes direkt aus OUTPUT-Pins ziehen möchtest.

dimix100

Hallo,
danke für die Antwort.

Meine Ausgangspin sind von 24...38 und Eingang ist auf Pin 50.

Ich muss alles noch verarbeiten. Ich hatte Nachtschicht und muss mich noch mal alles durchlesen.
Danke
Gruß

michael_x

Quote
Meine Ausgangspin sind von 24...38 und Eingang ist auf Pin 50.
Und?
Willst du andeuten, dass du einen Arduino MEGA (Nachbau) hast? Schön für dich ;)

Udo BlinkenLight hätte den Reset-Knopf verwendet und 20 LED an einem Uno betrieben. Ohne delay natürlich ...

dimix100

Ich bin neu in dem Bereich.
Hab einfach ein Biard genommen der viele ein/Ausgänge hat. Für alle Fälle.
Ich wollte nicht angeben, falls du das meinst...
Gruß

michael_x

Quote
falls du das meinst
nein, eher nicht. Angeben geht hier andersrum: je kleiner bei gleicher Funktion, desto toller.

Ich fürchtete eher, dass du annimmst, jemand könnte diese Information benötigen, um dir den Sketch gebrauchsfertig  zu liefern. ;)

jurs

#11
Feb 16, 2017, 03:18 pm Last Edit: Feb 16, 2017, 03:23 pm by jurs
Hallo,
danke für die Antwort.

Meine Ausgangspin sind von 24...38 und Eingang ist auf Pin 50.
Pins 24 bis 38 einschließlich? Das wären insgesamt 15 Pins.

15 Ausgangspins zum Schalten von 14 LEDs?
Das klingt ein wenig verschwenderisch.
Irrtum Deinerseits?
Oder soll das so und eine von den 14 LEDs soll über zwei Pins steuerbar sein?

dimix100

Pins 24 bis 38 einschließlich? Das wären insgesamt 15 Pins.

Ne Sorry hab mich vertan...
24 bis 37 sind led, 38 ist belegt als Reserve.

jurs

#13
Feb 16, 2017, 04:11 pm Last Edit: Feb 16, 2017, 04:13 pm by jurs
Pins 24 bis 38 einschließlich? Das wären insgesamt 15 Pins.

Ne Sorry hab mich vertan...
24 bis 37 sind led, 38 ist belegt als Reserve.
OK, also 14 LEDs von 24 bis 37.

So ein Programm besteht im Prinzip aus zwei Elementen:
- Datenstrukturen und Algorithmen

Als Datenstruktur für die LED-Pins schlage ich dann mal ein Array aus byte-Konstanten vor:

const byte ledPins[]={24,25,26,27,28,29,30,31,32,33,34,35,36,37};

So lassen sich die Pins aus einem Programm leicht über einen Array-Index von 0 bis 13 ansprechen
, etwa um in der setup() Funktion mit einer for-Schleife alle Pins auf pinMode OUTPUT zu setzen.


Ich glaube, im englischsprachigen Teil des Forums hatte icherst vor ein bis zwei Wochen ein ähnliches Programm zur Demonstration einer Finite State Machine (FSM/Zustandsautomat) gepostet. Das Beispielprogramm behandelte zwar nur 6 LEDs. aber dafür sollten alle 6 LEDs auch an PWM Ausgängen in der Helligkeit geregelt werden, erst hochdimmen, dann nach einer Weile wieder runterdimmen. Soll ich das hier bei mir vorhandeneFSM-Beispielprogramm mal auf Deine Schaltlogik für 14 LEDs ändern und dann hier den Code posten?


Was verwendest Du für LED?s Und was für Vorwiderstände? Weiße 5mm  low-Power LEDs mit 330 Ohm Vorwiderstand, oder was?

Whandall

Mit der Taste habe ich es mir einfach gemacht und die Library Bounce2 benutzt.
Den momentanen Zustand repräsentiere ich in einem Byte,
0 alles aus, 1 die erste LED leuchtet.... .... 14 die ersten 14 LEDs leuchten ... 27 die erste leuchtet.
Die Dauer aller Schritte ist 0,5 Sekunden, nur im Schritt 14 sollen es 10 Sekunden sein.
Ein Tastendruck (re)startet die Sequenz in Schritt 1.
Die Anzahl der anzuschaltenden LEDs wird aus der Schrittnummer berechnet.

Code: [Select]
#include <Bounce2.h>

const byte ledPin[] = { 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
const byte tastenPin = 50;
const byte ledPins = sizeof(ledPin) / sizeof(ledPin[0]);

Bounce Taste;

void setup() {
  Taste.attach(tastenPin, INPUT_PULLUP);
  for (byte i = 0; i < ledPins; i++) {
    pinMode(ledPin[i], OUTPUT);
  }
}

void loop() {
  static unsigned long letzteAktion;
  static unsigned long dauerDiesesSchritts;
  static byte zustand;
  unsigned long topLoop = millis();
  if (Taste.update() && Taste.fell()) {
    zustand = 1;
    dauerDiesesSchritts = 1;
  }
  if (dauerDiesesSchritts && topLoop - letzteAktion >= dauerDiesesSchritts) {
    letzteAktion = topLoop;
    byte anzahlVonLeuchtendenLeds = zustand <= ledPins ? zustand : 2 * ledPins - zustand;
    for (byte i = 0; i < ledPins; i++) {
      digitalWrite(ledPin[i], i < anzahlVonLeuchtendenLeds);
    }
    dauerDiesesSchritts = zustand == ledPins ? 10000 : 500;
    if (++zustand > 2 * ledPins) {
      dauerDiesesSchritts = 0;
    }
  }
}
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

Go Up