The rMP3 has (as of firmware version 100.02-b002) a command to retrieve values from a built-in spectrum analyzer. You can select the number of, and the frequency of the bands you want to monitor).
You can read more about the firmware update here: rMP3 Beta Firmware
You'll need the following Arduino libraries:
Setting and retrieving the values from the rMP3 is the easy part.
First, you need to set the bands you want to work with. I did this in the playTrack() function:
void playTrack(void) { char mp3path[128]; // ... rmp3.playfile(mp3path); rmp3.setspectrumanalyzer(bandfreqs, 10); Serial.println("Playing"); }
Then, to retrieve the values (while the rMP3 is playing the file):
void doLCDSpec(void) { // prepare for up to 23 bands uint8_t v[23]; rmp3.getspectrumanalyzer(v);
The tough part is getting it displayed on the LCD.
Luckily I wrote some functions to make vertical bars get displayed on the SerLCD controlled LCD.
First you need to prepare all of the “custom characters” on the LCD - we need to have the 8 different levels because each character on the LCD has 8 rows.
void lcdCustomChars(void) { // sets up the custom chars byte chars[] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 }; for (int i = 0; i < 8; i++) lcdSetCustomChar(i, chars + i*8); delay(100); }
Now for the weird and strange looking math. We need to translate a value into a vertical bar to be displayed on the LCD. It's a bit tricky, but not all that difficult.
The function below maps the value to match the number of bars (i.e. how tall? if you have a 2 line LCD, you can either use 1 or 2 bars). Then it draws the bar as tall as it needs based on the value. FYI: x refers to which column you are drawing.
void lcdSpecMap(int x, int value, int numBars) { int8_t i, val; // map value of 0 - maxSpecValue -> 0->7, 0->15, 0->23, 0->31 if (value > maxSpecValue) value = maxSpecValue; value = map(value, 0, maxSpecValue, 0, 8*numBars); for (i = 0; i < numBars; i++) { lcdGotoXY(x, i); val = value - (8 * (numBars - 1 - i)); if (val <= 0) val = ' '; else if (val > 8) val = 7; else val -= 1; LCD.print(val, BYTE); } }
#include <RogueMP3.h> #include <RogueSD.h> #include <NewSoftSerial.h> NewSoftSerial LCD(255, 4); NewSoftSerial rmp3_s(6, 7); RogueMP3 rmp3(rmp3_s); RogueSD filecommands(rmp3_s); uint16_t bandfreqs[] = { 50, 120, 200, 500, 1000, 2000, 5000, 8000, 10000, 20000 }; uint16_t numfiles = 0; #define MP3PATH "/mp3/" // you need to put the two double quotes ("") in the middle below, // because the Arduino IDE looks for unclosed comments. #define MP3FILTER "/mp3/""*.mp3" #define lcdHeight 4 #define lcdWidth 20 #define maxSpecValue 20 void lcdClear() { LCD.print(0xFE, BYTE); //command flag LCD.print(0x01, BYTE); //clear command. } void lcdBacklightOn(uint8_t level) { //turns on the backlight LCD.print(0x7C, BYTE); //command flag for backlight stuff LCD.print(level, BYTE); //light level. } void lcdBacklightOff() { //turns off the backlight LCD.print(0x7C, BYTE); //command flag for backlight stuff LCD.print(0x80, BYTE); //light level for off. } void lcdGotoXY(int x, int y) { int pos; if (x >= lcdWidth) x = lcdWidth-1; if (y >= lcdHeight) y = lcdHeight-1; pos = x + ((y % 2) * 0x40); if (y >= 2) pos += lcdWidth; LCD.print(0xFE, BYTE); LCD.print(0x80 + pos, BYTE); } void lcdSetCustomChar(byte pos, byte values[]) { LCD.print(0xFE, BYTE); LCD.print(0x40 + pos * 8, BYTE); for (int i = 0; i < 8; i++) LCD.print(values[i], BYTE); } void lcdCustomChars(void) { // sets up the custom chars byte chars[] = { 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b00000, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b00000, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 }; for (int i = 0; i < 8; i++) lcdSetCustomChar(i, chars + i*8); delay(100); } void lcdSpecMap(int x, int value, int numBars) { int8_t i, val; // map value of 0 - maxSpecValue -> 0->7, 0->15, 0->23, 0->31 if (value > maxSpecValue) value = maxSpecValue; value = map(value, 0, maxSpecValue, 0, 8*numBars); for (i = 0; i < numBars; i++) { lcdGotoXY(x, i); val = value - (8 * (numBars - 1 - i)); if (val <= 0) val = ' '; else if (val > 8) val = 7; else val -= 1; LCD.print(val, BYTE); } } void doLCDSpec(void) { // prepare for up to 23 bands uint8_t v[23]; rmp3.getspectrumanalyzer(v); for (uint8_t i=0; i<10; i++) { // lcdSpecMap(i, v[i], 4); // we are displaying each band in two columns. // so, band 0 goes on columns 0 and 1, band 1 on 2 and 3, band 2 on 4 and 5, etc... lcdSpecMap(2*i, v[i], 4); lcdSpecMap(2*i+1, v[i], 4); } } void setup(void) { Serial.begin(9600); Serial.println("Started"); LCD.begin(9600); for(int i = 0; i < 10; i++) { LCD.print(18, BYTE); delay(20); } LCD.print(124, BYTE); LCD.print(16, BYTE); delay(20); LCD.begin(38400); rmp3_s.begin(38400); pinMode(2, INPUT); pinMode(3, INPUT); lcdCustomChars(); lcdClear(); Serial.println("Starting sync"); rmp3.sync(); filecommands.sync(); Serial.println("Done sync"); lcdGotoXY((lcdWidth - 5)/2, 0); LCD.print("Ready"); } void playTrack(void) { char mp3path[128]; numfiles = filecommands.filecount(MP3FILTER); Serial.print("MP3 count: "); Serial.println(numfiles, DEC); // play a file (random) strcpy(mp3path, MP3PATH); filecommands.entrytofilename(mp3path + strlen(mp3path), 127, MP3FILTER, random(0, numfiles)); Serial.println(mp3path); rmp3.playfile(mp3path); rmp3.setspectrumanalyzer(bandfreqs, 10); Serial.println("Playing"); } void loop(void) { int i; static char status = 'S'; status = rmp3.getplaybackstatus(); while (status == 'P') { doLCDSpec(); status = rmp3.getplaybackstatus(); } if (status == 'S') { lcdGotoXY((lcdWidth - 7) / 2, 0); LCD.print("Stopped"); if (filecommands.status() == 0) // card is inserted and waiting playTrack(); status = rmp3.getplaybackstatus(); } }
Please, if you have any questions, don't hesitate to ask. Make comments below.
Discussion
Friend, where to buy! and most impotante this spectrum allows the code changes, putting graphic effects in the program through the arduino. the code of this graph is open to change? ex: ten effect http://www.youtube.com/watch?v=9M5OOPE06x4&feature=related
Friend, where to buy! and most impotante this spectrum allows the code changes, putting graphic effects in the program through the arduino. the code of this graph is open to change? ex: ten effect http://www.youtube.com/watch?v=9M5OOPE06x4&feature=related