I can't connect my Perfume Dispenser to my music Visualizer . I am using an Arduino Uno.

edited February 2018 in Arduino
import cc.arduino.*;
//import org.firmata.*;

import ddf.minim.*;
import ddf.minim.analysis.*;
import processing.serial.*;



Minim minim;
AudioPlayer song;
FFT fft;
BeatDetect beat;
BeatListener bl;
//Serial myPort; // Create object from Serial class
Arduino arduino;


// Variables that define the "zones" of the spectrum
// For example, for bass, we take only the first 4% of the total spectrum
float specLow = 0.03; // 3%
float specMid = 0.125; // 12.5%
float specHi = 0.20; // 20%
float specLLow = 0.009;
// This leaves 64% of the possible spectrum that will not be used.
//These values are usually too high for the human ear anyway.

//Scoring values for each zone.
float scoreLow = 0;
float scoreMid = 0;
float scoreHi = 0;

// Previous value, to soften the reduction
float oldScoreLow = scoreLow;
float oldScoreMid = scoreMid;
float oldScoreHi = scoreHi;

// Softening value
float scoreDecreaseRate = 25;

// Cubes appearing in space
int nbCubes;
Cube[] cubes;

//Lines that appear on the sides
int nbMurs = 500;
Mur[] murs;
boolean isPlaying = false;
//Arduino
int ledPin = 11; // LED connected to digital pin 11
float kickSize;

int deltime = 15; //Time to make the relay on after a beat is detected
boolean delayboolean = false;




void setup()
{

//Display in 3D on the entire screen
fullScreen(P3D);

//Load the minim library
minim = new Minim(this);
arduino = new Arduino(this, Arduino.list()[0], 57600);

Arduino.list();
//Load song
song = minim.loadFile("song.mp3");

//Create the FFT object to analyze the song
fft = new FFT(song.bufferSize(), song.sampleRate());

//One cube per frequency band
nbCubes = (int)(fft.specSize()*specHi);
cubes = new Cube[nbCubes];
println(nbCubes);
//As many walls as we want
murs = new Mur[nbMurs];
println(nbMurs);
//Create all objects
//Create cubic objects
for (int i = 0; i < nbCubes; i++) {
cubes[i] = new Cube();

}

//Create wall objects
//Left walls
for (int i = 0; i < nbMurs; i+=4) {
murs[i] = new Mur(0, height/2, 10, height); 
}

//Straight walls
for (int i = 1; i < nbMurs; i+=4) {
murs[i] = new Mur(width, height/2, 10, height); 
}

//Low walls
for (int i = 2; i < nbMurs; i+=4) {
murs[i] = new Mur(width/2, height, width, 10); 
}

//High walls
for (int i = 3; i < nbMurs; i+=4) {
murs[i] = new Mur(width/2, 0, width, 10); 
}

//Black background
background(0);

//Start the song
song.play(0);

// a beat detection object that is FREQ_ENERGY mode that 
// expects buffers the length of song's buffer size
// and samples captured at songs's sample rate
beat = new BeatDetect(song.bufferSize(), song.sampleRate());
// set the sensitivity to 300 milliseconds
// After a beat has been detected, the algorithm will wait for 300 milliseconds 
// before allowing another beat to be reported. You can use this to dampen the 
// algorithm if it is giving too many false-positives. The default value is 10, 
// which is essentially no damping. If you try to set the sensitivity to a negative value, 
// an error will be reported and it will be set to 10 instead. 
beat.setSensitivity(100); 
kickSize= 16;
// make a new beat listener, so that we won't miss any buffers for the analysis
bl = new BeatListener(beat, song); 
textFont(createFont("Helvetica", 16));
textAlign(CENTER);

arduino.pinMode(ledPin, Arduino.OUTPUT); 
}


