Help programming LED strip custom functions

There are some great Youtube Arduino tutorial series out there.
You seem like you need to go back to understanding what the point of a variable is, which is prerequisite to seeing the point of a for loop is.
In brief, you can copy/paste a code. 15 times where you only change a single number to tell the 15 leds the same thing, or you just use the one code with a function that automatically counts up every time the program runs through.

You were doing well at the point of individually setting those 3 red leds, then jumped too far ahead going back to trying to use code you don't understand. You say you want it spelled out for you thoroughly but at the same time you're impatient. That doesn't work well.

Thanks guys,

I'm doing my best not to be impatient as I said before and one reason for seeming that way is that I don't know what the next step needs to be for any given objective.

I think my understanding of a for loop is getting better but like you said, my understanding of the components that the for loop control/reference is very rough.

Maybe it would be simpler to explain what I want to achieve?

All I'd like to start with is a simple single led cyclon, effect but just to travel in one direction and repeat over and over. Exmaples of this already exist but I'd like to understand each element myself.

Beyond your example:

void loop() { 
  // Turn the LED on, then pause
  for(int i=0; i<NUM_LEDS; i++) {
     leds[i] = CRGB(random(0, 255), random(0, 255), random(0, 255));  // random colors
  }
  FastLED.show();
  delay(100);
}

Which element of a cyclon code causes the first led to come on first and then the second and third etc. What's stopping all of the leds to turn on instantaneously? In your example, all of the leds turn on immeddiately and individually change to random colours based on the for loop.

How about a simpler function? How about a strip that instead of the first led turning on and then off and then the the next one etc, the first led stays on and then the second one and then the third, until the whole strip is on. Like if the strip is vertical and you're pouring light into it.

I'm probably getting ahead of myself again but it's difficult to seem patient when I don't know what questions to ask. Here's my understanding of a variable:

A problem I seem to have with learning in general is that I find the study of examples to be a good way to learn. It's difficult for me to understand a function, such as a variable, without seeing what it's for and what effect it has on an led strip etc.

I certainly know more now than I did yesterday :wink: so I guess I'm heading in the right direction thanks to you guys.

Kyle

I am not sure what you call a cyclone

Do you want one LED to move step-by-step forward and then start again?

If so what you need to do is to maintain in a variable which led is on

At each Step of the loop you turn that one off and turn the next one on - memorize this is the new one - display for a while and loop

There is a small trick to take into account when you reach the end of the strip that you want to go back to 0

Cylon or cyclone or whatever are just sample animation codes from FastLED.

Again I would slowly build up to what you want instead of staring at a whole code and trying to let it osmosis in.

Don't worry about using the random function. But for future note, random(255) is the same thing as random(0,255), as they both pick a number from 0 to 255. Use two numbers if you want to restrict the lower end.

Animation codes are not modular, they aren't singular pieces of information that the light strip knows, "oh you want me to do a chase pattern, okay". All codes simulate animation effects by describing every single step. Turn this on, turn this off, wait this long, then do this, then this, then this, etc. It's like watching a movie where you have to describe every single frame, because that is exactly what you are doing. When one light turns on, then off, and the one next to it turns on, your monkey brain tells you it's the same light that 'moved'. The trick is to use this understanding of the monkey brain to simulate movement in your leds.

Go back to where you were in post #6:

void loop() { 
  leds[0] = CRGB::Red;
  leds[1] = CRGB::Red;
  leds[2] = CRGB::Red;
  FastLED.show();
  delay(500);
  FastLED.showColor(CRGB::Black);
  delay(500);
}

Compare that to:

void loop() { 
  leds[0] = CRGB(255,0,0);
  FastLED.show();
  delay(500);
  FastLED.showColor(CRGB::Black);
  delay(500);

  leds[1] = CRGB(255,0,0);
  FastLED.show();
  delay(500);
  FastLED.showColor(CRGB::Black);
  delay(500);

  leds[2] = CRGB(255,0,0);
  FastLED.show();
  delay(500);
  FastLED.showColor(CRGB::Black);
  delay(500);
}

And tell us what you learned.
You should be able to make your strip do exactly what you want it to do with just the information contained in this. Change the numbers, see what happens. Copy those chunks, make 15 of them, see if you can make the whole strip do it. The for loop stuff is just to make shorter code, but do it the long way first for understanding.

