WS2801 LED strip - Guidance Adapting "First Light" example from FAST.LED lib

Hello all,

This is my first attempt ever using arduino, so apologies if i’m asking something that might be blatantly obvious. The company I work for are keen for me to multi-task into the electronics department, where i have VERY limited knowledge.

I have an arduino UNO (with a wifi-shield attached but shall be ignored) And I have a strip of 26 leds (WS2801) I’ve adapted the example code from “firstlight” example, to reflect my pins and my led count, The script works successfully moving a white LED up the strip. bit i need to get a little more complicated…

What i need the program to do eventually is this:

1.) All LEDS dimly lit white (lets say 20% brightness)
2.) When a switch is pushed (not sure if pull up or push down switch yet, or which pins it will reside on) I need a spectrum of colours to chase (just once) from the arduino to the ends of the strip then stop. By spectrum i mean… a red led, a blue led, a green led, a yellow led that chase around the strip. If i can adjust the speed easily by defining it at the top of the script that would also be marvelous. additionally, if i’m able to change my mind about the order and colours of the spectrum that would be great but not essential.

OPTION 2: I’ve been told I could have 2 seperate strips one for the dim lighting which is continually on, and then just run the chaser program on a seperate strip. If this is a better option then please let me know how to code for this setup.

Appreciate all the help guys, If anyone helps with code please comment the code as well as it will help me in understanding how and why you’ve used that solution. Big thanks in advance and a pint on me if you live local to London.

// Use if you want to force the software SPI subsystem to be used for some reason (generally, you don't)
// #define FORCE_SOFTWARE_SPI
// Use if you want to force non-accelerated pin access (hint: you really don't, it breaks lots of things)
// #define FORCE_SOFTWARE_SPI
// #define FORCE_SOFTWARE_PINS
#include "FastLED.h"

///////////////////////////////////////////////////////////////////////////////////////////
//
// Move a white dot along the strip of leds.  This program simply shows how to configure the leds,
// and then how to turn a single pixel white and then off, moving down the line of pixels.
// 

// How many leds are in the strip?
#define NUM_LEDS 26

// Data pin that led data will be written out over
#define DATA_PIN 2

// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define CLOCK_PIN 3

// This is an array of leds.  One item for each led in your strip.
CRGB leds[NUM_LEDS];

// This function sets up the ledsand tells the controller about them
void setup() {
	// sanity check delay - allows reprogramming if accidently blowing power w/leds
   	delay(2000);

      // Uncomment one of the following lines for your leds arrangement.
      // FastLED.addLeds<TM1803, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<TM1804, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<TM1809, DATA_PIN, RGB>(leds, NUM_LEDS);
      //FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
      // FastLED.addLeds<WS2811_400, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<GW6205, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<GW6205_400, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<UCS1903, DATA_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<UCS1903B, DATA_PIN, RGB>(leds, NUM_LEDS);

      //FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<SM16716, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<LPD8806, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<P9813, RGB>(leds, NUM_LEDS);
      
      FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<SM16716, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
      // FastLED.addLeds<LPD8806, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
}

// This function runs over and over, and is where you do the magic to light
// your leds.
void loop() {
   // Move a single white led 
   for(int whiteLed = 0; whiteLed < NUM_LEDS; whiteLed = whiteLed + 1) {
      // Turn our current led on to white, then show the leds
      leds[whiteLed] = CRGB::White;

      // Show the leds (only one of which is set to white, from above)
      FastLED.show();

      // Wait a little bit
      delay(100);

      // Turn our current led back to black for the next loop around
      leds[whiteLed] = CRGB::Black;
   }
}

kainevfx: What i need the program to do eventually is this:

1.) All LEDS dimly lit white (lets say 20% brightness)

So where is the problem?

If you want "20% brightness" you just need to know that the brightness that is recognized by the human eye is not linear to the LED current or PWM value, but rather logarithmic.

So if you want to have 8 steps of brigthness from dark to bright, the PWM values would go something like:

0, 4, 8, 16, 32, 64, 128, 255

So if you want "dim white" you'd perhaps not use "20% of 255"= rgb(51,51,51), but just rgb(8,8,8) as a "dim white" value for the LEDs.

Thanks Jurs,

I vaguely understand how i can convert percentage to actual values the LED strip can understand,