void draw()
{
//Forward the song. One draw () for each "frame" of the song ...
fft.forward(song.mix);

//Calculation of "scores" (power) for three categories of sound
//First, save old values
oldScoreLow = scoreLow;
oldScoreMid = scoreMid;
oldScoreHi = scoreHi;

//Reset values
scoreLow = 0;
scoreMid = 0;
scoreHi = 0;




//Calculate the new "scores"
for(int i = 0; i < fft.specSize()*specLow; i++)
{ 
scoreLow += fft.getBand(i);

}

for(int i = (int)(fft.specSize()*specLow); i < fft.specSize()*specMid; i++)
{
scoreMid += fft.getBand(i);

}

for(int i = (int)(fft.specSize()*specMid); i < fft.specSize()*specHi; i++)
{
scoreHi += fft.getBand(i);

}

//To slow down the descent.
if (oldScoreLow > scoreLow) {
scoreLow = oldScoreLow - scoreDecreaseRate;
}

if (oldScoreMid > scoreMid) {
scoreMid = oldScoreMid - scoreDecreaseRate;
}

if (oldScoreHi > scoreHi) {
scoreHi = oldScoreHi - scoreDecreaseRate;
}

//Volume for all frequencies at this time, with the highest sounds higher.
//This allows the animation to go faster for more high-pitched sounds, which we would notice more.
float scoreGlobal = 0.66*scoreLow + 0.8*scoreMid + 1*scoreHi;

//subtle color background
background(scoreLow/100, scoreMid/100, scoreHi/100);

//Cube for each frequency band
for(int i = 0; i < nbCubes; i++)
{
//Value of the frequency band
float bandValue = fft.getBand(i);
//println(bandValue);

//The color is represented as: red for bass, green for medium sounds and blue for high.
//The opacity is determined by the volume of the tape and the overall volume.
cubes[i].display(scoreLow, scoreMid, scoreHi, bandValue, scoreGlobal);
}

//Walls lines, here we must keep the value of the previous tape and the next to connect them together
float previousBandValue = fft.getBand(0);

//Distance between each line point, negative because on the z dimension
float dist = -25;

//Multiply the height by this constant
float heightMult = 2;

//For each band
for(int i = 1; i < fft.specSize(); i++)
{
//Value of the frequency band, we multiply the bands farther to make them more visible.
float bandValue = fft.getBand(i)*(1 + (i/50));




//Selection of the color according to the strengths of the different types of sounds.
stroke(100+scoreLow, 100+scoreMid, 100+scoreHi, 255-i);
strokeWeight(1 + (scoreGlobal/100));

//lower left line
line(0, height-(previousBandValue*heightMult), dist*(i-1), 0, height-(bandValue*heightMult), dist*i);
line((previousBandValue*heightMult), height, dist*(i-1), (bandValue*heightMult), height, dist*i);
line(0, height-(previousBandValue*heightMult), dist*(i-1), (bandValue*heightMult), height, dist*i);

//upper left line
line(0, (previousBandValue*heightMult), dist*(i-1), 0, (bandValue*heightMult), dist*i);
line((previousBandValue*heightMult), 0, dist*(i-1), (bandValue*heightMult), 0, dist*i);
line(0, (previousBandValue*heightMult), dist*(i-1), (bandValue*heightMult), 0, dist*i);

//lower right line
line(width, height-(previousBandValue*heightMult), dist*(i-1), width, height-(bandValue*heightMult), dist*i);
line(width-(previousBandValue*heightMult), height, dist*(i-1), width-(bandValue*heightMult), height, dist*i);
line(width, height-(previousBandValue*heightMult), dist*(i-1), width-(bandValue*heightMult), height, dist*i);

//upper right line
line(width, (previousBandValue*heightMult), dist*(i-1), width, (bandValue*heightMult), dist*i);
line(width-(previousBandValue*heightMult), 0, dist*(i-1), width-(bandValue*heightMult), 0, dist*i);
line(width, (previousBandValue*heightMult), dist*(i-1), width-(bandValue*heightMult), 0, dist*i);

//Save the value for the next loop round
previousBandValue = bandValue; 
}

//Rectangular walls
for(int i = 0; i < nbMurs; i++)
{
//Each wall is assigned a band, and its strength is sent to it.
float intensity = fft.getBand(i%((int)(fft.specSize()*specHi))); 
murs[i].display(scoreLow, scoreMid, scoreHi, intensity, scoreGlobal);
}
}

//Class for cubes floating in space.
class Cube {
//Z position of "spawn" and maximum Z position
float startingZ = -10000;
float maxZ = 1000;

//Position values
float x, y, z;
float rotX, rotY, rotZ;
float sumRotX, sumRotY, sumRotZ;

//Contructor
Cube() {
//Make the cube appear in a random place
x = random(0, width);
y = random(0, height);
z = random(startingZ, maxZ);

//Give the cube a random rotation
rotX = random(0, 1);
rotY = random(0, 1);
rotZ = random(0, 1);
}

void display(float scoreLow, float scoreMid, float scoreHi, float intensity, float scoreGlobal) {
//Selection of the color, opacity determined by the intensity (volume of the band)
color displayColor = color(scoreLow*0.67, scoreMid*0.67, scoreHi*0.67, intensity*5);
fill(displayColor, 255);


//Color lines, they disappear with the individual intensity of the cube
color strokeColor = color(255, 150-(20*intensity));
stroke(strokeColor);
strokeWeight(1 + (scoreGlobal/300));

//Creating a transformation matrix to perform rotations, enlargements
pushMatrix();

//Displacement
translate(x, y, z); 

//Calculation of the rotation according to the intensity for the cube
sumRotX += intensity*(rotX/1000); 
sumRotY += intensity*(rotY/1000);
sumRotZ += intensity*(rotZ/1000); 

//Application of the rotation
rotateX(sumRotX);
rotateY(sumRotY);
rotateZ(sumRotY); 

//Creation of the box, variable size according to the intensity for the cube
box(100+(intensity/2));

//Application of the matrix
popMatrix();

//Dislacement Z
z+= (1+(intensity/5)+(pow((scoreGlobal/150), 2))); 

//Replace the box at the back when it is no longer visible
if (z >= maxZ) {
x = random(0, width);
y = random(0, height);
z = startingZ;
}
}
}


