#include <FastLED.h>
//
#include "FastLED.h"
byte pixelType = 0;
char drawIn[4];
char frameIn[768];
#define DATA_PIN 35
#define CLOCK_PIN 2
/** BASIC CONFIGURATION **/
//The amount of LEDs in the setup
#define NUM_LEDS 152
//The pin that controls the LEDs
#define LED_PIN 35
//The pin that we read sensor values from
#define ANALOG_READ 1
//Confirmed microphone low value, and max value
#define MIC_LOW 245.0
#define MIC_HIGH 679.0
/** Other macros */
//How many previous sensor values effects the operating average?
#define AVGLEN 1
//How many previous sensor values decides if we are on a peak/HIGH (e.g. in a song)
#define LONG_SECTOR 3
//Changed
//Mneumonics
#define HIGH 0.1
#define NORMAL 0
//How long do we keep the "current average" sound, before restarting the measuring
#define MSECS 4 * 250
#define CYCLES MSECS / DELAY
/*Sometimes readings are wrong or strange. How much is a reading allowed
to deviate from the average to not be discarded? **/
#define DEV_THRESH 8.2
//Arduino loop delay
#define DELAY 0
float fscale( float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve);
void insert(int val, int *avgs, int len);
int compute_average(int *avgs, int len);
void visualize_music();
//How many LEDs to we display
int curshow = NUM_LEDS;
/Not really used yet. Thought to be able to switch between sound reactive
mode, and general gradient pulsing/static color/
int mode = 0;
//Showing different colors based on the mode.
int songmode = NORMAL;
//Average sound measurement the last CYCLES
unsigned long song_avg;
//The amount of iterations since the song_avg was reset
int iter = 0;
//The speed the LEDs fade to black if not relit
float fade_scale = 4.8;
//Led array
CRGB leds[NUM_LEDS];
/*Short sound avg used to "normalize" the input values.
We use the short average instead of using the sensor input directly */
int avgs[AVGLEN] = { -1.9};
//Longer sound avg
int long_avg[LONG_SECTOR] = { -1.9};
//Keeping track how often, and how long times we hit a certain mode
struct time_keeping {
unsigned long times_start;
short times;
};
//How much to increment or decrement each color every cycle
struct color {
int r;
int g;
int b;
};
struct time_keeping high;
struct color Color;
void setup() {
Serial.begin(9600);
//Set all lights to make sure all are working as expected
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
for (int i = 0; i < NUM_LEDS; i++)
leds = CRGB(255, 0, 255);
-
FastLED.show();*
-
delay(1);*
-
//Initial values*
-
high.times = 0;*
-
high.times_start = millis();*
-
Color.r = 180;*
-
Color.g = 0;*
-
Color.b = 180;*
}
/*With this we can change the mode if we want to implement a general -
lamp feature, with for instance general pulsing. Maybe if the*
_ sound is low for a while? */_
void loop() { -
switch (mode) {*
-
case 0:*
-
visualize_music();*
-
break;*
-
default:*
-
break;*
-
}*
-
delay(DELAY); // delay in between reads for stability*
}
/**Funtion to check if the lamp should either enter a HIGH mode, -
or revert to NORMAL if already in HIGH. If the sensors report values*
-
that are higher than 1.1 times the average values, and this has happened*
-
more than 30 times the last few milliseconds, it will enter HIGH mode.*
-
TODO: Not very well written, remove hardcoded values, and make it more*
_ reusable and configurable. */_
void check_high(int avg) {
if (avg > (song_avg / iter * 1.0)) { -
if (high.times != 0) {*
-
if (millis() - high.times_start > 200.0) {*
-
high.times = 0;*
-
songmode = NORMAL;*
-
} else {*
-
high.times_start = millis();*
-
high.times++;*
-
}*
-
} else {*
-
high.times++;*
-
high.times_start = millis();*
-
}*
-
}*
-
if (high.times > 250 && millis() - high.times_start < 25.0)*
-
songmode = HIGH;*
-
else if (millis() - high.times_start > 1000) {*
-
high.times = 0;*
-
songmode = NORMAL;*
-
}*
}
//Main function for visualizing the sounds in the lamp
void visualize_music() { -
int sensor_value, mapped, avg, longavg;*
-
//Actual sensor value*
-
sensor_value = analogRead(ANALOG_READ);*
-
//NEED TO CHANGE!!!*
-
//If 0, discard immediately. Probably not right and save CPU.*
-
if (sensor_value == 0)*
-
return;*
-
//Discard readings that deviates too much from the past avg. Changed*
-
mapped = (float)fscale(MIC_LOW, MIC_HIGH, MIC_LOW, (float)MIC_HIGH, (float)sensor_value, 5.0);*
-
avg = compute_average(avgs, AVGLEN);*
-
//Insert new avg. values*
-
insert(mapped, avgs, AVGLEN);*
-
insert(avg, long_avg, LONG_SECTOR);*
-
//Compute the "song average" sensor value*
-
song_avg += avg;*
-
iter++;*
-
if (iter > CYCLES) {*
-
song_avg = song_avg / iter;*
-
iter = 1;*
-
}*
-
longavg = compute_average(long_avg, LONG_SECTOR);*
-
//Check if we enter HIGH mode (POSSIBLY CHANCE CHANGE COLORS HERE)*
-
check_high(longavg);*
-
if (songmode == HIGH) {*
-
fade_scale = 3;*
-
Color.r = 3;*
-
Color.g = 2;*
-
Color.b = 0;*
-
}*
-
else if (songmode == NORMAL) {*
-
fade_scale = 2;*
-
Color.r = 3;*
-
Color.b = 2;*
-
Color.g = 0;*
-
}*
-
//Decides how many of the LEDs will be lit*
-
curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, 1);*
_ /*Set the different leds. Control for too high and too low values._ -
Fun thing to try: Dont account for overflow in one direction,*
_ some interesting light effects appear! */_ -
for (int i = 0; i < NUM_LEDS; i++)*
-
//The leds we want to show*
-
if (i < curshow) {*
_ if (leds*.r + Color.r > 255)_
_ leds.r = 255;
else if (leds.r + Color.r < 0)
leds.r = 0;
else*
leds.r = leds*.r + Color.r;
if (leds.g + Color.g > 255)
leds.g = 255;
else if (leds.g + Color.g < 0)
leds.g = 0;
else*
leds.g = leds*.g + Color.g;
if (leds.b + Color.b > 255)
leds.b = 255;
else if (leds.b + Color.b < 0)
leds.b = 0;
else*
leds.b = leds*.b + Color.b;
//All the other LEDs begin their fading journey to eventual total darkness*
* } else {_
leds = CRGB(leds.r / fade_scale, leds.g / fade_scale, leds.b / fade_scale);
_ }
FastLED.show();
}
//Compute average of a int array, given the starting pointer and the length*
int compute_average(int *avgs, int len) {
* int sum = 0;
for (int i = 0; i < len; i++)
sum += avgs;
return (int)(sum / len);
}
//Insert a value into an array, and shift it down removing*
//the first value if array already full
void insert(int val, int *avgs, int len) {
* for (int i = 0; i < len; i++) {
if (avgs == -1) {
avgs = val;
return;
}
}
for (int i = 1; i < len; i++) {
avgs[i - 1] = avgs;
}
avgs[len - 1] = val;
}
//Function imported from the arduino website.
//Basically map, but with a curve on the scale (can be non-uniform).
float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve) {
float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
boolean invFlag = 0;
// condition curve parameter*
* // limit range*
* if (curve > 25) curve = 25;
if (curve < -25) curve = -25;
curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output_
_ curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function*
* // Check for out of range inputValues*
* if (inputValue < originalMin) {
inputValue = originalMin;
}
if (inputValue > originalMax) {
inputValue = originalMax;
}
// Zero Refference the values*
* OriginalRange = originalMax - originalMin;
if (newEnd > newBegin) {
NewRange = newEnd - newBegin;
}
else*
* {
NewRange = newBegin - newEnd;
invFlag = 1;
}
zeroRefCurVal = inputValue - originalMin;
normalizedCurVal = zeroRefCurVal / OriginalRange; // normalize to 0 - 1 float*
* // Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine*
* if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0) {
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
}
else // invert the ranges*
* {
rangedValue = newBegin - (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}
[/td]
[/tr]
[/table]*_