ich bin gerade dabei, mich in die Thematik des Blink without Delay einzuarbeiten und hab es im großen und ganzen schon soweit verstanden, dass ich verschiedene Funktionen unabhängig voneinander steuern kann. Da ich den Arduino (bzw. die damit programmierten Attinys) für den Modellbau nutze, um bei Einsatzfahrzeugen die Lampen und LEDs zu steuern, bin ich nun auf ein Problem gestoßen, bei dem ich nicht weiter komme und Hilfe benötige:
Es geht darum, bei einer LED die Ein- und Ausschaltdauer unterschiedlich lang zu gestalten. Mit meinem bisherigen Sketch schaffe ich es bloß, sie gleichmäßig blinken zu lassen (z.B. 100ms ein, 100ms aus). Aber wie kann ich es individuell gestalten, so wie man es mit Delays bewerkstelligen könnte (z.B. 50ms ein, 100ms aus)? Oder noch verrückter, 50ms ein, 100ms aus, 50ms ein, 200ms aus? Kann mir da jemand weiter helfen?
Im folgenden mal ein einfacher Sketch, den ich bisher nutze.
Der Code ist noch umfangreicher, deswegen kann ich auch kein Delay verwenden. Ich habe jetzt aber die unrelevanten Stellen weggelassen.
Vielen Dank schonmal!
typischer C++ Code: eine Zeile Code, 5 Zeilen Erklärung. (die leider fehlen)
Aber, ja, wenn ich etwas drüber nachdenke, dann verstehe ich es auch.
Ein schöner Code!
Aber viele Wege führen nach Rom.
Zum Beispiel auch der hier:
Kannst du das auch mal in verständliche Einzelzeilen aufdröseln?
Was willst Du da aufgedröselt haben, es steht doch alles da: Aus dem stetig hochzählenden Millisekundenzähler bildet er durch Modulo-Division einen Zähler, der in wesentlich kürzeren Zyklen überläuft:
millis() % zyklenDauer ==> das ist ein Zähler, der ständig von 0 bis zyklenDauer-1 hochläuft, und dann bei 0 neu startet
Und so lange dieser Zähler kleiner als eine vorgegebene Einschaltzeit "onZeit" ist, wird der Pin eingeschaltet.
Kleine Schwächen des Codes:
1.) Es wird eine Modulo-Division verwendet, die vergleichsweise zeitaufwändig ist, und es wird digitalWrite() bei jedem Durchlaufen der loop() aufgerufen und nicht nur bei Änderungen des Schaltstatus, was sich bei manchen extrem zeitkritischen Programmen, bei denen es auf jede einzelne Mikrosekunde Rechenzeit ankommt, nachteilig auf das Laufzeitverhalten auswirken kann
2.) Einmal alle knapp 50 Tage Programmlaufzeit wird ein Zyklus zeitlich falsch gesteuert, wenn der millis() Zähler überläuft, was ggf. nachteilig für Programme sein kann, die mehrere Monate am Stück laufen sollen.
Aber für "normale" Programme völlig einwandfrei verwendbar.
Also der Sketch von combie funktioniert super, hab ich gleich ausprobiert. Ich habe ja keine großen Ansprüche daran, von daher reicht der vollkommen aus.
Jetzt wäre es bloß noch toll, wenn ich einen Doppelblitz machen könnte (z.B. 100ms ON, 100ms OFF, 100ms ON, 2000ms OFF). Kann mir da noch jemand helfen?
Den Code von guntherb habe ich noch nicht zum Laufen gebracht, den verstehe ich noch nicht so ganz.
Clemi:
Also der Sketch von combie funktioniert super, hab ich gleich ausprobiert. Ich habe ja keine großen Ansprüche daran, von daher reicht der vollkommen aus.
Jetzt wäre es bloß noch toll, wenn ich einen Doppelblitz machen könnte (z.B. 100ms ON, 100ms OFF, 100ms ON, 2000ms OFF)
Das geht mit Combies Variante nicht so leicht.
Ich würde einen Gesamtzylus machen, und (um mal auch einen Trick zu zeigen)
mit festen 100ms Schritten rechnen:
const int ZYKLUS = 2300;
const int SCHRITT = 100;
void loop() {
static unsigned long lastcycle;
if (millis-lastcycle > ZYKLUS) lastcycle = millis();
int phase = (millis - lastcycle)/SCHRITT; // 0 .. 22
switch (phase) {
case 0:
case 2:
digitalWrite(13,HIGH);
break; // probier mal spasseshalber hier delay(20); statt break ;)
default:
digitalWrite(13, LOW);
}
}
Clemi:
Also der Sketch von combie funktioniert super, hab ich gleich ausprobiert. Ich habe ja keine großen Ansprüche daran, von daher reicht der vollkommen aus.
Jetzt wäre es bloß noch toll, wenn ich einen Doppelblitz machen könnte (z.B. 100ms ON, 100ms OFF, 100ms ON, 2000ms OFF). Kann mir da noch jemand helfen?
In dem Sketch werden sechs verschiedene Leuchtturmfeuer geschaltet, mit wahlweise verschieden vielen Ein- und Ausschaltzeiten innerhalb eines Gesamtzyklus.
Die Anzahl der ein/aus Unterzyklen innerhalb eines Gesamtzyklus kann noch deutlich größer werden wie im Sketch gezeigt und über den Wert 'n' innerhalb der Datenstruktur für jedes Leuchtfeuer gesondert gesetzt werden.
Für 2 Ein- und 2 Ausschaltungen innerhalb eines Schaltzyklus wäre n=4, wie am Beispiel "Pilsum_timing[] " im Sketch.
Der Sketch wurde von mir damals zwar für langsam schaltende Leuchtfeuer-Simulationen geschrieben, aber die zeitliche Auflösung ist Millisekunden.
Wenn man die Schaltungsmöglichkeiten nicht so variabel haben möchte, sondern fest für 2 Einschaltzeiten und zwei Ausschaltzeiten pro Gesamtzyklus, ließen sich natürlich sowohl die Datenstruktur wie auch der Code natürlich vereinfachen.
Clemi:
Den Code von guntherb habe ich noch nicht zum Laufen gebracht, den verstehe ich noch nicht so ganz.
Echt nicht?
Einfach nur die Variablen deklarieren und schon läuft er.
const int ledPin1 = 13;
const unsigned long Ontime1 = 200; // Andauer der LED ms
const unsigned long interval1 = 1000; // Periodendauer (=AN + AUS) der LED ms
unsigned long previousMillis1;
void setup() {
pinMode(ledPin1,OUTPUT);
}
void loop()
{
if (millis() - previousMillis1 > Ontime1){
digitalWrite(ledPin1, LOW);
}
if (millis() - previousMillis1 > interval1){
previousMillis1 = millis();
digitalWrite(ledPin1, HIGH);
}
}
Aber wenn du komplexere Blinkfolgen willst, ist diese Version nicht geeignet.
Ich dachte eigentlich, die sei einfacher zu verstehen als die von Combie und Jurs.
So kann man sich täuschen.
guntherb:
Aber wenn du komplexere Blinkfolgen willst, ist diese Version nicht geeignet.
Ich dachte eigentlich, die sei einfacher zu verstehen als die von Combie und Jurs.
So kann man sich täuschen.
Doch, ist schon einfach zu verstehen, vom Aufbau her ist er sehr simpel. Ich glaube ich habe irgendeinen Fehler bei den Variablen gemacht, deswegen hat er nicht funktioniert. Jetzt läuft es Danke!