Project in progress
UW-Makeathon: Laser Drums

UW-Makeathon: Laser Drums © GPL3+

Laser Cut Arduino Midi Drum Pads and Audio Waveform Visualizer

  • 3,432 views
  • 0 comments
  • 7 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)
Lasercutter
Laser cutter (generic)
Hy gluegun
Hot glue gun (generic)

Apps and online services

About this project

Music can be expressed and modeled in so many different ways, and as engineers we are taking advantage of that. The drum boxes were fabricated in the makerspace, and when hit create a midi signal that can be computed and turned into any sound imaginable. The visual display takes a microphone's input, and runs the Fast Fourier Transform algorithm on it to get a list of amplitudes across different frequencies and display that on a set of NEOPixel strips.

Code

MusicVisualizationArduino
Displays a music waveform to the NEOPixel display
#include <arduinoFFT.h>
#include <math.h>
#include <FastLED.h>
#include <LEDColumn.h>

#define SAMPLES 32
#define SAMPLING_FREQUENCY 10000
#define DATAPIN1 43
#define DATAPIN2 53
#define NUM_LEDS 300
#define AIN A7

CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];

arduinoFFT FFT = arduinoFFT();

unsigned int sampling_period_us;
unsigned long microseconds;

double vReal[SAMPLES];
double vImag[SAMPLES];
LEDColumn LEDColumns1[10];
LEDColumn LEDColumns2[10];
void setup()
{
  sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
  FastLED.addLeds<NEOPIXEL, DATAPIN1>(leds1, NUM_LEDS);
  FastLED.addLeds<NEOPIXEL, DATAPIN2>(leds2, NUM_LEDS);

  //sets up each LED Column
  for (int i = 0; i < 10; i++)
  {
    int startingLED = (i * 30);
    int evenOdd = (i % 2);
    LEDColumns1[i] = *(new LEDColumn(evenOdd));
    LEDColumns2[i] = *(new LEDColumn(evenOdd));
  }
  //make the bottom of every column light up
  for (int i = 0; i < 10; i++) {
    if (LEDColumns1[i].isUpsideDown()) {
      leds1[((30 * i) + 29)] = CRGB(0, 0, 100);
      leds2[((30 * i) + 29)] = CRGB(0, 0, 100);
    } else {
      leds1[(30 * i)] = CRGB(0, 0, 100);
      leds2[(30 * i)] = CRGB(0, 0, 100);
    }
  }
  FastLED.show();

}

void loop()
{
  /*SAMPLING*/
  for (int i = 0; i < SAMPLES; i++)
  {
    microseconds = micros();    //Overflows after around 70 minutes!

    vReal[i] = analogRead(AIN);
    vImag[i] = 0;

    while (micros() < (microseconds + sampling_period_us)) {
    }
  }
  /*FFT*/
  FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

  //get the max value of the magnitude and pass it to LEDColumn to compute
  for (int i = 0; i < 20; i++) {
    double max = 0;
    for (int j = 0; j < (SAMPLES / 20); j++) {
      double currentReal = vReal[((SAMPLES / 20) * i + j)];

      if (currentReal > max) {
        max = currentReal;
      }
    }
    double computedMax = log(max * max * max);
    if (i < 10) {
      //the height of the LED columns must have increased
      if (LEDColumns1[i].computeHeight(computedMax) > 0) {

        if (LEDColumns1[i].isUpsideDown()) {
          leds1[(30 * i) + 29 - LEDColumns1[i].getHeight()] = CRGB(0, 0, 100);

        } else {
          leds1[(30 * i) + LEDColumns1[i].getHeight()] = CRGB(0, 0, 100);
        }
      } else {
        if (LEDColumns1[i].isUpsideDown()) {
          leds1[(30 * i) + 29 - LEDColumns1[i].getHeight() - 1] = CRGB::Black;
        } else {
          leds1[(30 * i) + LEDColumns1[i].getHeight() + 1] = CRGB::Black;
        }
      }
      FastLED.show();
    } else {
      if (LEDColumns2[i - 10].computeHeight(computedMax) > 0) {

        if (LEDColumns2[i - 10].isUpsideDown()) {
          leds2[(30 * (i - 10)) + 29 - LEDColumns2[i - 10].getHeight()] = CRGB(0, 0, 100);

        } else {
          leds2[(30 * (i - 10)) + LEDColumns2[i - 10].getHeight()] = CRGB(0, 0, 100);
        }
      } else {
        if (LEDColumns2[i - 10].isUpsideDown()) {
          leds2[(30 * (i - 10)) + 29 - LEDColumns2[i - 10].getHeight() - 1] = CRGB::Black;
        } else {
          leds2[(30 * (i - 10)) + LEDColumns2[i - 10].getHeight() + 1] = CRGB::Black;
        }
      }
      FastLED.show();
    }

  }
}
LEDColumnC/C++
Class that controls data for each LED Column
#include "Arduino.h"
#include "LEDColumn.h"

