Go Down

Topic: Mysterious Code Problem - WS2812B (Read 634 times) previous topic - next topic

NDalton23

Hi guys,

I have written a kind of lengthy process for a LED strip. My goal is for 1/3 of the LEDs to be RED, 1/3 YELLOW, and 1/3 ORANGE. And I want them to fade up and down, but out of sync with each other. I am mostly trying to adapt code I found from an example on this webpage to create the desired effect.

https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/

The problem that I am running into is that my lights will brightly flash once, then do nothing at all no matter how long I leave the program running. I am powering the lights and the arduino from 4 AA batteries run in series to get the 5-6 volts I need for the LED strip/Arduino

Here is what I have. There are some unnecessary parts (extra variables etc.) to make it easier to understand (imo).

Code: [Select]



#include <FastLED.h>

#define NUM_LEDS 60
#define DATA_PIN 6

const int delayVal = 5;

CRGB leds[NUM_LEDS];

void setup() {
  // put your setup code here, to run once:
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
 
  for(int j = 0; j < 57; j=j+3){ //Red
    leds[j].setRGB(255, 0, 0);
  }
  for(int j = 1; j< 57; j=j+3){ //Yellow
    leds[j].setRGB(255, 255, 0);
  }
  for(int j = 2; j < 57; j=j+3){ //Orange
    leds[j].setRGB(255, 125, 0);
  }
  FastLED.show();

 
  delay(delayVal);
}

void loop() {
  // put your main code here, to run repeatedly:
  standardLoop();

}

void setPixel(int Pixel, byte red, byte green, byte blue) {
  leds[Pixel].setRGB(red, green, blue);
}

void standardLoop(){
 
//  float rRed = 255;
//  float gRed = 0;
//  float bRed = 0;
//  //255, 0, 0 is MAX, Start at MAX
//  float rOrange = 1;
//  float gOrange = 1;
//  float bOrange = 1;
//  // 255, 125, 0 is MAX, Start at MIN
//  float rYellow = 125;
//  float gYellow = 125;
//  float bYellow = 1;
//  //255, 255, 0 is MAX, Start at HALF

  float rRed, gRed, bRed;
  float rOrange, gOrange, bOrange;
  float rYellow, gYellow, bYellow;

  for(int k = 1; k < 256; k++){
    rRed = (k/256.0) * rRed; //Dim the RED

    rOrange = ( (255-k) /256.0) * rOrange; //Brighten the ORANGE
    gOrange = ( ( (255-k)/2 ) /256.0) * gOrange;

    rYellow = ( (k/2)/256.0 ) * rYellow; //Keep the yellow at half the brightness of RED
    gYellow = ( (k/2)/256.0 ) * gYellow;
   
    for(int j = 0; j<57; j++){
      setPixel(j, rRed, gRed, bRed);
      setPixel(j+1, rYellow, gYellow, bYellow);
      setPixel(j+2, rOrange, gOrange, bOrange);
    }

    FastLED.show();
    delay(100);
  }
 
  for(int k = 255; k > 1; k=k-2){
    rRed = (k/256.0) * rRed; //Dim the RED

    rOrange = ( (255-k) /256.0) * rOrange; //Brighten the ORANGE
    gOrange = ( ( (255-k)/2 ) /256.0) * gOrange;

    rYellow = ( (k/2)/256.0 ) * rYellow; //Keep the yellow at half the brightness of RED
    gYellow = ( (k/2)/256.0 ) * gYellow;
   
    for(int j = 0; j<57; j++){
      setPixel(j, rRed, gRed, bRed);
      setPixel(j+1, rYellow, gYellow, bYellow);
      setPixel(j+2, rOrange, gOrange, bOrange);
    }
    FastLED.show();
    delay(100);
  }

}



ieee488

#1
Feb 09, 2018, 02:52 am Last Edit: Feb 09, 2018, 04:05 am by ieee488
Are you powering the strip and the Arduino from the batteries?
Tell me it ain't so!

That isn't going to cut it.

Grumpy_Mike

