Go Down

Topic: Random fade animation & coulour change (Read 3124 times) previous topic - next topic

twananas

Hi,

I am new to programming and I would really appreciate some help.
I'm a costume designer and I made a dress with optic fiber.

I have an Arduino Gemma chip with 4 Neopixels working, however I would like a different animation. The show is next week so I am very close to the deadline.

I would like the 4 LEDs to fade separate and random from each other and randomly change colour between 4 different set colours. It should kinda create a sparkle/twinkle effect in the dress.

Could someone help me please?

Colours:

RGB
100, 200, 255 Blue
255, 250, 170 Yellow
255, 170, 255 Pink
255, 255, 255 White

The idea but it needs to be a bit slower:
https://youtu.be/y10m-h4Fads?t=10s

Thank you!

Twan

PaulMurrayCbr

I'm not familiar with the neopixel library or the gemma.

Would it be any use to you to have some code that worked by calling a function named "setNeopixelColor(int n, int r, int g, int b)", and it's up to you to write that function so as to get the colours out to the neopixels?

To put it another way - you have an existing animation. Do you have code for that? It might be reasonably easy to hack it up to do what you want, even without having the hardware.
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

twananas

Hi,

Thanks for your reply.

I've got this on there at the moment:

void rgbFadeInAndOut(uint8_t red, uint8_t green, uint8_t blue, uint8_t wait) {
for(uint8_t b = 180; b <255; b++) {
for(uint8_t i=0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, red * b/255, green * b/255, blue * b/255);
}
strip.show();
delay(wait);
};
for(uint8_t b=255; b > 179; b--) {
for(uint8_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, red * b/255, green * b/255, blue * b/255);
}
strip.show();
delay(wait);
};
};


I changed the colour to a pink colour. But it just fades in and out simultaneous right now and stays the same colour.



I know this is a bit of code to set up the fav colours:

#include <Adafruit_NeoPixel.h>
 
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(6, 6, NEO_GRB + NEO_KHZ800);
Adafruit_LSM303 lsm;
 
// Here is where you can put in your favorite colors that will appear!
// just add new {nnn, nnn, nnn}, lines. They will be picked out randomly
//                                  R   G   B
uint8_t myFavoriteColors[][3] = {{200,   0, 200},   // purple
                                 {200,   0,   0},   // red
                                 {200, 200, 200},   // white
                               };
// don't edit the line below
#define FAVCOLORS sizeof(myFavoriteColors) / 3



And this is to call a colour I think but I really don't know enough about it:

void flashRandom(int wait, uint8_t howmany) {
 
  for(uint16_t i=0; i<howmany; i++) {
    // pick a random favorite color!
    int c = random(FAVCOLORS);
    int red = myFavoriteColors[c][0];
    int green = myFavoriteColors[c][1];
    int blue = myFavoriteColors[c][2];
 
    // get a random pixel from the list
    int j = random(strip.numPixels());
    //Serial.print("Lighting up "); Serial.println(j);
   
    // now we will 'fade' it in 5 steps
    for (int x=0; x < 5; x++) {
      int r = red * (x+1); r /= 5;
      int g = green * (x+1); g /= 5;
      int b = blue * (x+1); b /= 5;
     
      strip.setPixelColor(j, strip.Color(r, g, b));
      strip.show();
      delay(wait);
    }
    // & fade out in 5 steps
    for (int x=5; x >= 0; x--) {
      int r = red * x; r /= 5;
      int g = green * x; g /= 5;
      int b = blue * x; b /= 5;
     
      strip.setPixelColor(j, strip.Color(r, g, b));
      strip.show();
      delay(wait);
    }
  }
  // LEDs will be off when done (they are faded to 0)
}

Thanks

PaulMurrayCbr

Ok, man. I have done up a bit of a thing, FWIW. Haven't tested it or anything, but it does compile.

You will need to insert into this sketch your setup() for the neopixels, and you will want to replace the calls to my dummy function setPixelColor with calls to the actual strip.setPixelColor .

Source code is also on github at PaulMurrayCbr/arduino_topic_363073 .

If it works, Karma me! Or Karma me anyway, just for the example code :) .

Code: [Select]

// we want to randomly select from these colours

const int COLOURS[][3] = {
{100, 200, 255}, //Blue
{255, 250, 170}, //Yellow
{255, 170, 255}, //Pink
{255, 255, 255} //White
};

const int NCOLOURS = sizeof(COLOURS) / sizeof(*COLOURS);

// this structure holds the state of the given pixel

struct PixelState {
  // is the pixel currently on
  boolean on;
  // time at which the pixel was turned on or off
  unsigned long timeMarkMs;
  // amount of time for which the pixel should remain off
  unsigned long offTimeMs;
  // selected colout if the pixel is on
  int selectedColour;
  // most recent max brightness. We keep this to stop us
  // sending colour changes to the pixels if it is unnecessary
  // this is important, because neopixels use a timing-based protocol
  int mostRecentBrightness;
};

// we have 4 pixels

const int NPIXELS = 4;
struct PixelState pixel[NPIXELS];

// I want the pixels to sparkle, so I will use a triangle wave,
// which is to say that they will come on at full brightness and them fade

const unsigned long FADE_TIME_MS = 3000; // three seconds

// the pixels should come on at a random time, To simulate this,
// the pixel will be off for a random amount of time.

const int MIN_OFF_TIME_MS = 100;
const int MAX_OFF_TIME_MS = 250;

void setup() {
  for(int i = 0; i<NPIXELS;i++) {
    pixel[i].on = false;
    pixel[i].timeMarkMs = millis();
    pixel[i].offTimeMs = 0;
  }
}

// this is a dummy function. I put it here just to check that the code compiles.
// Replace calls to this function with your
// strip.setPixelColor function
void setPixelColor(int strip, int r, int g, int b) {
}

void loop() {
  for(int i = 0; i< NPIXELS; i++) {
    if(pixel[i].on) {
      // pixel is on
     
      if(millis() - pixel[i].timeMarkMs >= FADE_TIME_MS) {
        // time to turn the pixel off
        setPixelColor(i,0,0,0);
        pixel[i].timeMarkMs = millis();
        pixel[i].offTimeMs = random(MIN_OFF_TIME_MS, MAX_OFF_TIME_MS);
        pixel[i].mostRecentBrightness = 0;
        pixel[i].on = false;
      }
      else {
        // calculate the new brightness as flaoting point
        // this is the bit that you change if you want the fade pattern to change
        float brightness = 1 - (millis() - pixel[i].timeMarkMs)/((float)FADE_TIME_MS);
       
        // ok. do we actually need to change the pixel colour?
        int mostRecentBrightness = 255 * brightness;
        if(mostRecentBrightness != pixel[i].mostRecentBrightness) {
          // yes we do
          pixel[i].mostRecentBrightness = mostRecentBrightness;
          setPixelColor(i,
             (int)(COLOURS[pixel[i].selectedColour][0] * brightness),
             (int)(COLOURS[pixel[i].selectedColour][1] * brightness),
             (int)(COLOURS[pixel[i].selectedColour][2] * brightness)
          );
        }
      }
    }
    else {
      // pixel is off. do we need to turn it on?
     
      if(millis()-pixel[i].timeMarkMs > pixel[i].offTimeMs) {
        pixel[i].on = true;
        pixel[i].mostRecentBrightness = 0; // this will force an update next loop
        pixel[i].selectedColour = random(NCOLOURS);
      }
    }
  }
}


http://paulmurraycbr.github.io/ArduinoTheOOWay.html

twananas

Thank you! I will test it when I get home :)
I wish I could test it here at work so I can just work on finishing costumes at home :(

I was playing around with code on a sim and it didn't give any errors, but I doubt it actually works LOL


I will let you know and thank you from the bottom of my heart. This whole costume making took 20 years off my life! :O

PaulMurrayCbr

Thank you! I will test it when I get home :)
Points to note:

The LEDs will all start when the board is powered up, and will gradually move out of sync and random. Fixing it so that they *start* out of sync and random from the get-go is pretty easy.

You can alter the timings by fiddling with the constants.
FADE_TIME_MS
MIN_OFF_TIME_MS
MAX_OFF_TIME_MS

