Page 1 of 1

Arduino – All LEDStrip effects in one (NeoPixel and FastLED)

Arduino – All LEDStrip effects in one (NeoPixel and FastLED)
   80

If you’ve read the article I wrote a while ago “LEDStrip effects for NeoPixel and FastLED“, then you might have noticed quite a few requests to combine all these effects in one single sketch.

I have seen some users come up with some nice examples, but the challenge remained (for me): how do I instantly toggle from effect to another?

Well, today I’ll have such a sketch available for you; it allows you toggle between effects with a simple switch.




Overview

Framework – NeoPixel or FastLED

Well, I have to admit that I have become a FastLED fan – it’s become much more mature and advanced than NeoPixel. However, as with the original article, I wanted this to work for both. FastLED might be more advanced, but NeoPixel takes up less memory. This way you have a choice – it’s up to you. With the Arduino Uno R3 though, this works great with FastLED.

I do recommend reading the original article “LEDStrip effects for NeoPixel and FastLED“, but it is not required since I will be posting the full code for both libraries.

Installing FastLED or NeoPixel

The Arduino IDE has come a long way since I’ve written the original article, and installing a library has become much easier.

The Arduino IDE can be dowloaded from their website for free – I have never used their online IDE, so please stick with the regular one that you install on your computer.

After starting the Arduino IDE, which may take a bit, go to the menu and choose “SketchInclude LibraryManage Libraries“.
In the window that pops up, enter either “neopixel” or “fastled” in the filter field, and press ENTER for the library you’d like to use. I prefer FastLED, but I leave that choice up to you.

Your selected library will be listed, where you can select a version (I used v3.1.0 of FastLED and v1.1.3 of NeoPixel) and click “Install“.

And that’s all there is to it …

Arduino IDE - Install a Library

Arduino IDE – Install a Library

Download LEDEffect Sketches

At the end I’ll list the full code, but you can save yourself the typing or copy and paste efforts by just downlading them here.

Settings … make sure you set them right! 

Obviously, there are a few settings in the source code you will have to match to your setup.

#define PIN 5
Make sure this number (5) matches the PIN on your Arduino that you’re used for Din of your LED strip – this could for example by 6.

#define NUM_LEDS 60
Make sure this number (60) matches the LED count of your LED strip(s).

For FastLED, make sure the “FastLED.addLeds” function is set correctly for your LED strip – I’ve used a WS2811/WS218 LED stip – and the correct color order (RGB vs GRB)!
For NeoPixel, make sure the “Adafruit_NeoPixel strip” line matches your hardware – again: I used a WS2811/WS2812 – and the correct colors (NEO_RGB in this case).

Note :
The use of PIN 2 for the button is a requirement since it allows the button to interrupt your code. Pin 3 will work as well – just remember to chaneg the #define BUTTON 2 to #define BUTTON 3. This is all set for the Arduino UNO R3. Other Arduino models this might be a different pin.

DOWNLOAD - AllEffects LEDStrip Effect (FastLED) 

Filename: AllEffects_FastLED.ino.zip
Version: 1.0
Size: 4.6 KiB
Date: January 3, 2018
 Download Now 

DOWNLOAD - AllEffects LEDStrip Effect (NeoPixel) 

Filename: AllEffects_NeoPixel.ino.zip
Version: 1.0
Size: 4.6 KiB
Date: January 3, 2018
 Download Now 

LED Hardware Setup

Since we want to be able to toggle effects, we will need to change the hardware a little bit by adding a button.

Note: I’ve used PIN 6 in the drawing but PIN 5 in the code. So please either use PIN 6 (modify the #define PIN 5 line to #define PIN 6) or read the drawing below as PIN 5 (instead of PIN 6) – apologies for the confusion here.

The setup is the same as the original article, I’ve just added a push switch.
This push switch is of the type that makes contact when you push it, but breaks contact once you let it go.

Arduino, LED strip, Switch and Power Supply setup

Arduino, LED strip, Switch and Power Supply setup

Challenges Explained

Most users that tried to combine effects have ran into the same issues. I’ll briefly explain how I resolved them so it may be of use to someone – if you don’t care about the challenges, then feel free to ignore it and test the sketch right away.

Challenge 1 – Endless effects

Some of the effects last for ever – for example the bouncing balls. One of the visitors here, Daniel, pointed me in the right direction on how to address this. I made some improvements so it accommodates multiple bouncing balls.

In short, the bouncing balls kept going forever because of an endless while loop:


...
  while(true) {
  ...
  }
...

For one bouncing ball this could be caught in the if ( ImpactVelocity[i] < 0.01 ) { ... } part, but for multiple balls this became a little more challenging.

The basic solution was to keep track of all balls, to see if they are still finishing their bounce session. If all stopped bouncing then we exit the procedure.

Below you can see the final bouncingBalls() procedure.
I’ve added a parameter to this function so one can choose to let a ball bounce until it’s done, or have a ball restart bouncing over and over again.


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
void BouncingColoredBalls(int BallCount, byte colors[][3], boolean continuous) {
  float Gravity = -9.81;
  int StartHeight = 1;
 
  float Height[BallCount];
  float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
  float ImpactVelocity[BallCount];
  float TimeSinceLastBounce[BallCount];
  int   Position[BallCount];
  long  ClockTimeSinceLastBounce[BallCount];
  float Dampening[BallCount];
  boolean ballBouncing[BallCount];
  boolean ballsStillBouncing = true;
 
  for (int i = 0 ; i < BallCount ; i++) {  
    ClockTimeSinceLastBounce[i] = millis();
    Height[i] = StartHeight;
    Position[i] = 0;
    ImpactVelocity[i] = ImpactVelocityStart;
    TimeSinceLastBounce[i] = 0;
    Dampening[i] = 0.90 - float(i)/pow(BallCount,2);
    ballBouncing[i]=true;
  }

  while (ballsStillBouncing) {
    for (int i = 0 ; i < BallCount ; i++) {
      TimeSinceLastBounce[i] =  millis() - ClockTimeSinceLastBounce[i];
      Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000;
 
      if ( Height[i] < 0 ) {                      
        Height[i] = 0;
        ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
        ClockTimeSinceLastBounce[i] = millis();
 
        if ( ImpactVelocity[i] < 0.01 ) {
          if (continuous) {
            ImpactVelocity[i] = ImpactVelocityStart;
          } else {
            ballBouncing[i]=false;
          }
        }
      }
      Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
    }

    ballsStillBouncing = false; // assume no balls bouncing
    for (int i = 0 ; i < BallCount ; i++) {
      setPixel(Position[i],colors[i][0],colors[i][1],colors[i][2]);
      if ( ballBouncing[i] ) {
        ballsStillBouncing = true;
      }
    }
   
    showStrip();
    setAll(0,0,0);
  }
}

Challenge 2 – Catching that button

Next challenge was adding a button to toggle the effects.

Initially I started with following the good Button tutorial on the Arduino website, until I found a slightly easier method. As you can see in the Arduino tutorial, they use a resistor. Now it seems (took me a while before I bumped into that one by accident) there is an internal resistor for this as well – so I decided to use that to keep the hardware setup easier.

Of course we need to define what PIN we want to use for our button. Here we have to pay attention (you’ll see more about that in the next challenge).
We want the button to basically “interrupt” an effect so we can switch right away to another effect.
If we would do it the “usual” way, then we’d find ourselves adding lots and lots of code to try to catch the button status – something I’d like to avoid.

To have a button “interrupt” the flow of the code, we must use either PIN 2 and PIN 3 (on an Arduino UNO). Per the guide of the Arduino website:

Pins for Interrupt Button
 Uno, Nano, Mini, other 328-based  2, 3
 Mega, Mega2560, MegaADK  2, 3, 18, 19, 20, 21
 Micro, Leonardo, other 32u4-based  0, 1, 2, 3, 7
 Zero  All digital pins, except pin 4
 MKR1000 Rev.1  0, 1, 4, 5, 6, 7, 8, 9, A1, A2
 Due  all digital pins
 101  2, 5, 7, 8, 10, 11, 12, 13

To make a button work with the internal pull-up resistor, we will have to add a line to the “setup()” function:


digitalWrite (BUTTON, HIGH);  // internal pull-up resistor

Later we can test if a button was pressed with:


if (digitalRead (BUTTON) == HIGH) {
  ...
}

Challenge 3 – Interrupt an effect and catch that button

This method is what worked best for me, and I’m sure there are better options out there.

I used a so called interrupt, that’s why we choose pin 2 for the switch. We want to catch the button press at any given time and we want to attach a function to an interrupt caused by pressing the button and for this we can use the “attachInterrupt()” function. If you’d like to dig deeper in this topic, please read the Arduino attachInterrupt Documentation.

In essence: When the state of the button (BUTTON) changes (CHANGE), we’d like to call for our own function (changeEffect()).

Which in code would look something like this:


attachInterrupt (digitalPinToInterrupt(BUTTON), changeEffect, CHANGE); // pressed

When reading the documentation you might wonder why I used the “CHANGE” mode instead of the “LOW” or “HIGH” mode. The reason is that both produced unexpected effects, like I pressed the button multiple times. So instead I used “CHANGE” and in our own function “changeEffect()” I then determine what the button state is and react accordingly. This is super fast!

This works surprisingly well!


void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
  }
}

Once a button is pressed, our function will increase the value of “selectedEffect” by one.

Challenge 4 – Initiate the start of a new effect

So now we can catch the button being pressed at any time. Great!
But how do we go back to the beginning of the “loop()” function?

Since we have different levels of nested loops and functions, simply using “break” or “return” is not going to cut it.
So I had to come up with something better. How do I restart the loop?

Well, again there is no simple straight forward method for that it seems, and where ever you look on the Internet; questions like these will simply not be answered since folks think they need to explain that we need to program things differently. What’s up with that?

Eventually I found a sweet little piece of assembler code (unlike the C language Arduino uses) that resets the Arduino and starts over again – we basically let the Arduino jump back to address 0 (zero) so it starts over again. This works great:


asm volatile ("  jmp 0");

This line can be added anywhere in your code and your Arduino WILL reset.

Combined with the previous challenge, our button press will call:


1
2
3
4
5
6
void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    asm volatile ("  jmp 0");
  }
}

Note: this is more complicated than it sounds and comes with consequences – none of them harm your Arduino – which more experienced developers will tell you to pay attention to.

There is a ginormous downside to resetting your Arduino though: you’ll loose all your variables!
Or better said: the value the variables had, since they will be reinitiated blank …

So … that’s a problem, since we now no longer know what the selected effect was supposed to be.

Challenge 5 – Variable surviving a reset

You can imagine I had a good day trying to figure all this out – it was fun though,… now that it works.

So how do we store a value (the selected effect) without losing it? It’s not like the Arduino has a harddrive or SD card on which we can store the value …
Ehm … that’s not entirely true. The Arduino has an EEPROM – a piece of memory that does not loose it’s content after power is dropped, or a reset is being done.

Your Arduino actually has some functions for that! See the EEPROM documentation for more details.

