Light up bra with added on mic amp sensor
Materials:
FLORA board
6 jumper wires
3 thin grey wires
1 soldering iron
1 soldering wire
1 decorative bra/costume
1 3.3v batter
wire clippers
wire strippers
heat shrink
1 mic amp sensor
1. Because I was adding an additional sensor and neopixel ring to my project, I had to put my original code together with my mic amp (sound sensor) code.
2. I added another neopixel ring onto the bra next to the first one and had soldered it together the same way as the first one. I cut and stripped the 3 jumper cables then soldered them to the thin grey wires, and then put a piece of heat shrink over all 3.
3. I soldered the 3 grey wires to the appropriate pins on the FLORA board. Power to power, ground to ground, input to pin TX1.
4. I soldered the 3 pins from the mic amp sensor to the FLORA as well. Power to power, ground to ground, output to pin #12.
4. I connected the flora to the computer and uploaded the integrated code between the mic amp sensor and accelormeter and the additional neopixel ring. The Idea behind this is when at a music festival, the loudness of the music triggers the neopixel ring to light up in sequence.
Code :
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_NeoPixel.h>
#define PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, PIN, NEO_GRB + NEO_KHZ800);
int ringRightSide[] = {0, 1, 2, 3, 4, 5};
int ringLeftSide[] = {11, 10, 9, 8, 7, 6, 5};
// Used for software SPI
//#define LIS3DH_CLK 13
//#define LIS3DH_MISO 12
#define LIS3DH_MOSI 10
// Used for hardware & software SPI
#define LIS3DH_CS 9
// software SPI
//Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS, LIS3DH_MOSI, LIS3DH_MISO, LIS3DH_CLK);
// hardware SPI
//Adafruit_LIS3DH lis = Adafruit_LIS3DH(LIS3DH_CS);
// I2C
Adafruit_LIS3DH lis = Adafruit_LIS3DH();
#define N_PIXELS 12 // Number of pixels in strand
#define MIC_PIN A11 // Microphone is attached to this analog pin
#define LED_PIN 1 // NeoPixel LED strand is connected to this pin
#define DC_OFFSET 0 // DC offset in mic signal – if unusure, leave 0
#define NOISE 10 // Noise/hum/interference in mic signal
#define SAMPLES 20 // Length of buffer for dynamic level adjustment
#define TOP (N_PIXELS + 2) // Allow dot to go slightly off scale
#define PEAK_FALL 4 // Rate of peak falling dot
byte
peak = 0, // Used for falling dot
dotCount = 0, // Frame counter for delaying dot-falling speed
volCount = 0; // Frame counter for storing past volume data
int
vol[SAMPLES], // Collection of prior volume samples
lvl = 10, // Current “dampened” audio level
minLvlAvg = 0, // For dynamic adjustment of graph low & high
maxLvlAvg = 400;
Adafruit_NeoPixel
strip2 = Adafruit_NeoPixel(N_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);
#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endif
// Adjust this number for the sensitivity of the ‘click’ forc
// this strongly depend on the range! for 16G, try 5-10
// for 8G, try 10-20. for 4G try 20-40. for 2G try 40-80
#define CLICKTHRESHHOLD 60
void setup(void) {
strip.begin();
strip.show(); // Initialize all pixels to ‘off’
strip2.begin();
strip2.show(); // Initialize all pixels to ‘off’
memset(vol, 0, sizeof(vol));
#ifndef ESP8266
while (!Serial); // will pause Zero, Leonardo, etc until serial console opens
#endif
Serial.begin(9600);
// Serial.println(“Adafruit LIS3DH Tap Test!”);
if (! lis.begin(0x18)) { // change this to 0x19 for alternative i2c address
// Serial.println(“Couldnt start”);
while (1);
}
// Serial.println(“LIS3DH found!”);
lis.setRange(LIS3DH_RANGE_2_G); // 2, 4, 8 or 16 G!
//Serial.print(“Range = “); Serial.print(2 << lis.getRange());
// Serial.println(“G”);
// 0 = turn off click detection & interrupt
// 1 = single click only interrupt output
// 2 = double click only interrupt output, detect single click
// Adjust threshhold, higher numbers are less sensitive
lis.setClick(2, CLICKTHRESHHOLD);
delay(100);
}
int pos = 0;
int pos2 = 0;
void loop() {
// vuMeter();
rainbow(1);
uint8_t click = lis.getClick();
//if (click == 0) return;
//if (! (click & 0x30)) return;
//Serial.print(“Click detected (0x”); Serial.print(click, HEX); Serial.print(“): “);
if (click & 0x10 || click & 0x6A || click & 0x6C || click & 0x61 || click & 0x1A) {
// Serial.print(” single click”);
lights();
}
// else {
// rainbow(1);
// }
//strip.show(); // Initialize all pixels to ‘off’
// Serial.println();
//delay(10);
return;
}
void lights() {
for (int x=0; x<9; x++) {
// Draw 5 pixels centered on pos. setPixelColor() will clip any
// pixels off the ends of the strip, we don’t need to watch for that.
strip.setPixelColor(ringRightSide[abs((pos – 2) % 7)], strip.Color(0, 0, 80)); // Dark blue
strip.setPixelColor(ringLeftSide[abs((pos – 2) % 7)], strip.Color(0, 0, 80)); // Dark blue
strip.setPixelColor(ringRightSide[abs((pos – 1) % 7)], strip.Color(0, 0, 150)); // Medium blue
strip.setPixelColor(ringRightSide[abs((pos ) % 7)], strip.Color(15, 15, 200)); // Center pixel is brightest
strip.setPixelColor(ringRightSide[abs((pos + 1) % 7)], strip.Color(0, 0, 150)); // Medium blue
strip.setPixelColor(ringRightSide[abs((pos + 2) % 7)], strip.Color(0, 0, 80)); // Dark blue
strip.setPixelColor(ringLeftSide[abs((pos – 2) % 7)], strip.Color(0, 0, 80)); // Dark blue
strip.setPixelColor(ringLeftSide[abs((pos – 1) % 7)], strip.Color(0, 0, 150)); // Medium blue
strip.setPixelColor(ringLeftSide[abs((pos ) % 7)], strip.Color(15, 15, 200)); // Center pixel is brightest
strip.setPixelColor(ringLeftSide[abs((pos + 1) % 7)], strip.Color(0, 0, 150)); // Medium blue
strip.setPixelColor(ringLeftSide[abs((pos + 2) % 7)], strip.Color(0, 0, 80)); // Dark blue
strip.show();
delay(200);
// Rather than being sneaky and erasing just the tail pixel,
// it’s easier to erase it all and draw a new one next time.
for (int j = -2; j <= 1; j++) {
strip.setPixelColor(ringRightSide[(pos + j) % 9], 0);
strip.setPixelColor(ringLeftSide[(pos + j) % 9], 0);
// strip.setPixelColor(singlePixels[(pos2+j)%5], 0);
}
pos += 1;
if (pos < 0) {
pos = 1;
} else if (pos >= 7) {
pos = 0;
}
pos2 += 1;
if (pos2 < 0) {
pos2 = 1;
} else if (pos2 >= 1) {
// } else if(pos2 >= 6) {
pos2 = 0;
}
}
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
void rainbow(uint8_t wait) {
uint16_t i, j;
for(j=0; j<256; j++) {
vuMeter();
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
strip2.show();
delay(wait);
// delay(2);
}
}
void vuMeter() {
uint8_t i;
uint16_t minLvl, maxLvl;
int n, height;
n = analogRead(MIC_PIN); // Raw reading from mic
//Serial.println(MIC_PIN);
n = abs(n – 512 – DC_OFFSET); // Center on zero
n = (n <= NOISE) ? 0 : (n – NOISE); // Remove noise/hum
lvl = ((lvl * 7) + n) >> 3; // “Dampened” reading (else looks twitchy)
// Serial.print(“Level “);
Serial.println(lvl);
//lvl = abs(map(lvl,20, 450, 0, 1024));
// Calculate bar height based on dynamic min/max levels (fixed point):
height = TOP * (lvl – minLvlAvg) / (long)(maxLvlAvg – minLvlAvg);
if (height < 0L) height = 0; // Clip output
else if (height > TOP) height = TOP;
if (height > peak) peak = height; // Keep ‘peak’ dot at top
// Color pixels based on rainbow gradient
for (i = 0; i < N_PIXELS; i++) {
if (i >= height) strip2.setPixelColor(i, 0, 0, 0);
else strip2.setPixelColor(i, Wheel(map(i, 0, strip2.numPixels() – 1, 30, 150)));
}
// Draw peak dot
// if (peak > 0 && peak <= N_PIXELS – 1) strip2.setPixelColor(peak, Wheel(map(peak, 0, strip2.numPixels() – 1, 30, 150)));
strip2.show(); // Update strip2
// Every few frames, make the peak pixel drop by 1:
if (++dotCount >= PEAK_FALL) { //fall rate
if (peak > 0) peak–;
dotCount = 0;
}
vol[volCount] = n; // Save sample for dynamic leveling
if (++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter
// Get volume range of prior frames
minLvl = maxLvl = vol[0];
for (i = 1; i < SAMPLES; i++) {
if (vol[i] < minLvl) minLvl = vol[i];
else if (vol[i] > maxLvl) maxLvl = vol[i];
}
// minLvl and maxLvl indicate the volume range over prior frames, used
// for vertically scaling the output graph (so it looks interesting
// regardless of volume level). If they’re too close together though
// (e.g. at very low volume levels) the graph becomes super coarse
// and ‘jumpy’…so keep some minimum distance between them (this
// also lets the graph go to zero when no sound is playing):
if ((maxLvl – minLvl) < TOP) maxLvl = minLvl + TOP;
minLvlAvg = (minLvlAvg * 63 + minLvl) >> 6; // Dampen min/max levels
maxLvlAvg = (maxLvlAvg * 63 + maxLvl) >> 6; // (fake rolling average)
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r – g – b – back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 – WheelPos;
if(WheelPos < 85) {
return strip.Color(255 – WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return strip.Color(0, WheelPos * 3, 255 – WheelPos * 3);
}
WheelPos -= 170;
return strip.Color(WheelPos * 3, 255 – WheelPos * 3, 0);
}
Video: