Project in progress
UW-Makeathon: Laser Drums

UW-Makeathon: Laser Drums © GPL3+

Laser Cut Arduino Midi Drum Pads and Audio Waveform Visualizer

  • 1,119 views
  • 0 comments
  • 2 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

Laser Pointer Panther Tank

Project tutorial by Arduino “having11” Guy

  • 5,269 views
  • 1 comment
  • 12 respects

WW2 Tank Laser Tag Sherman & Panther

Project tutorial by Arduino “having11” Guy

  • 16,352 views
  • 1 comment
  • 57 respects

IoTrix (Smart Advertisement LED Board)

Project tutorial by Ravi Parmar

  • 2,382 views
  • 0 comments
  • 21 respects

UW-Makeathon Bio-View: A modular bioreactor for cell culture

Project in progress by 3 developers

  • 753 views
  • 0 comments
  • 11 respects

Timer Based Laser Wall Clock

by screwpilot

  • 4,390 views
  • 6 comments
  • 4 respects

Arduino 101 - Intel Curie Pattern Matching Dress

Project tutorial by Kitty Yeung

  • 9,460 views
  • 17 comments
  • 50 respects
Add projectSign up / Login