User Tools

Site Tools


rusty_vu

This is an old revision of the document!


Introduction

ASCII The Rusty VU is a project carried over from Maker Faire Bay Area 2008, when the first ShiftBrites were introduced. Each tube contains ten ShiftBrite RGB LED modules. The control system was a proto-boarded audio filtering and ATmega128 circuit. For Maker Faire 2009, the methods and code have been updated significantly. The Rusty VUs are now running on a Seeeduino and Shifty VU Shield. Audio enters the Shifty VU Shield and is processed with an analog circuit, then read by the Arduino's analog pins. The resulting values are smoothed in software, and mapped to a customizable gradient. The overall effect is a pair of colored light bars that rise and fall as the volume of the music source varies.

Code

rusty_vu.pde

#include <math.h>
#include <avr/pgmspace.h>
#include "rgbdefs.h"
 
#define clockpin 13
#define enablepin 10
#define latchpin 9
#define datapin 11
 
#define NumLEDs 10
 
float adc1avg = 0;
float adc2avg = 0;
 
int LEDChannels[NumLEDs*2][3] = {0};
int SB_CommandMode;
int SB_RedCommand;
int SB_GreenCommand;
int SB_BlueCommand;
int CRegCount = 0;
 
PROGMEM prog_uchar Gradients[4][24] = {
  {0,0,0, 25,25,0, 50,50,0, 100,100,0, 150,150,0, 200,200,0, 255,255,0, 0,0,0},
  {255,0,0, 255,0,0, 255,0,0, 255,0,0, 0,0,255, 0,0,255, 0,0,255, 0,0,255},
  {0,255,0, 0,255,0, 0,255,0, 0,255,0, 0,255,0, 0,255,0, 0,255,0, 255,0,0},
  {255,255,255, 255,0,255, 0,0,255, 0,255,0, 0,255,0, 255,255,0, 255,0,0, 0,0,0}
};
 
byte PlasmaGradient[8][3] = {0};
 
void SelectGradient(int gradient) {
 
    for (int d = 0; d < 8; d++) {
 
      PlasmaGradient[d][0] = pgm_read_byte_near(Gradients[gradient] + d * 3);
      PlasmaGradient[d][1] = pgm_read_byte_near(Gradients[gradient] + d * 3 + 1);
      PlasmaGradient[d][2] = pgm_read_byte_near(Gradients[gradient] + d * 3 + 2);
 
    }
}
 
void setup() {
 
   pinMode(datapin, OUTPUT);
   pinMode(latchpin, OUTPUT);
   pinMode(enablepin, OUTPUT);
   pinMode(clockpin, OUTPUT);
 
   SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(1<<SPR0);
   digitalWrite(latchpin, LOW);
   digitalWrite(enablepin, LOW);
   analogReference(INTERNAL);
}
 
void SB_SendPacket() {
 
    if (SB_CommandMode == B01) {
     SB_RedCommand = 127;
     SB_GreenCommand = 127;
     SB_BlueCommand = 127;
    }
 
    SPDR = SB_CommandMode << 6 | SB_BlueCommand>>4;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_BlueCommand<<4 | SB_RedCommand>>6;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_RedCommand << 2 | SB_GreenCommand>>8;
    while(!(SPSR & (1<<SPIF)));
    SPDR = SB_GreenCommand;
    while(!(SPSR & (1<<SPIF)));
 
}
 
void WriteLEDArray() {
 
    SB_CommandMode = B00; // Write to PWM control registers
    for (int h = 0;h<NumLEDs*2;h++) {
	  SB_RedCommand = LEDChannels[h][0];
	  SB_GreenCommand = LEDChannels[h][1];
	  SB_BlueCommand = LEDChannels[h][2];
	  SB_SendPacket();
    }
 
    delayMicroseconds(1);
 
    PORTB |= (1 << 1);
    delayMicroseconds(1);
    PORTB |= (1 << 2);
 
    delayMicroseconds(1);
 
    PORTB &= ~(1 << 2);
    delayMicroseconds(1);
    PORTB &= ~(1 << 1);
 
 
      SB_CommandMode = B01; // Write to current control registers
      for (int z = 0; z < NumLEDs*2; z++) SB_SendPacket();
      delayMicroseconds(1);
      PORTB |= (1 << 1);
      delayMicroseconds(1);
      PORTB &= ~(1 << 1);
 
}
 
 
RGBType GradientMap(int color) {
 
  if (color < 0 ) color = 0;
  if (color > 255) color = 255;
 
  float GradientRed = 0;
  float GradientGreen = 0;
  float GradientBlue = 0;
 
  int GradientIndex1 = color/32;
  int GradientIndex2 = color/32 + 1;
  int GradientRatio = color % 32;
 
  if (GradientIndex2 > 7) GradientIndex2 = 7;
 
  GradientRed   = (PlasmaGradient[GradientIndex1][0] * (32 - GradientRatio) + PlasmaGradient[GradientIndex2][0] * (GradientRatio)) / 8160.0;
  GradientGreen = (PlasmaGradient[GradientIndex1][1] * (32 - GradientRatio) + PlasmaGradient[GradientIndex2][1] * (GradientRatio)) / 8160.0;
  GradientBlue  = (PlasmaGradient[GradientIndex1][2] * (32 - GradientRatio) + PlasmaGradient[GradientIndex2][2] * (GradientRatio)) / 8160.0;  
 
  RGBType RGB;
 
  RETURN_RGB(GradientRed, GradientGreen, GradientBlue);
 
}
 
void drawGraph() {
 
  SelectGradient(3);
  RGBType specRGBleft;
  RGBType specRGBright;
 
  float scaleFactor = 255/(NumLEDs);
 
  for (int i = 0;i<NumLEDs;i++) {
 
     specRGBleft = GradientMap((i+1)*scaleFactor - adc1avg*1.5 + 255);
     specRGBright = GradientMap((i+1)*scaleFactor - adc2avg*1.5 + 255);
 
     LEDChannels[i][0] = specRGBleft.R*1023;
     LEDChannels[i][1] = specRGBleft.G*1023;
     LEDChannels[i][2] = specRGBleft.B*1023;
 
     LEDChannels[i+NumLEDs][0] = specRGBright.R*1023;
     LEDChannels[i+NumLEDs][1] = specRGBright.G*1023;
     LEDChannels[i+NumLEDs][2] = specRGBright.B*1023;    
 
  }    
 
}
 
void loop() {
 
  adc1avg = adc1avg * 0.95 + analogRead(2) * 0.05;
  adc2avg = adc2avg * 0.95 + analogRead(3) * 0.05;
  drawGraph();
  WriteLEDArray();
 
  delay(1);
 
}

rgbdefs.h #define RETURN_HSV(h, s, v) {HSV.H = h; HSV.S = s; HSV.V = v; return HSV;} #define RETURN_RGB(r, g, b) {RGB.R = r; RGB.G = g; RGB.B = b; return RGB;} #define UNDEFINED -1

typedef struct {float R, G, B;} RGBType;
typedef struct {float H, S, V;} HSVType;

RGB-HSV conversion functions from http://www.alvyray.com/Papers/hsv2rgb.htm

/home/macetec/public_html/docs/data/attic/rusty_vu.1245567989.txt.gz · Last modified: 2009/06/21 07:06 by macegr