One side note: you should not use the EEPROM for excessive read/write operations, as it has a limited live span (they say that I may fail after 100,000 read/write operations). Considering that this would take an awful lot of clicks, I’m not very worried with this application of the EEPROM.

Back to our last challenge: we just store the selected effect number (byte) in the EEPROM.

For this to work we will need to include the EEPROM library:


#include <EEPROM.h>

Writing and reading an EEPROM address is surprisingly easy:


// read EEPORM address 0 (1 byte)
EEPROM.get(0,selectedEffect);

// write EEPROM address 0 (also 1 byte)
EEPROM.put(0, selectedEffect);

As you can see in the code, the variable “selectedEffect” is of the type byte – which I did intentionally to keep things easy.
Address “0” of the EEPROM seems to be commonly used, so I didn’t see a reason to divert from that. Not all Arduino’s have the same amount of EEPROM space.

We cannot “set” the EEPROM in the “setup()” function with an initial value. After all, after a reset, the same “setup()” function would be called and … reset that value as well.

So instead I decided to read whatever is there. If the returning value is larger than the number of effects (18), then we set it to zero so it starts with the first effect again. Perfect to catch an odd value that was not initialized, and perfect for us cycling through effects.


EEPROM.get(0,selectedEffect);
 
if(selectedEffect>18) {
  selectedEffect=0;
  EEPROM.put(0,0);
}

Our button press function will now look like this:


void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect); // store the chose effect
    asm volatile ("  jmp 0");      // reset the Arduino
  }
}

Sources

You can download the sources in the beginning of this article.
If you’d like to review, then take a look here;

FastLED


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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
#include "FastLED.h"
#include <EEPROM.h>
#define NUM_LEDS 60
CRGB leds[NUM_LEDS];
#define PIN 5

#define BUTTON 2
byte selectedEffect=0;

void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  digitalWrite (BUTTON, HIGH);  // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
}

// *** REPLACE FROM HERE ***
void loop() {
  EEPROM.get(0,selectedEffect);
 
  if(selectedEffect>18) {
    selectedEffect=0;
    EEPROM.put(0,0);
  }
 
  switch(selectedEffect) {
   
    case 0  : {
                // RGBLoop - no parameters
                RGBLoop();
                break;
              }

    case 1  : {
                // FadeInOut - Color (red, green. blue)
                FadeInOut(0xff, 0x00, 0x00); // red
                FadeInOut(0xff, 0xff, 0xff); // white
                FadeInOut(0x00, 0x00, 0xff); // blue
                break;
              }
             
    case 2  : {
                // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
                Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
                break;
              }

    case 3  : {
                // HalloweenEyes - Color (red, green, blue), Size of eye, space between eyes, fade (true/false), steps, fade delay, end pause
                HalloweenEyes(0xff, 0x00, 0x00,
                              1, 4,
                              true, random(5,50), random(50,150),
                              random(1000, 10000));
                HalloweenEyes(0xff, 0x00, 0x00,
                              1, 4,
                              true, random(5,50), random(50,150),
                              random(1000, 10000));
                break;
              }
             
    case 4  : {
                // CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
                CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);
                break;
              }
             
    case 5  : {
                // NewKITT - Color (red, green, blue), eye size, speed delay, end pause
                NewKITT(0xff, 0x00, 0x00, 8, 10, 50);
                break;
              }
             
    case 6  : {
                // Twinkle - Color (red, green, blue), count, speed delay, only one twinkle (true/false)
                Twinkle(0xff, 0x00, 0x00, 10, 100, false);
                break;
              }
             
    case 7  : {
                // TwinkleRandom - twinkle count, speed delay, only one (true/false)
                TwinkleRandom(20, 100, false);
                break;
              }
             
    case 8  : {
                // Sparkle - Color (red, green, blue), speed delay
                Sparkle(0xff, 0xff, 0xff, 0);
                break;
              }
               
    case 9  : {
                // SnowSparkle - Color (red, green, blue), sparkle delay, speed delay
                SnowSparkle(0x10, 0x10, 0x10, 20, random(100,1000));
                break;
              }
             
    case 10 : {
                // Running Lights - Color (red, green, blue), wave dealy
                RunningLights(0xff,0x00,0x00, 50);  // red
                RunningLights(0xff,0xff,0xff, 50);  // white
                RunningLights(0x00,0x00,0xff, 50);  // blue
                break;
              }
             
    case 11 : {
                // colorWipe - Color (red, green, blue), speed delay
                colorWipe(0x00,0xff,0x00, 50);
                colorWipe(0x00,0x00,0x00, 50);
                break;
              }

    case 12 : {
                // rainbowCycle - speed delay
                rainbowCycle(20);
                break;
              }

    case 13 : {
                // theatherChase - Color (red, green, blue), speed delay
                theaterChase(0xff,0,0,50);
                break;
              }

    case 14 : {
                // theaterChaseRainbow - Speed delay
                theaterChaseRainbow(50);
                break;
              }

    case 15 : {
                // Fire - Cooling rate, Sparking rate, speed delay
                Fire(55,120,15);
                break;
              }


              // simple bouncingBalls not included, since BouncingColoredBalls can perform this as well as shown below
              // BouncingColoredBalls - Number of balls, color (red, green, blue) array, continuous
              // CAUTION: If set to continuous then this effect will never stop!!!
             
    case 16 : {
                // mimic BouncingBalls
                byte onecolor[1][3] = { {0xff, 0x00, 0x00} };
                BouncingColoredBalls(1, onecolor, false);
                break;
              }

    case 17 : {
                // multiple colored balls
                byte colors[3][3] = { {0xff, 0x00, 0x00},
                                      {0xff, 0xff, 0xff},
                                      {0x00, 0x00, 0xff} };
                BouncingColoredBalls(3, colors, false);
                break;
              }

    case 18 : {
                // meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay
                meteorRain(0xff,0xff,0xff,10, 64, true, 30);
                break;
              }
  }
}

void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("  jmp 0");
  }
}


// *************************
// ** LEDEffect Functions **
// *************************

void RGBLoop(){
  for(int j = 0; j < 3; j++ ) {
    // Fade IN
    for(int k = 0; k < 256; k++) {
      switch(j) {
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
    // Fade OUT
    for(int k = 255; k >= 0; k--) {
      switch(j) {
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
  }
}

void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
     
  for(int k = 0; k < 256; k=k+1) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
}

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
  for(int j = 0; j < StrobeCount; j++) {
    setAll(red,green,blue);
    showStrip();
    delay(FlashDelay);
    setAll(0,0,0);
    showStrip();
    delay(FlashDelay);
  }
 
 delay(EndPause);
}

void HalloweenEyes(byte red, byte green, byte blue,
                   int EyeWidth, int EyeSpace,
                   boolean Fade, int Steps, int FadeDelay,
                   int EndPause){
  randomSeed(analogRead(0));
 
  int i;
  int StartPoint  = random( 0, NUM_LEDS - (2*EyeWidth) - EyeSpace );
  int Start2ndEye = StartPoint + EyeWidth + EyeSpace;
 
  for(i = 0; i < EyeWidth; i++) {
    setPixel(StartPoint + i, red, green, blue);
    setPixel(Start2ndEye + i, red, green, blue);
  }
 
  showStrip();
 
  if(Fade==true) {
    float r, g, b;
 
    for(int j = Steps; j >= 0; j--) {
      r = j*(red/Steps);
      g = j*(green/Steps);
      b = j*(blue/Steps);
     
      for(i = 0; i < EyeWidth; i++) {
        setPixel(StartPoint + i, r, g, b);
        setPixel(Start2ndEye + i, r, g, b);
      }
     
      showStrip();
      delay(FadeDelay);
    }
  }
 
  setAll(0,0,0); // Set all black
 
  delay(EndPause);
}

void CylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){

  for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }

  delay(ReturnDelay);

  for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
 
  delay(ReturnDelay);
}

void NewKITT(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){
  RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
}

// used by NewKITT
void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i =((NUM_LEDS-EyeSize)/2); i>=0; i--) {
    setAll(0,0,0);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
   
    setPixel(NUM_LEDS-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(NUM_LEDS-i-j, red, green, blue);
    }
    setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10);
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void OutsideToCenter(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((NUM_LEDS-EyeSize)/2); i++) {
    setAll(0,0,0);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
   
    setPixel(NUM_LEDS-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(NUM_LEDS-i-j, red, green, blue);
    }
    setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10);
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void LeftToRight(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void RightToLeft(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

void Twinkle(byte red, byte green, byte blue, int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
 
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),red,green,blue);
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(SpeedDelay);
}

void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
 
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255));
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(SpeedDelay);
}

void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,red,green,blue);
  showStrip();
  delay(SpeedDelay);
  setPixel(Pixel,0,0,0);
}

void SnowSparkle(byte red, byte green, byte blue, int SparkleDelay, int SpeedDelay) {
  setAll(red,green,blue);
 
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,0xff,0xff,0xff);
  showStrip();
  delay(SparkleDelay);
  setPixel(Pixel,red,green,blue);
  showStrip();
  delay(SpeedDelay);
}

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
 
  for(int i=0; i<NUM_LEDS*2; i++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS; i++) {
        // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
      }
     
      showStrip();
      delay(WaveDelay);
  }
}

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}

void rainbowCycle(int SpeedDelay) {
  byte *c;
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< NUM_LEDS; i++) {
      c=Wheel(((i * 256 / NUM_LEDS) + j) & 255);
      setPixel(i, *c, *(c+1), *(c+2));
    }
    showStrip();
    delay(SpeedDelay);
  }
}

// used by rainbowCycle and theaterChaseRainbow
byte * Wheel(byte WheelPos) {
  static byte c[3];
 
  if(WheelPos < 85) {
   c[0]=WheelPos * 3;
   c[1]=255 - WheelPos * 3;
   c[2]=0;
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   c[0]=255 - WheelPos * 3;
   c[1]=0;
   c[2]=WheelPos * 3;
  } else {
   WheelPos -= 170;
   c[0]=0;
   c[1]=WheelPos * 3;
   c[2]=255 - WheelPos * 3;
  }

  return c;
}

void theaterChase(byte red, byte green, byte blue, int SpeedDelay) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < NUM_LEDS; i=i+3) {
        setPixel(i+q, red, green, blue);    //turn every third pixel on
      }
      showStrip();
     
      delay(SpeedDelay);
     
      for (int i=0; i < NUM_LEDS; i=i+3) {
        setPixel(i+q, 0,0,0);        //turn every third pixel off
      }
    }
  }
}

void theaterChaseRainbow(int SpeedDelay) {
  byte *c;
 
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < NUM_LEDS; i=i+3) {
          c = Wheel( (i+j) % 255);
          setPixel(i+q, *c, *(c+1), *(c+2));    //turn every third pixel on
        }
        showStrip();
       
        delay(SpeedDelay);
       
        for (int i=0; i < NUM_LEDS; i=i+3) {
          setPixel(i+q, 0,0,0);        //turn every third pixel off
        }
    }
  }
}

void Fire(int Cooling, int Sparking, int SpeedDelay) {
  static byte heat[NUM_LEDS];
  int cooldown;
 
  // Step 1.  Cool down every cell a little
  for( int i = 0; i < NUM_LEDS; i++) {
    cooldown = random(0, ((Cooling * 10) / NUM_LEDS) + 2);
   
    if(cooldown>heat[i]) {
      heat[i]=0;
    } else {
      heat[i]=heat[i]-cooldown;
    }
  }
 
  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for( int k= NUM_LEDS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
  }
   
  // Step 3.  Randomly ignite new 'sparks' near the bottom
  if( random(255) < Sparking ) {
    int y = random(7);
    heat[y] = heat[y] + random(160,255);
    //heat[y] = random(160,255);
  }

  // Step 4.  Convert heat to LED colors
  for( int j = 0; j < NUM_LEDS; j++) {
    setPixelHeatColor(j, heat[j] );
  }

  showStrip();
  delay(SpeedDelay);
}

void setPixelHeatColor (int Pixel, byte temperature) {
  // Scale 'heat' down from 0-255 to 0-191
  byte t192 = round((temperature/255.0)*191);
 
  // calculate ramp up from
  byte heatramp = t192 & 0x3F; // 0..63
  heatramp <<= 2; // scale up to 0..252
 
  // figure out which third of the spectrum we're in:
  if( t192 > 0x80) {                     // hottest
    setPixel(Pixel, 255, 255, heatramp);
  } else if( t192 > 0x40 ) {             // middle
    setPixel(Pixel, 255, heatramp, 0);
  } else {                               // coolest
    setPixel(Pixel, heatramp, 0, 0);
  }
}

void BouncingColoredBalls(int BallCount, byte colors[][3], boolean continuous) {
  float Gravity = -9.81;
  int StartHeight = 1;
 
  float Height[BallCount];
  float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
  float ImpactVelocity[BallCount];
  float TimeSinceLastBounce[BallCount];
  int   Position[BallCount];
  long  ClockTimeSinceLastBounce[BallCount];
  float Dampening[BallCount];
  boolean ballBouncing[BallCount];
  boolean ballsStillBouncing = true;
 
  for (int i = 0 ; i < BallCount ; i++) {  
    ClockTimeSinceLastBounce[i] = millis();
    Height[i] = StartHeight;
    Position[i] = 0;
    ImpactVelocity[i] = ImpactVelocityStart;
    TimeSinceLastBounce[i] = 0;
    Dampening[i] = 0.90 - float(i)/pow(BallCount,2);
    ballBouncing[i]=true;
  }

  while (ballsStillBouncing) {
    for (int i = 0 ; i < BallCount ; i++) {
      TimeSinceLastBounce[i] =  millis() - ClockTimeSinceLastBounce[i];
      Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000;
 
      if ( Height[i] < 0 ) {                      
        Height[i] = 0;
        ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
        ClockTimeSinceLastBounce[i] = millis();
 
        if ( ImpactVelocity[i] < 0.01 ) {
          if (continuous) {
            ImpactVelocity[i] = ImpactVelocityStart;
          } else {
            ballBouncing[i]=false;
          }
        }
      }
      Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
    }

    ballsStillBouncing = false; // assume no balls bouncing
    for (int i = 0 ; i < BallCount ; i++) {
      setPixel(Position[i],colors[i][0],colors[i][1],colors[i][2]);
      if ( ballBouncing[i] ) {
        ballsStillBouncing = true;
      }
    }
   
    showStrip();
    setAll(0,0,0);
  }
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll(0,0,0);
 
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) {
   
   
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      }
    }
   
    showStrip();
    delay(SpeedDelay);
  }
}

// used by meteorrain
void fadeToBlack(int ledNo, byte fadeValue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
    // NeoPixel
    uint32_t oldColor;
    uint8_t r, g, b;
    int value;
   
    oldColor = strip.getPixelColor(ledNo);
    r = (oldColor & 0x00ff0000UL) >> 16;
    g = (oldColor & 0x0000ff00UL) >> 8;
    b = (oldColor & 0x000000ffUL);

    r=(r<=10)? 0 : (int) r-(r*fadeValue/256);
    g=(g<=10)? 0 : (int) g-(g*fadeValue/256);
    b=(b<=10)? 0 : (int) b-(b*fadeValue/256);
   
    strip.setPixelColor(ledNo, r,g,b);
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}

// *** REPLACE TO HERE ***



// ***************************************
// ** FastLed/NeoPixel Common Functions **
// ***************************************

// Apply LED color changes
void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

// Set a LED color (not yet visible)
void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

// Set all LEDs to a given color and apply it (visible)
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

NeoPixel


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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
#include <Adafruit_NeoPixel.h>
#include <EEPROM.h>

#define NUM_LEDS 60
#define PIN 5
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

#define BUTTON 2
byte selectedEffect=0;

void setup()
{
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  digitalWrite (BUTTON, HIGH);  // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
}

// *** REPLACE FROM HERE ***
void loop() {
  EEPROM.get(0,selectedEffect);
 
  if(selectedEffect>18) {
    selectedEffect=0;
    EEPROM.put(0,0);
  }
 
  switch(selectedEffect) {
   
    case 0  : {
                // RGBLoop - no parameters
                RGBLoop();
                break;
              }

    case 1  : {
                // FadeInOut - Color (red, green. blue)
                FadeInOut(0xff, 0x00, 0x00); // red
                FadeInOut(0xff, 0xff, 0xff); // white
                FadeInOut(0x00, 0x00, 0xff); // blue
                break;
              }
             
    case 2  : {
                // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
                Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
                break;
              }

    case 3  : {
                // HalloweenEyes - Color (red, green, blue), Size of eye, space between eyes, fade (true/false), steps, fade delay, end pause
                HalloweenEyes(0xff, 0x00, 0x00,
                              1, 4,
                              true, random(5,50), random(50,150),
                              random(1000, 10000));
                HalloweenEyes(0xff, 0x00, 0x00,
                              1, 4,
                              true, random(5,50), random(50,150),
                              random(1000, 10000));
                break;
              }
             
    case 4  : {
                // CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
                CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);
                break;
              }
             
    case 5  : {
                // NewKITT - Color (red, green, blue), eye size, speed delay, end pause
                NewKITT(0xff, 0x00, 0x00, 8, 10, 50);
                break;
              }
             
    case 6  : {
                // Twinkle - Color (red, green, blue), count, speed delay, only one twinkle (true/false)
                Twinkle(0xff, 0x00, 0x00, 10, 100, false);
                break;
              }
             
    case 7  : {
                // TwinkleRandom - twinkle count, speed delay, only one (true/false)
                TwinkleRandom(20, 100, false);
                break;
              }
             
    case 8  : {
                // Sparkle - Color (red, green, blue), speed delay
                Sparkle(0xff, 0xff, 0xff, 0);
                break;
              }
               
    case 9  : {
                // SnowSparkle - Color (red, green, blue), sparkle delay, speed delay
                SnowSparkle(0x10, 0x10, 0x10, 20, random(100,1000));
                break;
              }
             
    case 10 : {
                // Running Lights - Color (red, green, blue), wave dealy
                RunningLights(0xff,0x00,0x00, 50);  // red
                RunningLights(0xff,0xff,0xff, 50);  // white
                RunningLights(0x00,0x00,0xff, 50);  // blue
                break;
              }
             
    case 11 : {
                // colorWipe - Color (red, green, blue), speed delay
                colorWipe(0x00,0xff,0x00, 50);
                colorWipe(0x00,0x00,0x00, 50);
                break;
              }

    case 12 : {
                // rainbowCycle - speed delay
                rainbowCycle(20);
                break;
              }

    case 13 : {
                // theatherChase - Color (red, green, blue), speed delay
                theaterChase(0xff,0,0,50);
                break;
              }

    case 14 : {
                // theaterChaseRainbow - Speed delay
                theaterChaseRainbow(50);
                break;
              }

    case 15 : {
                // Fire - Cooling rate, Sparking rate, speed delay
                Fire(55,120,15);
                break;
              }


              // simple bouncingBalls not included, since BouncingColoredBalls can perform this as well as shown below
              // BouncingColoredBalls - Number of balls, color (red, green, blue) array, continuous
              // CAUTION: If set to continuous then this effect will never stop!!!
             
    case 16 : {
                // mimic BouncingBalls
                byte onecolor[1][3] = { {0xff, 0x00, 0x00} };
                BouncingColoredBalls(1, onecolor, false);
                break;
              }

    case 17 : {
                // multiple colored balls
                byte colors[3][3] = { {0xff, 0x00, 0x00},
                                      {0xff, 0xff, 0xff},
                                      {0x00, 0x00, 0xff} };
                BouncingColoredBalls(3, colors, false);
                break;
              }

    case 18 : {
                // meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay
                meteorRain(0xff,0xff,0xff,10, 64, true, 30);
                break;
              }
  }
}

void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect++;
    EEPROM.put(0, selectedEffect);
    asm volatile ("  jmp 0");
  }
}


// *************************
// ** LEDEffect Functions **
// *************************

void RGBLoop(){
  for(int j = 0; j < 3; j++ ) {
    // Fade IN
    for(int k = 0; k < 256; k++) {
      switch(j) {
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
    // Fade OUT
    for(int k = 255; k >= 0; k--) {
      switch(j) {
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
  }
}

void FadeInOut(byte red, byte green, byte blue){
  float r, g, b;
     
  for(int k = 0; k < 256; k=k+1) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
     
  for(int k = 255; k >= 0; k=k-2) {
    r = (k/256.0)*red;
    g = (k/256.0)*green;
    b = (k/256.0)*blue;
    setAll(r,g,b);
    showStrip();
  }
}

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
  for(int j = 0; j < StrobeCount; j++) {
    setAll(red,green,blue);
    showStrip();
    delay(FlashDelay);
    setAll(0,0,0);
    showStrip();
    delay(FlashDelay);
  }
 
 delay(EndPause);
}

void HalloweenEyes(byte red, byte green, byte blue,
                   int EyeWidth, int EyeSpace,
                   boolean Fade, int Steps, int FadeDelay,
                   int EndPause){
  randomSeed(analogRead(0));
 
  int i;
  int StartPoint  = random( 0, NUM_LEDS - (2*EyeWidth) - EyeSpace );
  int Start2ndEye = StartPoint + EyeWidth + EyeSpace;
 
  for(i = 0; i < EyeWidth; i++) {
    setPixel(StartPoint + i, red, green, blue);
    setPixel(Start2ndEye + i, red, green, blue);
  }
 
  showStrip();
 
  if(Fade==true) {
    float r, g, b;
 
    for(int j = Steps; j >= 0; j--) {
      r = j*(red/Steps);
      g = j*(green/Steps);
      b = j*(blue/Steps);
     
      for(i = 0; i < EyeWidth; i++) {
        setPixel(StartPoint + i, r, g, b);
        setPixel(Start2ndEye + i, r, g, b);
      }
     
      showStrip();
      delay(FadeDelay);
    }
  }
 
  setAll(0,0,0); // Set all black
 
  delay(EndPause);
}

void CylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){

  for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }

  delay(ReturnDelay);

  for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
 
  delay(ReturnDelay);
}

void NewKITT(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){
  RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
}

// used by NewKITT
void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i =((NUM_LEDS-EyeSize)/2); i>=0; i--) {
    setAll(0,0,0);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
   
    setPixel(NUM_LEDS-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(NUM_LEDS-i-j, red, green, blue);
    }
    setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10);
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void OutsideToCenter(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((NUM_LEDS-EyeSize)/2); i++) {
    setAll(0,0,0);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
   
    setPixel(NUM_LEDS-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(NUM_LEDS-i-j, red, green, blue);
    }
    setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10);
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void LeftToRight(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

// used by NewKITT
void RightToLeft(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
}

void Twinkle(byte red, byte green, byte blue, int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
 
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),red,green,blue);
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(SpeedDelay);
}