Maybe it would look better if they were on for a short time compared to the off time. If you want a different pattern for the brightness - ramping up to full brighness instaead of comming on suddenly or something, that's doable too. One thing that might be very worthwhile is taking the square of the brightness like so:

Code: [Select]

  float brightness = 1 - (millis() - pixel[i].timeMarkMs)/((float)FADE_TIME_MS);
  brightness =  brightness * brightness;


Taking the square effectively does a gamma correction of 2.

Oh, and altering the colours is just a matter of fiddling with the initializer of the COLOURS array. If you add more blocks, the code will just pick them up.



http://paulmurraycbr.github.io/ArduinoTheOOWay.html

twananas

I'll switch the whole thing on a few minutes before she goes on stage, so it should be fine I guess. Otherwise I will try what you suggested :)


I tried replacing the strip.setpixelcolor and then an error comes up?

(sketch file) Blink.ino:66:6: error: variable has incomplete type 'void'
void strip.setPixelColor(int strip, int r, int g, int b) {
     ^
(sketch file) Blink.ino:66:11: error: expected ';' after top level declarator
void strip.setPixelColor(int strip, int r, int g, int b) {
          ^
          ;
2 errors generated.

twananas

So I tried this. I probably have to change more than I know. As this has no errors but it's not working:

Code: [Select]

#include <Adafruit_NeoPixel.h>

#define PIN 1

// 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(4, PIN, NEO_GRB + NEO_KHZ800);

// we want to randomly select from these colours

const int COLOURS[][3] = {
  {100, 200, 255}, //Blue
  {255, 250, 170}, //Yellow
  {255, 170, 255}, //Pink
  {255, 255, 255} //White
};

const int NCOLOURS = sizeof(COLOURS) / sizeof(*COLOURS);

// this structure holds the state of the given pixel

struct PixelState {
  // is the pixel currently on
  boolean on;
  // time at which the pixel was turned on or off
  unsigned long timeMarkMs;
  // amount of time for which the pixel should remain off
  unsigned long offTimeMs;
  // selected colout if the pixel is on
  int selectedColour;
  // most recent max brightness. We keep this to stop us
  // sending colour changes to the pixels if it is unnecessary
  // this is important, because neopixels use a timing-based protocol
  int mostRecentBrightness;
};

// we have 4 pixels

const int NPIXELS = 4;
struct PixelState pixel[NPIXELS];

// I want the pixels to sparkle, so I will use a triangle wave,
// which is to say that they will come on at full brightness and them fade

const unsigned long FADE_TIME_MS = 3000; // three seconds

// the pixels should come on at a random time, To simulate this,
// the pixel will be off for a random amount of time.

const int MIN_OFF_TIME_MS = 100;
const int MAX_OFF_TIME_MS = 250;

void setup() {
  for (int i = 0; i < NPIXELS; i++) {
    pixel[i].on = false;
    pixel[i].timeMarkMs = millis();
    pixel[i].offTimeMs = 0;

  }
}

// this is a dummy function. I put it here just to check that the code compiles.
// Replace calls to this function with your
// strip.setPixelColor function
void colorWipe(int strip, int r, int g, int b) {
}

void loop() {
  for (int i = 0; i < NPIXELS; i++) {
    if (pixel[i].on) {
      // pixel is on

      if (millis() - pixel[i].timeMarkMs >= FADE_TIME_MS) {
        // time to turn the pixel off
        strip.setPixelColor(i, 0, 0, 0);
        pixel[i].timeMarkMs = millis();
        pixel[i].offTimeMs = random(MIN_OFF_TIME_MS, MAX_OFF_TIME_MS);
        pixel[i].mostRecentBrightness = 0;
        pixel[i].on = false;
      }
      else {
        // calculate the new brightness as flaoting point
        // this is the bit that you change if you want the fade pattern to change
        float brightness = 1 - (millis() - pixel[i].timeMarkMs) / ((float)FADE_TIME_MS);

        // ok. do we actually need to change the pixel colour?
        int mostRecentBrightness = 255 * brightness;
        if (mostRecentBrightness != pixel[i].mostRecentBrightness) {
          // yes we do
          pixel[i].mostRecentBrightness = mostRecentBrightness;
          strip.setPixelColor(i,
                        (int)(COLOURS[pixel[i].selectedColour][0] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][1] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][2] * brightness)
                       );
        }
      }
    }
    else {
      // pixel is off. do we need to turn it on?

      if (millis() - pixel[i].timeMarkMs > pixel[i].offTimeMs) {
        pixel[i].on = true;
        pixel[i].mostRecentBrightness = 0; // this will force an update next loop
        pixel[i].selectedColour = random(NCOLOURS);
      }
    }
  }
}



