Team Members¶
Section A - Joo Won Lee
Section B - Shlok Patel
Description¶
Schematic¶
Parts Needed¶
Five 8-LED WS2812b WRGB LED Strips
Sparkfun MicroSD Breakout Board
Adafruit SPW 2430 MEMS Microphone
Adafruit Bluefruit LE UART Friend
Sparkfun TPA2005D1 Class D Audio Amp
5V/2A AC to DC Power Adapter
330Ω Resistor (Orange - Orange - Brown - Gold)
Smartphone with Adafruit Bluefruit Connect App
(Optional) 10k Potentiometer
Wiring¶
WS2812b WRGB LED Strips¶
These LED Strips are chained together, with the output end of one strip connected to the input side of the next strip.
Additionally, a 330Ω Resistor is placed in series between mbed p21 and LED strip DIN to prevent any issues from voltage spikes.
mbed LED Strips
GND GND
P21 DIN
VOUT (3.3v) VCC
GND GND
MicroSD Breakout¶
mbed MicroSD Breakout
p8 CS
p5 DI
VOUT (3.3v) VCC
p7 SCK
GND GND
p6 DO
CD
MEMS Microphone¶
mbed MEMS 10uf decoupling capacitor
GND GND -
VU (5v) Vin +
p16 DC
Adafruit BLE Friend¶
mbed Adafruit BLE DC Barrel Jack
GND GND -
VIN (3.3-16V) +
nc RTS
GND CTS
p27 (Serial RX) TXO
p28 (Serial TX) RXI
Class D Audio Amp + Speaker¶
mbed TPA2005D1 DC Barrel Jack Speaker
GND PWR -, IN - -
PWR + +
p18 IN +
OUT + +
OUT - -
p29 S
Demo Setup¶
Demo Video¶
VIDEO
Code¶
main.cpp #include "mbed.h"
#include "PinDetect.h"
#include "NeoStrip.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "rtos.h"
#include <string>
#include <vector>
# define MAX_FILE 30
#define N 40
NeoStrip strip(p21, N);
//BusOut myleds(LED1,LED2,LED3,LED4);
DigitalOut myled(LED1);
DigitalIn b2(p29, PullUp);
Serial pc(USBTX, USBRX);
SDFileSystem sd(p5, p6, p7, p8, "sd");
Ticker sampletick;
AnalogOut speaker(p18); // Speaker (pin)
wave_player waver(&speaker);
Serial bt(p28, p27); // Bluetooth
DigitalOut mute(p29); // mute pin (low for shutdown)
PwmOut spk(p24);
Thread thread1;
Thread thread2;
Thread thread3;
Mutex sd_mtx;
volatile int src = 0; // 0 for Mic, 1 for SD card
vector<string> filenames; // list of files in sd card
volatile int cur_song = 1;
void read_file_names(char *dir) {
DIR *dp;
struct dirent *dirp;
dp = opendir(dir);
while ((dirp = readdir(dp)) != NULL) {
filenames.push_back(string(dirp->d_name));
}
closedir(dp);
}
class microphone
{
public :
microphone(PinName pin);
float read();
operator float ();
private :
AnalogIn _pin;
};
microphone::microphone (PinName pin):
_pin(pin)
{
}
float microphone::read()
{
return _pin.read();
}
inline microphone::operator float ()
{
return _pin.read();
}
microphone mymicrophone(p16);
uint8_t r = (uint8_t)0;
uint8_t g = (uint8_t)128;
uint8_t b = (uint8_t)0;
int red, green, blue;
// fancy function to make rainbow colors on LEDs
int hueToRGB(float h)
{
float r, g, b;
if (h > 360)
h -= 360;
if (h < 0)
h += 360;
int i = (int)(h / 60.0);
float f = (h / 60.0) - i;
float q = 1 - f;
switch (i % 6)
{
case 0: r = 1; g = f; b = 0; break;
case 1: r = q; g = 1; b = 0; break;
case 2: r = 0; g = 1; b = f; break;
case 3: r = 0; g = q; b = 1; break;
case 4: r = f; g = 0; b = 1; break;
case 5: r = 1; g = 0; b = q; break;
default: r = 0; g = 0; b = 0; break;
}
// scale to integers and return the packed value
uint8_t R = (uint8_t)(r * 255);
uint8_t G = (uint8_t)(g * 255);
uint8_t B = (uint8_t)(b * 255);
return (R << 16) | (G << 8) | B;
}
// convert float values to LED otuput for soundtest array
void float2LED(float value){
float fnumLED = abs((value - 0.5)/3.3)*100; // can mess with this scaling for better LED output
int numLED = (int)fnumLED;
if (numLED > 8) numLED = 8;
static float dh = 360.0 / 5;
static float x = 0;
for(int i = 0; i < numLED; i++){
int c = hueToRGB((dh * i) - x);
strip.setPixel(i, c);
strip.setPixel(i + 8, c);
strip.setPixel(i + 16, c);
strip.setPixel(i + 24, c);
strip.setPixel(i + 32, c);
}
for(int i = numLED; i < 8; i++){
strip.setPixel(i, 0x000000);
strip.setPixel(i + 8, 0x000000);
strip.setPixel(i + 16, 0x000000);
strip.setPixel(i + 24, 0x000000);
strip.setPixel(i + 32, 0x000000);
// old setup for 5 rows of 8 LEDs
//strip.setPixel(i + i * 7, 0x000000);
// strip.setPixel(i + 1 + i * 7, 0x000000);
// strip.setPixel(i + 2 + i * 7, 0x000000);
// strip.setPixel(i + 3 + i * 7, 0x000000);
// strip.setPixel(i + 4 + i * 7, 0x000000);
// strip.setPixel(i + 5 + i * 7, 0x000000);
// strip.setPixel(i + 6 + i * 7, 0x000000);
// strip.setPixel(i + 7 + i * 7, 0x000000);
}
x += 1;
if (x > 360)
x = 0;
}
// same thing but for the mic
void mic2LED(int mic){
static float dh = 360.0 / 5;
static float x = 0;
int numLED = 0;
if(mic == 0) numLED = 0;
else if(mic == 1) numLED = 1;
else if(mic == 2) numLED = 2;
else if(mic == 3) numLED = 3;
else if(mic == 4) numLED = 4;
else numLED = 5;
for(int i = 0; i < numLED; i++){
int c = hueToRGB((dh * i) - x);
strip.setPixel(i, c);
strip.setPixel(i + 8, c);
strip.setPixel(i + 16, c);
strip.setPixel(i + 24, c);
strip.setPixel(i + 32, c);
}
for(int i = numLED; i < 8; i++){
strip.setPixel(i, 0x000000);
strip.setPixel(i + 8, 0x000000);
strip.setPixel(i + 16, 0x000000);
strip.setPixel(i + 24, 0x000000);
strip.setPixel(i + 32, 0x000000);
}
x += 1;
if (x > 360)
x = 0;
}
void sound_thread() {
FILE *wave_file;
printf("\n\n\nHello, wave world!\n");
string songstr = "/sd/songs/" + filenames[cur_song];
printf("%s", songstr.c_str());
wave_file=fopen(songstr.c_str(),"r");
printf("file opened\n");
waver.play(wave_file);
fclose(wave_file);
Thread::yield();
}
unsigned short max_range = 0xFFFF;
// function that calls above functions
void patternSound(){
//for(int i = 0; i < 60; i++){
float sample;
float average = 0.67/3.3;//initial DC bias level
int buffer[20];
while(1){
if (src) {
// this part works for DAC PCM output //
float test = (float)waver.dac_data/max_range;
pc.printf("--%f", abs((test - 0.5)/3.3));
float2LED(test);
strip.write();
}
//------------------------------------//
else {
//microphone setup //
int centervalue;
for(int i = 0; i < 20; i++){
sample = mymicrophone;
//subtract 0.67V DC bias - but it varies quite a bit after loud or long sounds
average = 0.9999*average + 0.0001*sample;//try to slowly auto adjust the DC bias level
speaker = 0.5 +((sample - average)*33.0);//scale up to 0.0 to 1.0 for speaker output
int micvalue = int(abs((sample - average)*300.0));
//pc.printf("-%d-", micvalue); //scale to around 15 for LEDs
if(i == 1){
centervalue = micvalue;
}
buffer[i] = micvalue;
if(i > 10){
if(micvalue == buffer[1] && micvalue == buffer[2] && micvalue == buffer[3] &&
micvalue == buffer[4] && micvalue == buffer[5] && micvalue == buffer[6] &&
micvalue == buffer[7] && micvalue == buffer[8] && micvalue == buffer[9]){
centervalue = buffer[1];
//pc.printf("-%d-", centervalue);
}
}
int offset = micvalue-centervalue;
//pc.printf(" %d ", offset);
//myleds = micvalue;
mic2LED(2+offset);
wait(1.0/4000.0);
}
////////////////////////////////////////////////////////
strip.write();
Thread::wait(10);
}
}
}
void bt_thread() {
char bnum = 0;
char bhit = 0;
while(1) {
if (bt.readable()) {
if (bt.getc()=='!') {
if (bt.getc()=='B') { //button data
bnum = bt.getc(); //button number
bhit = bt.getc(); //1 = hit, 0 = release
if (bhit == '1') {
switch (bnum) {
case '1': // Button 1 for play/pause
if (waver.get_play_state() == 1) {
waver.set_play_state(0);
} else if (waver.get_play_state() == 0) {
waver.set_play_state(1);
thread2.start(sound_thread);
}
printf("%d\n\r", waver.get_play_state());
break;
case '2': // Button 2 for mute/unmute
mute = !mute;
break;
case '3': // Button 3 to switch between mic/sd
if (sd_mtx.trylock()) {
sd_mtx.lock();
src = src ? 0 : 1;
if (src) {
thread2.start(sound_thread);
} else {
waver.set_play_state(0);
while (thread2.get_state() == Thread::Running) {
Thread::yield();
}
thread2.terminate();
}
sd_mtx.unlock();
Thread::wait(100);
}
break;
case '7': // Left arrow for previous
if (sd_mtx.trylock()) {
sd_mtx.lock();
waver.set_play_state(0);
if (cur_song > 0) {
--cur_song;
}
while (thread2.get_state() == Thread::Running) {
Thread::yield();
}
thread2.terminate();
thread2.start(sound_thread);
waver.set_play_state(1);
sd_mtx.unlock();
}
break;
case '8': // Right arrow for skip
if (sd_mtx.trylock()) {
sd_mtx.lock();
waver.set_play_state(0);
if (cur_song < filenames.size() - 1) {
++cur_song;
}
while (thread2.get_state() == Thread::Running) {
Thread::yield();
}
thread2.terminate();
thread2.start(sound_thread);
waver.set_play_state(1);
sd_mtx.unlock();
}
break;
default:
break;
}
}
}
}
}
Thread::wait(100);
}
}
int main() {
read_file_names("/sd/songs");
strip.setBrightness(0.05);
mute = 1;
thread1.start(bt_thread);
thread2.start(sound_thread);
thread3.start(patternSound);
while(1){
myled = !myled;
Thread::wait(100);
}
}
working LED code #include "mbed.h"
#include <string>
#include "PinDetect.h"
#include "NeoStrip.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "rtos.h"
# define MAX_FILE 30
#define N 40
NeoStrip strip(p21, N);
BusOut myleds(LED1,LED2,LED3,LED4);
DigitalIn b2(p29, PullUp);
Serial pc(USBTX, USBRX);
SDFileSystem sd(p5, p6, p7, p8, "sd");
Ticker sampletick;
AnalogOut speaker(p18); // Speaker (pin)
wave_player waver(&speaker);
PwmOut spk(p24);
Thread thread1;
Thread thread2;
Thread thread3;
Thread thread4;
class microphone
{
public :
microphone(PinName pin);
float read();
operator float ();
private :
AnalogIn _pin;
};
microphone::microphone (PinName pin):
_pin(pin)
{
}
float microphone::read()
{
return _pin.read();
}
inline microphone::operator float ()
{
return _pin.read();
}
microphone mymicrophone(p16);
uint8_t r = (uint8_t)0;
uint8_t g = (uint8_t)128;
uint8_t b = (uint8_t)0;
int red, green, blue;
// fancy function to make rainbow colors on LEDs
int hueToRGB(float h)
{
float r, g, b;
if (h > 360)
h -= 360;
if (h < 0)
h += 360;
int i = (int)(h / 60.0);
float f = (h / 60.0) - i;
float q = 1 - f;
switch (i % 6)
{
case 0: r = 1; g = f; b = 0; break;
case 1: r = q; g = 1; b = 0; break;
case 2: r = 0; g = 1; b = f; break;
case 3: r = 0; g = q; b = 1; break;
case 4: r = f; g = 0; b = 1; break;
case 5: r = 1; g = 0; b = q; break;
default: r = 0; g = 0; b = 0; break;
}
// scale to integers and return the packed value
uint8_t R = (uint8_t)(r * 255);
uint8_t G = (uint8_t)(g * 255);
uint8_t B = (uint8_t)(b * 255);
return (R << 16) | (G << 8) | B;
}
// convert float values to LED otuput for soundtest array
void float2LED(float value){
float fnumLED = abs((value - 0.5)/3.3)*100; // can mess with this scaling for better LED output
int numLED = (int)fnumLED;
if (numLED > 8) numLED = 8;
static float dh = 360.0 / 5;
static float x = 0;
for(int i = 0; i < numLED; i++){
int c = hueToRGB((dh * i) - x);
strip.setPixel(i, c);
strip.setPixel(i + 8, c);
strip.setPixel(i + 16, c);
strip.setPixel(i + 24, c);
strip.setPixel(i + 32, c);
}
for(int i = numLED; i < 8; i++){
strip.setPixel(i, 0x000000);
strip.setPixel(i + 8, 0x000000);
strip.setPixel(i + 16, 0x000000);
strip.setPixel(i + 24, 0x000000);
strip.setPixel(i + 32, 0x000000);
// old setup for 5 rows of 8 LEDs
//strip.setPixel(i + i * 7, 0x000000);
// strip.setPixel(i + 1 + i * 7, 0x000000);
// strip.setPixel(i + 2 + i * 7, 0x000000);
// strip.setPixel(i + 3 + i * 7, 0x000000);
// strip.setPixel(i + 4 + i * 7, 0x000000);
// strip.setPixel(i + 5 + i * 7, 0x000000);
// strip.setPixel(i + 6 + i * 7, 0x000000);
// strip.setPixel(i + 7 + i * 7, 0x000000);
}
x += 1;
if (x > 360)
x = 0;
}
// same thing but for the mic
void mic2LED(int mic){
static float dh = 360.0 / 5;
static float x = 0;
int numLED = 0;
if(mic == 0) numLED = 0;
else if(mic == 1) numLED = 1;
else if(mic == 2) numLED = 2;
else if(mic == 3) numLED = 3;
else if(mic == 4) numLED = 4;
else numLED = 5;
for(int i = 0; i < numLED; i++){
int c = hueToRGB((dh * i) - x);
strip.setPixel(i, c);
strip.setPixel(i + 8, c);
strip.setPixel(i + 16, c);
strip.setPixel(i + 24, c);
strip.setPixel(i + 32, c);
}
for(int i = numLED; i < 8; i++){
strip.setPixel(i, 0x000000);
strip.setPixel(i + 8, 0x000000);
strip.setPixel(i + 16, 0x000000);
strip.setPixel(i + 24, 0x000000);
strip.setPixel(i + 32, 0x000000);
}
x += 1;
if (x > 360)
x = 0;
}
void sound_thread() {
while(1){
FILE *wave_file;
printf("\n\n\nHello, wave world!\n");
wave_file=fopen("/sd/runningmono.wav","r");
printf("file opened\n");
waver.play(wave_file);
fclose(wave_file);
Thread::yield();
}
}
unsigned short max_range = 0xFFFF;
// function that calls above functions
void patternSound(){
//for(int i = 0; i < 60; i++){
float sample;
float average = 0.67/3.3;//initial DC bias level
int buffer[20];
while(1){
// this part works for DAC PCM output //
float test = (float)waver.dac_data/max_range;
pc.printf("--%f", abs((test - 0.5)/3.3));
float2LED(test);
//------------------------------------//
//microphone setup //
//int centervalue;
// for(int i = 0; i < 20; i++){
// sample = mymicrophone;
// //subtract 0.67V DC bias - but it varies quite a bit after loud or long sounds
// average = 0.9999*average + 0.0001*sample;//try to slowly auto adjust the DC bias level
// speaker = 0.5 +((sample - average)*33.0);//scale up to 0.0 to 1.0 for speaker output
//
// int micvalue = int(abs((sample - average)*300.0));
// //pc.printf("-%d-", micvalue); //scale to around 15 for LEDs
//
// if(i == 1){
// centervalue = micvalue;
// }
// buffer[i] = micvalue;
// if(i > 10){
// if(micvalue == buffer[1] && micvalue == buffer[2] && micvalue == buffer[3] &&
// micvalue == buffer[4] && micvalue == buffer[5] && micvalue == buffer[6] &&
// micvalue == buffer[7] && micvalue == buffer[8] && micvalue == buffer[9]){
// centervalue = buffer[1];
// //pc.printf("-%d-", centervalue);
// }
// }
// int offset = micvalue-centervalue;
// pc.printf(" %d ", offset);
// myleds = micvalue;
// mic2LED(2+offset);
// wait(1.0/4000.0);
// }
////////////////////////////////////////////////////////
strip.write();
Thread::wait(10);
}
}
int main() {
strip.setBrightness(0.05);
thread1.start(patternSound);
thread2.start(sound_thread);
while(1){
Thread::wait(100);
}
}