Hardware components | ||||||
| × | 64 | ||||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
Hand tools and fabrication machines | ||||||
![]() |
| |||||
![]() |
|
I wanted to create a display of 8x8 square pixels that could work independently on a table in my room. And to easily reprogram it to display different animations. Also I don't have a 3D printer, so I needed to make it out of things around the house.
First I made a jig to hold the LED's in place whilst I soldered them together.
The LED's are joined in a zig-zag left to right.
I then pushed the leds into a piece of cardboard to hold them in place once I was finished with the jig.
The most difficult part was making the square grill. I found some thin cardboard and managed to slot them together to create the squares. Then I used a glue gun to mount it onto the flat piece of cardboard. It actually worked a lot better then I expected. The squares are slightly wobbly but it give some character.
Next I needed to find a material to cover over the front of the squares. I found that baking paper diffused the light the best.
Now I just needed to find a box to put it all together. I found an empty black ice-cream tub and decided to use that. I cut a hole in the lid and stuck the baking paper over it. Also I mounted a switch on the top to turn it on and off and a hole drilled in the back to allow the 5v power wire to come in.
Also I made a DIY arduino that I can just keep inside the box, I'll document how I made that another time. Now it is a self contained unit ready to be programmed with animations.
The next part is to program the arduino. Brainy bits here can explain it much better than me.
https://www.brainy-bits.com/post/making-an-arduino-animated-frame-with-256-rgb-leds
Basically we use some free software called LCD Image Converter to covert the pixel colours into code that the arduino software will understand. First open an image that you want to display that is the correct size, in our case 8 pixels by 8 pixels.
Can download the software from here https://sourceforge.net/projects/lcd-image-converter
Then click Options - Convert. Then Image tab and change 'Block size' to 24bit
Then Prepare tab - change Type to Color
Then tick 'Use custom script' and paste the following...
for (var y = 0; y < image.height; y++)
{
if ( y % 2 == 0)
for (var x = 0; x < image.width; x++)
{
image.addPoint(x, y);
}
else
for (var x = image.width - 1; x >= 0; x--)
{
image.addPoint(x, y);
}
}
Then click Show Preview, copy what is in the box and then paste it into your ardunio code. Each pixel will now show the correct colour for your image.
/* Arduino 256 RGB LEDs Matrix Animation Frame
* Using WS2812 LED Strips
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!
*/
#include <avr/pgmspace.h> // Needed to store stuff in Flash using PROGMEM
#include "FastLED.h"
#define NUM_LEDS 64
#define DATA_PIN 9
CRGB leds[NUM_LEDS];
#define FRAMES_PER_SECOND 120 //screensaver
// Create the array of retro arcade characters and store it in Flash memory
const long Spaceship1[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x00ff00, 0x00ff00, 0x000000, 0x00ff00,
0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x000000,
0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x00ff00,
0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000
};
const long Spaceship2[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x00ff00, 0x000000, 0x00ff00, 0x00ff00, 0x00ff00, 0x000000, 0x00ff00, 0x000000,
0x000000, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00,
0x00ff00, 0x00ff00, 0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x00ff00, 0x000000,
0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00
};
const long Bang0[] PROGMEM =
{
0x000000, 0x000001, 0x010001, 0x010001, 0x010100, 0x010101, 0x000100, 0x000101,
0x010100, 0x000101, 0xd50101, 0x010100, 0x010101, 0x010001, 0x010000, 0x010100,
0x000100, 0x010001, 0xd50100, 0x000000, 0xfeeb3a, 0x010100, 0x010001, 0x010101,
0x010101, 0x010101, 0xffea3a, 0xfffffe, 0xffea3b, 0x000101, 0x000001, 0x010101,
0x000100, 0x010000, 0x000000, 0x010100, 0xfeeb3b, 0x000100, 0x000100, 0x010000,
0x000101, 0x000001, 0x010001, 0x010101, 0x010000, 0x000101, 0x000000, 0x000001,
0x010100, 0x010101, 0x000001, 0x010000, 0x010100, 0x000100, 0x010000, 0x010000,
0x010000, 0x000001, 0x010001, 0x010101, 0x000001, 0x000001, 0x000101, 0x010001
};
const long Bang1[] PROGMEM =
{
0x000000, 0x000000, 0xff1f1f, 0x000000, 0x000000, 0x000000, 0x000000, 0xff1f1f,
0x000000, 0xf9d042, 0xf9d042, 0x000000, 0xf9d042, 0x000000, 0x000000, 0xff1f1f,
0x000000, 0xf9d042, 0xf9d042, 0xf9d042, 0xf9d042, 0xf9d042, 0x000000, 0x000000,
0xf9d042, 0xf9d042, 0xf9d042, 0x000000, 0x000000, 0xf9d042, 0x000000, 0xff1f1f,
0x000000, 0x000000, 0xf9d042, 0xf9d042, 0xf9d042, 0xf9d042, 0x000000, 0x000000,
0xff1f1f, 0xff1f1f, 0x000000, 0xf9d042, 0x000000, 0x000000, 0xff1f1f, 0x000000,
0xff1f1f, 0xff1f1f, 0x000000, 0xff1f1f, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
};
const long Bang2[] PROGMEM =
{
0x010001, 0x010001, 0xf9d043, 0x010100, 0x010101, 0xd50000, 0x010101, 0xf9d143,
0x000000, 0xd40001, 0x000001, 0x010100, 0x010001, 0x010101, 0x000100, 0x000101,
0x000000, 0x010100, 0x010101, 0x000101, 0x010101, 0x010101, 0x010101, 0x010100,
0xd50100, 0x010000, 0x010001, 0x000101, 0x000100, 0x010101, 0x000101, 0xf8d043,
0x000000, 0x000101, 0x010101, 0x010101, 0x050100, 0x000001, 0x010000, 0x010100,
0x000100, 0x000000, 0x010000, 0x000101, 0x010100, 0x000100, 0xd50001, 0x000001,
0xf9d043, 0x000001, 0xd50000, 0x010100, 0x010000, 0x000101, 0xd50100, 0x010001,
0x000100, 0x010000, 0x000001, 0xf8d043, 0x010101, 0x010100, 0x000100, 0x010001
};
const long Number0[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000
};
const long Number1[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000
};
const long Number2[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x00ff00, 0x00ff00, 0x000000, 0x000000
};
const long Number3[] PROGMEM =
{
0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000, 0x00ff00, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x00ff00, 0x00ff00, 0x000000, 0x000000, 0x000000
};
const long Z1[] PROGMEM =
{
0x000000, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x7da269,
0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x328dfd, 0x328dfd,
0x328dfd, 0x328dfd, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0,
0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x000000, 0x000000,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x7da269, 0x7da269
};
const long Z2[] PROGMEM =
{
0x7da269, 0x000000, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x000000,
0x000000, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0,
0x328dfd, 0x328dfd, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x328dfd, 0x328dfd,
0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0x000000,
0x000000, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269,
0x7da269, 0x7da269, 0x000000, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x638596,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269
};
const long Z3[] PROGMEM =
{
0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x328dfd, 0x328dfd,
0x328dfd, 0x328dfd, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0,
0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x000000, 0x000000,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x7da269, 0x7da269,
0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x000000, 0x638596,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269
};
const long Z4[] PROGMEM =
{
0x328dfd, 0x328dfd, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x328dfd, 0x328dfd,
0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0x000000,
0x000000, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269,
0x7da269, 0x7da269, 0x000000, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x638596,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269,
0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x000000, 0x638596,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x000000, 0x7da269
};
const long Z5[] PROGMEM =
{
0x328dfd, 0x328dfd, 0xf0f0f0, 0xfd3232, 0xfd3232, 0xfd3232, 0xf0f0f0, 0x000000,
0x000000, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0, 0xf0f0f0,
0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x000000, 0x000000,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x000000, 0x7da269, 0x7da269,
0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x000000, 0x638596,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x7da269,
0x7da269, 0x000000, 0x000000, 0x000000, 0x7da269, 0x7da269, 0x000000, 0x638596,
0x638596, 0x000000, 0x7da269, 0x7da269, 0x7da269, 0x7da269, 0x5e7253, 0x7da269
};
void setup() {
FastLED.addLeds<WS2811,DATA_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(50);
}
void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(250); } } //SWEEP
void loop() {
/////////////////////////////////////////////////////////////////////////////////////
// Put Spaceship1 first frame
for(int passtime = 0; passtime < 4; passtime++) { // Display it 8 times
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Spaceship1[i])); // Read array from Flash
}
FastLED.show();
delay(500);
// Put Spaceship2 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Spaceship2[i]));
}
FastLED.show();
delay(500);
}
// Swipe effect
static uint8_t hue = 0;
// First slide the led in one direction
for(int i = 0; i < NUM_LEDS; i++) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(25);
}
for(int i = (NUM_LEDS)-1; i >= 0; i--) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
////////////////////////////////////////////////////////////////////////////////////
// 3 2 1 0 BANG
for(int passtime = 0; passtime < 1; passtime++) { // Display it 8 times
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Number3[i])); // Read array from Flash
}
FastLED.show();
delay(1000);
// Put Number2 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Number2[i]));
}
FastLED.show();
delay(1000);
// Put Number1 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Number1[i]));
}
FastLED.show();
delay(1000);
// Put Number0 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Number0[i]));
}
FastLED.show();
delay(1000);
}
///////////////////////////////////////////////////////////////////
// Put Bang0 first frame
for(int passtime = 0; passtime < 4; passtime++) {
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Bang0[i]));
}
FastLED.show();
delay(350);
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Bang1[i]));
}
FastLED.show();
delay(350);
// Put Bang2 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Bang2[i]));
}
FastLED.show();
delay(350);
}
// Swipe effect
for(int i = 0; i < NUM_LEDS; i++) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(25);
}
for(int i = (NUM_LEDS)-1; i >= 0; i--) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
////////////////////////////////////////////////////////////////////////////////////
// Z1
for(int passtime = 0; passtime < 1; passtime++) { // Display it 8 times
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Z1[i])); // Read array from Flash
}
FastLED.show();
delay(1000);
// Put Z2 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Z2[i]));
}
FastLED.show();
delay(1000);
// Put Z3 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Z3[i]));
}
FastLED.show();
delay(1000);
// Put Z4 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Z4[i]));
}
FastLED.show();
delay(1000);
// Put Z5 second frame
FastLED.clear();
for(int i = 0; i < NUM_LEDS; i++) {
leds[i] = pgm_read_dword(&(Z5[i]));
}
FastLED.show();
delay(1000);
}
///////////////////////////////////////////////////////////////////
// Swipe effect
for(int i = 0; i < NUM_LEDS; i++) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(25);
}
for(int i = (NUM_LEDS)-1; i >= 0; i--) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
}
Comments
Please log in or sign up to comment.