Thanks for your continuing replies,

I'm sure your idea of a cyclon is clearer than mine but I think of it as a night rider effect.

What I'd like to be able to write is a sort of adaptation of this effect.

Here's a video of my setup with the exact effect I'd like to understand:

and here's the code:

#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 15
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  colorWipe(0xff,0xa2,0x00, 40);
  colorWipe(0x00,0x00,0x00, 5);
}

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 showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H 
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

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
}

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

This might be known as a colour wipe. As I understand it, it is doing the same thing twice? One cycle lights the leds in sequence and the second cycle turns them off. In order to create the effect I want, I have increased the speed of the second 'black' led cycle:

void loop() {
  colorWipe(0xff,0xa2,0x00, 40);
  colorWipe(0x00,0x00,0x00, 5);

This is because I want the leds to simply 'turn off' as quickly as possible.

When it comes to the first for loop, am I right in saying that the variable i (set pixel) which starts at 0 and then continues until the end of the strip (NUM_LEDS) in increments of 1 (i++)??

Again, I'm not trying to rush, just showing what I'm trying to do and the extent of my understanding of the code it requires.

Kyle

Sorry,

I posted my last before seeing yours. Thanks very much, we're getting somewhere now.

I've modified the example you kindly wrote to emulate a single cycle of my intended function:

I also removed the 'FastLED.showColor(CRGB::Black); since I'd like them to stay on.

I'm not sure if i've learnt the right things but I did realise that this is a timeline (at least in this instance). I also learnt that assigning a colour to an led is a seperate step to turning the led on which goes back to what you said about describing every single frame.

Thanks again,

Kyle

Thanks again for the help,

How do I now turn the leds off and loop these functions?

Is this the next logical step?

Kyle

kylefoster:
How do I now turn the leds off and loop these functions?

Didn't you just write this before??

I also removed the 'FastLED.showColor(CRGB::Black); since I'd like them to stay on.

That command you took out so each one wouldn't turn off. Put one of those at the end.

I told you this was rocket science to me!

I tried to put one at the end but I assume I'm doing it wrong since they don't turn off. I'd like them all to turn off simultaneously. Here's the code:

#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 15

// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 6
#define CLOCK_PIN 13

// Define the array of leds
CRGB leds[NUM_LEDS];

void setup() { 
    
       FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

     
}

void loop() { 
  leds[0] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  leds[1] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  leds[2] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  leds[3] = CRGB(255,0,0);
  FastLED.show();
  delay(50);  

  leds[4] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
 
  leds[5] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  leds[6] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  leds[7] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
 
  leds[8] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  leds[9] = CRGB(255,0,0);
  FastLED.show();
  delay(50);

  leds[10] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
 
  leds[11] = CRGB(255,0,0);
  FastLED.show();
  delay(50);

  leds[12] = CRGB(255,0,0);
  FastLED.show();
  delay(50);

  leds[13] = CRGB(255,0,0);
  FastLED.show();
  delay(50);

  leds[14] = CRGB(255,0,0);
  FastLED.show();
  delay(50);
  
  FastLED.showColor(CRGB::Black);
}

If I add a delay, they flash but I'm not sure what to add in order to just turn them off.

Thanks again,

Kyle

what happens if you do

delay(5000);

at the very end (just after FastLED.showColor(CRGB::Black):wink:

Try using

FastLED.clear();

instead of the

FastLED.showColor(CRGB::Black);

Hi guys,

Sorry for the late reply! I had a hectic long weekend with the family and I was no where near my laptop or wifi for that matter!

Thanks for the hints, I'll give that a go when I'm at my desk and see how it looks.

Thanks again for your help guys and I look forward to making some more progress. My only worry is how complex my intended end result will be!

Kyle

Hi guys,

I used

FastLED.clear();

which has done the trick it seems:

It's also looping now compared to using

FastLED.showColor(CRGB::Black);

Why is that?

I also noticed that the first led always remained on instead of turning off when clearing the strip which I'm guessing is because the initial state of the loop was always turning the first led on? I added the FastLED.ShowColor back in at the start with a delay in order to achieve a gap as I'd like:

#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 15

// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 6
#define CLOCK_PIN 13

// Define the array of leds
CRGB leds[NUM_LEDS];

void setup() { 
    
       FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

     
}

void loop() { 
  FastLED.showColor(CRGB::Black);
  delay(200);
  
  leds[0] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[1] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[2] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[3] = CRGB(255,0,0);
  FastLED.show();
  delay(25);  

  leds[4] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
 
  leds[5] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[6] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[7] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
 
  leds[8] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[9] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[10] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
 
  leds[11] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[12] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[13] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[14] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  FastLED.clear();
  delay(250);
}

Thanks again for the help. This is the main function that I was hoping to achieve but eventually, this will be controlled by a button so it's either on or off. Based on this, what would be best? Would it be a good idea to consolidate this code using for loops and then add a button or would it be best to leave it as it is and built the code for a button around it?

Now, I've read up a bit on adding a button but when it comes to controlling a strip with one (as usual) I'm not entirely how to implement that code into my existing code.

I'll continue to read up to see if I can work it out but any help would be appreciated.

Thanks again guys,

Kyle

Create a function with all your LED code (take it outside the main loop) and call that function from the loop to ensure all works. Now your main loop is 1 line of code.

Then look at sample codes for dealing with buttons and debouncing, add that into your main loop and once you see the button pressed, call your display function.

My educated guess about the difference between ShowBlack thing and Clear is that ShowBlack is coded in the library somehow as a temporary setting, which doesn't replace the last instruction each individual led was given by you. So when the first FastLED.show triggered upon the second time the loop ran, all of the LEDs were still remembering (255,0,0) as ShowBlack didn't actually set them all to (0,0,0).
Buuuut that doesn't explain why ShowBlack worked for turning off each one and keeping them off, so ignore all that. Idk.

It's not crucial to simplify those 15 chunks down to 1 chunk with a for loop, but it's a good idea to learn for loops for the sake of learning. It's rewarding to see shorter code do the exact same thing.

Your first led is on even during the delay after Clear?

The problem with starting off with a black/clear and delay is that that will be a lag time once you have a button set up. I.e., push button, 'nothing' happens for 200ms. Extend the last delay to space out the repeat, and figure out why your first led is staying on.

As for turning all of what you have in the void loop into a function as JML said, you literally just go replace the word "loop" with another word like "dothething" and you now have a function to refer to.

Then it's just making a new void loop.

void loop(){
dothething();
}

Then when you figure out the button part, it'll look like

void loop(){

//code for if button being pushed{
dothething();
}
}

Hi guys,

I've created a function as you said and added a void loop, calling up the function:

#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 15

// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN.  For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 6


// Define the array of leds
CRGB leds[NUM_LEDS];

void setup() { 
    
       FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
       
      
}

void IndicatorSweep() { 
      
  leds[0] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[1] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[2] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[3] = CRGB(255,0,0);
  FastLED.show();
  delay(25);  

  leds[4] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
 
  leds[5] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[6] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[7] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
 
  leds[8] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  leds[9] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[10] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
 
  leds[11] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[12] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[13] = CRGB(255,0,0);
  FastLED.show();
  delay(25);

  leds[14] = CRGB(255,0,0);
  FastLED.show();
  delay(25);
  
  FastLED.clear();
  delay(500);
}

void loop() {
 IndicatorSweep();
}

I can't work out what I need to add to clear the first led. I've been trying to reference other examples but no joy yet.

Thanks again,

Kyle

Hi guys,

I've also consolidated my code into a for loop now I understand it a little more. The broken out code helped me to understand the language generally:

#include "FastLED.h"

#define NUM_LEDS_PER_STRIP 15
CRGB leds[NUM_LEDS_PER_STRIP];


void setup() { 

  
  FastLED.addLeds<NEOPIXEL, 6>(leds, NUM_LEDS_PER_STRIP);
}

void TurnSignal() {
  for(int i = 0; i < NUM_LEDS_PER_STRIP; i++) {
    leds[i] = CRGB::Red;
    FastLED.show();
    leds[i] = CRGB::Red;
    delay(50);
  }
}

void loop() {
  FastLED.show();
  delay(50);
  TurnSignal();
  FastLED.clear();
  
}

I'm still not sure how to clear the first led without a small delay.

Thanks again,

Kyle