My main sticking point is how to get 5 or 6 differently coloured LEDs to chase along the strip at the push of the buttom. Any ideas on how one might achieve this effect?

Thanks, Kaine

kainevfx: My main sticking point is how to get 5 or 6 differently coloured LEDs to chase along the strip at the push of the buttom. Any ideas on how one might achieve this effect?

Step along with 'hard switching' single LEDs on or off?

In that case the programming logic would create 'steps' of a certain time duration while the effect is the same, then switches to the next.

Maybe (example using 10 steps per second):

void setLEDcolors(unsigned long time)
{
  // calculate and set the colors and on/off state of each LED here
  // all calculations based on time/steps
  FastLED.show(); // show the pattern calculated above
}


#define STEPDURATION 100
unsigned long stepTime;
unsigned long lastLEDupdate;

void loop() 
{ 
  if (millis()-lastLEDupdate>=STEPDURATION)
  {
     lastLEDupdate+=STEPDURATION;
     stepTime++;
     setLEDcolors(stepTime);
  }
}

Thanks Jurs!

I think I understand that, I'll return home this evening and tinker with this code, Essentially i'm setting a few LEDs and "stepping" those set LEDs along the strip.

Thanks for your reply, I'll have a go at it and come back if in stuck. Cheers!

kainevfx:
I think I understand that, I’ll return home this evening and tinker with this code, Essentially i’m setting a few LEDs and “stepping” those set LEDs along the strip.

Yes. Perhaps with three chasing LEDs like that:

void setLEDcolors(unsigned long time)
{
  memset(leds,0,sizeof(leds));
  int led1=(time%NUM_LEDS);
  leds[led1]=CRGB(255,0,0); 
  int led2=((time+1)%NUM_LEDS);
  leds[led2]=CRGB(0,255,0); 
  int led3=((time+2)%NUM_LEDS);
  leds[led3]=CRGB(0,0,255); 
  FastLED.show();
}


#define STEPDURATION 100
unsigned long stepTime;
unsigned long lastLEDupdate;

void loop() 
{ 
  if (millis()-lastLEDupdate>=STEPDURATION)
  {
    lastLEDupdate+=STEPDURATION;
    stepTime++;
    setLEDcolors(stepTime);
  }
}

Or as you like.

Back again and need some help if anyone would be so kind,
(As previously mentioned, My electronics and coding knowledge are virtually zilch)

WHERE I’M AT:

I have a strip of 124 LEDS on pin 2 (this goes to the LED strip data wire)
I have a momentary switch on pin 4 which either reads HIGH or LOW.
(Pretty sure when it is held down it reads HIGH)

and I have two LED PATTERNS/states…

FIRST PATTERN: about 20 red leds in a row chasing along the strip indefinetly.
SECOND PATTERN: Single white LED chasing along the strip indefinetly.

when turned on, the led strip is in its first pattern (good), and when i HOLD down the button is stays in its second pattern. (good)

WHAT I NEED HELP WITH:

I need the first state to light all the leds up white by default (255,255,255) (This is the resting state) without having to manually write every single led. (Anyone know a nice way of setting all the leds to the same value in a short piece of code?)

then when the button is pushed i need the second pattern to run for a while before it goes back to its first state automatically. the button isn’t intended to be held down. its simply supposed to be hit… the leds chase for a while (lets say 10 seconds) then the leds go back to being white.

Please if anyone can help me, I would be eternally grateful. I’ve been trying to get it to work all day… It’s s giving me a headache and i’m supposed to have it finished to show my superiors tomorrow.

I’m gonna need to be walked through this like a toddler guys, as i’m simply not understanding the code very well.

Much appreciate, KVR, code below.

#include "FastLED.h"
// How many leds are in the strip?
#define NUM_LEDS 124
// Data pin that led data will be written out over
#define DATA_PIN 2
// Clock pin only needed for SPI based chipsets when not using hardware SPI
#define CLOCK_PIN 3
// This is an array of leds.  One item for each led in your strip.
CRGB leds[NUM_LEDS];

const int buttonPin = 4;     // the number of the pushbutton pin
const int ledPin =  2;      // the number of the LED pin

// variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

