LED RGB-Steuerung ohne Delay

Hallo,

ich habe für ein 5 Meter LED RGB-Strip einen Driver hier gekauft, der mit folgenden Sketch funktioniert:

//Demo for LED Strip Driver controling single RGB LED strip by Catalex
//Hardware: A LED Strip Driver and 5 meters of RGB LED strip
//Board: Carduino or Arduino UNO R3 
//IDE:   Arduino-1.0
//Function: Show 7 colors with a single RGB LED.
//Store: catalex.taobao.com
/***************************************************************/
#include "RGBdriver.h"
#define CLK 3//pins definitions for the driver        
#define DIO 2//pins definitions for the driver  
RGBdriver Driver(CLK,DIO);
const int FadeZeit = 250; // Ein höherer Wert verlangsamt den farbwechsel
int r, g, b;
void setup()  
{ 

}  
void loop()  
{ 
  /*Function: SetColor()					          */
  /*Parameters: red:0~255 						    */
  /*            green:0~255						    */
  /*            blue:0~255						    */
  /*Note: the greater the value,the brighter the LED*/
  
  // Wechsel von Blau zu Lila
  for (r = 0; r < 256; r++){
  Driver.begin();
  Driver.SetColor(r, 0, 255);
  Driver.end();
 delay(FadeZeit);
  }
  
  // Wechsel von Lila zu Rot
    for (b = 255; b > 0; b--){
  Driver.begin();
  Driver.SetColor(255, 0, b);
  Driver.end();
 delay(FadeZeit);
  }
  
  // Wechsel von Rot zu Gelb
    for (g = 0; g < 256; g++){
  Driver.begin();
  Driver.SetColor(255, g, 0);
  Driver.end();
 delay(FadeZeit);
   }
   
   // Wechsel von Gelb zu Gruen
    for (r = 255; r > 0; r--){
  Driver.begin();
  Driver.SetColor(r, 255, 0);
  Driver.end();
 delay(FadeZeit);
   }
   
   // Wechsel von Gruen zu Petrol
    for (b = 0; b < 256; b++){
  Driver.begin();
  Driver.SetColor(0, 255, b);
  Driver.end();
 delay(FadeZeit);
    }
    
    // Wechsel von Petrol zu Blau
    for (g = 255; g > 0; g--){
  Driver.begin();
  Driver.SetColor(0, g, 255);
  Driver.end();
 delay(FadeZeit);
}}

Mit dem Wert

const int FadeZeit = 250;

kann die Zeit des Farbwechsel eingestellt werden. Bei dem Wert 250, dauert ein Farbwechsel so ca. 2 Minuten.
Da ich diesen Code aber in einen bestehenden Sketch mit einbauen möchte, darf der Farbwechsel allerdings nicht mit der ‘delay’- Funktion ablaufen.

Ich habe mir gedacht dann stelle ich den Sketch von ‘delay’ auf ‘millis’ um, den ich dann wie folgt versucht habe umzubauen:

//Demo for LED Strip Driver controling single RGB LED strip by Catalex
//Hardware: A LED Strip Driver and 5 meters of RGB LED strip
//Board: Carduino or Arduino UNO R3 
//IDE:   Arduino-1.0
//Function: Show 7 colors with a single RGB LED.
//Store: catalex.taobao.com
/***************************************************************/
#include "RGBdriver.h"
#define CLK 3//pins definitions for the driver        
#define DIO 2
RGBdriver Driver(CLK,DIO);
const int FadeZeit = 250L; // Ein höherer Wert verlangsamt den farbwechsel
int r, g, b;
uint8_t status;
uint32_t nextMillis = 0;
void setup()  
{ 

}  
void loop()  
{ 
  /*Function: SetColor()					          */
  /*Parameters: red:0~255 						    */
  /*            green:0~255						    */
  /*            blue:0~255						    */
  /*Note: the greater the value,the brighter the LED*/
    if(status == 0 && millis() > nextMillis) 
  {
   status = 1;
  // Wechsel von Blau zu Lila
  for (r = 0; r < 256; r++){
  Driver.begin();
  Driver.SetColor(r, 0, 255);
  Driver.end();
  nextMillis = millis() + FadeZeit;
  }
  }else if(status == 1 && millis() > nextMillis) 
  {
   status = 2;
  // Wechsel von Lila zu Rot
    for (b = 255; b > 0; b--){
  Driver.begin();
  Driver.SetColor(255, 0, b);
  Driver.end();
nextMillis = millis() + FadeZeit; 
  }
  
      }else if(status == 2 && millis() > nextMillis) // Es wurde mindestens 1 Sensor gefunden
  {
    status = 3;
  // Wechsel von Rot zu Gelb
    for (g = 0; g < 256; g++){
  Driver.begin();
  Driver.SetColor(255, g, 0);
  Driver.end();
nextMillis = millis() + FadeZeit; 
   }
  
      }else if(status == 3 && millis() > nextMillis) // Es wurde mindestens 1 Sensor gefunden
  {
    status = 4; 
   // Wechsel von Gelb zu Gruen
    for (r = 255; r > 0; r--){
  Driver.begin();
  Driver.SetColor(r, 255, 0);
  Driver.end();
nextMillis = millis() + FadeZeit; 
   }
   
       }else if(status == 4 && millis() > nextMillis) // Es wurde mindestens 1 Sensor gefunden
  {
    status = 5;
   // Wechsel von Gruen zu Petrol
    for (b = 0; b < 256; b++){
  Driver.begin();
  Driver.SetColor(0, 255, b);
  Driver.end();
nextMillis = millis() + FadeZeit; 
    }
    
        }else if(status == 5 && millis() > nextMillis) // Es wurde mindestens 1 Sensor gefunden
  {
    status = 6;
    // Wechsel von Petrol zu Blau
    for (g = 255; g > 0; g--){
  Driver.begin();
  Driver.SetColor(0, g, 255);
  Driver.end();
nextMillis = millis() + FadeZeit; 

status = 0;

  }}}

Leider läuft der Farbwechsel nun mit diesem Sketch nicht mehr in der gewünschten Zeit von ca. 2 Minuten ab, sondern in 3-4 Sekunden. Ich kann zwar den Wert:

const int FadeZeit = 250L;

erhöhen, allerdings muss ich diesen auf den Wert von ca. ‘25000L’ erhöhen, was zwar den Start des nächsten Farbwechsel verlängert, aber die Fade-Zeit des Farbwechsel selbst immer noch in ca. 3-4 Sekunden abläuft.

Wie muss ich diesen Sketch nun ändern?

Danke.

Gruß Jens

