Black Friday = Pricewatch Bekijk onze selectie van de beste Black Friday-deals en voorkom een miskoop.

[WS2801] Ik loop een beetje vast met animeren van LED strip

Pagina: 1
Acties:

  • xoniq
  • Registratie: April 2005
  • Laatst online: 12-11 19:23
Ik ben het experimenteren met WS2801 LED-strips.
Met leds in specifieke kleuren verlichten werkt het prima. Ik ben echter vast komen te zitten in het maken van animaties.

Ik wil specifieke secties op laten lichten (de zogenaamde 'strands' in mijn code).
Virtueel deel ik de LED-strip op tot 14 secties van 9 leds per sectie.

Ik wil deel 1 (0 of hoe je het wilt noemen) faden naar 100% helderheid, met een snelheid die in een variabele kan worden gedefinieerd. Op dit moment gebruik ik een delay(1), en het faden is nu te traag.
Overigens denk ik dat ik niet de delay() moet gebruiken. Waarom? Ik wil niet wachten tot sectie één volledig verlicht is. Ik wil dat sectie 2 begint te faden kort voor sectie 1 klaar is, dus een bijna vloeiende overgang.

En nadat alle secties zijn verlicht, wacht 2 volle seconden, en beginnen te uit faden op exact dezelfde volgorde.

Kortom: De secties moeten 1 voor 1 'aan' faden, en 2 seconden nadat ze allemaal zijn verlicht, weer 1 voor 1 'uit' faden, één sectie per keer. (Met de mogelijkheid om de volgende sectie animatie te beginnen terwijl de actieve sectie niet helemaal nog niet helemaal klaar is)


Mijn huidige code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Initialize libraries
#include "Adafruit_WS2801.h"
#include "SPI.h"

#define NUM_LEDS 128
#define STRANDS 14

#define DATA_PIN 5
#define CLOCK_PIN 6

// Initialize LED strip
Adafruit_WS2801 strip = Adafruit_WS2801(NUM_LEDS, DATA_PIN, CLOCK_PIN);

// Variables
int ledsPerStrain = 0;

// Initialize
void setup(){
    ledsPerStrain = (NUM_LEDS/STRANDS); // Current outcome: 9 LEDs per strand
    bootSequence();
}

// Run application
void loop() {
    runAnimation(0, 0, 255, 1);
}

void bootSequence(){
    strip.begin(); // Initialize strip
    strip.show(); // Empty strip

    // TODO: Create boot sequence (self-test) animation
}

void runAnimation(uint8_t red, uint8_t green, uint8_t blue, uint8_t wait) {
    unsigned long currentMillis = millis();

    //
    // Turn on all strands
    //
    for(uint8_t s=0; s < STRANDS; s++){
        for(uint8_t b=0; b <255; b++) {
            for(uint8_t i=(s*ledsPerStrain); i < ((s*ledsPerStrain)+ledsPerStrain); i++) {
                strip.setPixelColor(i, red*b/255, green*b/255, blue*b/255);
            }
            strip.show();
            delay(wait);
        }
    }
    delay(2000); // Wait 2 seconds after everything is lit

    //
    // Turn off all strands
    //
    for(uint8_t s=0; s < STRANDS; s++){
        for(uint8_t b=0; b <255; b--) {
            for(uint8_t i=(s*ledsPerStrain); i < ((s*ledsPerStrain)+ledsPerStrain); i++) {
                strip.setPixelColor(i, red*b/255, green*b/255, blue*b/255);
            }
            strip.show();
            delay(wait);
        }
    }
    delay(2000); // Wait 2 seconds after everything went dark
};

// Create a 24 bit color value from R,G,B
uint32_t Color(byte r, byte g, byte b){
    uint32_t c;
    c = r;
    c <<= 8;
    c |= g;
    c <<= 8;
    c |= b;
    return c;
}

  • LED-Maniak
  • Registratie: Oktober 2003
  • Laatst online: 18:13
Je kan het interrupt based uitvoeren:

Huidige staat van elke RGB pixel bijhouden, daarna periodiek(elke interrupt) de waarde ophogen. Wil je langzamer faden, dan voeg je een extra delay byte toe zodat je elke x interrupts ophoogt.

Mitsubishi externe temperatuur sensor (Home Assistant compatible): V&A - ClimaControl - Ook voor Panasonic & LG.


  • xoniq
  • Registratie: April 2005
  • Laatst online: 12-11 19:23
Heb je een misschien voorbeeld? Ik doe wel het eea met Arduino bordjes, maar de LED strip met losse addressable LEDs is voor mij relatief nieuw.

  • epic007
  • Registratie: Februari 2004
  • Laatst online: 10-11 15:59
Ik zou afstappen van het gebruik van delay(), en het geheel implementeren in de loop() met behulp van millis().

Bijvoorbeeld:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void loop()
{
    unsigned long phase = (millis() % 10000) / 10;

    // phase is nu een getal dat in 10 sec van 0 tot 1000 gaat

    if (phase >= 0 && phase < 256)
    {
        strip.setPixelColor(1,  phase, ... ,...);
    }

    if (phase >= 128 && phase < (256 + 128))
    {
        strip.setPixelColor(2,  phase-128, ... , ... );
    }

    // Je kan nu ook inputs uitlezen tijdens de loop, wat niet kan in een delay()
    digitalRead(...); 
}


Dit kan veel eleganter opgelost worden maar het demonstreert wel hoe je led 1 & 2 onafhankelijk van elkaar (parallel) kan besturen.

Zie hier voor een ander voorbeeld.


Verschillende animaties zou je met een switch statement kunnen doen:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
enum State { FadeIn, FadeOut, Idle };

State currentState = Idle;

void loop()
{
    switch(state)
    {
        case FadeIn:
               strip.SetColor(...);
               break;
        case FadeOut:
               break;
        case Idle:
               if (elapsedMs > 1000) 
                   state = FadeIn;
               break;
    }

}

[ Voor 27% gewijzigd door epic007 op 24-08-2015 09:12 ]