// This function sets up the leds and tells the controller about them
void setup() {
	// sanity check delay - allows reprogramming if accidently blowing power w/leds
   	delay(2000);
      FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);    
   Serial.begin(9600);
}

//SETS STEP TIMING
#define STEPDURATION 10
unsigned long stepTime;
unsigned long lastLEDupdate;

//SETTING FIRST PATTERN
void setLEDcolors(unsigned long time)
{
  memset(leds,0,sizeof(leds));
  int led1=((time)%NUM_LEDS);
  leds[led1]=CRGB(25,0,0); 
  int led2=((time+1)%NUM_LEDS);
  leds[led2]=CRGB(50,0,0); 
  int led3=((time+2)%NUM_LEDS);
  leds[led3]=CRGB(75,0,0); 
   int led4=((time+3)%NUM_LEDS);
  leds[led4]=CRGB(100,0,0); 
  int led5=((time+4)%NUM_LEDS);
  leds[led5]=CRGB(125,0,0); 
  int led6=((time+5)%NUM_LEDS);
  leds[led6]=CRGB(150,0,0); 
    int led7=((time+6)%NUM_LEDS);
  leds[led7]=CRGB(175,0,0); 
  int led8=((time+7)%NUM_LEDS);
  leds[led8]=CRGB(200,0,0); 
  int led9=((time+8)%NUM_LEDS);
  leds[led9]=CRGB(225,0,0); 
   int led10=((time+9)%NUM_LEDS);
  leds[led10]=CRGB(255,0,0); 
  int led11=((time+10)%NUM_LEDS);
  leds[led11]=CRGB(225,0,0); 
  int led12=((time+11)%NUM_LEDS);
  leds[led12]=CRGB(200,0,0); 
   int led13=((time+12)%NUM_LEDS);
  leds[led13]=CRGB(175,0,0); 
   int led14=((time+13)%NUM_LEDS);
  leds[led14]=CRGB(150,0,0); 
   int led15=((time+14)%NUM_LEDS);
  leds[led15]=CRGB(125,0,0); 
   int led16=((time+15)%NUM_LEDS);
  leds[led16]=CRGB(100,0,0); 
   int led17=((time+16)%NUM_LEDS);
  leds[led17]=CRGB(75,0,0); 
   int led18=((time+17)%NUM_LEDS);
  leds[led18]=CRGB(50,0,0); 
   int led19=((time+18)%NUM_LEDS);
  leds[led19]=CRGB(25,0,0); 
   int led20=((time+19)%NUM_LEDS);
  FastLED.show();
}

//SETTING SECOND PATTERN
void setLEDcolors2(unsigned long time)
{
  memset(leds,0,sizeof(leds));
  int led1=(time%NUM_LEDS);
  leds[led1]=CRGB(255,255,255); 
  FastLED.show();
}

void loop() 
{ 
   // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    { 
  if (millis()-lastLEDupdate>=10)
  {
    lastLEDupdate+=STEPDURATION;
    stepTime++;
    setLEDcolors(stepTime);
  }
} 
  }
  else {
    if (millis()-lastLEDupdate>=10)
      {
    lastLEDupdate+=STEPDURATION;
    stepTime++;
    setLEDcolors2(stepTime);
  }
 
  }
}

kainevfx:
WHAT I NEED HELP WITH:

I need the first state to light all the leds up white by default (255,255,255) (This is the resting state) without having to manually write every single led. (Anyone know a nice way of setting all the leds to the same value in a short piece of code?)

  for (int i=0;i<NUM_LEDS;i++)  leds[i]=CRGB(255,255,255); 
  FastLED.show();

kainevfx:
then when the button is pushed i need the second pattern to run for a while before it goes back to its first state automatically. the button isn’t intended to be held down. its simply supposed to be hit… the leds chase for a while (lets say 10 seconds) then the leds go back to being white.

I don’t see how you want to control three states:

  • all LEDs set to white
  • Pattern-1
  • Pattern-2
    including pattern-fallback actions by time with just one button. I didn’t understand from your writing how you want to manage that.
    What’s the button press logic for doing that?

Hey Jurs!

Thanks for helping again, your a saint.

Not 3 patterns just two states.

Initial state, all white leds. upon button being pressed... second state begins which is a red chaser.. return to first state after 10 secs.

