DIY Desktop Light Sculpture

This visually pleasing project has endless possibilities for customization and design.

Favorited Favorite 2

light sculpture overview

My latest project, the Desktop Light Sculpture, is a digitally fabricated object featuring a 3D-printed base and laser-etched acrylic inserts. Inside the base you can find a neopixel matrix, a Qduino Mini, and a few other basic electronic components for usability.

The idea for this project is dependent on edge-lighting the acrylic. What this means is that when light is applied to the edge of a piece of acrylic, it will be picked up by any etched parts on the surface of the plastic as well as along its edges. This creates a beautiful visual effect!

The major element of this project is definitely the digital fabrication. I really love that there are two parts to design that have very different design constraints. The first, the 3D-printed base, needs to be designed to fit the electronic parts, hold the acrylic, and separate the light from each row of LEDs (as to not affect a neighboring piece of acrylic). The parameters offer a good design engineering challenge, but offer less in the way of creativity.

The second part, our acrylic inserts, must fit into the slot in the base, but otherwise offer complete creative freedom. They can be any shape or size and feature any etched design. With endless colors, patterns, and animations to program your LEDs, the design possibilities of this project are endless!

light sculpture blue

light sculpture pink

light sculpture rainbow

light sculpture 3/4 view

If you would like to make this project at home, you can grab everything you need from my Light Sculpture Wishlist.

Both the .stl for the 3D-printed base and the Illustrator file for the acrylic insert shape can be found on thingiverse. The images below illustrate how the parts fit into the base.

light sculpture matrix placement

light sculpture neopixel rows

light sculpture components

light sculpture power cord

You will notice that in addition to the LEDs and microcontroller, the project features a button, a switch and a potentiometer. The button is used to cycle through different LED colors, patterns and animations. The switch will turn the project on or off, and the potentiometer controls the brightness of your LEDs. The diagram below illustrates the circuit used in this project.

light sculpture circuit

Having a hard time seeing the circuit? Click on the image for a closer look.

Below is the program I used for this project. It utilizes the Adafruit Neopixel Library.

//Desktop Light Sculpture by Melissa Felderman for SparkFun Electrnoics July/31/2018

#include <Adafruit_NeoPixel.h> //include afafruit library 
#define PIN 6 //LED matrix pin
#define brightPot A0 //potentiometer to controll brightness
#define pwrSwitch 4 //power switch
#define momBut 5 //button to control LED mode
int numPix = 64; //total LED count
int brightPotVal; //Variable to hold pot value
int pixelBrightness; //variabe to hold brightness value
int switchState; //variable to hold switch value
int butState; //variable to hold button value
int mode = 0; //starting mode for switch state
int prevButState = LOW;
boolean butBool = false;
int topMode = 4; //max number of LED modes in switch state

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 200;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(numPix, PIN, NEO_GRB + NEO_KHZ800); //declare neopixel matrix


//create an array for each row of LEDs
int rowOne[] = {0, 1, 2, 3, 4, 5, 6, 7};
int rowTwo[] = {8, 9, 10, 11, 12, 13, 14, 15};
int rowThree[] = {16, 17, 18, 19, 20, 21, 22, 23};
int rowFour[] = {24, 25, 26, 27, 28, 29, 30, 31};
int rowFive[] = {32, 33, 34, 35, 36, 37, 38, 39};
int rowSix[] = {40, 41, 42, 43, 44, 45, 46, 47};
int rowSeven[] = {48, 49, 50, 51, 52, 53, 54, 55};
int rowEight[] = {56, 57, 58, 59, 60, 61, 62, 63};

void setup() {
  Serial.begin(9600);
  strip.begin();
  strip.show();

  pinMode(momBut, INPUT);
  pinMode(pwrSwitch, INPUT);

}


void loop() {
  brightPotVal = analogRead(brightPot);
  pixelBrightness = map(brightPotVal, 0, 1023, 0, 200);

  switchState = digitalRead(pwrSwitch);
  butState = digitalRead(momBut);

  strip.setBrightness(pixelBrightness);
  strip.show();

  //function to debounce button
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if ((butState == HIGH) && (butBool == false)) {
      butBool = true;
      mode++;
      lastDebounceTime = millis();
    } butBool = false;
  } if (mode > topMode) {
    mode = 0;
  }

  Serial.println(mode);

  //switch state function to cycle through modes on LEDs, you can add as many or as few as you would like
  if (switchState == HIGH) {

    switch ( mode ) {
      case 0:
        for (int i = 0; i < numPix; i++) {
          strip.setPixelColor(i, 255, 255, 255);
        }
        strip.show();
        break;
      case 1:
        rainbow();
        break;
      case 2:
        buleGreenGradient();
        break;
      case 3:
        pinkGradient();
        break;
      case 4:
        yellowGradient();
        break;

    }
  } else if (switchState == LOW) {
    for (int i = 0; i < numPix; i++) {
      strip.setPixelColor(i, 0, 0, 0);
    }
    strip.show();
  }
}



//functions for LED colors


