Go Down

Topic: Smooth animation with an 8x8 RGB LED matrix (Read 31572 times) previous topic - next topic

giladaya

Below are several videos that demonstrate smooth animations running on an 8x8 RGB LED matrix.

The main factors that contribute to the effect:

  • Use of a diffuser screen, placed at just the right distance from the LEDs.
    I used a tracing paper for the screen - it is opaque enough so the pixels blend, but not too much so some contrast remains.
    The physical setup can be seen in the attached images.

  • The calculations that produce the animation are done using a larger number of "virtual pixels" than the ones actually available. These are then rendered onto the low-res matrix.

  • The frame rate is high enough to create the illusion of smooth motion




Examples:
Fire simulation
The logic here is pretty simple.
For each keyframe, a new row of pixels with random brightness values is generated.
In each sub-frame, the matrix is gradually shifted up, interpolating between full rows.
The calculated "raw" brightness is faded according to a fixed mask, to give the flame a shape.
The hue of each pixel is taken from a constant mask, so the inner area of the fire is yellow and the outer area deep red.
The code for this example is available on github.
http://www.youtube.com/watch?v=AspZ8Np3_Bo

Particle systems
These next examples use the same hardware setup, but the animation is generated using a particle system library that I posted about yesterday.
http://www.youtube.com/watch?v=dpA7wznAwgc

http://www.youtube.com/watch?v=w89Qrq5i1SE

http://www.youtube.com/watch?v=9r_VlEYINW4


Enjoy

fungus

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

JoeN

Holy cow that is really well done.  Where did you get that diffuser screen?  I don't know a lot about them but I have tried diffusing with thin white cloth and paper and never got a good result.

Care to share any code or schematics?
I have only come here seeking knowledge. Things they would not teach me of in college.

giladaya

Thanks, sure :)

The diffuser screen is made of a sheet of tracing paper, attached to a frame made of foam core - see attached image.
Standard paper is too white and opaque which results in really low contrast and the light hardly getting through.
Note that the distance of the screen from the LED matrix is really important and will be different depending on the specific material used.

The circuit itself is just an off-the-shelf Colorduino - I believe that a Rainbowduino would work just as well.

The code for all the examples (library and sketches) is available on github.



Riva


The circuit itself is just an off-the-shelf Colorduino - I believe that a Rainbowduino would work just as well.

Hi giladaya,
I can confirm the code works on Rainbowduino with very little modification. Fantastic work.

Trib

Hello giladaya,

this really looks great. I was searching for some nice Matrix Animations and started a thread, which was not very succesful
LED Matrix - animation pattern.
I´ll try to port your code to my matrix and go on collecting some nice effects :)

Some time ago I wrote a .NET program which can demonstrate matix animations on a PC. Maybe I´ll release it to make it easier to create some new effects.

Greetings
Thomas

Helmuth

#6
Mar 02, 2013, 03:46 pm Last Edit: Mar 04, 2013, 12:47 pm by Helmuth Reason: 1
Respect, well done! Good presentation, too.

I can imagine, that it would look great on a huge indirect working matrix (so, that you just see the projection at a wall) with powerful LED strip elements...

edit, next day:

I have to test that with a serious output device...  ;)


jon_s

This looks great!

Once my 8x8 matrix arrives, I'd like to try to adapt it as an interactive nightlight, where new particles would be triggered if a PIR motion detector is triggered while ambient light is low. I was thinking I might be able to accomplish this by updating your "Flame.ino" example (https://github.com/giladaya/arduino-particle-sys/blob/master/examples/Flame/Flame.ino). In that example, some of the parameters for the particle system are established in Setup:
Code: [Select]
source.x = 112;  
source.y = 1;  
Emitter_Fountain::minLife = 20;  
Emitter_Fountain::maxLife = 80;  
Particle_Std::ay = 1;


I was thinking that I could add some lines to Loop that would adjust these continuously. For instance:
Code: [Select]
if (triggerPin == HIGH && ambientLight <= lightThreshold) {      //assuming these are all defined elsewhere...
  Particle_Std::ay = 1;
}
else { Particle_Std::ay = 0; }


I expect this would leave the particles at the bottom of the display most of the time, but then they'd shoot up when the PIR is triggered in the dark.
Any ideas or suggestions for a more elegant implementation, or smarter usage of the library? Thanks! I'm looking forward to experimenting with this.

mkl0815

@giladaya: Could it be, that you swapped columns and rows ( width and height) in you code?
I'm currently trying to port your "fire"-code to a WS2812 LED strip with 6 columns ( 6 pixel width) and 8 rows (8 pixel hight).

As I understand your code, the function "generateline()" creates a new pixel-line on the bottom line of the matrix. But your code says:
Code: [Select]

/**
* Randomly generate the next line (matrix row)
*/
void generateLine(){
  for(unsigned char x=0;x<ColorduinoScreenHeight;x++) {
      line[x] = random(64, 255);
  }
}

So you are using "x" for the position of the "cursor" on the line, but you use the ColorduinoScreenHeight as upper border.
This is not a problem, as long as you use this nomenclature consistently and yout matrix has exactly the same number of rows and columns.
Problems start if the number of columns and rows differ.
Another point is the declaration of the mask-Arrays (valueMask[ColorduinoScreenWidth][ColorduinoScreenHeight] and hueMask[ColorduinoScreenWidth][ColorduinoScreenHeight])
Mario.

toxman