and on and on like that... so essentially i want a continuously fully lit strip of white.. everytime i hit the button i want it to chase red for ten seconds before returning to white.

that make sense? I'm sure its simple to do but i think i'm really overcomplicating it.

kainevfx: Not 3 patterns just two states.

Initial state, all white leds. upon button being pressed... second state begins which is a red chaser.. return to first state after 10 secs.

and on and on like that... so essentially i want a continuously fully lit strip of white.. everytime i hit the button i want it to chase red for ten seconds before returning to white.

That's much clearer than what you wrote before. Should be easy.

What about your button hardware:

Pretty sure when it is held down it reads HIGH

So you are sure that the button reads HIGH while pressed. And what about the reading while the button is not pressed? LOW? For sure? All the time? Do you have a "pull-down resistor" connected to the button?

Yes indeed, Apologies, I have re-read my initial post and realised how overly-confusing it is haha.

Yeah pretty sure it reads HIGH when depressed (that would make sense as per my code anyway) Yeah i believe i'm using a 10k pull down resistor.

so theoretically the arudino always sees LOW unless the button is depressed (In which case it would read high for as long as my finger holds down the button)

Hope that explains fully!

Thanks again, i really cant explain how much pressure i've been under today trying to get this working.

Blue goes to pin 2 on the arduino
Brown is Gnd
Red is of course power.

in the attached images. also shows the resistor i’m using… PS: i’m only using that resistor because i’ve tried copying a schematic for a simple button, i dont entirelly understand why i’m using it or its purpose.

Although i do vaguely realize its keeping the reading LOW unless the button is pressed.

KVR

kainevfx:
Although i do vaguely realize its keeping the reading LOW unless the button is pressed.

OK, then perhaps something like that might work:

void setSameColor(byte r, byte g, byte b)
{
  for (int i=0;i<NUM_LEDS;i++)  leds[i]=CRGB(r,g,b); 
  FastLED.show();    
}

void setColorChase(unsigned long time)
{
  memset(leds,0,sizeof(leds));
  for (int i=0;i<20;i++) // 20 leds
    leds[(time+i)%NUM_LEDS]=CRGB(255,0,0);  // red?
  FastLED.show();
}


#define STEPDURATION 100
#define CHASEDURATION 10000
unsigned long stepTime;
unsigned long lastLEDupdate;
unsigned long lastButtonPress=-CHASEDURATION;

void loop() 
{ 
  // read button input and remember the time if the button was pressed
  if (millis()-lastButtonPress>=CHASEDURATION)
  {
    boolean pressed=digitalRead(buttonPin);
    if (pressed) lastButtonPress=millis();
  }
  
  // check if it is time to set new colors
  if (millis()-lastLEDupdate>=STEPDURATION)
  {
    lastLEDupdate+=STEPDURATION;
    stepTime++;
    if (millis()-lastButtonPress>=CHASEDURATION) // button press is long time ago
      setSameColor(127, 127, 127); // show same color (white with 'nearly full intensity')
    else  
      setColorChase(stepTime); // color chase
  }
}

You are a true savior. that is exactly what i needed!

Thank-you!

I think i've soaked up enough of your time, and I certainly don't wanna push my luck here.. but there's a very high liklihood i'll be asked if i can expand this circuit to include one more LED strip tomorrow.

If its simple, would you be able to help me with that too? I'll probably have to add a new led strip (on say pin5) will do exactly the same (except when the button is pushed it flashes on and off white instead of chases)

is this simple to add or am i pushing my luck? haha Thanks again, KVR

kainevfx:
If its simple, would you be able to help me with that too? I’ll probably have to add a new led strip (on say pin5) will do exactly the same (except when the button is pushed it flashes on and off white instead of chases)

is this simple to add or am i pushing my luck?

I have no idea. I never tested with more than one LED strip at a time.
And when I test some LEDs, I always test with WS2812 strips, I never had any WS2801 LEDs using a clock line.

But here you can read something about Using Multiple Controllers with the FastLED library.

no problemo, like i said.. your an absolute savior. pint on me if your every in london and want to redeem it"!

Hello,

100% new to Arduino. Have been a Pi user.

Can't figure out for the life of me how or where to connect a string of WS2801 Led lights to Arduino Uno. Can't find diagrams or anything.

Any help would be appreciated thank you!