LEDColumn::LEDColumn(void)
{
    //Fake Constructor to get around wierd type error
}
LEDColumn::LEDColumn(int evenOdd)
{
    //Real Constructor
    _Odd = evenOdd;
    height = 0;
}
boolean LEDColumn::isUpsideDown()
{
    return (_Odd == 1);
}
int LEDColumn::getHeight()
{
    return height;
}
// return the height

/**
 * calculate the new height of the columns based on whether it is incremented or decremented
 * return 1 if the height is incremented, -1 if it is decremented, or 0 if it stays the same
 */

int LEDColumn::computeHeight(double FFT_data)
{
    if (height < FFT_data)
    {
        if (height == 29)
        {
            return 0;
        }
        height++;
        return 1;
    }
    else
    {
        if (height == 0)
        {
            return 0;
        }
        height--;
        int guyo = -1;
        Serial.println(guyo);
        return guyo;
    }
}
LEDColumn Header fileC/C++
Header for the LEDColumn class.
#ifndef LEDColumn_h
#define LEDColumn_h

#include "Arduino.h"
class LEDColumn
{
  public:
  /* Constructor */
	  LEDColumn(void);
    LEDColumn(int evenOdd);
    int computeHeight(double FFT_DATA);
    int getHeight();
    boolean isUpsideDown();
  private:
    int height;
    int _Odd;

    
};

#endif

Custom parts and enclosures

6x6 Box EVA Foam Pad
Drum Pad for the 6x6 Modules
5_75x5_75_eva_foam_GEX8cVmXRX.ai
6x6x2" Box
Laser Cut Box for Drum Module x7
6x6x2_boxes_x7_TiW8rauQXx.ai
7x7x2" Box
Laser Cut Box for Main Drum Module
7x7x2_box_6C8vNNvEPM.ai
6x6" Box EVA Foam Spacers
Foam Spacers for the 6x6 Modules
6x6_spacers_BqWd7AbJX7.ai
7x7 Box EVA Foam
EVA Foam Drum Pad and spacers for the 7x7 Module
7x7_eva_foam_CxPvTsvjsu.ai

Comments

Similar projects you might like

Build a Laser Harp with a LIDAR and Arduino

by Doctor Volt

  • 13,484 views
  • 1 comment
  • 27 respects

Kravox! Wireless, Motion and Touch-Sensing Instrument

Project tutorial by Tim Krahmer

  • 11,528 views
  • 20 comments
  • 37 respects

Minimal MIDI Drum Kit with 3D Printer

Project tutorial by ryokosaka

  • 28,224 views
  • 6 comments
  • 52 respects

New Electronic Music Instrument Design

Project showcase by cpeckmusic

  • 9,266 views
  • 1 comment
  • 28 respects

Laser Pointer Panther Tank

Project tutorial by Arduino “having11” Guy

  • 10,175 views
  • 1 comment
  • 18 respects

Timer Based Laser Wall Clock

by screwpilot

  • 9,995 views
  • 7 comments
  • 11 respects
Add projectSign up / Login