Sorry I just don't know enough to work it out :(

PaulMurrayCbr

Sorry I just don't know enough to work it out :(
I'll have a look when I get home. Unfortunately, my windowbox has  fallen down, *and* I'm playing Guild Ball for the first time tonight. So much to do!

The first thing I do will be to get some serial output from the sketch. I'll temporarily comment out the call to strip.setPixel (because I don't have the hardware), put in Serial.begin, and do a print in the spot where it tries to set the pixel.

If I get a whole bunch of pixel setting output scrolling past, then I'll be asking you for an *entire* sketch that actually does set the pixels (even though it might not be setting them in the pattern you want). I'll be looking at that "wait" parameter. How important is it?

If I don't get a whole bunch of pixel setting output scrolling past, then I'll be fixing my code :) .
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

PaulMurrayCbr

#9
Dec 03, 2015, 12:59 pm Last Edit: Dec 03, 2015, 01:00 pm by PaulMurrayCbr
Gaaah! Found the error.

After this line
Code: [Select]

        pixel[i].selectedColour = random(NCOLOURS);

We need a
Code: [Select]

        pixel[i].timeMarkMs = millis();


Try this:

Code: [Select]


#include <Adafruit_NeoPixel.h>

#define PIN 1

// 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(4, PIN, NEO_GRB + NEO_KHZ800);

// we want to randomly select from these colours

const int COLOURS[][3] = {
  {100, 200, 255}, //Blue
  {255, 250, 170}, //Yellow
  {255, 170, 255}, //Pink
  {255, 255, 255} //White
};

const int NCOLOURS = sizeof(COLOURS) / sizeof(*COLOURS);

// this structure holds the state of the given pixel

struct PixelState {
  // is the pixel currently on
  boolean on;
  // time at which the pixel was turned on or off
  unsigned long timeMarkMs;
  // amount of time for which the pixel should remain off
  unsigned long offTimeMs;
  // selected colout if the pixel is on
  int selectedColour;
  // most recent max brightness. We keep this to stop us
  // sending colour changes to the pixels if it is unnecessary
  // this is important, because neopixels use a timing-based protocol
  int mostRecentBrightness;
};

// we have 4 pixels

const int NPIXELS = 4;
struct PixelState pixel[NPIXELS];

// I want the pixels to sparkle, so I will use a triangle wave,
// which is to say that they will come on at full brightness and them fade

const int FADE_TIME_MS = 3000;

// the pixels should come on at a random time, To simulate this,
// the pixel will be off for a random amount of time.

const int MIN_OFF_TIME_MS = 500;
const int MAX_OFF_TIME_MS = 1500;

void setup() {
  for (int i = 0; i < NPIXELS; i++) {
    pixel[i].on = false;
    pixel[i].timeMarkMs = millis();
    pixel[i].offTimeMs = 0;
  }
}

