Using the AdaFruit NeoPixel and AdaFruit NeoMatrix Library
Using adresseable LED's creating a matrix to light up a skybox, let you show different images and lightpattern on the skydrop. Using the AdaFruit NeoPixel library and the NeoMatrix library and an Arduino, gives you different backdrops using light. Using some of the routines, you can load an image into the matrix, shown in this extended description.
I made a backdrop box using 3 mm cardboard with foam, covering the box with milkwhite plasticfoil, so the light could be diffused by the foil and display different images on the backdrop.
The different LED's can be adressed and set to the color and brightness you want by the Arduino sketch. What I want to use, is an image with a nice colored heaven, and convert that to an low-resolution image to power the LED-matrix in the skybox. I have also an image of an aurora borealis or northern light in the demonstration sketch.
LED-matrix 7 by 19 pixels skybox
I used a LED-strip with 150 LED's to create a 17x by 9 pixels, using a WS2812B 30Led/m RGBW LED-strip. The matrix should have had 153 LED's, the strip has only 150. The last 3 LED's are not there, but it does not matter, because it's behind and covered by a building.
Its not many pixels to create a good image, so more pixels would have given a better resolution, but I think the effect I wanted, was "good enough" with this small matrix.
To create the low resolution "image", with the color and brightness setting for each LED in the matrix, I started with an image of the heaven I want to use. Did some editing of the edges and modified the number of pixels in the x- and y- direction to be the same ratio as my LED-matrix.
Creating different images and the corresponding code, gave me different options to light up the background, as shown in the images.
A sunset background example:
The image is then converted to 17 by 9 pixels and saved, before the image is converted to code.
Convert the image to code
To create the programcode for the image, I used an utility found on the net, that converted the JPG file from pixels to actual code.
The routine used to convert rasterfiles: http://www.rinkydinkelectronics.com/t_imageconverter565.php
Rasterfiles used for the 17x9 matrix, must have a 1.88 or 0.52 aspect ratio. An image used for background color must be set up with this ratio, 17x9, and reduced to 17 by 9 pixels, before the imageconverter565 is run on the image file. The resulting codes are used to light up the led matrix. The routine, because of 17x9 pixels, will not fill the entire matrix. The last 6 numbers(if I remember correctly) may be copied and added manually, so the whole ledstrip is lighted.
The resulting code used in the Arduino sketch for the 2 images shown above, the sunset and the aurora borealis:
// Generated by : ImageConverter 565 Online
// Generated from : himmel3_17x9.jpg
// Time generated : Sun, 07 Jun 20 21:24:21 +0200 (Server timezone: CET)
// Image Size : 17x9 pixels
// Memory usage : 306 bytes
#if defined(__AVR__)
#include <avr/pgmspace.h>
#elif defined(__PIC32MX__)
#define PROGMEM
#elif defined(__arm__)
#define PROGMEM
#endif
const unsigned short himmel3_17x9[153] PROGMEM={
0x0020, 0x0000, 0x0800, 0x0821, 0x0000, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0010 (16) pixels
0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, // 0x0020 (32) pixels
0x0000, 0x0000, 0x0083, 0x11C8, 0x120A, 0x122B, 0x1A2B, 0x1A6C, 0x226C, 0x226C, 0x228C, 0x2A8C, 0x2AAC, 0x2ACD, 0x2AAD, 0x2AAD, // 0x0030 (48) pixels
0x2AAD, 0x228C, 0x1105, 0x1168, 0x3BB1, 0x3C95, 0x4CB6, 0x5CD8, 0x5D18, 0x5D38, 0x6539, 0x6D99, 0x6DBA, 0x75BA, 0x75DA, 0x75DA, // 0x0040 (64) pixels
0x75BA, 0x75DA, 0x6D79, 0x326A, 0x2167, 0x5432, 0x5D16, 0x6517, 0x7538, 0x7D78, 0x7DB9, 0x8DDA, 0x95FA, 0x9E1B, 0x9E3B, 0xA65B, // 0x0050 (80) pixels
0xA63B, 0xA63B, 0xA63B, 0x95D9, 0x42AC, 0x29A7, 0x7472, 0x8535, 0x8D56, 0x9577, 0x9D97, 0xA5D8, 0xAE19, 0xB639, 0xBE59, 0xBE7A, // 0x0060 (96) pixels
0xC67A, 0xC67A, 0xBE79, 0xC659, 0xB5F8, 0x4AAB, 0x2945, 0x7BAE, 0x9451, 0xA4B2, 0xAD12, 0xB512, 0xBD53, 0xBD95, 0xC5D5, 0xCDF5, // 0x0070 (112) pixels
0xCE15, 0xCE15, 0xD615, 0xD615, 0xD615, 0xC593, 0x5AA9, 0x3121, 0x930A, 0xAB6B, 0xB3EB, 0xBC4C, 0xC44C, 0xD48D, 0xD4CE, 0xDCEE, // 0x0080 (128) pixels
0xE52F, 0xE52F, 0xED2F, 0xED2F, 0xED2F, 0xED2F, 0xDCCD, 0x6226, 0x1840, 0x3903, 0x5164, 0x5983, 0x61A4, 0x61A4, 0x69E4, 0x71E4, // 0x0090 (144) pixels
0x1840, 0x3903, 0x5164, 0x5983, 0x61A4, 0x61A4, 0x69E4, 0x71E4,
};
To show this image on the backdrop, you can use this complete sketch. It vil also simulate some lightening effect and show the different images:
/* example_skydrop_matrix.ino by Svein-Martin Holt, www.platelayer.com, november 2021
This Arduino sketch gives an example of using the AdaFruit NeoMatrix Library to create light animations for the ZityEdge layout, www.zityedge.co.
Adafruit_NeoMatrix skydrop_matrix 17 x 9, 150 LED's
Strip 7: Skydrop NeoPixel Matrix 17x9: WS2812B 30Led/m RGBW, 5V, number of leds: 150, order GRBW, +/-/D
The matrix should have had 153 LED's, the strip has only 150. The last 3 LED's are not there, but it does not matter, because it's behind a building.
Rasterfiles used for the 17x9 matrix, must have a 1.88 or 0.52 aspect ratio.
An image used for background color must be set up with this ratio, 17x9, and reduced to 17 by 9 pixels, before the imageconverter565 is run on the image file.
The resulting codes are used to light up the led matrix. The routine, because of 17x9 pixels, will not fill the entire matrix.
The last 6 numbers(if I remember correctly) may be copied and added so the whole ledstrip is lighted.
convert rasterfiles: http://www.rinkydinkelectronics.com/t_imageconverter565.php
*/
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#define FASTLED_INTERNAL // Disable version number message in FastLED library (looks like an error)
#include "FastLED.h"
#ifndef PSTR
#define PSTR // Make Arduino Due happy
#endif
//int16_t Value = 0; // Integer variabel
//int16_t Brightness = 128; //
#define LED7_PIN 7 // Strip 7, RGBW+D 150 leds matrix 17x9
// How many LEDS are attached to the Arduino?
#define LED_COUNT_7 150
// Max is 255,
#define BRIGHTNESS_7 5
uint8_t BRIGHT_CURR_7 = BRIGHTNESS_7;
//#define LED_TYPE WS2811
//#define COLOR_ORDER GRB
// Declare our NeoPixel strip object:
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 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)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
// 1 x RGBW-strip (FastLED has no support for RGBW LED-stripes)
Adafruit_NeoPixel strip_7(LED_COUNT_7, LED7_PIN, NEO_GRBW + NEO_KHZ800);
// Declare our NeoPixel Matrix object:
// Define matrix width and height.
#define matrix_7width 17
#define matrix_7height 9
// MATRIX DECLARATION:
// Parameter 1 = width of NeoPixel matrix
// Parameter 2 = height of matrix
// Parameter 3 = pin number (most are valid)
// Parameter 4 = matrix layout flags, add together as needed:
// NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
// Position of the FIRST LED in the matrix; pick two, e.g.
// NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
// NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
// rows or in vertical columns, respectively; pick one or the other.
// NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
// in the same order, or alternate lines reverse direction; pick one.
// Parameter 5 = 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_GRBW Pixels are wired for GRBW bitstream (RGB+W NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// Skydrop matrix, 150 RGBW Leds
Adafruit_NeoMatrix matrix_7 = Adafruit_NeoMatrix(matrix_7width, matrix_7height, LED7_PIN,
NEO_MATRIX_TOP + NEO_MATRIX_RIGHT +
NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
NEO_GRBW + NEO_KHZ800);
// Color definitions
// This could also be defined as matrix->color(255,0,0) but those defines
// are meant to work for adafruit_gfx backends that are lacking color()
#define LED_BLACK 0
#define LED_RED_HIGH (31 << 11)
#define LED_GREEN_HIGH (63 << 5)
#define LED_BLUE_HIGH 31
#define LED_WHITE_HIGH (LED_RED_HIGH + LED_GREEN_HIGH + LED_BLUE_HIGH)
// include the different matrix raster images definitions
// Generated by : ImageConverter 565 Online
// Generated from : himmel3_17x9.jpg
// Time generated : Sun, 07 Jun 20 21:24:21 +0200 (Server timezone: CET)
// Image Size : 17x9 pixels
// Memory usage : 306 bytes
#if defined(__AVR__)
#include <avr/pgmspace.h>
#elif defined(__PIC32MX__)
#define PROGMEM
#elif defined(__arm__)
#define PROGMEM
#endif
const unsigned short himmel3_17x9[153] PROGMEM = {
0x0020, 0x0000, 0x0800, 0x0821, 0x0000, 0x0000, 0x0800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0x0010 (16) pixels
0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, // 0x0020 (32) pixels
0x0000, 0x0000, 0x0083, 0x11C8, 0x120A, 0x122B, 0x1A2B, 0x1A6C, 0x226C, 0x226C, 0x228C, 0x2A8C, 0x2AAC, 0x2ACD, 0x2AAD, 0x2AAD, // 0x0030 (48) pixels
0x2AAD, 0x228C, 0x1105, 0x1168, 0x3BB1, 0x3C95, 0x4CB6, 0x5CD8, 0x5D18, 0x5D38, 0x6539, 0x6D99, 0x6DBA, 0x75BA, 0x75DA, 0x75DA, // 0x0040 (64) pixels
0x75BA, 0x75DA, 0x6D79, 0x326A, 0x2167, 0x5432, 0x5D16, 0x6517, 0x7538, 0x7D78, 0x7DB9, 0x8DDA, 0x95FA, 0x9E1B, 0x9E3B, 0xA65B, // 0x0050 (80) pixels
0xA63B, 0xA63B, 0xA63B, 0x95D9, 0x42AC, 0x29A7, 0x7472, 0x8535, 0x8D56, 0x9577, 0x9D97, 0xA5D8, 0xAE19, 0xB639, 0xBE59, 0xBE7A, // 0x0060 (96) pixels
0xC67A, 0xC67A, 0xBE79, 0xC659, 0xB5F8, 0x4AAB, 0x2945, 0x7BAE, 0x9451, 0xA4B2, 0xAD12, 0xB512, 0xBD53, 0xBD95, 0xC5D5, 0xCDF5, // 0x0070 (112) pixels
0xCE15, 0xCE15, 0xD615, 0xD615, 0xD615, 0xC593, 0x5AA9, 0x3121, 0x930A, 0xAB6B, 0xB3EB, 0xBC4C, 0xC44C, 0xD48D, 0xD4CE, 0xDCEE, // 0x0080 (128) pixels
0xE52F, 0xE52F, 0xED2F, 0xED2F, 0xED2F, 0xED2F, 0xDCCD, 0x6226, 0x1840, 0x3903, 0x5164, 0x5983, 0x61A4, 0x61A4, 0x69E4, 0x71E4, // 0x0090 (144) pixels
0x1840, 0x3903, 0x5164, 0x5983, 0x61A4, 0x61A4, 0x69E4, 0x71E4,
};
// Generated by : ImageConverter 565 Online
// Generated from : nordlys17x9.jpg
// Time generated : Sat, 04 Apr 20 15:37:11 +0200 (Server timezone: CET)
// Image Size : 17x9 pixels
// Memory usage : 306 bytes
#if defined(__AVR__)
#include <avr/pgmspace.h>
#elif defined(__PIC32MX__)
#define PROGMEM
#elif defined(__arm__)
#define PROGMEM
#endif
const unsigned short nordlys17x9[153] PROGMEM = {
0x3B09, 0x3B2A, 0x432A, 0x434A, 0x4B4B, 0x4B6B, 0x436B, 0x4B6B, 0x4B6C, 0x4B6B, 0x4B6B, 0x4B4B, 0x4B4B, 0x4B4B, 0x4B4A, 0x4B2B, // 0x0010 (16) pixels
0x4B2B, 0x4CED, 0x44EC, 0x44EC, 0x44ED, 0x44ED, 0x4CED, 0x4CCD, 0x4CAD, 0x4CAD, 0x54AD, 0x4C6C, 0x4C6C, 0x4C6D, 0x544C, 0x540C, // 0x0020 (32) pixels
0x4C0C, 0x542D, 0x460C, 0x460C, 0x460C, 0x462D, 0x4E4D, 0x4E6E, 0x4E4E, 0x4E2E, 0x562E, 0x560E, 0x55EE, 0x55EE, 0x55CE, 0x55CD, // 0x0030 (48) pixels
0x556D, 0x552D, 0x5D4E, 0x3B09, 0x3B08, 0x3B28, 0x3B89, 0x3C0A, 0x444A, 0x3C4A, 0x446A, 0x44EB, 0x4CEC, 0x4D4C, 0x55CC, 0x55ED, // 0x0040 (64) pixels
0x55ED, 0x560D, 0x5E2D, 0x666E, 0x3B29, 0x3308, 0x3349, 0x3389, 0x3369, 0x3B29, 0x3B09, 0x3B29, 0x3B4A, 0x3B2A, 0x3B49, 0x3BCA, // 0x0050 (80) pixels
0x448A, 0x446A, 0x444A, 0x4CCB, 0x5D6C, 0x4628, 0x3E27, 0x4E87, 0x4EC8, 0x4688, 0x4668, 0x4E69, 0x4E49, 0x4E69, 0x564A, 0x4DAA, // 0x0060 (96) pixels
0x456A, 0x4D89, 0x4D6A, 0x44CA, 0x3C49, 0x43EA, 0x44A6, 0x3D25, 0x3D85, 0x45A5, 0x45A5, 0x45A6, 0x45E6, 0x4606, 0x4E86, 0x5F06, // 0x0070 (112) pixels
0x5F46, 0x5F66, 0x6FA6, 0x6FA6, 0x6F86, 0x6F67, 0x66A9, 0x3266, 0x2A85, 0x2A44, 0x29C5, 0x29A6, 0x31A6, 0x31C6, 0x29C6, 0x2A26, // 0x0080 (128) pixels
0x32E6, 0x43E5, 0x4CE4, 0x4D24, 0x55A3, 0x6622, 0x6E82, 0x76C3, 0x2105, 0x2125, 0x2145, 0x2125, 0x2124, 0x1904, 0x2145, 0x2986, // 0x0090 (144) pixels
0x76C3, 0x2105, 0x2125, 0x2145, 0x2125, 0x2124, 0x1904, 0x2145, 0x2986,
};
void setup() {
//setup RGBW strip and matrix
strip_7.begin();
strip_7.setBrightness ( BRIGHTNESS_7 );
strip_7.show(); // Initialize all pixels to 'off'
matrix_7.begin ();
matrix_7.setBrightness ( BRIGHTNESS_7 );
matrix_7.setCursor ( 0, 0 );
}
void loop() {
//run the test of the matrix skybox
matrix_setting_test();
}
void matrix_setting_test() {
// draw image of sunset
matrix_7.setBrightness ( 10 );
matrix_7.drawRGBBitmap(0, 0, (const uint16_t *) himmel3_17x9, matrix_7width, matrix_7height);
matrix_7.show ();
delay(3000);
//draw image of borealis(nordlys)
matrix_7.setBrightness ( 50 );
matrix_7.drawRGBBitmap(0, 0, (const uint16_t *) nordlys17x9, matrix_7width, matrix_7height);
matrix_7.show ();
delay(3000);
//draw some lines on the matrix to simulate lightening
lighting1();
lighting2();
delay(2000);
//turn off the matrix
matrix_7.fillScreen ( LED_BLACK );
matrix_7.show ();
delay(1000);
}
void lighting1() {
matrix_7.setBrightness ( 250 );
matrix_7.drawLine(5, 0, 8, 9, LED_WHITE_HIGH);
matrix_7.show();
delay(100);
strip_7.clear();
delay(20);
matrix_7.show();
delay(50);
strip_7.clear();
strip_7.show();
matrix_7.setBrightness ( BRIGHTNESS_7 );
strip_7.show();
}
void lighting2() {
matrix_7.setBrightness ( 250 );
matrix_7.drawLine(17, 0, 6, 9, LED_WHITE_HIGH);
matrix_7.show();
delay(100);
strip_7.clear();
delay(20);
matrix_7.show();
delay(50);
strip_7.clear();
strip_7.show();
matrix_7.setBrightness ( BRIGHTNESS_7 );
strip_7.show();
}