Arduino - Wie lasse ich eine LED im Takt blinken?
Hallo, ich will mit meinem Arduino eine LED im Takt blinken lassen, aber da der Microcontroller nicht jede Millisekunde das Programm wiederholt, (deshalb auch das >= in der if Schleife) ist die LED sehr schnell nichtmehr syncron. Ich bin noch recht neu auf dem ganzen Gebiet und weis nicht wie sich das Problem beheben lässt und wollte deshalb fragen ob mir jemand eventuell dabei helfen kann.
Danke im Vorraus.
Mein Code:
1 Antwort
Der Arduino ist schon im Takt. Er durchläuft das Programm mehrmals pro Millisekunde... Im Mikrosekundenbereich ist er nicht schnell genug um jede Mikrosekunde zu zählen...
Etwas statisch zu einem Takt zu synchronisieren ist schwer. Wenn der Arduino den Takt mit 126BPM 100% einhält, aber die Audio ggf 126,2BPM tatsächlich hat, dann läuft es schon auseinander... Nur Programme, die BPM-Erkennung anbieten, zeigen wohl nie auf Komma genau an... Deshalb synchronisieren die Lichtcomputer im Regelfall Sound-to-Light mit entsprechenden Filtern, um z.B. den Bassbeat zu erfassen und darauf die Synczeit zu berechnen... Ich habe mal einen Arduino in ähnlicher Form einen Ausgang schalten lassen und mit dem Osziloskop nachgemessen. Die Zykluszeiten, wie der Ausgang geschaltet hat, war 100% identisch... Da gab es keine Zeitabweichungen zwischen den Schaltperioden... Abweichungen vom Timing kommen aber auch von ungenauen CPU-Frequenzen. So hab ich mal kleine Attiny ohne ext Quarz betrieben und jeder hatte zum anderen einen zeitlichen Versatz. Einer war schneller, der nächste langsamer, weil die internen Quarz nicht kalibiert waren. Nach Anschluss ext Quarz (wie es beim Arduino auch der Fall ist) gab es keine Abweichungen mehr. Die laufen jetzt als 6h/18h-Timer mit Quarz für Lichterketten... Schalten auf die Sekunde präzise...
Ich schätze, dass serialPrint dein Programm ausbremmst. Die Zeit, die er den Text sendet, läuft das Programm nicht weiter, sondern er steuert die Schnittstelle. In meinem Versuch hatte ich kein serialPrint. Aus Spaß habe ich mal einen Arduino wie folgt schalten lassen:
digitalWrite (2, !digitalRead(2));
Er hat also in jedem Durchlauf immer direkt umgeschaltet... Die Ausgangsfrequenz war um die 80ns meine ich...
Der Arduino hat eine extra 16Mhz Quarz um eine hohe Genauigkeit zu erziehlen...
Ich muss zugeben, dass ich nie die Zykluszeiten mit mehreren If gemessen habe... Du könntest ggf auf eine If reduzieren und nur auf die Zeit abfragen. Eine Variable setzen und und diese entsprechend meinem Beispiel toggeln...
var1 = !var1;
So wird die Variable immer umgekehrt, wenn die If erfüllt ist. Und die Ausgönge kannst Du dann entsprechend der Variablen setzen..
digitalWrite(2,var1);
Damit solltest Du noch etwas Zeit gut machen. Ein Befehl im Arduino braucht mehrere Taktzyklen der Grundfrequenz, somit verlangsamt sich die Programmzykluszeit, je mehr Befehle ausgeführt werden. Nur wie viel Einfluss das ganze hat, hab ich nie ausprobiert.
Aber wenn ich so Vorgehe ist es nicht mehr möglich die LEDs mit analogWrite individuelle zu dimmen oder?
Naja, wenn es ans dimmen geht, kommt eh noch einiges an Code hinzu... Spätestens dann musst Du Dir ums Timing noch mehr Gedanken machen... Je größer der Code, je mehr Befehle, um so länger der Programmzyklus... Da hilft nur ausprobieren, wenn der Code mal so steht, wie er soll und ggf optimieren, was geht. Also so Schlank wie möglich...
Okay, ich werd Mal schauen was ich hinbekomme. Aufjedenfall vielen Dank für deine Hilfe!
Im übrigen nehmen Serial-Print-Befehle viel Zeit in Anspruch... Da kann es ggf schon mal zu Zeitversatz kommen. Den führst Du jeden Zyklus aus... Das würde ich weg lassen... Hast ja die LEDs als Anzeige, ob er geschaltet hat...
Warum steuerst Du die eig mit analogWrite an, nimm doch digitalWrite... PWM nutzt Du ja eh nicht zum dimmen, sondern schaltest nur ein oder aus...
Das Programm war nur zum Test gedacht und deshalb leuchtet die LED nur in weiß. Und wenn ich den Serial-Print -Befehl weglasse ist das Ergebnis leider auch nicht besser.
Aber wenn der Arduino das Programm mehrmals in der Millisekunde durchläuft, warum funktioniert es dann nur wenn ich
if (currentMillis - previousMillis >= LEDWert)
schreibe und wenn ich
if (currentMillis - previousMillis == LEDWert)
schreibe nicht mehr?
Und ein externer Quartz kann mir also helfen die CPU-Frenquenz zu vergenauern und somit also auch die Synchronisation zu verbessern?