void loop() {
  for (int i = 0; i < NPIXELS; i++) {
    if (pixel[i].on) {
      // pixel is on

      if (millis() - pixel[i].timeMarkMs >= FADE_TIME_MS) {
        // time to turn the pixel off
        strip.setPixelColor(i, 0, 0, 0);
        pixel[i].timeMarkMs = millis();
        pixel[i].offTimeMs = random(MIN_OFF_TIME_MS, MAX_OFF_TIME_MS);
        Serial.print("off time");
        Serial.print( pixel[i].offTimeMs);
        Serial.println();
        pixel[i].mostRecentBrightness = 0;
        pixel[i].on = false;
      }
      else {
        // calculate the new brightness as flaoting point
        // this is the bit that you change if you want the fade pattern to change
        float brightness = 1 - (millis() - pixel[i].timeMarkMs) / ((float)FADE_TIME_MS);
        brightness = brightness * brightness; //gamma correction

        // ok. do we actually need to change the pixel colour?
        int mostRecentBrightness = 255 * brightness;
        if (mostRecentBrightness != pixel[i].mostRecentBrightness) {
          // yes we do
          pixel[i].mostRecentBrightness = mostRecentBrightness;
          strip.setPixelColor(i,
                        (int)(COLOURS[pixel[i].selectedColour][0] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][1] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][2] * brightness)
                       );
        }
      }
    }
    else {
      // pixel is off. do we need to turn it on?

      if (millis() - pixel[i].timeMarkMs > pixel[i].offTimeMs) {
        pixel[i].on = true;
        pixel[i].mostRecentBrightness = 0; // this will force an update next loop
        pixel[i].selectedColour = random(NCOLOURS);
        pixel[i].timeMarkMs = millis();
        strip.setPixelColor(i,
                      COLOURS[pixel[i].selectedColour][0],
                      COLOURS[pixel[i].selectedColour][1],
                      COLOURS[pixel[i].selectedColour][2]
                     );
      }
    }
  }
}
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

twananas

LOL Thanks! I was just about to post what I think it should be including from the things you told me. I have looked at other codes and it seems to work on codebender.cc but that was the same yesterday and in Arduino it didn't work. But I shall see when I get home again :D

Code: [Select]

#include <Adafruit_NeoPixel.h>

#define PIN 1

// 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(4, PIN, NEO_GRB + NEO_KHZ800);

// we want to randomly select from these colours

const int COLOURS[][3] = {
  {100, 200, 255}, //Blue
  {255, 250, 170}, //Yellow
  {255, 170, 255}, //Pink
  {255, 255, 255} //White
};

const int NCOLOURS = sizeof(COLOURS) / sizeof(*COLOURS);

// this structure holds the state of the given pixel

struct PixelState {
  // is the pixel currently on
  boolean on;
  // time at which the pixel was turned on or off
  unsigned long timeMarkMs;
  // amount of time for which the pixel should remain off
  unsigned long offTimeMs;
  // selected colout if the pixel is on
  int selectedColour;
  // most recent max brightness. We keep this to stop us
  // sending colour changes to the pixels if it is unnecessary
  // this is important, because neopixels use a timing-based protocol
  int mostRecentBrightness;
};

// we have 4 pixels

const int NPIXELS = 4;
struct PixelState pixel[NPIXELS];

// I want the pixels to sparkle, so I will use a triangle wave,
// which is to say that they will come on at full brightness and them fade

const unsigned long FADE_TIME_MS = 3000; // three seconds

// the pixels should come on at a random time, To simulate this,
// the pixel will be off for a random amount of time.

const int MIN_OFF_TIME_MS = 100;
const int MAX_OFF_TIME_MS = 250;

void setup() {
  for (int i = 0; i < NPIXELS; i++) {
    pixel[i].on = false;
    pixel[i].timeMarkMs = millis();
    pixel[i].offTimeMs = 0;
  strip.begin();                   // Allocate NeoPixel buffer
  strip.clear();                   // Make sure strip is clear
  strip.show(); 
  }
}

// this is a dummy function. I put it here just to check that the code compiles.
// Replace calls to this function with your
// strip.setPixelColor function
void colorWipe(int strip, int r, int g, int b) {
}

void loop() {
  for (int i = 0; i < NPIXELS; i++) {
    if (pixel[i].on) {
      // pixel is on

      if (millis() - pixel[i].timeMarkMs >= FADE_TIME_MS) {
        // time to turn the pixel off
        strip.setPixelColor(i, 0, 0, 0);
        pixel[i].timeMarkMs = millis();
        pixel[i].offTimeMs = random(MIN_OFF_TIME_MS, MAX_OFF_TIME_MS);
        pixel[i].mostRecentBrightness = 0;
        pixel[i].on = false;
      }
      else {
        // calculate the new brightness as flaoting point
        // this is the bit that you change if you want the fade pattern to change
        float brightness = 1 - (millis() - pixel[i].timeMarkMs) / ((float)FADE_TIME_MS);
 
   //Serial.print("Lighting up "); Serial.println(j);
   
        // ok. do we actually need to change the pixel colour?
        int mostRecentBrightness = 255 * brightness;
        if (mostRecentBrightness != pixel[i].mostRecentBrightness) {
          // yes we do
          pixel[i].mostRecentBrightness = mostRecentBrightness;
          strip.setPixelColor(i,
                        (int)(COLOURS[pixel[i].selectedColour][0] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][1] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][2] * brightness)
                       );
      strip.show();
      }
      }
    }
    else {
      // pixel is off. do we need to turn it on?

      if (millis() - pixel[i].timeMarkMs > pixel[i].offTimeMs) {
        pixel[i].on = true;
        pixel[i].mostRecentBrightness = 0; // this will force an update next loop
        pixel[i].selectedColour = random(NCOLOURS);
        pixel[i].timeMarkMs = millis();
       
      strip.show();


      }
    }
  }
}

