Hallo,
ich möchte gerne an meinem ESP32 20 LEDs in unterschiedlichen Frequenzen
blinken lassen.
Mir ist bewusst, dass das nur mit der "millis()" Methode funktioniert,
also nicht mit delays, da ja sonst mein ganzes Programm pausiert.
Nun ist der millis Code für 20 LEDs extrem lang. Daher suche ich
irgendeine elegante Möglichkeit, wo ich in der Main Loop einfach nur
eine Funktion Aufrufe und als Parameter den GPIO und die Blinkfrequenz
übergebe.
Ich suche schon ziemlich lange, jedoch finde ich immer nur Beispiele mit
nur einer bzw. zwei LEDs, wo natürlich der Standardansatz noch
problemlos (mit relativ wenig Zeilen Code) möglich ist.
Habt ihr ein Tipp wie ich anders suchen kann bzw. habt ihr Links?
Sowas muss doch schonmal jemand vor mir gemacht haben!
VG
Tobi
Vorschlag
Dispatcher ruft LED-Funktion alle 1ms auf.
Diese hat 2 Tabellen. 1. Tabelle enthält die Zeiten. 2. Tabelle enthält
aktuelle Zeitwerte, da werden bei 0 die Werte der 1. Tabelle eingetragen
und bei >0 runtergezählt.
Tobi schrieb:> Sowas muss doch schonmal jemand vor mir gemacht haben!
Es gibt Leute, die ganze Landkarten mit Leuchttürmen erstellt haben, und
die so blinken liessen wie in echt, alle verschieden.
Ist nicht schwer. Man muss halt die Blinkmuster definieren, z.B. mit AN
und AUS Zeiten in einer Tabelle. Blinken ist ja eher langsam aus Sicht
eines uC.
Auf dem ESP läuft, en ich das richtig im Kopf habe, freeRTOS. Also mach
doch einfach 20 Threads auf und in denen kannst du dann deine millis
Funktion nutzen.
Da nirgendwo steht das die LEDs kontrolliert blinken sollen
selbstblinkende LEDs nehmen. Die kommen nach ein paar Minuten aus dem
Takt und blinken unterschiedlich vor sich hin.
Wenn's kontrolliert sein einfach anständig programmieren. Ein
Timer-Interrupt der gleich dem kleinsten gewünschte Zeitunterschied
zwischen den LEDs ist. Für jede unabhängig steuerbare LED ein Bitmuster
in einem Array und einen Index haben. Bei jedem Interrupt für jede LED
das nächste Bit aus dem Bitmuster in den jeweiligen LED-Pin takten.
Optimierungen sind natürlich möglich (Ports auf einmal ansteuern, im
Interrupt nur Zähler weiter setzen und in der Mainloop die LEDs steuern,
WS28xx LEDs, Algorithmus statt Array, ...).
Wer's mag und kann, kann auch mit einem variablen Timer arbeiten. Dann
steht in einem Arrays eine (relative) Zeit zu der die nächste Änderung
stattfinden soll und welche.
Tobi schrieb:> "millis()" Methode
Also Arduino?
> Daher suche ich irgendeine elegante Möglichkeit> ...> Ich suche schon ziemlich lange
Irgendwann wirst du mal deine erste eigene Zeile Code programmieren
müssen, weil du auf ein Problem stößt, das keiner vor dir gehabt, gelöst
und ins Netz gestellt hat.
> Nun ist der millis Code für 20 LEDs extrem lang.
Was stört dich daran, dass der Code "extrem lang" ist? Hast du eine zu
kleine Festplatte?
Aber probiers doch einfach mal so: wenn du 1 Code für 1 LED geschrieben
hast und den dann für die nächste(n) LED(s) kopierst, dann kannst du dir
nebenher Gedanken um Gemeinsamkeiten machen und überlegen, ob du die
Arbeit nicht auch mit einer for-Schleife und passenden Arrays mit 20
Elementen für die 20 Zeiten und die 20 Pins erledigen kannst.
Seis drum...
> ESP32 20 LEDs in unterschiedlichen Frequenzen blinken lassen.
Wie/wo sind denn diese 20 LEDs an den ESP32 angeschlossen? Hast du einen
Schaltplan davon?
Tobi schrieb:> Hallo,>> ich möchte gerne an meinem ESP32 20 LEDs in unterschiedlichen Frequenzen> blinken lassen.>> Mir ist bewusst, dass das nur mit der "millis()" Methode funktioniert,> also nicht mit delays, da ja sonst mein ganzes Programm pausiert.
Richtig!
> Nun ist der millis Code für 20 LEDs extrem lang.
Nö.
> Daher suche ich> irgendeine elegante Möglichkeit, wo ich in der Main Loop einfach nur> eine Funktion Aufrufe und als Parameter den GPIO und die Blinkfrequenz> übergebe.
Richtig.
Beitrag "Re: mehrere Millis()"
Hmm, das Beispiel ist nicht so ganz übersichtlich. Dann eher siehe
Multitasking, wenn gleich man beim Arduino eher mit millis()
arbeitet.
Wenn's besonders "ducheinander" aussehen soll, dann verwende für die An-
und Auszeiten der jeweiligen LEDs unterschiedliche Primzahlen.
Primzahlen haben die Besonderheit, nur durch 1 und durch sich selbst
teilbar zu sein. Gleichtakt zwischen 2 Kanälen gibt es dann alle A mal B
mal C mal D Durchläufe, wobei A Kanal 1 an, B Kanal 1 aus, C Kanal 2 an,
D Kanal 2 aus ist. Das mal Anzahl der LEDs ist schon ordentlich.
Tabellen mit Primzahlen sollten sich ebenfalls im Internet finden
lassen. 4 stellige Primzahlen eignen sich z.B. für millis Zeiten ;-)
Nimm 20 WS2812B-LEDs und steuer diese an. Braucht man nur einen GPIO und
es gibt fertige Libraries dafür mit unterschiedlichsten Effekten.
Oder installier gleich WLED, da gibt es auch einen Random-Effekt.
Du solltest dir auch Gedanken über die Ansteuerung machen.
Die üblichen 2 Methoden die ich anwenden würde sind, entweder über ein
Portexpander o. einfach WS2812LED's zu nehmen.
Beide haben vor und Nachteile.
Das blinken selbst ist danach nur noch eine Frage der Software.
Wobei ich das am einfachsten über eine Schleife mit Milli-Zähler machen
würde. Dann kann ich vorher die LED's über ein Array festlegen und mit
den Daten den Zeittakt bestimmen.
Durch das Array lade ich dann einfach neue Programmdaten für die
Blink-Freq. und das war's.
Schlaumaier schrieb:> Das blinken selbst ist danach nur noch eine Frage der Software.
Aber eben DIESE Frage steht im Raum! Da nützt der Hinweis auf
Portexpander und intelligente LEDs gar nichts!
Ich hab mir mal eine Zusammenstellung gemacht, die mit einem Timer
mehrere (1-viele) unabhängige Zeiten verwalten lässt.
Nicht für Arduino, das kann ich nicht, nur in C.
Vielleicht hilft es ...
Old P. (Firma: nix) schrieb:> Warum nimmt du nicht einfach 20 Arduinos?
Das erinnert mich an den Witz von der Mutter, die ihrem Nachwuchs
Nachhilfe bei den Hausaufgaben gibt: "Also Fritzchen, stell dir mal vor,
du hast 7 Taschenrechner und nimmst dann 3 davon weg. Wieviele
Taschenrechner bleiben da übrig?"
Tobi schrieb:> Mir ist bewusst, dass das nur mit der "millis()" Methode funktioniert,...
Sei dir lieber bewußt, daß du noch nicht programmieren kannst, sondern
nur mit quasi Bauklötzchen spielst. Was du brauchst, ist eine Strategie,
wie dein Vorhaben zu machen wäre. Das ist etwas anderes, als das Tippen
auf der Tastatur zwecks Erzeugen einer Quellcode-Datei.
Also, du hast eine Funktion, die dir anzeigt, wie der momentane Stand
irgend eines Zählers ist, der jede Millisekunde um eins weiter zählt.
Nun, sowas ist doch schon mal eine Zeitbasis. Und da deine LEDs blinken
und nicht flimmern sollen, braucht es für jede Leucht- und jede
Dunkel-Zeit wenigstens so etwa 100 Millisekunden, also recht viel Zeit
aus Sicht des µC.
Jetzt ist es deine Angelegenheit, dir da eine dir gefallende Strategie
zu Ein- oder Ausschalten deiner LEDs einfallen zu lassen. Ich würde
sowas mittels "delayed Events" machen, weil bei meinem Zeugs (meinem
Portfolio) sowas bereits vorhanden ist. Aber da du mein Zeugs nicht hast
und auch der ESP32 eine ganz andere Plattform ist als meine Controller,
mußt du schon selber ran, dir etwas auszudenken. Aber im Prinzip wird
das ähnlich werden, also Zeitpunkte (aus Intervallen) zu bestimmen, bei
denen Ein- und Ausschalt-Aktionen stattfinden sollen und Vergleiche
zwischen millis und den bestimmten Zeitpunkten zu tun, um
herauszufinden, ob grad eine Aktion stattfinden soll oder nicht. Denke
jetzt mal selber.
W.S.
Hier mal ein Entwurf. Man kann alle LEDs mit verschiedenen Frequenzen
und Tastverhältnissen blinken lassen. Sogar die Phasenverschiebung kann
man dynamisch anpassen, wenn man das will! Und das Beste von Allem, der
Arduino kann nebenbei noch SEHR viel machen. Siehe Multitasking.
Falk B. schrieb:> Und das Beste von Allem, der> Arduino kann nebenbei noch SEHR viel machen. Siehe Multitasking.
Müsste es dann nicht die Arduino heissen? :-)
Ralf X. schrieb:>> Und das Beste von Allem, der>> Arduino kann nebenbei noch SEHR viel machen. Siehe Multitasking.>> Müsste es dann nicht die Arduino heissen? :-)
Mein Italienisch liegt zwischen nicht vorhanden und 0,xppm. KATZO! ;-)
Falk B. schrieb:> Aber eben DIESE Frage steht im Raum! Da nützt der Hinweis auf> Portexpander und intelligente LEDs gar nichts!
Richtig und Falsch gleichzeitig.
DENN. Die Hardware bestimmt die Software nicht anders herum.
Und je nachdem was ich ansteuere, ist der Code total anders.
Bei 20 LED's ohne ein Arduino-Mega habe ich ein Problem. Also brauch ich
ein Portexpander.
Ansonsten ist das Programm-Technisch eh nur eine Frage der IF-THEN
abfragen.
Wie der TO schon richtig erkannt hat, würde ich das auch über Millis
machen.
Allerdings benutzte ich Millis nur als TAKTGEBEN und zwar so.
akt_millis = millis()
led_1_millis = akt_millis + 500 ' init den Status und schaltet alle
LED's sync.
led_1_status = low
do loop
akt_millis = millis()
if Led_1_millis < akt_millis then
if led_1_status = low then LED_1_status = high else led_1_status_=low
led_1_millis = led_1_millis + schalt_zeit
end if
'*** hier dann schalten nach Status und Hardware ****
loop
Das bisschen da in C Syntax übersetzen und das war's. Ist ja im Prinzip
ein Ablaufdiagramm ;)
Das ist für 1 LED. Ich persönlich würde ein Array aufbauen, und eine
For_next Schleife das macht das Leben einfacher.
Aber das soll der TO selbst machen.
Schlaumaier schrieb:> Die üblichen 2 Methoden die ich anwenden würde sind, entweder über ein> Portexpander o. einfach WS2812LED's zu nehmen.
Der ESP32 hat üblicherweise mehr als 20 GPIO, braucht also die teure
Methoden nicht sondern kann billige LED direkt ansteuern - was sich auch
am einfachsten programmieren lässt.
MaWin schrieb:> Der ESP32 hat üblicherweise mehr als 20 GPIO, braucht also die teure> Methoden nicht sondern kann billige LED direkt ansteuern - was sich auch> am einfachsten programmieren lässt.
Grundsätzlich gebe ich dir Recht.
Aber nur wenn der TO KEIN Komfort will. Weil ich würde das mit einer
Klebe-Membranen-Tastatur, Display (1602) + IR-Empfangsdiode ausstatten.
Was ich nebenbei bei fast allen meiner Projekte mache. Materialwert :
ca. 5-6 Euro.
Dann hat er die Möglichkeit (falls er brauchbar programmieren kann) sich
unterschiedliche Blink-Programme zu erstellen. Das gewünschte Programm
zu modifizieren und via IR-Fernbedienung zu Starten/wechseln.
Und dann wird es mit den Pins verdammt eng. Weshalb ich meist die
PCF-8574 einsetze, weil Preiswert und einfach anzusteuern und bei mir
war der noch nie zickig. Macht für den TO 2-3 Euro (a ca. 1 Euro)
Was unter dem Strich heißt. Opfert der TO ca. 10-12 Euro extra hat ein
eine Beleuchtung die Mega Flexibel ist.
Davon abgesehen 4-5 Zeilen mehr in den Code und er hat sogar noch eine
UNGENAUEN Zeittimer drin. 2 Euro mehr (dcf-77-Modul) und er hat eine
Top-Genaue-Timersteuerung die er mit der Tastatur dann Problemlos nach
programmieren kann.
Was alles in allen meine Aussage erklärt : Die Hardware bestimmt die
Software.
Und ein ESP32 ist fast das selbe wie ein Arduino. Die IDE ist die selbe,
der Code fast auch. Man muss nur die Eigenschaften des ESP32
berücksichtigen.
Falk B. schrieb:> Hier mal ein Entwurf.
Den habe ich mal durch die Mühle gedreht und daraus einen Gegenentwurf
gemacht.
Allerdings ungetestet, da kein ESP32 erreichbar.
Tobi schrieb:> Mir ist bewusst, dass das nur mit der "millis()" Methode funktioniert> also nicht mit delays, da ja sonst mein ganzes Programm pausiert.
Wenn du das ohne Mithilfe eines Betriebssystems machen willst, stimme
ich dir zu. Dein ESP hat allerdings ein solches (RTOS). Du kannst also
durchaus dessen Threads oder Timer nutzen. Oder du machst es ohne - geht
auch.
Tobi schrieb:> Habt ihr ein Tipp wie ich anders suchen kann bzw. habt ihr Links?http://stefanfrings.de/multithreading_arduino/index.html
Stefan ⛄ F. schrieb:> stimme ich dir zu.
Ich stimme nicht zu.
Denn delay() blockiert nur eine Task auf einem Core. Der Rest läuft
ungetrübt weiter. Was ja durchaus erwünscht sein kann.
Nur der Arduinofickler gibt sich mit "Blinken" zufrieden.
In den fortgeschritteneren Regionen der Welt, erwartet man eine
an das Helligkeitsempfinden des Auges angepasste sinusodiale
Schwingung der Helligkeiten.
Geblinkt wurde da gestern...
Seblst mein uraltes Dummfon signalisiert seinen Standbymodus
mi angenehmen Sinusabschnitten.
W.S. schrieb:> ....(eine Provokation)....
Falls du es noch nicht bemerkt hast, wir reden hier über einen ESP.
Was dir auch evtl. durch die Lappen gegangen ist:
Der von mit gezeigte Umbau funktioniert auch neben einem delay(), und
auf den kleinen AVRs
Beispiel: (für einen Arduino UNO)
1
structLed
2
{
3
bytepin;
4
unsignedlongonTime;
5
unsignedlongoffTime;
6
unsignedlongzeitMerker;
7
8
voidinit()
9
{
10
pinMode(pin,OUTPUT);
11
zeitMerker=0;
12
}
13
14
voidrun()
15
{
16
boolstate=digitalRead(pin);
17
unsignedlonginterval=state?onTime:offTime;
18
if(millis()-zeitMerker>interval)
19
{
20
zeitMerker+=interval;
21
digitalWrite(pin,!state);
22
}
23
}
24
};
25
26
Ledleds[]=
27
{
28
// IO-Pin, onTime, offTime alle in millisec
29
// {1, 200, 100},
30
{2,300,50},
31
{3,400,30},
32
{4,990,50},
33
{5,770,600},
34
{6,660,600},
35
{7,880,50},
36
{9,1010,500},
37
{10,2000,1000},
38
{11,3000,100},
39
{12,4000,3500},
40
{13,5000,2500},
41
{14,10000,1000},
42
{15,9990,1000},
43
{16,7770,1000},
44
{17,8880,1000},
45
{18,4440,1000},
46
{19,3330,1000},
47
// {20, 1110, 1000},
48
};
49
50
51
voidyield()
52
{
53
for(Led&led:leds)led.run();
54
}
55
56
voidsetup()
57
{
58
for(Led&led:leds)led.init();
59
}
60
61
voidloop()
62
{
63
delay(4711);
64
}
Du siehst, nur ein minimaler Umbau.
Offensichtlich hast du zu wenig Ahnung von Arduino um substantielle
Kritik zu üben.
Für die Simulation einer Diskothek auf der Eisenbahnanlage habe ich in
einem tiny13 5 32 Bit Zufallsgeneratoren (Rückgekoppelte
Schieberegister) laufen. Das rückgekoppelte Bit zählt bei 3 Kanälen
zusätzlich einen Zähler rauf bzw. runter, mit dem die Helligkeit einer
LED gesteuert wird. (Über PDM, einer Art einfachem noise shaping)
Die beiden anderen steuern zwei weiße LEDs als Blitzer an.
http://jobstens.mooo.com/elektronik/bahn/disco/
Gruß
Jobst