void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
 
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255));
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(SpeedDelay);
}

void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,red,green,blue);
  showStrip();
  delay(SpeedDelay);
  setPixel(Pixel,0,0,0);
}

void SnowSparkle(byte red, byte green, byte blue, int SparkleDelay, int SpeedDelay) {
  setAll(red,green,blue);
 
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,0xff,0xff,0xff);
  showStrip();
  delay(SparkleDelay);
  setPixel(Pixel,red,green,blue);
  showStrip();
  delay(SpeedDelay);
}

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
 
  for(int i=0; i<NUM_LEDS*2; i++)
  {
      Position++; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS; i++) {
        // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
      }
     
      showStrip();
      delay(WaveDelay);
  }
}

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}

void rainbowCycle(int SpeedDelay) {
  byte *c;
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< NUM_LEDS; i++) {
      c=Wheel(((i * 256 / NUM_LEDS) + j) & 255);
      setPixel(i, *c, *(c+1), *(c+2));
    }
    showStrip();
    delay(SpeedDelay);
  }
}

// used by rainbowCycle and theaterChaseRainbow
byte * Wheel(byte WheelPos) {
  static byte c[3];
 
  if(WheelPos < 85) {
   c[0]=WheelPos * 3;
   c[1]=255 - WheelPos * 3;
   c[2]=0;
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   c[0]=255 - WheelPos * 3;
   c[1]=0;
   c[2]=WheelPos * 3;
  } else {
   WheelPos -= 170;
   c[0]=0;
   c[1]=WheelPos * 3;
   c[2]=255 - WheelPos * 3;
  }

  return c;
}

void theaterChase(byte red, byte green, byte blue, int SpeedDelay) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < NUM_LEDS; i=i+3) {
        setPixel(i+q, red, green, blue);    //turn every third pixel on
      }
      showStrip();
     
      delay(SpeedDelay);
     
      for (int i=0; i < NUM_LEDS; i=i+3) {
        setPixel(i+q, 0,0,0);        //turn every third pixel off
      }
    }
  }
}

void theaterChaseRainbow(int SpeedDelay) {
  byte *c;
 
  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < NUM_LEDS; i=i+3) {
          c = Wheel( (i+j) % 255);
          setPixel(i+q, *c, *(c+1), *(c+2));    //turn every third pixel on
        }
        showStrip();
       
        delay(SpeedDelay);
       
        for (int i=0; i < NUM_LEDS; i=i+3) {
          setPixel(i+q, 0,0,0);        //turn every third pixel off
        }
    }
  }
}

void Fire(int Cooling, int Sparking, int SpeedDelay) {
  static byte heat[NUM_LEDS];
  int cooldown;
 
  // Step 1.  Cool down every cell a little
  for( int i = 0; i < NUM_LEDS; i++) {
    cooldown = random(0, ((Cooling * 10) / NUM_LEDS) + 2);
   
    if(cooldown>heat[i]) {
      heat[i]=0;
    } else {
      heat[i]=heat[i]-cooldown;
    }
  }
 
  // Step 2.  Heat from each cell drifts 'up' and diffuses a little
  for( int k= NUM_LEDS - 1; k >= 2; k--) {
    heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
  }
   
  // Step 3.  Randomly ignite new 'sparks' near the bottom
  if( random(255) < Sparking ) {
    int y = random(7);
    heat[y] = heat[y] + random(160,255);
    //heat[y] = random(160,255);
  }

  // Step 4.  Convert heat to LED colors
  for( int j = 0; j < NUM_LEDS; j++) {
    setPixelHeatColor(j, heat[j] );
  }

  showStrip();
  delay(SpeedDelay);
}

void setPixelHeatColor (int Pixel, byte temperature) {
  // Scale 'heat' down from 0-255 to 0-191
  byte t192 = round((temperature/255.0)*191);
 
  // calculate ramp up from
  byte heatramp = t192 & 0x3F; // 0..63
  heatramp <<= 2; // scale up to 0..252
 
  // figure out which third of the spectrum we're in:
  if( t192 > 0x80) {                     // hottest
    setPixel(Pixel, 255, 255, heatramp);
  } else if( t192 > 0x40 ) {             // middle
    setPixel(Pixel, 255, heatramp, 0);
  } else {                               // coolest
    setPixel(Pixel, heatramp, 0, 0);
  }
}

void BouncingColoredBalls(int BallCount, byte colors[][3], boolean continuous) {
  float Gravity = -9.81;
  int StartHeight = 1;
 
  float Height[BallCount];
  float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
  float ImpactVelocity[BallCount];
  float TimeSinceLastBounce[BallCount];
  int   Position[BallCount];
  long  ClockTimeSinceLastBounce[BallCount];
  float Dampening[BallCount];
  boolean ballBouncing[BallCount];
  boolean ballsStillBouncing = true;
 
  for (int i = 0 ; i < BallCount ; i++) {  
    ClockTimeSinceLastBounce[i] = millis();
    Height[i] = StartHeight;
    Position[i] = 0;
    ImpactVelocity[i] = ImpactVelocityStart;
    TimeSinceLastBounce[i] = 0;
    Dampening[i] = 0.90 - float(i)/pow(BallCount,2);
    ballBouncing[i]=true;
  }

  while (ballsStillBouncing) {
    for (int i = 0 ; i < BallCount ; i++) {
      TimeSinceLastBounce[i] =  millis() - ClockTimeSinceLastBounce[i];
      Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i]/1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i]/1000;
 
      if ( Height[i] < 0 ) {                      
        Height[i] = 0;
        ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
        ClockTimeSinceLastBounce[i] = millis();
 
        if ( ImpactVelocity[i] < 0.01 ) {
          if (continuous) {
            ImpactVelocity[i] = ImpactVelocityStart;
          } else {
            ballBouncing[i]=false;
          }
        }
      }
      Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
    }

    ballsStillBouncing = false; // assume no balls bouncing
    for (int i = 0 ; i < BallCount ; i++) {
      setPixel(Position[i],colors[i][0],colors[i][1],colors[i][2]);
      if ( ballBouncing[i] ) {
        ballsStillBouncing = true;
      }
    }
   
    showStrip();
    setAll(0,0,0);
  }
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll(0,0,0);
 
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) {
   
   
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      }
    }
   
    showStrip();
    delay(SpeedDelay);
  }
}

// used by meteorrain
void fadeToBlack(int ledNo, byte fadeValue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
    // NeoPixel
    uint32_t oldColor;
    uint8_t r, g, b;
    int value;
   
    oldColor = strip.getPixelColor(ledNo);
    r = (oldColor & 0x00ff0000UL) >> 16;
    g = (oldColor & 0x0000ff00UL) >> 8;
    b = (oldColor & 0x000000ffUL);

    r=(r<=10)? 0 : (int) r-(r*fadeValue/256);
    g=(g<=10)? 0 : (int) g-(g*fadeValue/256);
    b=(b<=10)? 0 : (int) b-(b*fadeValue/256);
   
    strip.setPixelColor(ledNo, r,g,b);
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}

// *** REPLACE TO HERE ***



// ***************************************
// ** FastLed/NeoPixel Common Functions **
// ***************************************

// Apply LED color changes
void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

// Set a LED color (not yet visible)
void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

// Set all LEDs to a given color and apply it (visible)
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

 

Donation options


Donations are very much appreciated, but not required. Donations will be used for web-hosting expenses, project hardware or a motivational boost (a drink or snack). Thank you very much for those have donated already! It's truly AwEsOmE to see that folks like our articles and small applications.

Comments