https://www.facebook.com/pages/TonyMake/160740054064026

(mezzi a disposizione)*(intelligenza)= K (costante)

JoeN


my dream is to make one of this.....



Set your dreams higher.  This guy did a great job but at this point this is almost a canned project, all the data you need is right here and it isn't all that expensive.  So just do it.  Then design something yourself, that is the real challange.
I have only come here seeking knowledge. Things they would not teach me of in college.

toxman

beginning from the low side..... nest step is higher  XD
https://www.facebook.com/pages/TonyMake/160740054064026

(mezzi a disposizione)*(intelligenza)= K (costante)

substatica

@mkl0815 did you ever manager to port this? I've tried to make this library independent but it seems to rely on the colorduino libraries. All I need is to be able to define the columns and rows and get r,g,b for each pixel. Haven't had any luck so far, if I remove the colorduino library reference everything goes to pot.


@giladaya: Could it be, that you swapped columns and rows ( width and height) in you code?
I'm currently trying to port your "fire"-code to a WS2812 LED strip with 6 columns ( 6 pixel width) and 8 rows (8 pixel hight).

As I understand your code, the function "generateline()" creates a new pixel-line on the bottom line of the matrix. But your code says:
Code: [Select]

/**
* Randomly generate the next line (matrix row)
*/
void generateLine(){
  for(unsigned char x=0;x<ColorduinoScreenHeight;x++) {
      line[x] = random(64, 255);
  }
}

So you are using "x" for the position of the "cursor" on the line, but you use the ColorduinoScreenHeight as upper border.
This is not a problem, as long as you use this nomenclature consistently and yout matrix has exactly the same number of rows and columns.
Problems start if the number of columns and rows differ.
Another point is the declaration of the mask-Arrays (valueMask[ColorduinoScreenWidth][ColorduinoScreenHeight] and hueMask[ColorduinoScreenWidth][ColorduinoScreenHeight])
Mario.

Helmuth

Hi, here a concept, how to map 2 rows to a RGB strip using FastSPI_LED...

Code: [Select]
/*
* Copyright (C) 2013 Gilad Dayagi.  All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/

/*
  * An example for the Arduino particle system library
  * A wandering particle that emits colorful smoke
  *
  * Note: this example uses the colorduino library becuse that is what I had,
  * but any device that supports setting a pixel to an RGB value can be used
  */

//#include <Colorduino.h>

#include <FastSPI_LED.h>
#include "ParticleSys.h"
#include "Particle_Std.h"
#include "Particle_Fixed.h"
#include "Emitter_Fountain.h"
#include "PartMatrix.h"

#define NUM_LEDS 20

//change the order of your rgb here
struct CRGB { unsigned char r; unsigned char g; unsigned char b; };
struct CRGB *leds;


const byte numParticles = 50;
boolean pulseOn = false;

Particle_Std particles[numParticles];
Particle_Fixed source;
Emitter_Fountain emitter(0, 0, 5, &source);
ParticleSys pSys(numParticles, particles, &emitter);
PartMatrix pMatrix;

/**
* Render the particles into a low-resolution matrix
*/
void drawMatrix(){
    pMatrix.reset();
    pMatrix.render(particles, numParticles);
    //update the actual LED matrix
    for (byte y=0;y<8;y++) {
        //for(byte x=0;x<8;x++) {
            //Colorduino.SetPixel(x, y, pMatrix.matrix[x][y].r, pMatrix.matrix[x][y].g, pMatrix.matrix[x][y].b);
              leds[y].r = pMatrix.matrix[3][y].r;
              leds[y].g = pMatrix.matrix[3][y].g;
              leds[y].b = pMatrix.matrix[3][y].b;
             
              leds[NUM_LEDS-y].r = pMatrix.matrix[4][y].r;
              leds[NUM_LEDS-y].g = pMatrix.matrix[4][y].g;
              leds[NUM_LEDS-y].b = pMatrix.matrix[4][y].b;
             
             
             
             
             
     //   }
    }
}

void setup()
{
  FastSPI_LED.setLeds(NUM_LEDS);
  //select your chipset according to your strip type here - have a look at FastSPI documentation
  //i´m using a LPD1101 right know who behaves like a LPD6803
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  FastSPI_LED.init();
  FastSPI_LED.start();
  leds = (struct CRGB*)FastSPI_LED.getRGBData();
   
 
  //Colorduino.Init(); // initialize the board
 
  // compensate for relative intensity differences in R/G/B brightness
  // array of 6-bit base values for RGB (0~63)
  // whiteBalVal[0]=red
  // whiteBalVal[1]=green
  // whiteBalVal[2]=blue
  //byte whiteBalVal[3] = {36,63,7}; // for LEDSEE 6x6cm round matrix
  //Colorduino.SetWhiteBal(whiteBalVal);
 
  randomSeed(analogRead(0));
 
  //source.vx = 3;
  //source.vy = 1;
  source.x = 112;
  source.y = 1;
  Emitter_Fountain::minLife = 20;
  Emitter_Fountain::maxLife = 80;
  Particle_Std::ay = 1;
  //PartMatrix::isOverflow = false;

  //init all pixels to zero
  pMatrix.reset();
}

void loop()
{
    pSys.update();
    drawMatrix();
    FastSPI_LED.show();

    delay(20);
}

oiuchi

This is incredible work! Can it be adapted to plain arduino and single color 8x8 matrix ?

Go Up