Die Schleifen sind falsch. Eine for-Schleife wird solange ausführt, bis g == 0. In dieser Schleife hätte dein delay gehört, was aber blockiert.

  for (g = 255; g > 0; g--){[color=#222222][/color]
  Driver.SetColor(0, g, 255);[color=#222222][/color]
  }

Du musst die Strategie ändern.

if(g > 0) {
g--;
}
else {
return bla; // gib irgendwas zurück, dass deiner Hauptfunktion sagt, die Schleife ist durchlaufen.
}

Hallo,
danke schon mal für die Antwort.

So ganz will es mir allerdings nicht erschließen.
Die 'millis' sollen doch bleiben, richtig? Oder gibt es eine andere Möglichkeit, den 1. Code der ja funktioniert, anders aufzustellen?
Es müsste nur die 'delay-Warteschleife' weg, da es mir den gesamten Ablauf in einem bestehenden Sketch, wo der Ablauf mit rein soll verzögert/unterbricht.
Was ist mit [color=#222 gemeint?

Danke. :slight_smile:

Gruß Jens

/*
data			Led-Array
SIZE_OF_DATA	Groeße Led-Array
value			Sollwert
steps			Anzahl Schritte, falls steps >= 2

Rueckgabewert	0	Sollwert != Istwert
				1	Sollwert == Istwert
*/
uint8_t fade(uint8_t *data, const uint8_t SIZE_OF_DATA, uint8_t value, uint8_t steps)
{
	for(uint8_t step = 0; step < steps; step++) {
		for(uint8_t posData = 0; posData < SIZE_OF_DATA; posData++)	{
			if(data[posData] > value) data[posData]--;
			else if(data[posData] < value) data[posData]++;
		}
	}
	
	if(data[0] == value) return 1;
	else return 0;
}

Hier eine Fade Funktion aus einem meiner Programme. Die for-Schleife mit steps kannst du auch komplett rausnehmen.

if(millis() - lastMillis >= interval)
{
	lastMillis = millis();

	switch(state)
	{
		case 0:
		// Wenn Rueckgabewert >0 dann wird in den naechsten Fall gewechselt
		state += fade(data, sizeof(data), 255, 1);
		break;

		case 1:
		state += fade(data, sizeof(data), 0, 1);
		break;
	}
}

Kann man denn die Zeit für den Farbwechsel jetzt noch ändern?

Gruß Jens

Knippi:
Kann man denn die Zeit für den Farbwechsel jetzt noch ändern?

Die Zeit steckt in interval. Wenn Du interval als Variable definierst, kannst Du den Wert jederzeit ändern. Sinnvoll ist das wohl beim Weiterzählen von state.

Also z.b. 'state=250', richtig?

Gruß Jens

Nein.

"interval" ist deine Variabel, die die Zeit angibt, wie lange jeder Schritt dauert. Gibt fade 1 zurück, so wird dieser auf state aufaddiert. Es startet der nächste Farbverlauf

Zum Testen habe ich einen Lichtpunkt eines APA102-LED-Streifens genommen. Der zeigt ein schönes Faden durch die Farben mit unterschiedlicher Geschwindigkeit aufgrund verschiedener Verzögerungszeiten. Wenn Du das bei Dir laufen lassen möchtest, mußt Du den Sketch an Deine Programmbibliothek anpassen.

// getestet mit Nano
#include "FastLED.h"
FASTLED_USING_NAMESPACE
#define LED_TYPE    APA102
#define COLOR_ORDER BGR
#define BRIGHTNESS  64
#define NUM_LEDS    62
// #define CLK 3  // bei Hardware-SPI Pin 13
// #define DIO 2  // bei Hardware-SPI Pin 11

CRGB leds[NUM_LEDS];
const byte farben[6][3] = {
//  r    g    b
    0,   0, 255,  // 0 r++
  255,   0, 255,  // 1 b--
  255,   0,   0,  // 2 g++
  255, 255,   0,  // 3 r--
    0, 255,   0,  // 4 b++
    0, 255, 255   // 5 g--
};
const unsigned long zeiten[] = {10, 20, 30, 40, 30, 20};

byte status, r, g, b;
unsigned long aktMillis, fadeMillis, fadeZeit;

void setup() {
  FastLED.addLeds<LED_TYPE, COLOR_ORDER>(leds, NUM_LEDS);  // MOSI Pin11 an DIN; ACK  Pin13 an CIN
  FastLED.setBrightness(BRIGHTNESS);
  LEDS.showColor(CRGB(0, 0, 0));
  farbenFestlegen(status = 0);
}

void loop() {
  aktMillis = millis();
  if (aktMillis - fadeMillis >= fadeZeit) {
    fadeMillis = aktMillis;
    switch (status) {
      case 0:
        if (r < 255) {
          r++;
        } else {
          farbenFestlegen(status = 1);
        }
        break;
      case 1:
        if (b > 0) {
          b--;
        } else {
          farbenFestlegen(status = 2);
        }
        break;
      case 2:
        if (g < 255) {
          g++;
        } else {
          farbenFestlegen(status = 3);
        }
        break;
      case 3:
        if (r > 0) {
          r--;
        } else {
          farbenFestlegen(status = 4);
        }
        break;
      case 4:
        if (b < 255) {
          b++;
        } else {
          farbenFestlegen(status = 5);
        }
        break;
      case 5:
        if (g > 0) {
          g--;
        } else {
          farbenFestlegen(status = 0);
        }
        break;
    }
    leds[0] = CRGB(r, g, b);
    FastLED.show();
  }
}

void farbenFestlegen(byte sta) {
  r = farben[sta][0];
  g = farben[sta][1];
  b = farben[sta][2];
  fadeZeit = zeiten[sta];
}

Wundert mich dass das noch niemand angesprochen hat:

allerdings muss ich diesen auf den Wert von ca. '25000L' erhöhen, was zwar den Start des nächsten Farbwechsel verlängert, aber die Fade-Zeit des Farbwechsel selbst immer noch in ca. 3-4 Sekunden abläuft.

In einen int gehen nur maximal (2 ^ 15) - 1 = 32,767. In einen unsigned int gehen (2 ^ 16) - 1 = 65,535. In einen unsigned long gehen (2 ^ 32) - 1 = 4,294,967,295

Das ist doch ein ganz anderer LED-Streifen.

Das bekomme ich so nicht zum Laufen und ich habe jetzt mehrer Stunden versucht, irgendwie eine Lösung zu finden. :slightly_frowning_face:

Ich bekomme die Vorschläge von euch nicht zum Laufen oder ich setzte diese im Sketch immer falsch um. >:(

Kann mir jemand den Sketch einmal so komplettieren, dass dieser funktioniert und vielleicht die Stellen kommentieren, wo ich den Fehler gemacht habe.

Vielen Dank, schon mal. :slight_smile:

Gruß Jens

Knippi:
Kann mir jemand den Sketch einmal so komplettieren, dass dieser funktioniert und vielleicht die Stellen kommentieren, wo ich den Fehler gemacht habe.

Also ich zumindest sehe mich dazu nicht in der Lage, sorry. Einen Hinweis hätte ich.

Knippi:
Leider läuft der Farbwechsel nun mit diesem Sketch nicht mehr in der gewünschten Zeit von ca. 2 Minuten ab, sondern in 3-4 Sekunden.

Diese Schleife ist blockierend und beinhaltet keine nennenswerte Verzögerung:

for (r = 0; r < 256; r++) {
  Driver.begin();
  Driver.SetColor(r, 0, 255);
  Driver.end();
  nextMillis = millis() + FadeZeit;
}

Knippi:
Das ist doch ein ganz anderer LED-Streifen.

Stimmt, Deine Hardware habe ich halt nicht. Aber die Logik zur Ansteuerung ist identisch.

Ohne die Bibliothek RGBdriver zu kennen, habe ich die Aufrufe in meinen Sketch eingebunden, ausdrücklich ohne Gewähr:

// ungetestet !!!
#include "RGBdriver.h"
#define CLK 3//pins definitions for the driver        
#define DIO 2//pins definitions for the driver  
RGBdriver Driver(CLK,DIO);

const byte farben[6][3] = {
//  r    g    b
    0,   0, 255,  // 0 r++
  255,   0, 255,  // 1 b--
  255,   0,   0,  // 2 g++
  255, 255,   0,  // 3 r--
    0, 255,   0,  // 4 b++
    0, 255, 255   // 5 g--
};
const unsigned long zeiten[] = {10, 10, 10, 10, 10, 10};

byte status, r, g, b;
unsigned long aktMillis, fadeMillis, fadeZeit;

void setup() {
  farbenFestlegen(status = 0);
}

void loop() {
  aktMillis = millis();
  if (aktMillis - fadeMillis >= fadeZeit) {
    fadeMillis = aktMillis;
    switch (status) {
      case 0:
        if (r < 255) {
          r++;
        } else {
          farbenFestlegen(status = 1);
        }
        break;
      case 1:
        if (b > 0) {
          b--;
        } else {
          farbenFestlegen(status = 2);
        }
        break;
      case 2:
        if (g < 255) {
          g++;
        } else {
          farbenFestlegen(status = 3);
        }
        break;
      case 3:
        if (r > 0) {
          r--;
        } else {
          farbenFestlegen(status = 4);
        }
        break;
      case 4:
        if (b < 255) {
          b++;
        } else {
          farbenFestlegen(status = 5);
        }
        break;
      case 5:
        if (g > 0) {
          g--;
        } else {
          farbenFestlegen(status = 0);
        }
        break;
    }
  Driver.begin();
  Driver.SetColor(r, g, b);
  Driver.end();
  }
}

void farbenFestlegen(byte sta) {
  r = farben[sta][0];
  g = farben[sta][1];
  b = farben[sta][2];
  fadeZeit = zeiten[sta];
}

Ohne die Bibliothek RGBdriver zu kennen, habe ich die Aufrufe in meinen Sketch eingebunden, ausdrücklich ohne Gewähr:

Das nenne ich einmal eine Punktlandung. :slight_smile:

Ich hätte mich wahrscheinlich noch ein paar Tage im Kreis gedreht. :astonished:

Vielen Dank dafür.

Gruß Jens