There are 80 comments. You can read them below.
You can post your own comments by using the form below, or reply to existing comments by using the "Reply" button.

  • Jan 7, 2018 - 5:43 PM - Spike Comment Link

    Hi Hans,

    Thank you so much for working all this out and sharing it with us.

    It is all way above my ability, which explains why I never managed to get it to work :-)

    I’m looking forward to getting the time to try this out.

    All the best

    Spike

    Reply

    Spike

    • Jan 8, 2018 - 3:14 PM - hans - Author: Comment Link

      Thanks Spike!

      And you’re most welcome – wish I could do these kind of articles all day long 
      But … keep in mind that I had to do my share of research as well, since some of these challenges are exactly that: challenges.

      Enjoy! 

      Reply

      hans

  • Jan 9, 2018 - 9:57 PM - Daniel Comment Link

    Hello Hans, thanks for the nice “All-in-One” Wonder!
    I test it and all seams to work ok.

    I smole problem that i have is the debouncing problem of
    the button, i use a Nano 328 and the latest Arduino IDE.

    When pushing the button, it jumps from selectedEffect 0
    to lets say 3 or 5, so i must click very fast the button to jump to
    nr. 2 and 3…

    In your setup()
    you use: digitalWrite (BUTTON, HIGH);  // internal pull-up resistor
    for buttons i use this line: pinMode(2,INPUT_PULLUP);
    …this sets the D2 as input and also activates the internal 40 kOhm
    in one wash.

    The new “meteorRain” is the coolest effect :-)
    With “FastLED”-Library i have some colored points in the String,
    behind this Effect, but only white color in “Adafruit_NeoPixel”.
    Is that the same in your string? Is “Adafruit_NeoPixel”
    not able to handle this colors?

    Reply

    Daniel

    • Jan 12, 2018 - 10:27 AM - hans - Author: Comment Link

      Hi Daniel,

      So using 

      pinMode(2,INPUT_PULLUP);

      instead of

      digitalWrite (BUTTON, HIGH); 

      works better? If you confirm that, then I will modify the code accordingly.
      (can’t test right now, since I stowed my stuff away again – argh – I need a workshop!)

      I did not experience the debouncing problem though – maybe the nature of the switch I’m using?

      FastLED is much more advanced when it comes to colors, ADAFruit NeoPixel is pretty limited. On my strand the meteor rain works correct with both, however the effect is much more refined with FastLED. A refinement of the fadeToBlack function might be helpful – as you can see, for FastLED I use a build in function, and for neoPixel I have to glue something together.

      Reply

      hans

      • Jan 13, 2018 - 3:04 PM - Daniel Comment Link

        Hello Hans, yes i allways use

        pinMode(Button,INPUT_PULLUP); //Activate internal 40k resistor to +5V

        because it is all done in one line, set digitalport to input and also set this input to +5v

        so i dont need any aditional 10k resistors from input-pin to ground and a button from

        input to +5v.

        This is allway better with PULUP because all ports are FET Inputs and so they have a very

        hi impedance witch is good …but a high impedance input, always pick up some noise or

        static loads…so the pins driving slowly to HIGH or at least 2-3V from ground away.

        I made a VU-Meter with Neopixels and i have the problem…in the pause (no sound)…

        the A= port starts climbing up and my Pixel starts one after another…so i put

        a 1 Megaohm from A0 to ground, then the port can not start growibg up because the 1M

        resistor descharge the port. 1M is very high, i use it to not influence the A0 port.

        Here in this case i can not PULLUP because the Pixels will light all full from the +5V.

        But for Buttons i’m allways using PULLUP, no need of 10kohm and port is not rising up

        because he is allready at +5v :-)

        You don’t have to change the code for this, i hope other readers understand what i mean.

        Ok i hade no problems till now with the NeoPixel -lIbrary, but i also try the FastLED, it use

        around 1kb more memory but else no relevant changes.

        Ok Hans have a nice weekend, cheers de Daniel 72

        Reply

        Daniel

        • Jan 21, 2018 - 1:38 PM - hans - Author: Comment Link

          Thanks Daniel!

          Thanks for the great explanation – I can (and like to) learn something every day as well! 

          I’ll play with your suggestion once I get time to play again. 

          Reply

          hans

  • Jan 17, 2018 - 8:41 AM - Bob Comment Link

    I want to thank you for this awesome articular on LEDS strips.   It gave me some great ideas for my latest Jukebox project using these Neo-pixal strips.  Your welcome to  check out my latest LED effects using some of your coding at  https://youtu.be/ZWGdVXJNOww.&nbsp; I am using a Arduino Mega to control three strips of 180 leds per strip plus additional  59 leds that I am using in a keyboard/index display which is controlled by a Arduino Micro. The complete Jukebox build can be viewed here if you are interested. https://youtu.be/mNt3cUORvak

    Thanks 

    Reply

    Bob

    • Jan 21, 2018 - 2:05 PM - hans - Author: Comment Link

      Hi Bob!

      Thanks you for taking the time to post a thank you note.
      I’ve just looked at your jukebox project – that’s awesome!!! (the first YouTube link didn’t work)

      Wow, you’ve given me an idea for a project – amazingly well build! 

      Reply

      hans

  • Jan 19, 2018 - 9:36 AM - Marco Weinkauf Comment Link

    Hi Hans,

    thank you so much for this nice work! 

    What changes in setup and define section do I have to make for SPI (APA102) LEDs working for that demo? 

    Reply

    Marco Weinkauf

    • Jan 21, 2018 - 2:15 PM - hans - Author: Comment Link

      Hi Marco!

      Thank you for the compliment! It’s much appreciated! 

      I’ve never worked with the APA102, so I’m afraid I will have to point you to the reference of (for example) FastLED: Setting up LEDs.
      I did see an example there:

      FastLED.addLeds<APA102>(leds, NUM_LEDS);

      And I did find more info here: SPI Hardware or Bit banging:

      FastLED.addLeds<APA102,7,11>(leds,NUM_LEDS);

      There is even the option to change the frequency:

      FastLED.addLeds<APA102,7,11,RGB,DATA_RATE_MHZ(10)>(leds,NUM_LEDS);

      There is more info, especially on that second link.

      I hope this is helpful.

      Reply

      hans

  • Jan 23, 2018 - 10:48 PM - Alan Comment Link

    Hans–

    Great stuff.  Readily tweakable to all the color palettes I like.  Using it on two diff 5M neopixel strips to pep up my house’s entrance way for a party.

    My one question:   Would there be an easy way to insert an analog potentiometer input into the wiring and code that could control brightness universally through all the cases?

    Reply

    Alan

    • Jan 25, 2018 - 12:34 PM - hans - Author: Comment Link

      Hi Alan,

      Awesome! 

      Yes, I would assume so. I have not tried this yet, but with the use of one of the Analog pins of the Arduino, and some code to set the overall brightness (FastLED is really good at that) should do the trick.

      The only issue I’d see is that turning a potentiometer would have to be read, kind-a like the push of the button, to make sure it works right away. This then makes it a challenge since triggering this works for buttons, but not (as far as I know) for potentiometers. 

      Reply

      hans

  • Jan 30, 2018 - 8:17 AM - Jimmie M Comment Link

    Thank you for this awesome write-up!! I am trying to do exactly this but instead of a button I need to trigger by serial input, when a particular character is read it would trigger a particular effect. This is all new to me so I’m a bit in over my head. 

    Reply

    Jimmie M

    • Feb 16, 2018 - 10:50 AM - hans - Author: Comment Link

      Hi Jimmie,

      your approach would come with a challenge. Unless you add some electronics and/or a second Arduino.
      The switch is connected to a pin that allows interruption of your program. I don’t think this will work with serial data though.

      Reply

      hans

  • Mar 3, 2018 - 3:23 AM - Samim SK Comment Link

    Dear Sir, My interesting subject and most helpful. Thanks lot

    Reply

    Samim SK

    • Mar 3, 2018 - 5:42 AM - hans - Author: Comment Link

      Hi Samim!

      thank you very much for the complement and for taking the time to post a thank-you – it’s very much appreciated! 

      Reply

      hans

  • Mar 3, 2018 - 7:29 PM - kabodos Comment Link

    great proyect, im new on arduino programing, but is any way or guide to control  with a bluetooth instead of a push button?

    Reply

    kabodos

    • Mar 7, 2018 - 3:00 AM - hans - Author: Comment Link

      Hi Kabodos,

      I have yet to play with Bluetooth, but I’m sure there must be a way to do this.
      There will be 2 challenges; get Bluetooth to work of course and make sure that a response from Bluetooth can actually interrupt the code. The latter might be a little challenging, as I have zero experience with Bluetooth and Arduino.

      Reply

      hans

  • Mar 8, 2018 - 10:05 AM - Jerry Campbell Comment Link

    I would like to run a continuous light show using all the different patterns without using a button to switch between them. 

    Reply

    Jerry Campbell

    • Mar 11, 2018 - 3:20 AM - hans - Author: Comment Link

      Hi Jerry,

      You can, by modifying the “loop()”, something like this:

      void loop() { 
                      // RGBLoop - no parameters
                      RGBLoop();
                      // FadeInOut - Color (red, green. blue)
                      FadeInOut(0xff, 0x00, 0x00); // red
                      FadeInOut(0xff, 0xff, 0xff); // white 
                      FadeInOut(0x00, 0x00, 0xff); // blue
                      // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
                      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
                      // HalloweenEyes - Color (red, green, blue), Size of eye, space between eyes, fade (true/false), steps, fade delay, end pause
                      HalloweenEyes(0xff, 0x00, 0x00, 
                                    1, 4, 
                                    true, random(5,50), random(50,150), 
                                    random(1000, 10000));
                      HalloweenEyes(0xff, 0x00, 0x00, 
                                    1, 4, 
                                    true, random(5,50), random(50,150), 
                                    random(1000, 10000));
                      // CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
                      CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);
                      // NewKITT - Color (red, green, blue), eye size, speed delay, end pause
                      NewKITT(0xff, 0x00, 0x00, 8, 10, 50);
                      // Twinkle - Color (red, green, blue), count, speed delay, only one twinkle (true/false) 
                      Twinkle(0xff, 0x00, 0x00, 10, 100, false);
                      // TwinkleRandom - twinkle count, speed delay, only one (true/false)
                      TwinkleRandom(20, 100, false);
                      // Sparkle - Color (red, green, blue), speed delay
                      Sparkle(0xff, 0xff, 0xff, 0);
                      // SnowSparkle - Color (red, green, blue), sparkle delay, speed delay
                      SnowSparkle(0x10, 0x10, 0x10, 20, random(100,1000));
                      // Running Lights - Color (red, green, blue), wave dealy
                      RunningLights(0xff,0x00,0x00, 50); // red
                      RunningLights(0xff,0xff,0xff, 50); // white
                      RunningLights(0x00,0x00,0xff, 50); // blue
                      // colorWipe - Color (red, green, blue), speed delay
                      colorWipe(0x00,0xff,0x00, 50);
                      colorWipe(0x00,0x00,0x00, 50);
                      // rainbowCycle - speed delay
                      rainbowCycle(20);
                      // theatherChase - Color (red, green, blue), speed delay
                      theaterChase(0xff,0,0,50);
                      // theaterChaseRainbow - Speed delay
                      theaterChaseRainbow(50);
                      // Fire - Cooling rate, Sparking rate, speed delay
                      Fire(55,120,15);

                    // simple bouncingBalls not included, since BouncingColoredBalls can perform this as well as shown below
                    // BouncingColoredBalls - Number of balls, color (red, green, blue) array, continuous
                    // CAUTION: If set to continuous then this effect will never stop!!! 
                      // mimic BouncingBalls
                      byte onecolor[1][3] = { {0xff, 0x00, 0x00} };
                      BouncingColoredBalls(1, onecolor, false);
                      // multiple colored balls
                      byte colors[3][3] = { {0xff, 0x00, 0x00}, 
                                            {0xff, 0xff, 0xff}, 
                                            {0x00, 0x00, 0xff} };
                      BouncingColoredBalls(3, colors, false);
                      // meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay 
                      meteorRain(0xff,0xff,0xff,10, 64, true, 30);
      }

      I have not been able to test this, and it’s still early in the morning here (I need one more coffee I think haha).
      If one of the effects is endless then it will get “stuck” with that effect and we’d need to tweak the effect to not be endless.
      Each effect is ran only once, so you may want to to a “for-loop” around an effect to make it appear multiple times.

      Hope this helps!

      Reply

      hans

      • Mar 12, 2018 - 8:18 AM - Jerry Campbell Comment Link

        Thanks Hans,

        I’ll give it a try this evening.

        Reply

        Jerry Campbell

      • Mar 12, 2018 - 8:20 AM - hans - Author: Comment Link

        Keep us posted! 

        Reply

        hans

        • Mar 12, 2018 - 7:50 PM - Jerry Campbell Comment Link

          Big Thank You, Hans

          Worked perfectly, just what I was wanting. 

          Reply

          Jerry Campbell

          • May 7, 2018 - 11:58 AM - Daniel Fernandes Comment Link

            Hi Jerry, post a link to your modified code… Thanks

            Daniel Fernandes

        • Mar 14, 2018 - 4:39 AM - hans - Author: Comment Link

          Thanks Jerry!

          That’s good news 

          Reply

          hans

  • Mar 23, 2018 - 2:12 AM - Emiel Comment Link

    Hi.

    On the sample video you can see the led flicker when they get dimmed. 

    I quess this is to do with the PWM dimming. Can this be set to a higher frequency or is this preset in the led chips.

    I would to use in video recordings 

    Reply

    Emiel

    • Mar 24, 2018 - 2:57 AM - hans - Author: Comment Link

      Hi Emiel,

      not sure what video you’re referring to, but I did notice that FastLED is much better at this than NeoPixel – so I’d start by using FastLED.
      Another reason could be the method dimming is calculated. If the steps to the next level are too much, flickering may occur. I know FastLED has much better dimming techniques/functions available (NeoPixel not so much) which you may want to experiment with.

      Hope this helps 

      Reply

      hans

  • Mar 27, 2018 - 3:34 AM - Aaron Comment Link

    Thank you for all your work, it proves we all can do it as long as as we just give it a go.

    You inspired me to do some Christmas lights.

    I will try it out for my Christmas lights and add BLE or a button.,

    I don’t mind  if the script/sketch resets, I probably would prefer it.

    Regards

    Reply

    Aaron

    • Mar 28, 2018 - 8:27 AM - hans - Author: Comment Link

      Thanks Aaron!

      I very much appreciate your thank-you note! It’s much appreciated and it’s fun to hear that others get enthusiastic with this stuff as well! 

      Reply

      hans

  • Mar 30, 2018 - 4:10 PM - Mike Garber Comment Link

    Tip:      Your use of     asm volatile (” jmp 0″);   wont fly on a ESP8266  (Error:  “unknown opcode or format name jmp”)

    Reply

    Mike Garber

    • Mar 31, 2018 - 4:11 AM - hans - Author: Comment Link

      Thanks Mike for the tip!

      I read in a bug report that the ESP library has a reset/restart function.

      ESP.restart();

      and 

      ESP.reset();

      There seems to be a bug with the first reset call, and I’m not sure if this still is the case (since I have done nothing with ESP yet).
      One user suggest using this to reset:

      WiFi.forceSleepBegin(); wdt_reset(); ESP.restart(); while(1) wdt_reset();

      I cannot (yet) test this though, but it would be cool if it would work.

      Reply

      hans

  • Apr 13, 2018 - 7:38 AM - Arnaud Comment Link

    Hello,

    I don’t speack English so it’s difficult for me to understand all your explications.
    I try to use AllEffects LEDStrip Effect (NeoPixel) downloaded on this page.
    But I have some problem when I check the code.
    Could you help me please?

    1. AllEffects_NeoPixel.ino: In function ‘void setup()’:
    2. AllEffects_NeoPixel.ino:16:49: error: ‘digitalPinToInterrupt’ was not declared in this scope
    3. AllEffects_NeoPixel.ino: In function ‘void loop()’:
    4. AllEffects_NeoPixel.ino:21:10: error: ‘class EEPROMClass’ has no member named ‘get’
    5. AllEffects_NeoPixel.ino:25:12: error: ‘class EEPROMClass’ has no member named ‘put’
    6. AllEffects_NeoPixel.ino: In function ‘void changeEffect()’:
    7. AllEffects_NeoPixel.ino:170:12: error: ‘class EEPROMClass’ has no member named ‘put’
    Reply

    Arnaud

    • Apr 16, 2018 - 7:31 AM - hans - Author: Comment Link

      Hi Arnaud,

      What hardware are you using? (Arduino Uno R3?)
      If you’re using an Arduino Uno, then by the looks of the error messages you have a typo somewhere …

      Reply

      hans

      • Apr 16, 2018 - 12:10 PM - Arnaud Comment Link

        Hello Hans,

        Thank you for your answer.
        I use an Arduino Uno R3.
        I just found a solution. Not why it didn’t work but how to use your sketch.
        The problem was not typo but software.
        On my laptop I use Ubuntu and Arduino 2:1.0.5+dfsg2-4. Your sketch doesn’t work.
        I tried with my Android smartphone, ArduinoDroid, the same sketch and the same libraries. Your sketch works perfectly.

        Thank you Hans for your very good sketches and tutorials.

        Reply

        Arnaud

        • Apr 17, 2018 - 3:20 AM - hans - Author: Comment Link

          Hi Arnaud,

          what you could try, if you use copy and paste: copy the sketch text to a plain text editor (you could try Atom – freely available for Windows, Mac and Linux). After having it copied there, select all and copy again, and now paste it into the Arduino IDE. I have seen a few users with goofy effects of characters being copied from their browser. So maybe this is the case in your situation as well. 

          Reply

          hans

          • Apr 21, 2018 - 11:17 AM - Arnaud Comment Link

            Hello Hans,

            Thank you for your help.
            I installed Atom, copied-pasted our code inside, just changed “PIN 5” to “PIN 6” and copied-pasted all from Atom into the Arduino IDE.
            There is the same compilation error.

            Perhaps there is a problem with my EEPROM library on Linux. I will try to remove it and install it at new.
            But our code works fine when I use it from my phone with an Android OS. And for that I’m very happy.

            Arnaud

          • Apr 22, 2018 - 3:20 PM - hans - Author: Comment Link

            Thanks for the feedback – there must be an issue with the Arduino IDE you’re using. 
            Your version number seems a little odd, maybe you’d want to try to download the latest version from the Arduino website: https://www.arduino.cc/en/Main/Software – which at this time would be version 1.8.5.

            Would be nice to figure that one out, right? 

            hans

          • Apr 24, 2018 - 1:32 PM - Arnaud Comment Link

            Hello Hans,

            You’re right. I had a too old version.
            I installed the latest version as you advised me and there no check problem.
            The uploading is OK and your code works wonderfully.

            Many thanks for all.

            Arnaud

          • Apr 27, 2018 - 2:29 AM - hans - Author: Comment Link

            You’re most welcome!
            Glad it got resolved and thanks for posting the confirmation! 

            hans

  • May 6, 2018 - 9:15 PM - Daniel Fernandes Comment Link

    Hi Hans! First, thank you and congratulations for the “CHALLENGE!”
    I
    do not know if anyone here in the forum commented on it (I did not read
    everything because my language is Portuguese) but, instead of using a
    Button, like you did, I would not be able to sequence these codes with a
    kind of “Delay”, or
    either, each time one code ends, the other starts, and so on?
    See that they are words of a practically “layman” in the subject; hug from Brazil

    Reply

    Daniel Fernandes

    • May 9, 2018 - 3:23 AM - hans - Author: Comment Link

      Hi Daniel,

      yes you most certainly can put them in sequence so it rotates automatically.

      Probably the easiest to do this is by making a small change to the loop();

      replace this:

      void loop() { 
        EEPROM.get(0,selectedEffect); 
        
        if(selectedEffect>18) { 
          selectedEffect=0;
          EEPROM.put(0,0); 
        } 

      with this:

      void loop() { 
        selectedEffec++;  
        if(selectedEffect>18) { 
          selectedEffect=0;
          delay(1000); // 1 second delay
        } 
        ... // the effects

      Hope this helps. 

      Reply

      hans

      • May 9, 2018 - 11:55 AM - Daniel Fernandes Comment Link

        Hi Hans!

        I did so, as you said:

        void loop() {
          selectedEffec++;
         
          if(selectedEffect>18) {
            selectedEffect=0;
            delay(1000); // 1 second delay
          }
           
          switch(selectedEffect) {

        case 0,  1,  2 …

        And showed the following error:

        ‘selectedEffec’ was not declared in this scope


        Hugs

        Reply

        Daniel Fernandes

        • May 9, 2018 - 2:20 PM - hans - Author: Comment Link

          Hi Daniel!

          I see, typo on my end … it should have been selectedEffect – forgot the “t” at the end 

          Corrected:

          void loop() { 
            selectedEffect++; // <--- I forgot the "t" in selectedEffect
           
            if(selectedEffect>18) { 
              selectedEffect=0;
              delay(1000); // 1 second delay
            } 
          Reply

          hans

          • May 13, 2018 - 11:06 AM - Daniel Fernandes Comment Link

            Hi Hans! One more time, it did not work!
            He performs some four sequences and stops at a set of red lights;

            Daniel Fernandes

          • May 14, 2018 - 5:20 AM - hans - Author: Comment Link

            Hi Daniel,

            oh man, we keep running into small problems 

            Can you verify that the numbers in the “case” statement are sequential (ie. there is no gap in the numbers).

              switch(selectedEffect) {
                
                case 0 : {
                            // RGBLoop - no parameters
                            RGBLoop();
                            break;
                          }
                case 1 : {
                            // FadeInOut - Color (red, green. blue)
                            FadeInOut(0xff, 0x00, 0x00); // red
                            FadeInOut(0xff, 0xff, 0xff); // white 
                            FadeInOut(0x00, 0x00, 0xff); // blue
                            break;
                          }
                ...

            You should see: case 0, case 1, case 2, …, case 18.

            Are you using FastLED (better) or NeoPixel?

            And is your powersupply powerful enough to have all LEDs powered?

            So the 4th or 5th sequence fails? You could comment out an effect and see which one is failing, for example like so, see effect “case 4- CylonBounce” where I added “//” before the effect.

                case 3  : {
                            // HalloweenEyes - Color (red, green, blue), Size of eye, space between eyes, fade (true/false), steps, fade delay, end pause
                            HalloweenEyes(0xff, 0x00, 0x00, 
                                          1, 4, 
                                          true, random(5,50), random(50,150), 
                                          random(1000, 10000));
                            HalloweenEyes(0xff, 0x00, 0x00, 
                                          1, 4, 
                                          true, random(5,50), random(50,150), 
                                          random(1000, 10000));
                            break;
                          }
                          
                case 4 : {
                            // CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
                            // CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);  // <--- here, added "//" to comment out the effect
                            break;
                          }
                          
                case 5 : {
                            // NewKITT - Color (red, green, blue), eye size, speed delay, end pause
                            NewKITT(0xff, 0x00, 0x00, 8, 10, 50);
                            break;
                          }

            hans

  • May 14, 2018 - 2:41 PM - Daniel Fernandes Comment Link

    Hi Hans, It worked! Very cool!
    I think it was not enough to connect the Source Negative to Arduino’s GND;
    I’ll always be looking on your site for a few more effects additions.
    Now I have a few more questions:
    1) Is there a Delay between each effect or is it a Delay for all?
    2) Is this code supported by an ATtiny85 8MHz (by size and versatility)?
    3) To cancel an effect, for example “HalloweenEyes”, do I only comment on the effect with “//” or exclude all “case 3”?
    Once again, thank you very much and congratulations for the feat!

    Reply

    Daniel Fernandes

    • May 15, 2018 - 2:51 AM - hans - Author: Comment Link

      Hi Daniel,

      Glad to hear it works! 

      Ill try to answer your questions:

      1) Delay between effects can be accomplished by adding a delay at the end of loop(), like so (watch out for the accolade):

          case 18 : {
                      // meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay 
                      meteorRain(0xff,0xff,0xff,10, 64, true, 30);
                      break;
                    }
        }
        delay(1000); // <-- added a 1 second delay after an effect has been executed
      }

      2) I have no idea if the ATtiny can handle this – if it would be limited then it would be because of the size of the code. You could also consider an ESP8266, which I haven’t tested yet. They are very cheap and very capable.

      3) Cancelling an effect;
      The best way would be to remove the code and change the numbers of the “case x:” lines, for example:

          ...
          case 2 : {
                      // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
                      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
                      break;
                    }
          case 3 : {
                      // HalloweenEyes - Color (red, green, blue), Size of eye, space between eyes, fade (true/false), steps, fade delay, end pause
                      HalloweenEyes(0xff, 0x00, 0x00, 
                                    1, 4, 
                                    true, random(5,50), random(50,150), 
                                    random(1000, 10000));
                      HalloweenEyes(0xff, 0x00, 0x00, 
                                    1, 4, 
                                    true, random(5,50), random(50,150), 
                                    random(1000, 10000));
                      break;
                    }
                    
          case 4 : {
                      // CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
                      CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);
                      break;
                    }
         ...

      becomes:

          case 2  : {
                      // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
                      Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
                      break;
                    }
          // case 3 removed
          case 3 : { // case 4 has been renumbered to case 3, ditto for the following "case" numbers (ie. case 5 becomes case4 etc)
                      // CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
                      CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);
                      break;
                    }

      Hope this helps. 

      Reply

      hans

  • May 18, 2018 - 12:54 PM - Jim Comment Link

    Hi

    Thank you so much for your article and your explanation. I’m new to arduino and programming. I’ve by looking quite a long time for an answer to that problem of interrupt with Neopixel but didn’t fnd anything until I found your webpage.

    I took your code structure (Neopixel) and replaced your animations by mine (I kept some of your animations…). It works quite well. But there are 2 minor problems.

    1) Starting Case:

    When I switch on the arduino (or reset), it starts at case 1 instead of case 0. I could fix this by changing the code at line 9:  byte selectedEffect=0; to byte selectedEffect=18. If I choose selectedEffect= Max Nr of cases, then it starts at case 0. I don’t understand why but it works, so it’s fine for me. I’m just curious to know why it happens…

    2) Switch debounce:

    While toggling through the cases, it often starts again at case 0 before having reached the last case. I don’t know what the reason is but I guess it has something to do with switch bouncing. I don’t know how to fix this with an interrupt. Can somebody help me with this? I would prefer a software solution than a hardware solution but any solution is welcome.

    Thanks a lot!

    Jim

    Reply

    Jim

    • May 20, 2018 - 9:57 AM - hans - Author: Comment Link

      Hi Jim,

      welcome at Tweaking4All and thank you very much for the very nice and motivating compliments! 

      1) Starting point

      Theoretically the EEPROM should hold the value where you left off last time the Arduino ran – but I have found that not to be reliable, which makes me wonder a little about the EEPROM. I guess it needs to remain power to actually hold that value (and that’s why it survives a reset).

      To force it to start at zero you could make this modification (untested);

      void setup()
      {
        strip.begin();
        strip.show(); // Initialize all pixels to 'off'
        digitalWrite (BUTTON, HIGH); // internal pull-up resistor
        attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
        EEPROM.put(0,0);  // <-- add this
      }

      2) Debouncing the switch

      I do not have access to my gear at the moment (I’m on vacation for the next 4 weeks). Maybe try another switch (I did some testing with just 2 wires, which worked very well). Keep us in the loop for what you see or find on this topic – anything to improve the sketch is naturally very welcome.
      When I get back home, I’ll try to make some time and look at this, but I can understand that 4 weeks is a rather long time to wait 

      Reply

      hans

  • May 18, 2018 - 10:48 PM - Brent Roberson Comment Link

    Hello Hans,

    I wanted to say thank you for this awesome information and also ask a couple questions. I am a beginner with arduino but I am working on a project where I use a potentiometer to smoothly change the colors in the spectrum. My code ends up not working in the end and I think it is just because I don’t really know what I am doing. Do you have any ideas or know any websites that can show me how to do this? I also wanted to make it dimmer and brighter as it reacts to music so if you have any ideas on how I should go about that please let me know. I also have one more question about your code. The function setAll is not being recognized the arduino and it says it was not declared in this scope even though I have downloaded and included the fast led and adafruit library. Do you have any idea why this would not work? Thanks so much and if you don’t have the time to spend on this long question or part of the question I understand. 

    Reply

    Brent Roberson

    • May 20, 2018 - 10:03 AM - hans - Author: Comment Link

      Hi Brent,

      welcome to Tweaking4all and thank you very much for the kind compliments – it’s very much appreciated. 

      As for playing with potentiometers (watch the different kinds – linear vs non-linear) and reacting to music; I’ve not played much with potentiometers, but I have done some playing with a microphone and a line-in setup to “read” music volume and found that it’s not as straight forward as one would hope. With a microphone you will need to add a tiny amp (single chip, real cheap) and even then things are not as consistent as I wanted it to be (I wanted the fire effect to respond to music – like VU meters from back in the day). I’m on vacation right now, so I do not have all my stuff near me, you may end up consulting Google. Sorry … 

      As for the setAll() function; that’s kind a hard to determine without seeing the code, and posting the full code here is not desirable either (since comments then become huge over time). You could post you sketch in the forum and I can look at it and see what the issue may be.

      Reply

      hans

      • May 21, 2018 - 9:08 PM - Brent Roberson Comment Link

        Okay, thanks for the suggestions I’ll try that out. And somehow the setAll function worked the next day I tried it lol

        Reply

        Brent Roberson

      • May 22, 2018 - 8:09 AM - hans - Author: Comment Link

        Awesome – glad it is working now 

        Reply

        hans

  • Jun 13, 2018 - 10:08 PM - Blake Comment Link

    Sorry if this comment already posted. Does anyone have the code for all the effects without a button function? Would be greatly appreciated.

    Thanks!

    Reply

    Blake

    • Jun 16, 2018 - 9:16 AM - hans - Author: Comment Link

      Hi Blake,

      yes this was posted before. To save you the search:

      Change this piece of the code:

      void loop() { 
        EEPROM.get(0,selectedEffect); 
        
        if(selectedEffect>18) { 
          selectedEffect=0;
          EEPROM.put(0,0); 
        } 

      to:

      void loop() { 
        selectedEffect++;  
       
        if(selectedEffect>18) { 
          selectedEffect=0;
          delay(1000); // 1 second delay
        } 

      (this is the quick an dirty method)

      Reply

      hans

  • Jul 3, 2018 - 11:06 AM - Nathan Comment Link

    Hey Hans,

    You do amazing work. A question I have is that I want to power 1200 leds for a costume so I use an M0 board. Do you know what needs to be tweeked in your code? Right now its coming up with a fault about EEPROM. Ive read that you need to emulate EEPROM for M0 boards. Do you know how to do that?

    Thank you for all your hard efforts

    Reply

    Nathan

    • Jul 4, 2018 - 6:16 AM - hans - Author: Comment Link

      Hi Nathan,

      I’m not familiar with the MO board you’re referring to.
      Having said that: 1200 LEDs is a lot … but that sounds pretty awesome to play with 

      To power 1200 LEDs, you’ll need a pretty good power-supply. Not just that, but you’d want to connect +5V and GND of the strips, in multiple places so power distribution works OK. I have seen with 300 LEDs that the last LEDs seem to be getting less power. For 300 LEDs, the trick is to connect +5V and GND to both ends of the strand(s). I’d carefully assume the same goes for 1200 LEDs. Maybe power each strip separately?

      Since I’m not familiar with the board you’re using; I cannot help you with how to access EEPROM.
      I did find these posts that may be helpful though:

      Hope this is helpful … 

      Reply

      hans

      • Jul 13, 2018 - 10:03 PM - Nathan Comment Link

        I’m talking about the Trinket MO or the itsy bitsy MO. They are just like Arduino boards but smaller and can power way more LEDs. But they do not have eeprom. I have all the power and wiring done and figured out. Online I’ve read that you need to replace the eeprom part of the code with an emulated eeprom instead. I don’t know how to code though. It seems like it wouldn’t be too hard if I had a little more knowledge. This guide from you is the closest thing I’ve seen so far to finding a code with a button to change effects. You’re very talented

        Reply

        Nathan

      • Jul 14, 2018 - 4:06 AM - hans - Author: Comment Link

        Hi Nathan,

        I have no experience with either MO (even though they do sound interesting!).

        As for working with the eeprom on either of these boards, from what I can see is that there is some sorts of nonvolatile memory, but working with it seems to need one of the AVR (low level) libraries. 

        This code at Github (eeprom-blink) may be useful, but it’s definitely not as easy looking as the functions that come with the standard EEPROM libraries for other Arduino models. AdaFruits shows there are two working functions, but I have to say that the explanation/documentation is pretty poor.

        This flashstorage library may be helpful as well. I did see in a forum that a user confirmed this to work with the trinket.

        Something like this:

        #include <FlashStorage.h>
        ... // Reserve a portion of flash memory to store an "int" variable and call it "my_flash_store".
        FlashStorage(my_flash_store, int);
        ...
        void setup() { ...   int number;
          // Read the content of "my_flash_store" and assign it to "number"
          number = my_flash_store.read();
        ...
          // Save into "my_flash_store" the number increased by 1 for the
          // next run of the sketch
          my_flash_store.write(number + 1); ...
        }
        ...

        Not sure how helpful this info is, since I cannot test any of it.

        Reply

        hans

        • Jul 14, 2018 - 4:15 PM - Nathan Comment Link

          Thank you for your research. I’ll attempt trying that. I’m going to enroll in a class for this soon. I hate that I don’t know how to write my own code. I have to rely on finding it at the moment. Seeing your work is very motivating too. You should be very proud of your skills. If you learn any more about this in the future I’m always interested to learn more about it. Thanks again

          Reply

          Nathan

          • Jul 15, 2018 - 3:39 AM - hans - Author: Comment Link

            Hi Nathan,

            You’re most welcome and thank you very much for your compliments – it’s appreciated and motivating for myself as wel! 

            As for programming, I did write some articles for beginners but I’m not sure if this is what you’re looking for: Arduino Programming for Beginners. It starts with the basics, so it may or may not be what you’re looking for. 

            hans

  • Jul 28, 2018 - 7:53 AM - Christophe Gonthier-Georges Comment Link

    Bonjour, votre code fonctionne très bien, c’est exactement ce que je cherchais.

    Pourriez-vous juste me dire comment ajouter tous les led au début du programme s’il vous plaît?

    Reply

    Christophe Gonthier-Georges

    • Jul 29, 2018 - 7:37 AM - Christophe Gonthier-Georges Comment Link

      Sorry, but he did not translate the French text.

      I was saying:

        “Hello, your code works fine, that’s exactly what I was looking for.

      Could you just tell me how to add all the led off in the first sequence of the program please? “

      Thank you in advance

      Reply

      Christophe Gonthier-Georges

    • Jul 30, 2018 - 5:06 AM - hans - Author: Comment Link

      Hi Christophe!

      No worries…

      You can add an effect in the case statements.

      Something like:

          case 19 : {
                      // all off 
                      setAll(0,0,0);
                      break;
                    }

      You’ll need to modify line 23:

        if(selectedEffect>19) {  // increase the number 18 to 19
          selectedEffect=0;
          EEPROM.put(0,0); 
        } 

      I can imagine that you’d like to start with this effect, in that case, swap it with the effect at “case 0:”.

      Hope this helps 

      Reply

      hans

      • Jul 30, 2018 - 2:29 PM - Christophe Gonthier-Georges Comment Link

        I set up your code I have the effect in 19 but impossible to start on even putting it in box 0

        J’ai mis en place votre code j’ai bien l’effet en 19 mais impossible à démarrer dessus même en le mettant en case 0

        Reply

        Christophe Gonthier-Georges

      • Aug 8, 2018 - 6:31 AM - hans - Author: Comment Link

        Easiest way to do it:

        Add 

            case 0 : {
                        // all off 
                        setAll(0,0,0);
                        break;
                      }

        before line 30 (where “case 0: {” currently is).

        For all following case numbers, increase by one, so:

        –  the old “case 0: {” becomes, “case 1: {“,
        –  the old “case 1: {” becomes “case 2: {“,
        … etc until your reach “case 18: {” which becomes “case 19: {“.

        Make sure to modify the code at line 23 as well:

         if(selectedEffect>19) {  // increase the number 18 to 19
            selectedEffect=0;
            EEPROM.put(0,0); 
          } 
        Reply

        hans

        • Aug 8, 2018 - 5:02 PM - Christophe Gonthier-Georges Comment Link

          J’ai fait ce que tu as mis mais ça commence toujours sur le premier effet et non sur la LED.

          Je ne comprends pas :(

          J’ai fait ce que vous avez mis mais ça commence toujours sur le premier effet et non les LED éteintes.

          Je ne comprend pas :(

          Reply

          Christophe Gonthier-Georges

        • Aug 11, 2018 - 5:33 AM - hans - Author: Comment Link

          Hi Christophe,

          pretty please post in English only … my French is very bad, and this may be the case for other visitors as well.

          Your message (per Google Translate):

          I did what you put but it always starts on the first effect and not on the LED.

          I do not understand :(

          I did what you put but it always starts on the first effect and not the LEDs off.

          I do not understand :(

          Always starting with a given effect will be tricky. We use the EEPROM to store the value of the selected effect to survive a reset and powering the Arduino down would result the same effect. The only thing I could find (Arduino forum post) is this:

          void setup() {
           Serial.begin(38400);
           Serial.print("MCUSR: ");
           Serial.println(MCUSR);
           
           if (MCUSR & _BV(EXTRF)){
               // Reset button or otherwise some software reset
               Serial.println("Reset button was pressed.");
           }
           if (MCUSR & (_BV(BORF) | _BV(PORF))){
                // Brownout or Power On
                Serial.println("Power loss occured!");
           }
           if (MCUSR & _BV(WDRF)){
                //Watchdog Reset
                Serial.println("Watchdog Reset");
           }
           // Clear all MCUSR registers immediately for 'next use'
           MCUSR = 0;
          }

          So this would mean that we could change the “void setup()” code a little … (untested!!!!)

          void setup()
          {
            // Read the appropriate register to detect power on/off/brownout vs reset button press
            if (MCUSR & (_BV(BORF) | _BV(PORF))){
              selectedEffect=0;
              EEPROM.put(0, selectedEffect); // store the chose effect
            }
            FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
            digitalWrite (BUTTON, HIGH); // internal pull-up resistor
            attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
          }

          If this work appropriately, then please let us know, so I can update the code to accommodate for this.

          Reply

          hans

          • Sep 2, 2018 - 4:27 AM - Christophe Gonthier-Georges Comment Link

            Hi Hans, I found the solution to my problem.

            I deleted case 0 by case 1 and changed all the others and I can boot on any LED off.

            Here is my code for those interested:

            #include <Adafruit_NeoPixel.h>
            #include <EEPROM.h>

            #define NUM_LEDS 35 
            #define PIN 4 
            Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

            #define BUTTON 2
            byte selectedEffect=0;

            void setup()
            {
              strip.begin();
              strip.show(); // Initialize all pixels to 'off'
              digitalWrite (BUTTON, HIGH); // internal pull-up resistor
              attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
            }

            void loop() { 
              EEPROM.get(0,selectedEffect); 
              
              if(selectedEffect>20) { // increase the number 18 to 19
                selectedEffect=0;
                EEPROM.put(0,0); 
              } 
              
              switch(selectedEffect) {
               

                case 1 : {
                           // all off 
                            setAll(0,0,0);
                            break;
                           }
                case 2 : {
                            // Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
                            Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
                            break;
                          }

                ...

            thank you very much

            Christophe Gonthier-Georges

          • Sep 3, 2018 - 2:50 AM - hans - Author: Comment Link

            Hi Christophe!

            Good to hear you’ve got it to work! 
            I did shorten your code a little, since it is quite long for the comment section. I left the case section in tacts so folks can see what you are referring to.

            Thanks for posting! 

            hans

  • Aug 20, 2018 - 11:48 AM - JLPicard Comment Link

    New to this, should I purchase a UNO for this sketch?  Ebay ok?

    Reply

    JLPicard

    • Aug 20, 2018 - 12:16 PM - hans - Author: Comment Link

      Hi Star Trek Fan! 

      Yeah I’d start with an Uno, and preferably a genuine one from Arduino. You can find them at eBay and Amazon. Most clones work well, but it will remain a gamble since some have issue with their USB chip, where as the original does not. I always find a challenging to determine which one is genuine and which one is not, so at Amazon you can at least select the brand “Arduino”. I know it’s a little more than most clones … but when starting, it may be worth it. Also: there are some great started kits at Amazon (and I’m sure at eBay as well).

      Hope this helps …

      p.s. The Arduino Uno is also called the “Arduino Uno R3” – those are the same boards.

      Reply

      hans

  • Aug 28, 2018 - 6:20 PM - tratzum Comment Link

    I am impressed. I want to ask how I could slow some of these animations down. I know the basics of how it all works but everything after line 175 ish LEDEFFECT FUNCTIONS is mostly black magic to me.

    Reply

    tratzum

    • Aug 29, 2018 - 3:25 AM - hans - Author: Comment Link

      Hi Tratzum,

      thank you very much for the compliment, it’s very much appreciated.

      To delay effects, for most of the effects anyway, you can tinker a little with the “delay()” statement right before or after the “showStrip()” function calls in an effect. For example:

      void RGBLoop(){
        for(int j = 0; j < 3; j++ ) { 
          // Fade IN
          for(int k = 0; k < 256; k++) { 
            switch(j) { 
              case 0: setAll(k,0,0); break;
              case 1: setAll(0,k,0); break;
              case 2: setAll(0,0,k); break;
            }
            showStrip();
            delay(3); // <--- increase this value will slow down the effect
          }
          // Fade OUT
          for(int k = 255; k >= 0; k--) { 
            switch(j) { 
              case 0: setAll(k,0,0); break;
              case 1: setAll(0,k,0); break;
              case 2: setAll(0,0,k); break;
            }
            showStrip();
            delay(3); // <--- increase this value will slow down the effect
          }
        }
      }

      In some functions you may have to add a delay, for example:

      void FadeInOut(byte red, byte green, byte blue){
        float r, g, b;
            
        for(int k = 0; k < 256; k=k+1) { 
          r = (k/256.0)*red;
          g = (k/256.0)*green;
          b = (k/256.0)*blue;
          setAll(r,g,b);
          showStrip(); delay(10); // <--- added a delay here
        }
           
        for(int k = 255; k >= 0; k=k-2) {
          r = (k/256.0)*red;
          g = (k/256.0)*green;
          b = (k/256.0)*blue;
          setAll(r,g,b);
          showStrip(); delay(10); // <--- added a delay here
        }
      }

      You may have to experiment a little with the delay values (values in milliseconds, so 1000 = 1 second).
      Some of the effects already have a delay option build in; like

      Strobe();
      HalloweenEyes()
      CylonBounce();
      NewKITT();
      Twinkle();
      TwinkleRandom();
      Sparkle();
      SnowSparkle();
      RunningLights();
      colorWipe();
      theaterChase();
      Fire();
      meteorRain();

      Look for any delay or speed-delay parameters.

      Maybe one of these days I’ll convert all of them to include a speed/delay option. Unfortunately, I’m still trying to get settled after moving to a new home, so I do not have my gear readily available.

      Hope this helps … 

      Reply

      hans

  • Sep 1, 2018 - 2:32 PM - Philip King Comment Link

    Hi Hans,

    Brilliant sequence and explanation and I’m really impressed. Its also answered a future problem (for me), as I needed to add a button to 2 x 2.5m strips of 2812b to both my kids bedrooms (one per child) and wanted them to be able to switch between patterns. Thank you!

    I took the plunge about 8 months ago and have installed strips round the outside of my house ready for Christmas (took it slow as the leds are cheap but the infrastructure to run the 500 leds I have installed is substantial. (PSUs, buck converters, conduit, cable etc)), I’ll definitely be looking to add a few of your sequences to my (ever extending) list .

    I’ve tried to write a few (very unsuccessful)  sequences myself but just don’t seem to be mathematically capable YET!  

    I have a question though. I really want to modify the code so that the fire and bouncing ball sequences will run within my 500led outside lights. Try as I might I cannot get the sequences to work as I need the first 75 leds to work then miss out the next 142 then run again (but upside down) in the next 75 leds (I do hope you can follow). Can you see a way of doing it as I’ve been scratching my head so much its starting to bleed. LOL 

    The leds are arranged (outside) in one continuous loop. A vertical strip (going up) up the side of the house (75leds), a horizonal strip under the guttering (142 leds), another 75leds going down the opposite side, then a final horizontal set (208) linking back around a porch.

    I’ve set used the #define NUM_LEDS 500 and both look very silly when you try to run them round the house….

    Hope you can help.

    Philip

    Reply

    Philip King

    • Sep 2, 2018 - 2:53 AM - hans - Author: Comment Link

      Hi Philip!

      Thank you very much for the compliments! It’s very much appreciated!
      Wow you really are using LED strips a lot haha – I’m jealous! One of these days, when I own my own house, I’ll follow your approach! 

      I’ve started a forum topic, if you don’t mind, because I can see us talking about this for a bit to get things working …

      Here is the link to the forum topic.

      Reply

      hans

  • Sep 16, 2018 - 12:23 PM - Jakob Comment Link

    Hey,

    Great job on the code! I made a project with the led strip on a portable wooden stick and i use it for my photography. Quick question though: 

    I changed the code so that I could use a keypad matrix to switch between effects. But there’s a problem. The error comes up for every effect saying: 

    “‘theaterChaseRainbow’ was not declared in this scope” or “‘Fire’ was not declared in this scope”

    Is there anyway you can help?

    Reply

    Jakob



Your Comment …

Friendly request to not post large files here (like source codes, log files or config files). Please use the Forum for that purpose.

Please share:
*
*
Notify me about new comments (email).
       You can also use your RSS reader to track comments.


Tweaking4All uses the free Gravatar service for Avatar display.
Tweaking4All will never share your email address with others.