Yes their is a lot wrong,
For example in the setup function
Code: [Select]
for(int j = 0; j < 57; j=j+3){ //Red
    leds[j].setRGB(255, 0, 0);
  }
  for(int j = 1; j< 57; j=j+3){ //Yellow
    leds[j].setRGB(255, 255, 0);
  }
  for(int j = 2; j < 57; j=j+3){ //Orange
    leds[j].setRGB(255, 125, 0);
  }

Is a bit useless, that just over writes a great block of LEDs leaving just one led red one yellow and the rest blue.

In your main code, when ever the loop runs then all those variables are reset again and you never get anywhere.

Take a bit of sample code and modify it one small bit at a time, test to see it does what you expect with each small addition.

boolrules

What are the floats for?

(brightness_value / 2) is not half brightness. Your eyeball response is logarythmic.

Grumpy_Mike

You need to write your code as a state machine. Here is what one looks like:-
Code: [Select]

// Multiple patterns in a state machine format
// using the FastLED libiary
// by Mike Cook 2017

#include "FastLED.h"

// first set up the parameters to use in the pattern calling
unsigned long patternInterval [] = { 500, 40, 20, 200, 5 }; // how often each pattern updates
unsigned long lastUpdate [5] ;  // for millis() when last update occurred
boolean patternEnabled [] = {true,true,false,true,true}; // should the pattern be called at all
byte patternState[5]; // state machine variable for patterns - this initialises them to zero

// now set up the LEDs to use
#define NUM_LEDS 64
#define DATA_PIN 3
#define CLOCK_PIN 13


CRGB leds[NUM_LEDS];

// Constants for patterns
// for Fire2012
#define COOLING  20
#define SPARKING 50
#define COLOR_ORDER BGR

// now set up the array of pointers to each pattern
void (*patternPtrs[5])(int index,byte state); //the array of pattern pointers

void setup() {
  //initialises the array of pattern pointers
  patternPtrs[0] = blinkOne;
  patternPtrs[1] = cylon;
  patternPtrs[2] = fire;
  patternPtrs[3] = colorWipe;
  patternPtrs[4] = rainbowCycle;
  //initialises the FastLED driver you want
  //FastLED.addLeds<APA102,leds, NUM_LEDS); // 13 clock  and 11 data
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(leds, NUM_LEDS); // 13 clock  and 11 data
  FastLED.setBrightness(8);
}

void loop() {
  for(int i = 0; i<5; i++) { // go through all the patterns and see if it is time to call one
    if(patternEnabled[i] && millis() - lastUpdate[i] > patternInterval[i]){
      lastUpdate[i] = millis();
      callPatterns(i, patternState[i]);
    }
  }
}

void callPatterns(int index, byte state) {
  (*patternPtrs[index])(index,state); //calls the pattern at the index of `index` in the array
}

// These are the pattern functions written as a state machine
// this is the Blink program in FastLED's example folder
void blinkOne(int index,byte state) {
  if(state == 0){
    leds[3] = CRGB::Blue;
    FastLED.show();
    patternState[index] = 1; // move on the state machine for the next call
  }
  if(state == 1){
     leds[3] = CRGB::Black;
     FastLED.show();
     patternState[index] = 0;
   }
  }

// this is the Cylon program in FastLED's example folder
// we will use LEDs 8 to 15 to show this
void cylon(int index,byte state) {
  static int i = 8; // replaces the loop index
  if(state == 0){
    leds[i] = CRGB::Red;
    FastLED.show();
    patternState[index] = 1; // move on the state machine for the next call
  }
   if(state == 1){
    // now that we've shown the leds, reset the i'th led to black
    leds[i] = CRGB::Black;
    i++; // increment what was the loop variable
    if(i >= 16){ // we have finished one direction
     patternState[index] = 2;
     i--;
    }
    else {
    patternState[index] = 0;
    }
   }
   // Now go in the other direction only green
   if(state == 2){
     leds[i] = CRGB::Green;
    FastLED.show();
    patternState[index] = 3; // move on the state machine for the next call
   }
  if(state == 3){
    // now that we've shown the leds, reset the i'th led to black
    leds[i] = CRGB::Black;
    i--; // decrement what was the loop variable
    if(i < 8){ // we have finished the return, go back to the start
     patternState[index] = 0;
     i= 8; // ready to start again
    }
    else {
    patternState[index] = 2;
    }
    // note that this could be better implemented but it has been written like this to keep it close to the origional example
    // so you can see what changes have been made
  }
}

