Hallo zusammen, nach über 25 Jahren muss ich einmal wieder meine alten C++ Kenntnisse hervorholen, da ich jetzt vor dem Problem stehe diverse LED Streifen via Arduino zu programmieren.
leider sind die doch schwer "eingerostet".
ich habe folgendes Problem:
LED Streifen mit 145 LEDs soll in verschiedenen Farben leuchten.
Statisch habe ich das auch gelöst, indem ich in einer LOOP die LED anspreche und entsprechend des Counters die Farben zuordne. Dabei entsteht dann ein laufender Streifen, mit verschiedenen Farben, bis der LED Streifen voll eingeschaltet ist. Dann werden alle LEDs ausgeschaltet und der Vorgang beginnt vom Anfang neu.
Dieses funktioniert auch wenn ich mit dem Befehl #define Variable mit einen Wert für die Farbwechsel definiere, und statt einem Zahlenwert auf die Variable prüfe.
Was ich jetzt aber nicht hinbekomme, ist die Variable in jeden Schritt hochzuzählen. leider habe ich dazu auch in meinen alten Kenntnissen und diversen Foren keine Lösung gefunden. Ich habe wohl bei allen Versuchen einen Denkfehler.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 145 // Amount of LEDs on the stripe
#define DELAYVAL 90 // Time (in milliseconds) to pause between pixels
void setup() {
#define STARTCOLOR1 3
// #define STARTCOLOR2 40
// #define STARTCOLOR3 800
// #define STARTCOLOR4 120
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear ();
}
void loop() {
// The first NeoPixel in a strand is #0, second is 1, all the way up
// to the count of pixels minus one.
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness (20) ;
pixels.show();
for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
// Here we're using a moderately bright green color
if(i <= STARTCOLOR1 )
{
pixels.setPixelColor(i, pixels.Color(0, 150, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
else if (i <= 90) // check for the first block of color
{
pixels.setPixelColor(i, pixels.Color(150, 100, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
else if (i <= 110) // check for the second block of color
{
pixels.setPixelColor(i, pixels.Color(150, 150, 150));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
else if (i >= 110) // check for the fouth block of color
{
pixels.setPixelColor(i, pixels.Color(0, 0, 200));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
}
delay(DELAYVAL); // Pause before next pass through loop.
}
"STARTCOLOR1" soll mit "0" beginnen und dann bei jedem LOOP hochzählen, bis dann ein gewünschter Maximalwert erreicht ist.
mein Problem ist, generell erst einmal die Variable hochzuzählen, damit beim ersten Mal eine, dann zwei, dann 3 usw. an LEDs grün leuchten.
Das Ganze ist erst einmal eine Spielerei für mich, um wieder in die Programmierung einzusteigen. Wo ist da der Knoten bei mir ?
Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden.
Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.
mfg ein Moderator.
Danke erst einmal für den Hinweis. Also die Kenntnisse bei mir doch weit hinten irgendwo.
Und als Guru kann ich mich nicht bezeichnen, dazu bin ich viel zu lange raus aus dem Thema.
Werde jetzt mal sehen was ich hinbekomme und sende einen Status.
Ich bin halt der Praktiker, der es nicht so mit den OOP-Begriffen hat. Hauptsache für mich ist, der Wert steckt in der Variablen und ich kann damit arbeiten.
Diese meine Ungenauigkeiten stoßen hier im Forum durchaus zu Recht gerne mal auf Widerstand. Du darfst mich da gerne korrigieren
und natürlich die originale aus kommentiert.
dann erhalte ich folgende Fehlermeldung bei der Abfrage mit if welche LED angesprochen werden soll:
C:\Users\Bernardo\Documents\Arduino\libraries\Test\Test.ino: In function 'void loop()':
Test:38:14: error: 'STARTCOLOR1' was not declared in this scope
if(i <= STARTCOLOR1 )
^~~~~~~~~~~
Bibliothek Adafruit_NeoPixel in Version 1.10.3 im Ordner: C:\Users\Bernardo\Documents\Arduino\libraries\Adafruit_NeoPixel wird verwendet
exit status 1
'STARTCOLOR1' was not declared in this scope
jetzt bin ich ganz verwirrt.
Dieser Wert ist übrigens die Nummer der LED die in dem Band angesprochen werden soll.
Bitte Definitionen vor dem Setup Bereich. Dann sollte es gehen.
Edit: Schau Dir mal in der IDE (die Entwicklungsumgebung) das Beispiel "BlinkWithoutDelay" (Datei > Beispiele > 02.Digital > BlinkWithoutDelay) an. Da sieht man die Grundstruktur.
Danke Jürgen,
das war der Trick. Sollte Schluss machen, da ich bereits seit heute Vormittag mit den LED Systemen einiges getestet habe und natürlich erst einmal die Beispiele genutzt habe, um die ganze Sache zu verstehen. Habe verschiedene LED Streifen; Matrix Systeme erhalten, die ich erst einmal alle damit getestet habe, um zu sehen was damit geht.
Das Beispiel habe ich wohl heute Abend übersehen.
War eines der ersten mit dem ich "gespielt" habe
mir fehlt wenigstens irgendwas wo pixels initialisiert wird.
Und dann ist das mit dem for() schon eine ganz schlechte Idee. In der Zeit kannst Du nichts anderes machen.
Jedes delay innerhalb for() kann eigentlich sogar durch nur eines ersetzt werden.
Schlussendlich wird das dann aufgelöst nach millis().
Aus der Hosentasche - ich hab noch immer keine Pixel und jetzt auch nur umgeschrieben. Weil da doch einiges fehlt ohne Garantie, das es überhaupt geht.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
const byte PIN = 6; // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
const byte NUMPIXELS = 145; // Amount of LEDs on the stripe
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
const uint16_t startcolor[] = { 3, 40, 800, 120};
void setup()
{
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear ();
}
void loop()
{
pixelsUmlauf();
}
void pixelsUmlauf()
{
const unsigned long pauseZeit = 90;
static unsigned long zeitMerker = 0;
static unsigned int aktuellerPixel = 0;
if (millis() - zeitMerker > pauseZeit)
{
zeitMerker = millis();
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness (20) ;
if (aktuellerPixel < NUMPIXELS)
{
if (aktuellerPixel <= startcolor[0] )
{
pixels.setPixelColor(aktuellerPixel, pixels.Color(0, 150, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
}
else if (aktuellerPixel <= 90) // check for the first block of color
{
pixels.setPixelColor(aktuellerPixel, pixels.Color(150, 100, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
}
else if (aktuellerPixel <= 110) // check for the second block of color
{
pixels.setPixelColor(aktuellerPixel, pixels.Color(150, 150, 150));
pixels.show(); // Send the updated pixel colors to the hardware.
}
else if (aktuellerPixel >= 110) // check for the fouth block of color
{
pixels.setPixelColor(aktuellerPixel, pixels.Color(0, 0, 200));
pixels.show(); // Send the updated pixel colors to the hardware.
}
}
}
pixels.show();
}
Hier also der Schritt der funktioniert. Es war übrigens beim Kopieren eine Zeile mit den PIXELS verloren gegangen.
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 145 // Amount of LEDs on the stripe
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 90 // Time (in milliseconds) to pause between pixels
uint16_t STARTCOLOR1 = 3 ;
// #define STARTCOLOR1 3
// #define STARTCOLOR2 40
// #define STARTCOLOR3 800
// #define STARTCOLOR4 120
void setup() {
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear ();
}
void loop() {
// The first NeoPixel in a strand is #0, second is 1, all the way up
// to the count of pixels minus one.
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness (20) ;
pixels.show();
for(int i=0; i<NUMPIXELS; i++) { // For each pixel...
// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
// Here we're using a moderately bright green color
if(i <= STARTCOLOR1 )
{
pixels.setPixelColor(i, pixels.Color(0, 150, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
else if (i <= 90) // check for the first block of color
{
pixels.setPixelColor(i, pixels.Color(150, 100, 0));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
else if (i <= 110) // check for the second block of color
{
pixels.setPixelColor(i, pixels.Color(150, 150, 150));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
else if (i >= 110) // check for the fouth block of color
{
pixels.setPixelColor(i, pixels.Color(0, 0, 200));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL);
}
}
delay(DELAYVAL); // Pause before next pass through loop.
}
Jetzt sollte es auch gehen die Variable hochzuzählen.
Vor dem setup() ist das nun eine globale Variable geworden (mit übrigens unkonventioneller Schreibweise so ganz in Großbuchstaben).
Ich würde ggf. eine Deklaration in loop() oder einer noch zu erstellenden Funktion, die Farbenspiel organisiert, in Erwägung ziehen. Dann aber statisch.
Hallo Zusammen,
erst einmal vielen Dank für die weiteren Tipps.
Hatte als Grundlage für das Ganze eine bereits bestehende Programmierung aus einer Vorlage genutzt. Dort waren alle Variablen in Großbuchstaben. Daher hatte ich das auch weiter so übernommen. ich bin der Meinung, dass man in der Programmierung wegen der Übersicht eine einheitliche Schreibweise beibehalten sollte, und nicht dauernd wechseln. Das ist für mich einfach übersichtlicher, und ich glaube für viele andere auch. Bei der Definition von Variablen habt ihr Recht, die sollten immer nur für den notwendigen und somit kleinstmöglichen Bereich definiert werden. Dabei sollte man natürlich doppelte Namen, was ja in in zwei unterschiedlichen Bereichen möglich wäre unbedingt vermeiden, weil es nur Konfusion erzeigt.
Habe aber hier in dem Programm auf alles dieses erst einmal keine Rücksicht genommen, auch auf das Thema mit dem "for", da es mir primär darum ging den LED Komponenten erst einmal "zum Spielen" diverse Anzeigen zu entlocken. Der nächste Schritt ist für mich dann natürlich eine saubere Programmierung, zumal wenn die Anwendung dann irgendwann offiziell in den laufenden Betrieb geht. Zur Zeit aber sind alle Programme nur Tests, um die Möglichkeiten der Komponenten auszuloten.
Übrigens brauchte ich für das Hochzählen zur Kontrolle keinen Monitor, da ich dass direkt an der Anzahl der grünen LEDs auf dem Stripe kontrollieren konnte.
Von ca. zehn Hinweisen auf diese Debug-Möglichkeit bekomme ich ein "kannte ich noch nicht" zurück, daher hatte ich es geschrieben. Eine sinnvolle Verwendung von #define zur optionalen Verwenden des seriellen Monitors:
WS2812B ist m. E. die schlechteste Wahl, erwäge stattdessen WS2815 oder APA102.
Schaue Dir alternativ auch FastLED an.
Da IR-Fernbedienungen immer die unpassende Beschriftung haben, bin ich auf ESP32, WLAN und Webseite zur Bedienung umgestiegen. Anregungen zur "Turboentrostung" im Thema Treppenbeleuchtung die 50.
Danke agmue für die Hinweise. So langsam kommen die alten Kenntnisse wieder zurück.
Bei mir wird es sich im Moment erst einmal nur um die Steuerung von LED Bänder und Matrix Systemen handeln, die eine permanente Farbfolge oder ähnliches erhalten sollen. Wie weit das dann am Ende noch gehen wird, eventuell bis zur Steuerung über ein Eingabesystem vermag ich nicht zu sagen. Daher ist jeder Tipp zumindest Wert gelesen und im Hinterkopf behalten zu werden.
Zur Zeit bekommt das System eben einfach eine sich immer wiederholende Musterfolge, die einmal eingegeben nicht mehr geändert werden soll. Aber wie sagt man immer: "Man weiß es nicht.." oder "Sag niemals nie, denn das ist schon gelogen."
Zur Vervollständigung der ganzen Anfrage jetzt einmal das fertige "Spielprogramm".
Folgende Anforderung war gegeben: Band soll mit vier farbigen Blöcken erleuchtet werden. Dabei hatte ich zur besseren Unterscheidung die erste LED in dem ersten Block blau gemacht.
dann sollen diese Blöcke jeweils um ein LED verschoben werden, sodass es aussieht als würden die Blöcke nach rechts wandern und dann von links wieder hineingeschoben werden. so wie ein Lauflicht eben.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 256 // Amount of LEDs on the stripe 144, on Matrix 256
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels
uint16_t startcolor1 = 0 ;
uint16_t startcolor2 = startcolor1 +36 ;
uint16_t startcolor3 = startcolor2 +36 ;
uint16_t startcolor4 = startcolor3 +36 ;
uint16_t endcolor4 = startcolor4 +36 ;
uint16_t led = 0 ;
void setup() {
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.clear ();
}
void loop() {
// The first NeoPixel in a strand is #0, second is 1, all the way up
// to the count of pixels minus one.
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness (100);
pixels.show();
for(int i=0; i<NUMPIXELS ; i++) {
if (i == startcolor1 )
{
pixels.setPixelColor(i, pixels.Color(0, 0, 255)); // blue //
pixels.show(); // Send the updated pixel colors to the hardware.
// delay(DELAYVAL);
}
if (
((i > startcolor1 ) && (i < startcolor2 ))
or
// check if startcolor1 passed last LED and start new from first LED
(( i < startcolor2) and ( startcolor1 > startcolor2 ))
or
// fill final part if startcolor2 passed last led
(( i > startcolor1) and ( startcolor1 > startcolor2 ) and (startcolor1 < NUMPIXELS ))
)
{
pixels.setPixelColor(i, pixels.Color(255, 210, 0)); // Markus yellow //
pixels.show(); // Send the updated pixel colors to the hardware.
// delay(DELAYVAL);
}
// second block of color
if (
((i >= startcolor2 ) and (i < startcolor3 )) // check for normal row
or
// check if startcolor3 passed last LED and start new from first LED
(( i < startcolor3) and ( startcolor2 > startcolor3 ))
or
// fill final part if startcolor3 passed last led
(( i >= startcolor2 ) and ( startcolor2 > startcolor3) and ( startcolor2 < NUMPIXELS ))
)
{
pixels.setPixelColor(i, pixels.Color(0, 255, 0)); // green
pixels.show(); // Send the updated pixel colors to the hardware.
// delay(DELAYVAL);
}
// third block of color
if (
((i >= startcolor3 ) and (i < startcolor4 )) // check for normal row
or
// check if startcolor4 passed last LED and start new from first LED
(( i < startcolor4) and ( startcolor3 > startcolor4 ))
or
// fill final part if startcolor3 passed last led
(( i >= startcolor3 ) and ( startcolor3 > startcolor4 ) and ( startcolor3 < NUMPIXELS ))
)
{
pixels.setPixelColor(i, pixels.Color(255, 0, 255)); // pink
pixels.show(); // Send the updated pixel colors to the hardware.
// delay(DELAYVAL);
}
// forth block of color
if (
((i >= startcolor4 ) and (i < endcolor4 )) // check for normal row
or
// check encolor4 passed last LED and start new from first LED
(( i < endcolor4) and ( startcolor4 > endcolor4 ))
or
// fill final part if startcolor4 passed last led
(( i >= startcolor4 ) and ( startcolor4 > endcolor4 ) and ( startcolor4 < NUMPIXELS ))
)
{
pixels.setPixelColor(i, pixels.Color(255, 0, 0)); // red
pixels.show(); // Send the updated pixel colors to the hardware.
// delay(DELAYVAL);
}
}
startcolor1 = startcolor1 +1 ;
if ( startcolor1 == NUMPIXELS )
{ startcolor1 = 0 ; }
startcolor2 = startcolor2 +1 ;
if ( startcolor2 == NUMPIXELS )
{ startcolor2 = 0 ; }
startcolor3 = startcolor3 +1 ;
if ( startcolor3 == NUMPIXELS )
{ startcolor3 = 0 ; }
startcolor4 = startcolor4 +1 ;
if (startcolor4 == NUMPIXELS )
{ startcolor4 = 0 ; }
endcolor4 = endcolor4 +1 ;
if (endcolor4 >= NUMPIXELS )
{ endcolor4 = 0 ; }
delay(4 * DELAYVAL);
delay(DELAYVAL);
// delay(DELAYVAL);
}
Danke für die Rückmeldung, so, finde ich, gehört sich das
Solange Du nur das machst, was Du gerade machst, ist das OK.
Bei Erweiterungen kann Dir das aber schmerzlich auf die Füße fallen, weshalb Du Dir möglichst frühzeitig einen blockadearmen Programmierstil aneignen solltest. In der IDE gibt es dafür das Beispiel BlinkWithoutDelay, das Du Dir zu Gemüte führen solltest.
Als Übung: Lasse zwei oder mehr LEDs, auch als Teil eines Streifens, unabhängig mit unterschiedlichen Frequenzen blinken.
Hallo agmue,
Danke für die aufmunternden Worte. Ich hatte das Ganze an Hand eines Demoprogramms entwickelt, um erst einmal wieder in die C++ Programmierung rein zu kommen, und auf die Schnelle erst einmal zu sehen, wie die Komponenten gehandhabt werden müssen.
Leider sind nach über 25 Jahren des "Einstaubens" und nur "Herumliegens" einige Dinge nicht mehr so präsent, wie sie es sein sollten.
Selbstverständlich gibt es bessere Lösungen als den Rechner auf der Stelle laufen zu lassen, was ja bei einem Delay passiert, ohne das man die Zeit nutzen kann andere sinnvolle Dinge zu tun. Daher würde sich besser die Funktion "millis()" anbieten da dann auch Interrupts funktionieren.
Aber ich gebe ja die Hoffnung nicht auf, dass sich, wie bei einer Modelleisenbahn, die man als Kind hatte und die dann Jahrzehnte eingepackt irgendwo rum lag, auch nach und nach alle Einzelteile wieder finden.