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¶
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);
}
}