// this is the Fire2012 program in FastLED's example folder
void fire(int index,byte state) {
// using LEDs 16 to 32
// Array of temperature readings at each simulation cell
  const byte startLED = 16; // first LED in section
  const byte numLEDs = 16;
  static byte heat[numLEDs];

  random16_add_entropy( random());
  // Step 1.  Cool down every cell a little
    for( int i = 0; i < numLEDs; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }
 
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= numLEDs - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
   
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < numLEDs; j++) {
        leds[j+startLED] = HeatColor( heat[j]); // transfer heat array to LEDs
    }
    FastLED.show(); // display this frame
  }

//colorWipe  modified from Adafruit example to make it a state machine
// uses LEDs 32 to 40
void colorWipe(int index,byte state) {
  static int i =0; // used as state variable
  static byte firstLED = 32;
  static byte numLEDs = 8;
    leds[i+firstLED] = CRGB::Yellow;
    FastLED.show();
    i++;
  if(i >= numLEDs){
    i = 0;
    for(int j;j<numLEDs; j++) leds[j+firstLED] = CRGB::Black; // blank out strip
  }
}

 // rainbowCycle modified from Adafruit example to make it a state machine
 // uses LEDs 48 to 64
void rainbowCycle(int index,byte state) {
  static uint16_t j=0; // used as state variable
  static byte firstLED = 48;
  static byte numLEDs = 16;
    for(int i=0; i< numLEDs; i++) {
      leds[i+firstLED].setHSV( (((i * 256 / numLEDs) + j) & 255), 255, 255);
    }
    FastLED.show();
    j++;
    if(j >= 256*5) j=0;
}


NDalton23

Hi all, thanks for your attempts to help, but I managed to fix the problem on my own. The only problem was that I was assigning the RGB values as a function of themselves instead of as a function of the desired maximum values. So instead of saying

Code: [Select]


  for(int k = 1; k < 256; k++){
    rRed = (k/256.0) * rRed; //Dim the RED

    rOrange = ( (255-k) /256.0) * rOrange; //Brighten the ORANGE
    gOrange = ( ( (255-k)/2 ) /256.0) * gOrange;

    rYellow = ( (k/2)/256.0 ) * rYellow; //Keep the yellow at half the brightness of RED
    gYellow = ( (k/2)/256.0 ) * gYellow;
   
    for(int j = 0; j<57; j++){
      setPixel(j, rRed, gRed, bRed);
      setPixel(j+1, rYellow, gYellow, bYellow);
      setPixel(j+2, rOrange, gOrange, bOrange);
    }

    FastLED.show();
    delay(100);
  }


I just needed to change it to

Code: [Select]

  for(int k = 1; k < 256; k++){
    r1 = (k/256.0) * rRed; //Dim the RED

    r2 = ( (255-k) /256.0) * rOrange; //Brighten the ORANGE
    g2 = ( ( (255-k)/2 ) /256.0) * gOrange;

    r3 = ( (k/2)/256.0 ) * rYellow; //Keep the yellow at half the brightness of RED
    g3 = ( (k/2)/256.0 ) * gYellow;
   
    for(int j = 0; j<57; j++){
      setPixel(j, r1, gRed, bRed);
      setPixel(j+1, r2, g2, bYellow);
      setPixel(j+2, r3, g3, bOrange);
    }

    FastLED.show();
    delay(100);
  }


Its a subtle difference, but was causing all of my lights to go to Zero and not come back up. Of course, you have to declare r1, r2, g2, r3, and g3 as floats before running this chunk of code.

ieee488

Let's see how long your sketch runs before your 4 AA batteries runs out of juice.

Hi all, thanks for your attempts to help, but I managed to fix the problem on my own. The only problem was that I was assigning the RGB values as a function of themselves instead of as a function of the desired maximum values. So instead of saying

...

Its a subtle difference, but was causing all of my lights to go to Zero and not come back up. Of course, you have to declare r1, r2, g2, r3, and g3 as floats before running this chunk of code.
You don't need to tell us about the coding. I have a working sign with a 5m strip of WS2812B.


Go Up