void everyOther() {
  for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowOne[i], 255, 255, 255);
    strip.setPixelColor(rowThree[i], 255, 255, 255);
    strip.setPixelColor(rowFive[i], 255, 255, 255);
    strip.setPixelColor(rowSeven[i], 255, 255, 255);

    strip.setPixelColor(rowTwo[i], 0, 0, 0);
    strip.setPixelColor(rowFour[i], 0, 0, 0);
    strip.setPixelColor(rowSix[i], 0, 0, 0);
    strip.setPixelColor(rowEight[i], 0, 0, 0);
  }
  strip.show();
}


void pinkGradient() {
  for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowOne[i], 185, 0, 255);
    strip.setPixelColor(rowTwo[i], 195, 0, 230);
    strip.setPixelColor(rowThree[i], 205, 0, 200);
    strip.setPixelColor(rowFour[i], 215, 0, 160);
    strip.setPixelColor(rowFive[i], 225, 0, 120);
    strip.setPixelColor(rowSix[i], 235, 0, 80);
    strip.setPixelColor(rowSeven[i], 245, 0, 40);
    strip.setPixelColor(rowEight[i], 255, 0, 10);
  }
  strip.show();
}

void buleGreenGradient() {
  for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowOne[i], 0, 75, 255);
    strip.setPixelColor(rowTwo[i], 0, 100, 225);
    strip.setPixelColor(rowThree[i], 0, 125, 200);
    strip.setPixelColor(rowFour[i], 00, 150, 175);
    strip.setPixelColor(rowFive[i], 0, 175, 150);
    strip.setPixelColor(rowSix[i], 0, 200, 125);
    strip.setPixelColor(rowSeven[i], 0, 225, 100);
    strip.setPixelColor(rowEight[i], 0, 255, 75);
  }
  strip.show();
}

void yellowGradient() {
  for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowOne[i], 255, 255, 25);
    strip.setPixelColor(rowTwo[i], 255, 220, 25);
    strip.setPixelColor(rowThree[i], 255, 190, 25);
    strip.setPixelColor(rowFour[i], 255, 160, 25);
    strip.setPixelColor(rowFive[i], 255, 130, 25);
    strip.setPixelColor(rowSix[i], 255, 100, 25);
    strip.setPixelColor(rowSeven[i], 255, 70, 25);
    strip.setPixelColor(rowEight[i], 255, 40, 25);
  }
  strip.show();
}
void rainbow() {
  for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowOne[i], 255, 0, 0);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowTwo[i], 255, 100, 0);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowThree[i], 255, 255, 0);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowFour[i], 0, 255, 0);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowFive[i], 0, 255, 200);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowSix[i], 0, 0, 255);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowSeven[i], 255, 0, 255);
  } for (int i = 0; i < 8; i++) {
    strip.setPixelColor(rowEight[i], 255, 0, 130);
  }
  strip.show();
}

I hope you enjoyed this project! It was a lot of fun to make and I’m excited to continue building out the program for more LED colors, as well as making different designs on the laser-etched acrylic.

If you love this project and want to give it a go but don’t have access to digital fabrication tools, try checking out your local library or maker space. If all else fails there are always online digital fabrication services from which you can order your 3D print and laser-etched acrylic. As always, please share your thoughts, ideas, and suggestions about this project in the comments below!


Shop For This Project Download the Design Files


Comments 6 comments

  • How about controlling the pattern based on the Qduino’s analog inputs? You could set up an acrylic light organ in no time.

  • For your laser cut acrylic pieces, particularly the ones using the different shapes of acrylic (not the etched ones). Are the illuminated edges just the raw cut lines from your laser printer, or did you finish them somehow (like maybe a light sanding)?

    • Those edges are just raw laser cut. I noticed that the edges also held color after I tested the etched designs. I bet sanding the edges would only increase the intended effect, that’s a great idea!

  • Hi Feldi!

    Great project! Thanks for sharing!

    A couple of thoughts come to mind for possible enhancements. First woud be an ambient light sensor to automatically adjust for the light in the room. (I’d be inclined to keep the potentiometer, but combine the light sensor and potentiometer readings in software.)

    My second thought would be a mode where the colors are randomly chosen. I’ve done that on a couple of projects involving NeoPixels. Use the “max brightness” as the sum of the RGB values, then a random number between 0 and max for, say red, then a random number between zero and (max - red) for green, then blue gets ( max - ( red + green ). You could have it change every few seconds, or a “slowly changing”, and even play with light patterns (e.g., each row gets same color, each column gets same color, every LED gets its own color, diagonal of LEDs gets same color progressing across array, etc.)

    • Thank you! And thanks for sharing your input as always!

      I wanted manual control for brightness but if you prefer to have it automatically adjust, the light sensor is a great method. I definitely want to add animation to the LEDs as well. That’s an update that I plan to make before I bring one of these lil guys home with me!

      • At the risk of “over feature-izing” it, the thought occurs to me that you could set it up so that to “change” the “mode”, you hold the button for, say, 1 sec., then each button push it goes to next mode changing which plate is illuminated, and once you’ve gone say 5 sec. without pushing the button, it drops from “set mode” to “playing” that mode.

        BTW, the two brightness control methods are not mutually exclusive. You could have both implemented in hardware, then you select “manual”, “auto”, or “both” (or even maybe “none”) as a “mode”.

        I’m probably getting into “feature creep”… oh well… though I suppose using a processor with BLE and having an “app” on the cell phone WOULD be overkill! ;-)

Related Posts

That's no moon...

B-Squares

Recent Posts

Liquidation Sale

Tags


All Tags