twananas

#11
Dec 03, 2015, 08:45 pm Last Edit: Dec 03, 2015, 09:06 pm by twananas
Oh great it works now! Thank you so much!!!
The only thing I would like is for them not to switch off completely but stay at 50 brightness minimum. I couldn't find out how that works.

This is what it does right now. It fades out but then comes back on right away too

https://www.youtube.com/watch?v=xEFJSArOBzw&feature=em-upload_owner

PaulMurrayCbr

#12
Dec 04, 2015, 07:15 am Last Edit: Dec 04, 2015, 07:34 am by PaulMurrayCbr
Well, to alter the timing, fiddle with the values

Code: [Select]

const int MIN_OFF_TIME_MS = 100;
const int MAX_OFF_TIME_MS = 250;
const int FADE_TIME_MS = 3000;


They are in milliseconds. Try it with

Code: [Select]
const int MIN_OFF_TIME_MS = 500;
const int MAX_OFF_TIME_MS = 2000;
const int FADE_TIME_MS = 250;


To have a minimum brightness, easiest way is to express it as an amount between 0 and 1 rather than as a number between 0 and 255.

Code: [Select]
const float MIN_BRIGHTNESS = 50.0/255.0;

Change this
Code: [Select]
strip.setPixelColor(i, 0, 0, 0);
       
To this
Code: [Select]
strip.setPixelColor(i,
  (int)(255*MIN_BRIGHTNESS),
  (int)(255*MIN_BRIGHTNESS),
  (int)(255*MIN_BRIGHTNESS));


And after this line
Code: [Select]
float brightness = 1 - (millis() - pixel[i].timeMarkMs) / ((float)FADE_TIME_MS);
 
add
Code: [Select]
brighness = MIN_BRIGHTNESS + brightness / (1-MIN_BRIGHTNESS);


If you would prefer that the LEDs get brighter and dimmer rather than come on suddenly and then fade, after this line
Code: [Select]
float brightness = 1 - (millis() - pixel[i].timeMarkMs) / ((float)FADE_TIME_MS);

add
Code: [Select]
brightness = Math.sin(brightness * Math.PI);
to alter the contour.
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

twananas

#13
Dec 04, 2015, 08:40 am Last Edit: Dec 04, 2015, 12:00 pm by twananas
Even though included the math.h I get this error:











Fairy_fabulous.ino: In function 'void loop()':
Fairy_fabulous:99: error: 'Math' was not declared in this scope
In file included from /Users/Twan/Documents/Arduino/libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.h:23:0,
                 from Fairy_fabulous.ino:2:
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Arduino.h:47:12: error: expected unqualified-id before numeric constant
 #define PI 3.1415926535897932384626433832795
            ^
Fairy_fabulous.ino:99:49: note: in expansion of macro 'PI'
'Math' was not declared in this scope

Code: [Select]



#include <Adafruit_NeoPixel.h>
#include <math.h>

#define PIN 1

// 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(4, PIN, NEO_GRB + NEO_KHZ800);

// we want to randomly select from these colours

const int COLOURS[][3] = {
  {100, 200, 255}, //Blue
  {255, 250, 170}, //Yellow
  {255, 170, 255}, //Pink
  {255, 255, 255} //White
};

const int NCOLOURS = sizeof(COLOURS) / sizeof(*COLOURS);

// this structure holds the state of the given pixel

