arduino neopixel strip & painting

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
cafotenos
 
Posts: 9
Joined: Fri Mar 25, 2016 1:43 pm

arduino neopixel strip & painting

Post by cafotenos »

Hi! My project is using arduino & neopixel strips to illuminate & animate my paintings.I paint on silk fabric which is translucent. The painting is framed between 2 pieces of plexiglass. The neopixel strip runs along the perimeter of the plexiglass.
My knowledge is limited, but I've managed to use existing sketches on 2 previous paintings. I can play with values, make simple changes to suit.
For the current painting I'm using a sketch from this forum. Here's a link to the video:
https://youtu.be/JGHqbrPHJI0
Here's the code: /**

Code: Select all

     * Quick commented example of one way you could change LEDs down a NeoPixel strip
     * starting at any pixel on the strip (going outwords), where the next LED begins
     * fading on after the previous reaches 50%.
     *
     * @author SeiRruf MalaWolSki
     * @date Sept. 13, 2014
     * Free to use and distribute
     */

    #include <Adafruit_NeoPixel.h> // NeoPixel Library

    #define NeoPixel_Pin   6
    #define NeoPixels     140

    Adafruit_NeoPixel strip = Adafruit_NeoPixel ( NeoPixels, NeoPixel_Pin, NEO_GRB + NEO_KHZ800 );

    // Gamma correction improves appearance of midrange colors
  const uint8_t gamma[] PROGMEM = {
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
        0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,
        1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
        2,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
        5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9, 10,
        10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
        17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
        25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
        37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
       51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
       69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
       90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
       115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
       144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
       177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
       215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };



    void setup ()
    {
      strip.begin ();
      strip.show ();
      strip.setBrightness (220); // 0-255,  255== max brightness
      randomSeed ( analogRead(0) ); //ensure always random (optional)
     
      //trying to blend colors from daybreak to sunset
      //1st color purple

      fadeChaseFill (40, strip.Color (140, 0, 240), 0 );//purple
      //delay 1 second before starting next color
      delay ( 5 );
    }

    void loop ()
    {
      
      fadeChaseFill (43, strip.Color (120,0,200), strip.Color (0,0,0) );
      //delay ( 5 );//lt purple
      fadeChaseFill (49, strip.Color (100,20,180 ), strip.Color (120,0,200) );
      //delay ( 5 );//lt purple
       fadeChaseFill (56, strip.Color (13,100,220), strip.Color (100,0,180) );
      //delay ( 5 );
     
      //start at a random pixel, new color is blue, prevoius is green
       fadeChaseFill (63, strip.Color (160,84,120), strip.Color (13,78,241) );
       delay ( 5 );
      // light yellow
       
       fadeChaseFill (70, strip.Color (225,100,160), strip.Color (127,127,127) );
        delay ( 5 );
        //white
        fadeChaseFill (80, strip.Color (13,100,220), strip.Color (255,100,160) );
        delay(5); //lt blue gr
    
       fadeChaseFill (90, strip.Color (140,0,240), strip.Color (120,0,220 ));
       delay ( 5 );// lite purple
      
       fadeChaseFill (100, strip.Color (120,0,200  ), strip.Color ( 0,0,0 ) );
      //delay ( 1000 );
       fadeChaseFill (30, strip.Color (0,0,0), strip.Color (255,100,160) );
       delay ( 5 );
    }


    void fadeChaseFill ( uint8_t startPixel, uint32_t color, uint32_t pColor )
    {
      //for each pixel
      for ( uint8_t i=0; i<strip.numPixels()+2; i++ ) { //buffer added (+2 pixels)
       
        //level of color (up to 255, which is max brightness)
        for ( float level=127; level<255; level+=1 ) {

          //don't draw pixels if we're outside of our limit (with buffer pixel)
          if ( startPixel+i < strip.numPixels()+1 ) {
            //next pixel 0->127
            strip.setPixelColor ( startPixel+i,
              colorTween (
                opacity ( color, (level-127.0)/255.0 ),
                pColor,
                level-127.0
              )
            );
           
            //there is no previous pixel if we're starting at 0.
            if ( i != 0 ) {
              //last pixel 127->255
              strip.setPixelColor ( (startPixel-1+i),
                opacity ( color, level/255.0 )
              );
            }
          }
         
          //don't draw pixels if we're outside of our limit (with buffer pixel)
          if ( startPixel-i >= -1 ) {
            //next pixel 0->127
            strip.setPixelColor ( startPixel-i,
              colorTween (
                opacity ( color, (level-127.0)/255.0 ),
                pColor,
                level-127.0
              )
            );
           
            //last pixel 127->255
            if ( i != 0 ) {
              //last pixel 127->255
              strip.setPixelColor ( (startPixel+1-i),
                opacity ( color, level/255.0 )
              );
            }
          }
         
          strip.show ();
          delay ( 1 ); //CHANGE THIS TO SPEED UP/SLOW DOWN YOUR ANIMATION
        }
      }
    }


    /**
     * splitColor() - Receive a uint32_t value, and spread into bits.
     */
    uint8_t splitColor ( uint32_t c, char value )
    {
      /**
       * Quick code explanation:
       * 'x >> y' shifts the given var (x) over (y) bytes.
       * Since we're dealing with a 24byte color, in order red, green, blue,
       * Represented as 11111111 11111111 11111111 (assuming 255,255,255)
       * bit placement: 23-22-21-20-19-18-17-16, 15-14-13-12-11-10-9-8, 7-6-5-4-3-2-1-0
       * We want to take the first 16-23 bytes and call them red, and so on.
       * declaring the return value as uint8_t ensures we receive 0-255 expected value.
       */
      switch ( value ) {
        case 'r': return (uint8_t)(c >> 16);
        case 'g': return (uint8_t)(c >>  8);
        case 'b': return (uint8_t)(c >>  0);
        default:  return 0;
      }
    }


    //fade c1 over c2
    uint32_t colorTween ( uint32_t c1, uint32_t c2, float fadeRate )
    {
      //variables should never exceed one byte, so mark them as uint8_t.
      uint8_t r, g, b, r1, g1, b1, r2, g2, b2;
     
      //split our new color
      r1 = splitColor ( c1, 'r' );
      g1 = splitColor ( c1, 'g' );
      b1 = splitColor ( c1, 'b' );
     
      //split our old color
      r2 = splitColor ( c2, 'r' );
      g2 = splitColor ( c2, 'g' );
      b2 = splitColor ( c2, 'b' );
     
      //mix the color
      r = r1 + ((float)r2*(1-(fadeRate/127.0)));
      g = g1 + ((float)g2*(1-(fadeRate/127.0)));
      b = b1 + ((float)b2*(1-(fadeRate/127.0)));
     
      //assemble & send it on its way
      return (
        strip.Color ( r, g, b )
      );
    }


    // dim current given color. O can only range from 0.0 to 1.0
    uint32_t opacity ( uint32_t c, float o )
    { 
      /**
       * Quick code explanation:
       * To dim a color, you must split it's values individually. That's already done above.
       * Now we multiply each one by the value we want dimmed.
       * In this case, say 100%.  o =(100/100)=1. 255*1 = 255. Full brightness, yay!
       * How about 0%? o =(0/100)=0. 255*0 = 0. No brightness, aww..
       * How about 50%? o =(50/100)=0.50. 255*0.50=178. Only half on, woo!
       */
      return strip.Color (
        pgm_read_byte ( &gamma[int(splitColor(c,'r') * o)] ),
        pgm_read_byte ( &gamma[int(splitColor(c,'g') * 2)] ),
        pgm_read_byte ( &gamma[int(splitColor(c,'b') * o)] )
      );
      
    }
The video is time-lapsed.
2 things that I like about this sketch: 1)the sequence of lights can start at any point along the strip, and goes outward in both directions.
2) The neopixel colors are fantastic! Many possibilities using the 2 sets of colors.

In real time, the entire sketch takes about 8 minutes. Each sequence of lights takes about 41 seconds, & there's a delay of 33 seconds. I'm guessing that the delay is because the arduino has to get through a lot of code. So here's my question, is there a straightforward way, for me, of shortening the delay? Can you explain, perhaps, what part of the code are these dual colors dependent on? It'd like to use them again. Thank you
Last edited by adafruit_support_bill on Mon Feb 06, 2017 8:29 pm, edited 1 time in total.
Reason: please use [code] tags when posting code to the forums

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: arduino neopixel strip & painting

Post by adafruit_support_bill »

Your sketch uses a lot of floating point calculations. The Arduino has no floating point hardware, so this all has to be emulated in software - a very slow process. Many of your calculations could be converted to integer math with little or no loss of precision.

User avatar
cafotenos
 
Posts: 9
Joined: Fri Mar 25, 2016 1:43 pm

Re: arduino neopixel strip & painting

Post by cafotenos »

Thank you so much for your reply. You've given me a direction to follow.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”