//Class to display the lines on the sides
class Mur {
//Minimum and maximum position Z
float startingZ = -10000;
float maxZ = 50;

//Values at the position
float x, y, z; 
float sizeX, sizeY;

//Constructor
Mur(float x, float y, float sizeX, float sizeY) {
//Make the line appear at the specified place

this.x = x;
this.y = y;
//random depth
this.z = random(startingZ, maxZ); 

//We determine the size because the walls on the floors have a different size than those on the sides
this.sizeX = sizeX;
this.sizeY = sizeY;
}

//Display function
void display(float scoreLow, float scoreMid, float scoreHi, float intensity, float scoreGlobal) {
//Color determined by low, medium and high sounds
//Opacity determined by the overall volume
color displayColor = color(scoreLow*0.67, scoreMid*0.67, scoreHi*0.67, scoreGlobal);

//Make lines disappear in the distance to give an illusion of fog
fill(displayColor, ((scoreGlobal-5)/1000)*(255+(z/25)));
noStroke();

//First band, the one that moves according to the force
//Transformation Matrix
pushMatrix();

//Displacement
translate(x, y, z);

//extension
if (intensity > 100) intensity = 100;
scale(sizeX*(intensity/100), sizeY*(intensity/100), 20);

//Creation of the "box"
box(1);
popMatrix();

//Second band, the one that is still the same size
displayColor = color(scoreLow*0.5, scoreMid*0.5, scoreHi*0.5, scoreGlobal);
fill(displayColor, (scoreGlobal/5000)*(255+(z/25)));
//Transformation Matrix
pushMatrix();

//Displacement
translate(x, y, z);

//Extension
scale(sizeX, sizeY, 10);

//Creation of the "box"
box(1);
popMatrix();

//Displacemnt Z
z+= (pow((scoreGlobal/150), 2));
if (z >= maxZ) {
z = startingZ; 

if(beat.isKick()) {
arduino.digitalWrite(ledPin, Arduino.HIGH); // set the LED on
kickSize = 32;
delayboolean = true; //Tells a later if statement to delay for long enough for the lights to light up
}

arduino.digitalWrite(ledPin, Arduino.LOW); // set the LED off
textSize(kickSize);
text("KICK", width/4, height/2);
kickSize = constrain(kickSize * 0.95, 16, 32);


// if (bandValue == 0.01) 
//{ //if we clicked in the window
//myPort.write('1'); //send a 1
//println("1"); 
// } else 
//{ //otherwise
//myPort.write('0'); //send a 0
//} 

//try{
//Load band values
// ArrayList = (ArrayList) fft.getBand();

//float bandValue = fft.getBand();

//get first band value

// println(bandValue);

// Ascertain if the top band value is new (i.e. it's new) or if it's the same, has the count changed (i.e. it's the same value again).

// Update band value details.

//Arduino - standard LED blinky action. 

//arduino.digitalWrite(ledPin, Arduino.HIGH);
//delay(100);
//arduino.digitalWrite(ledPin, Arduino.LOW);
//}

// Slow everything down so you don't exceed perfume dispenser's rate limits. Check every 10 secs.
// delay(10000);
//} 


}
}

}
void mousePressed()
{
// if the song is already being played
// we pause it and change the value of isPlaying variable
if (isPlaying)
{
song.pause();
isPlaying = false;
}

// and if it is paused we play it and change 'isPlaying' accordingly
// :P pretty simple right?
else
{
song.play();
isPlaying = true;
}}
void stop() {
// always close Minim audio classes when you are finished with them
song.close();
// always stop Minim before exiting
minim.stop();
// this closes the sketch
super.stop();
}
void keyPressed()
{
if ( key == 'p' ) song.play(); // Press P to play the song.
if ( key == 's' ) song.pause(); // Press S to pause playing.
if ( key == 'h' ) song.rewind(); // Press H to reset to the start.
if ( key == 'f' ) song.skip(500); // Press F to fast forward.
if ( key == 'r' ) song.skip(-500); // Press R to rewind.
if ( key == 'q' ) song.close(); // Press Q to quit playing.
}

Answers

  • Is this a processing question?

    You might be better off on a specialised Arduino forum. Or a specialised perfume dispenser forum, of such a thing exists.

  • Actually, it was - the original question had 200 lines of code attached, but it was deleted by the poster...

This discussion has been closed.