struct PixelState {
  // is the pixel currently on
  boolean on;
  // time at which the pixel was turned on or off
  unsigned long timeMarkMs;
  // amount of time for which the pixel should remain off
  unsigned long offTimeMs;
  // selected colout if the pixel is on
  int selectedColour;
  // most recent max brightness. We keep this to stop us
  // sending colour changes to the pixels if it is unnecessary
  // this is important, because neopixels use a timing-based protocol
  int mostRecentBrightness;
};

// we have 4 pixels

const int NPIXELS = 4;
struct PixelState pixel[NPIXELS];

// I want the pixels to sparkle, so I will use a triangle wave,
// which is to say that they will come on at full brightness and them fade

const unsigned long FADE_TIME_MS = 2000; // three seconds

// the pixels should come on at a random time, To simulate this,
// the pixel will be off for a random amount of time.

const int MIN_OFF_TIME_MS = 500;
const int MAX_OFF_TIME_MS = 250;
const float MIN_BRIGHTNESS = 50.0/255.0;

void setup() {
  for (int i = 0; i < NPIXELS; i++) {
    pixel[i].on = false;
    pixel[i].timeMarkMs = millis();
    pixel[i].offTimeMs = 0;
  strip.begin();                   // Allocate NeoPixel buffer
  strip.clear();                   // Make sure strip is clear
  strip.show(); 
  }
}

// this is a dummy function. I put it here just to check that the code compiles.
// Replace calls to this function with your
// strip.setPixelColor function
void colorWipe(int strip, int r, int g, int b) {
}

void loop() {
  for (int i = 0; i < NPIXELS; i++) {
    if (pixel[i].on) {
      // pixel is on

      if (millis() - pixel[i].timeMarkMs >= FADE_TIME_MS) {
        // time to turn the pixel off
        strip.setPixelColor(i,
  (int)(255*MIN_BRIGHTNESS),
  (int)(255*MIN_BRIGHTNESS),
  (int)(255*MIN_BRIGHTNESS));
        pixel[i].timeMarkMs = millis();
        pixel[i].offTimeMs = random(MIN_OFF_TIME_MS, MAX_OFF_TIME_MS);
        pixel[i].mostRecentBrightness = 0;
        pixel[i].on = false;
        strip.show();
      }
      else {
        // calculate the new brightness as flaoting point
        // this is the bit that you change if you want the fade pattern to change
        float brightness = 1 - (millis() - pixel[i].timeMarkMs) / ((float)FADE_TIME_MS);
        brightness = Math.sin(brightness * Math.PI);
 
   //Serial.print("Lighting up "); Serial.println(j);
   
        // ok. do we actually need to change the pixel colour?
        int mostRecentBrightness = 255 * brightness;
        if (mostRecentBrightness != pixel[i].mostRecentBrightness) {
          // yes we do
          pixel[i].mostRecentBrightness = mostRecentBrightness;
          strip.setPixelColor(i,
                        (int)(COLOURS[pixel[i].selectedColour][0] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][1] * brightness),
                        (int)(COLOURS[pixel[i].selectedColour][2] * brightness)
                       );
      strip.show();
      }
      }
    }
    else {
      // pixel is off. do we need to turn it on?

      if (millis() - pixel[i].timeMarkMs > pixel[i].offTimeMs) {
        pixel[i].on = true;
        pixel[i].mostRecentBrightness = 0; // this will force an update next loop
        pixel[i].selectedColour = random(NCOLOURS);
        pixel[i].timeMarkMs = millis();
       
      strip.show();


      }
    }
  }
}

PaulMurrayCbr

#14
Dec 05, 2015, 03:24 am Last Edit: Dec 05, 2015, 03:29 am by PaulMurrayCbr
Even though included the math.h I get this error:
Mate, there's a line between "I honestly can't do this" and "I'm not prepared to make any effort". I'm ok about the algorithm, the problem of making lights change with independent timing, I get that that's hard, but correctly calling the "take the sine of a number" function (I wrote the code at work) is a slightly different kettle of fish. We haven't agreed on any money, so I am going to leave it to you to work out how to call sin(). Or you can just leave the code as it was and go with the "on full and fade".
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

Go Up