diff --git a/MSGEQ7.cpp b/MSGEQ7.cpp deleted file mode 100644 index 8d05226..0000000 --- a/MSGEQ7.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* -Copyright (c) 2014 NicoHood -See the readme for credit to other people. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include "MSGEQ7.h" - -//================================================================================ -// MSGEQ7 -//================================================================================ - -CMSGEQ7 MSGEQ7; - -CMSGEQ7::CMSGEQ7(void){ - // set pins to an invalid value to avoid writing to random pins if no begin() was called - _resetPin = 0xFF; - _strobePin = 0xFF; - _analogPinLeft = 0xFF; - _analogPinRight = 0xFF; - _countRead = 0; -} - -void CMSGEQ7::begin(uint8_t resetPin, uint8_t strobePin, - uint8_t analogPinLeft, uint8_t analogPinRight){ - - // initialize this instance's variables - _resetPin = resetPin; - _strobePin = strobePin; - _analogPinLeft = analogPinLeft; - - // if right pin wasnt set just read the other twice - if (analogPinRight == 0xFF) - analogPinRight = analogPinLeft; - _analogPinRight = analogPinRight; - - // do whatever is required to initialize the IC - pinMode(_resetPin, OUTPUT); - pinMode(_strobePin, OUTPUT); - pinMode(_analogPinLeft, INPUT); - pinMode(_analogPinRight, INPUT); - reset(); -} - -void CMSGEQ7::reset(void){ - //only this setting seems to works properly - digitalWrite(_strobePin, LOW); - digitalWrite(_resetPin, HIGH); - digitalWrite(_resetPin, LOW); -} - -void CMSGEQ7::read(void){ - // increase counter. reset if it reaches bounds - _countRead++; - if (_countRead == MSGEQ7_READINGS) _countRead = 0; - - // reset the IC, optional, do this on your own if needed - //reset(); - - // read all 7 channels - // 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz - for (int i = 0; i < 7; i++){ - // trigger next value - digitalWrite(_strobePin, HIGH); - digitalWrite(_strobePin, LOW); - - // allow the output to settle - delayMicroseconds(36); - - // read pins with 8 bit resolution - _left[i][_countRead] = analogRead(_analogPinLeft) >> 2; - _right[i][_countRead] = analogRead(_analogPinRight) >> 2; - } -} - -uint8_t CMSGEQ7::get(uint8_t frequency, uint8_t channel){ - // dont read out of bounds - if (frequency >= 7) return 0; - - // returns the average of the last MSGEQ7_READINGS - uint16_t average = 0; - - for (int i = 0; i < MSGEQ7_READINGS; i++){ - // left channel - if (channel == MSGEQ7_LEFT) - average += _left[frequency][i]; - // right channel - else if (channel == MSGEQ7_RIGHT) - average += _right[frequency][i]; - // left + right channel - else - average += (_left[frequency][i] + _right[frequency][i]) / 2; - } - return average / MSGEQ7_READINGS; -} - -uint8_t CMSGEQ7::peek(uint8_t frequency, uint8_t channel){ - // dont read out of bounds - if (frequency >= 7) return 0; - - // returns the very last measurement - - // left channel - if (channel == MSGEQ7_LEFT) - return _left[frequency][_countRead]; - // right channel - else if (channel == MSGEQ7_RIGHT) - return _right[frequency][_countRead]; - // left + right channel - else - return uint16_t(_left[frequency][_countRead] + _right[frequency][_countRead]) / 2; -} diff --git a/MSGEQ7.h b/MSGEQ7.h index ddbaa3c..01a7014 100644 --- a/MSGEQ7.h +++ b/MSGEQ7.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2014 NicoHood +Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -21,59 +21,87 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// include guard +#pragma once -#ifndef MSGEQ7_h -#define MSGEQ7_h +// software version +#define MSGEQ7_VERSION 120 -// needed for digitalRead() and analogRead() +// needed for digitalRead(), analogRead() and micros() #include //================================================================================ // MSGEQ7 //================================================================================ -//number of reading times for smoothing, default 5 -#define MSGEQ7_READINGS 5 - -// basic frequencys definitions (0-6 valid) +//#define MSGEQ7_10BIT +#define ReadsPerSecond(f) (1000000UL / (f)) + +// basic frequencys definitions (0-6 valid, 7 channels) +#define MSGEQ7_0 0 +#define MSGEQ7_1 1 +#define MSGEQ7_2 2 +#define MSGEQ7_3 3 +#define MSGEQ7_4 4 +#define MSGEQ7_5 5 +#define MSGEQ7_6 6 #define MSGEQ7_BASS 0 #define MSGEQ7_LOW 0 #define MSGEQ7_MID 3 #define MSGEQ7_HIGH 5 -// channel defintion for get/peek methodes -#define MSGEQ7_LEFT_RIGHT 0 -#define MSGEQ7_LEFT 1 -#define MSGEQ7_RIGHT 2 +// resolution dependant settings +#ifdef MSGEQ7_10BIT +typedef uint16_t MSGEQ7_data_t; +#define MSGEQ7_IN_MIN 20 +#define MSGEQ7_IN_MAX 1023 +#define MSGEQ7_OUT_MIN 0 +#define MSGEQ7_OUT_MAX 1023 +#else +typedef uint8_t MSGEQ7_data_t; +#define MSGEQ7_IN_MIN 20 +#define MSGEQ7_IN_MAX 255 +#define MSGEQ7_OUT_MIN 0 +#define MSGEQ7_OUT_MAX 255 +#endif +template class CMSGEQ7{ public: CMSGEQ7(void); - // user functions to interact with the IC - void begin(uint8_t resetPin, uint8_t strobPine, - uint8_t analogPinLeft, uint8_t analogPinRight = 0xFF); + // functions to get the IC ready for reading + void begin(void); + void end(void); void reset(void); - void read(void); - // function for the user to access the values, default l+r - uint8_t get(uint8_t frequency, uint8_t channel = MSGEQ7_LEFT_RIGHT); - uint8_t peek(uint8_t frequency, uint8_t channel = MSGEQ7_LEFT_RIGHT); + // functions to read the IC values and save them to the internal array + bool read(void); + bool read(const uint32_t currentMicros, const uint32_t interval); + bool read(const uint32_t interval); -private: - // pins to interact with the IC - uint8_t _resetPin; - uint8_t _strobePin; - uint8_t _analogPinLeft; - uint8_t _analogPinRight; + // function for the user to access the values + MSGEQ7_data_t get(const uint8_t frequency, const uint8_t channel); + MSGEQ7_data_t get(const uint8_t frequency); + MSGEQ7_data_t getVolume(uint8_t channel); + MSGEQ7_data_t getVolume(void); + + // tools + MSGEQ7_data_t map(MSGEQ7_data_t x, MSGEQ7_data_t in_min = MSGEQ7_IN_MIN, MSGEQ7_data_t in_max = MSGEQ7_IN_MAX, + MSGEQ7_data_t out_min = MSGEQ7_OUT_MIN, MSGEQ7_data_t out_max = MSGEQ7_OUT_MAX); +private: // array of all input values - uint8_t _left[7][MSGEQ7_READINGS]; - uint8_t _right[7][MSGEQ7_READINGS]; - uint8_t _countRead; + typedef struct frequency{ + MSGEQ7_data_t pin[1 + sizeof...(analogPins)]; + }; + frequency frequencies[7]; + + void nop(...) { + // little hack to take as many arguments as possible + // to execute several functions for the analogPins + } }; -extern CMSGEQ7 MSGEQ7; - -#endif - +// implementation inline, moved to another .hpp file +#include "MSGEQ7.hpp" diff --git a/MSGEQ7.hpp b/MSGEQ7.hpp new file mode 100644 index 0000000..3193e21 --- /dev/null +++ b/MSGEQ7.hpp @@ -0,0 +1,227 @@ +/* +Copyright (c) 2014-2015 NicoHood +See the readme for credit to other people. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +// include guard +#pragma once + +//================================================================================ +// MSGEQ7 +//================================================================================ + +// initialize the instance's variables +template +inline CMSGEQ7:: +CMSGEQ7(void) +{ + // empty +} + + +//================================================================================ +// IC setup +//================================================================================ + +template +inline void CMSGEQ7:: +begin(void){ + // do whatever is required to initialize the IC + pinMode(resetPin, OUTPUT); + pinMode(strobePin, OUTPUT); + pinMode(firstAnalogPin, INPUT); + nop((pinMode(analogPins, INPUT), 0)...); + reset(); +} + +template +inline void CMSGEQ7:: +end(void){ + // set pins to input again to safely remove connections if needed + pinMode(resetPin, INPUT); + pinMode(strobePin, INPUT); + pinMode(firstAnalogPin, INPUT); + nop((pinMode(analogPins, INPUT), 0)...); +} + +template +inline void CMSGEQ7:: +reset(void){ + // only this setting seems to works properly + digitalWrite(strobePin, LOW); + digitalWrite(resetPin, HIGH); + digitalWrite(resetPin, LOW); +} + + +//================================================================================ +// read +//================================================================================ + +template +inline bool CMSGEQ7:: +read(void){ + // reset the IC, optional, do this on your own if needed + //reset(); + + // read all 7 channels + // 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz + for (uint8_t i = 0; i < 7; i++){ + // trigger next value + digitalWrite(strobePin, HIGH); + digitalWrite(strobePin, LOW); + + // allow the output to settle + delayMicroseconds(36); + + // read pins with 8 bit resolution + frequency f = (frequency){ +#ifdef MSGEQ7_10BIT + analogRead(firstAnalogPin), + analogRead(analogPins)... +#else + (analogRead(firstAnalogPin) >> 2), + (analogRead(analogPins) >> 2)... +#endif + }; + + // save smooth values + if (smooth){ + for (uint8_t p = 0; p < (1 + sizeof...(analogPins)); p++){ + // round up if value increases + if (frequencies[i].pin[p] < f.pin[p]) + frequencies[i].pin[p]++; + frequencies[i].pin[p] = (frequencies[i].pin[p] + f.pin[p]) / 2; + } + } + // save peek values + else + frequencies[i] = f; + + } + return true; +} + +template +inline bool CMSGEQ7:: +read(const uint32_t currentMicros, const uint32_t interval){ + // read without delay + static uint32_t prevMicros = 0; + if ((currentMicros - prevMicros) > interval) { + prevMicros = currentMicros; + + // analyze + read(); + return true; + } + return false; +} + +template +inline bool CMSGEQ7:: +read(const uint32_t interval){ + return read(micros(), interval); +} + + +//================================================================================ +// get values +//================================================================================ + +template +inline MSGEQ7_data_t CMSGEQ7:: +get(const uint8_t frequency, const uint8_t channel){ + // dont read out of bounds + if (frequency >= 7 || channel >= (1 + sizeof...(analogPins))) + return 0; + + // returns the last measurement + return frequencies[frequency].pin[channel]; +} + +template +inline MSGEQ7_data_t CMSGEQ7:: +get(const uint8_t frequency){ + // dont read out of bounds + if (frequency >= 7) + return 0; + + // go through all channels/pins and add measured values + uint16_t average = 0; + for (uint8_t p = 0; p < (1 + sizeof...(analogPins)); p++) + average += frequencies[frequency].pin[p]; + + // return the average of all channels + return (average / (1 + sizeof...(analogPins))); +} + +template +inline MSGEQ7_data_t CMSGEQ7:: +getVolume(uint8_t channel){ + // dont read out of bounds + if (channel >= (1 + sizeof...(analogPins))) + return 0; + + // add all frequencies of a single channel to the overall volume + uint16_t vol = 0; + for (uint8_t i = 0; i < 7; i++) + vol += frequencies[i].pin[channel]; + + // return the average of this channels + return vol / 7; +} + +template +inline MSGEQ7_data_t CMSGEQ7:: +getVolume(void){ + // add all frequencies of all channels to the overall volume + uint16_t vol = 0; + for (uint8_t i = 0; i < 7; i++) + vol += get(i); + + // return the average of all channels + return vol / 7; +} + + +//================================================================================ +// tools +//================================================================================ + +template +inline MSGEQ7_data_t CMSGEQ7:: +map(MSGEQ7_data_t x, MSGEQ7_data_t in_min, MSGEQ7_data_t in_max, MSGEQ7_data_t out_min, MSGEQ7_data_t out_max) +{ + // if input is smaller/bigger than expected return the min/max out ranges value + if (x < in_min) + return out_min; + else if (x > in_max) + return out_max; + + // map the input to the output range. + // round up if mapping bigger ranges to smaller ranges + else if ((in_max - in_min) > (out_max - out_min)) + return (uint16_t)(x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min; + // round down if mapping smaller ranges to bigger ranges + else + return (uint16_t)(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} + diff --git a/Readme.md b/Readme.md index 85e51b2..8e61c27 100644 --- a/Readme.md +++ b/Readme.md @@ -5,27 +5,28 @@ MSGEQ7 Library 1.2 + Board v1.0 The MSGEQ7 is an IC designed to analyze music on different frequencies. This library reads the MSGEQ7 with 7 different frequencies from range 0-255, stereo or mono. It can be used to visualize audio through Leds for example. -This repository also includes the source of an [breakout board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). +This repository also includes the source of an [Breakout Board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). The frequencies are: 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz -**Examples included:** +####Features +* IDE 1.6.x with every Arduino compatibly +* [Sparkfun Spectrum Shield](https://www.sparkfun.com/products/13116) compatible +* Reads 1-n MSGEQ7 sensors +* Compact and fast implementation +* More compact and flexible 8 bit resolution +* Optional 10 bit resolution +* Value smoothing +* Tools to reduce noise +* A [Breakout Board](https://github.com/NicoHood/MSGEQ7/tree/dev#breakout-board). + +####Examples included:** * Led: blinks led, shows basic usage -* Serial: shows spectrum via serial and how to use a mono input +* Serial: shows spectrum via serial and how to use more channels * FastLED: blinks led strip with different frequencies. Shows how to use different syntax. Uses [FastLED library](https://github.com/FastLED/FastLED) -**Todo:** -* Left Right -> Stereo -* Update pins of examples -* board pictures + breadboard -* New header pic? -* update additional information readme -* API documentation (add to SW installation section) -* optional 10 bit resolution? -* different smooth code - More projects/contact: http://www.NicoHood.de @@ -44,9 +45,6 @@ See the [data sheet](https://www.sparkfun.com/datasheets/Components/General/MSGE * 4x 100nF Capacitor * 2x 33pF Capacitor * 2x 200k Ohm Resistor - -#####Optional parts -* 1x [Audio Jack 3.5mm](https://www.sparkfun.com/products/8032) (as audio output) * Led or Led strips * 1x 220 Ohm Resistor (for Led) @@ -64,6 +62,75 @@ Install the library as you are used to. More information can be found [here](http://arduino.cc/en/guide/libraries). +API Documentation +================= + +#####`template class CMSGEQ7` +Every CMSGEQ7 instance needs some pins passed via template to optimize the code. +If you want to smooth the readings with the last reading pass true as first argument. +The reset and strobe pin can be anyone on the board. +You can input as many analog pins as needed. +For example as mono mode only a single IC, stereo 2 or surround as many channels as you want. + +#####`void begin(void);` +Do whatever is required to initialize the IC and resets it. + +#####`void end(void);` +Sets pins to input again to safely remove connections if needed + +#####`void reset(void);` +Resets IC, so it starts reading at 0 again. +Normally this is not needed since its done in the `begin()` function. + +#####`bool read(void);` +Basic read function. Reads all channels and saves value inside the buffer. +You can access the buffer with the `get()` function. +Up to 400FPS are possible with 2 channels I've measured. + +#####`bool read(const uint32_t currentMicros, const uint32_t interval);` +To automatically read every X seconds you may also use this function. +Use the `ReadsPerSecond(f)` Makro with the interval and you can easily choose a good speed interval. +You can also leave out the first argument, this will be automatically replaced with a `micros()`. + +#####`MSGEQ7_data_t get(const uint8_t frequency, const uint8_t channel);` +Returns the data of the selected frequency and channel. +By default this returns an `uint8_t` value, for 10bit resolution `uint16_t`. +Frequency should be 0-6 where 0 is the lowest frequency (Bass) and 6 the highest. +Depending on how many analog pins you have attached you can select the channel here (0-n). +You can also leave out the channel variable to get an average value of all channels. + +#####`MSGEQ7_data_t getVolume(uint8_t channel);` +Returns the overall volume of all frequencies of a channel. +By default this returns an `uint8_t` value, for 10bit resolution `uint16_t`. +Depending on how many analog pins you have attached you can select the channel here (0-n). +You can also leave out the channel variable to get an average volume of all channels. + +#####`MSGEQ7_data_t map(MSGEQ7_data_t x, MSGEQ7_data_t in_min = MSGEQ7_IN_MIN, MSGEQ7_data_t in_max = MSGEQ7_IN_MAX, MSGEQ7_data_t out_min = MSGEQ7_OUT_MIN, MSGEQ7_data_t out_max = MSGEQ7_OUT_MAX);` +Maps the input from a given input range to an output range. +This is useful to reduce noise. All MSGEQ7 produce a noise of about 15-19 if no music is played. +This macro can be used to remap the input. You can leave out the last 4 arguments, they will be replaced with default values. +For 10 bit resolution the function uses `uint16_t` and 1023 as default maximum value. + +#####`Definitions` +```cpp +//#define MSGEQ7_10BIT +#define ReadsPerSecond(f) (1000000UL / (f)) + +// basic frequencys definitions (0-6 valid, 7 channels) +#define MSGEQ7_0 0 +#define MSGEQ7_1 1 +#define MSGEQ7_2 2 +#define MSGEQ7_3 3 +#define MSGEQ7_4 4 +#define MSGEQ7_5 5 +#define MSGEQ7_6 6 +#define MSGEQ7_BASS 0 +#define MSGEQ7_LOW 0 +#define MSGEQ7_MID 3 +#define MSGEQ7_HIGH 5 +``` + + Breakout Board ============== The MSGEQ7 Breakout Board lets you easily hook up an audio source or microphone to your microcontroller. @@ -81,6 +148,17 @@ It is fully open source so you can create a copy for yourself or modify it. * Easy to solder (DIP parts) * [Open Source Hardware](http://www.oshwa.org/definition/) +#####Required parts: +* 2x [MSGEQ7 IC](https://www.sparkfun.com/products/10468) +* 2x [Audio Jack 3.5mm](https://www.sparkfun.com/products/8032) +* 8 pin header male +* 2x IC socket 8 pins (optional) +* 2x 10nF Capacitor +* 4x 100nF Capacitor +* 2x 33pF Capacitor +* 2x 200k Ohm Resistor + + #####Files: You can find all needed files in the [board](board/) folder. Click view raw to download the PDF files. @@ -94,31 +172,41 @@ Click view raw to download the PDF files. Additional Information ====================== +This library started as my very first one and become better and better over the time. +To be honest it is now very complex, due to the optimization and API flexibility. + +The read function itself is simple though. Have a look at the library itself, its not so complicated. But keep attention to the LOW and HIGH setting of strobe and reset -Keep in mind that the smoothed value is created from the last 5(by default) reads. -If you analyze every 20ms this means the last 20*5=100 ms time period actually is analyzed. -I found out that reading every 20ms is a good value to start. +Keep in mind that the smoothed value is created from the last read + current read divided by 2. +I found out that reading with 50 FPS is a good value to use. -You can reset the IC with myMSGEQ7.reset() but you dont need that normally. +You can reset the IC with myMSGEQ7.reset() but you don't need that normally. If you only want to use mono mode or one IC just connect the two inputs together to the MSGEQ7 -and only use one analog input. Have a look at the Serial example of the library. +and only use one analog input. But you can also use multiply ICs and connect them to an analog input each. +The reset and strobe line is connected to every IC, so you don't need to multiply them. -The Output only ranges from 0-255 for saving memory and for easy use. It doesnt matter much. -If you still want to read up to 1023 remove the divide >> 2 in the library and use uint16_t +The output only ranges from 0-255 to save memory use it easier. You don't lose much information. +If you still want to read up to 1023 define MSGEQ7_10BIT before including the library. -The IC has a standard value at about 10. You should keep that in mind. +The IC has a standard value at about 10-19. You should keep that in mind. In this case the Led always glims a bit. Have a look at the map() function to improve this. + Version History =============== ``` -1.2 Release (xx.xx.2014) +1.2 Release (23.04.2015) * Added breakout board files v1.0 * Optimized performance -* Improve examples +* Variable number of ICs readable +* Added optional 10bit resolution +* Added more functions/tools +* Improved examples +* Added MSGEQ7_VERSION definition +* Added library.properties 1.1 Release (10.07.2014) * Changed syntax @@ -129,6 +217,7 @@ Version History * Added general functionality ``` + License and Copyright ===================== If you use this library for any cool project let me know! diff --git a/examples/MSGEQ7_FastLED/MSGEQ7_FastLED.ino b/examples/MSGEQ7_FastLED/MSGEQ7_FastLED.ino index 86f5b04..a425b52 100644 --- a/examples/MSGEQ7_FastLED/MSGEQ7_FastLED.ino +++ b/examples/MSGEQ7_FastLED/MSGEQ7_FastLED.ino @@ -1,114 +1,68 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. - MSGEQ7 Serial example - Output via led strip + MSGEQ7 FastLED example + Output via Led strip and FastLED library - Reads MSGEQ7 IC with 7 different frequencys from range 0-255 + Reads MSGEQ7 IC with 7 different frequencies from range 0-255 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz */ -// FastLed v2.1 -#include -const int numLeds = 50; -const int pinData = 11; -const int pinClock = 13; -CRGB leds[numLeds]; +// FastLED +#include "FastLED.h" -//MSGEQ7 -#include -const int pinAnalogLeft = A0; -const int pinAnalogRight = A1; -const int pinReset = A2; -const int pinStrobe = A3; +#define LED_PINS // DATA_PIN, or DATA_PIN, CLOCK_PIN, or empty for SPI +#define COLOR_ORDER GRB +#define CHIPSET LPD8806 +#define NUM_LEDS 20 -void setup() { - // Uncomment/edit one of the following lines for your leds arrangement. - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); +#define BRIGHTNESS 255 // reduce power consumption +#define DITHER 255 // try 0 to disable flickering +#define CORRECTION TypicalLEDStrip - FastLED.addLeds(leds, numLeds); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); +CRGB leds[NUM_LEDS]; // Define the array of leds - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); - // FastLED.addLeds(leds, NUM_LEDS); +// MSGEQ7 +#include "MSGEQ7.h" +#define pinAnalogLeft A0 +#define pinAnalogRight A1 +#define pinReset 6 +#define pinStrobe 4 +#define MSGEQ7_INTERVAL ReadsPerSecond(50) +#define MSGEQ7_SMOOTH true - FastLED.setDither(0); // prevent flickering - FastLED.show(); // needed! +CMSGEQ7 MSGEQ7; - // this will set the IC ready for reading - MSGEQ7.begin(pinReset, pinStrobe, pinAnalogLeft, pinAnalogRight); +void setup() { + // FastLED setup + FastLED.addLeds(leds, NUM_LEDS).setCorrection(CORRECTION); + FastLED.setBrightness( BRIGHTNESS ); + FastLED.setDither(DITHER); + FastLED.show(); // needed to reset leds to zero - // debug - Serial.begin(115200); - Serial.println("Startup"); + // this will set the IC ready for reading + MSGEQ7.begin(); } void loop() { - // read without delay - static long prevMillis = 0; - unsigned long currentMillis = millis(); - if (currentMillis - prevMillis > 20) { - prevMillis = currentMillis; - - // analyze - MSGEQ7.read(); - - // this should show different sytax to get the values from the IC - - // LOW and BASS is the name = 0 - // use LEFT and RIGHT for the different channels - uint8_t leftbass = MSGEQ7.get(MSGEQ7_BASS, MSGEQ7_LEFT); - uint8_t rightbass = MSGEQ7.get(MSGEQ7_LOW, MSGEQ7_RIGHT); - - // MID is equal to 3 - // you can use peek for a not smoothed value - uint8_t leftpeekmid = MSGEQ7.peek(MSGEQ7_MID, MSGEQ7_LEFT); - uint8_t rightpeekmid = MSGEQ7.peek(3, MSGEQ7_RIGHT); - - // you can use LEFT_RIGHT or leave it out to get both channels together - // use 0-6 for all frequencys - uint8_t high = MSGEQ7.get(MSGEQ7_HIGH, MSGEQ7_LEFT_RIGHT); - uint8_t veryhigh = MSGEQ7.get(6); + // analyze without delay + bool newReading = MSGEQ7.read(MSGEQ7_INTERVAL); - // smoothed values look way better, channel 3 and 4 are similar - uint8_t leftmid = MSGEQ7.get(4, MSGEQ7_LEFT); - uint8_t rightmid = MSGEQ7.get(4, MSGEQ7_RIGHT); + // Led strip output + if (newReading) { + // visualize the average bass of both channels + uint8_t val = MSGEQ7.get(MSGEQ7_BASS); - // visualize leds - // for better visualizations see "Visualizer" on Github - for (int i = 0; i < 5; i++) { - leds[i].setHSV(HUE_RED, 255, leftbass); - leds[i + 5].setHSV(HUE_ORANGE, 255, rightbass); - leds[i + 10].setHSV(HUE_YELLOW, 255, leftpeekmid); - leds[i + 15].setHSV(HUE_GREEN, 255, rightpeekmid); - leds[i + 20].setHSV(HUE_AQUA, 255, high); - leds[i + 25].setHSV(HUE_BLUE, 255, veryhigh); - leds[i + 30].setHSV(HUE_PURPLE, 255, leftmid); - leds[i + 35].setHSV(HUE_PINK, 255, rightmid); - } + // reduce noise + val = MSGEQ7.map(val); - // You can also calculate an overall volume level - // but thats more or less useless - uint16_t average = 0; - for (int i = 0; i < 7; i++) - average += MSGEQ7.get(i); - uint8_t overall = average / 7; - CRGB color = 0xFFAA11; - color.nscale8_video(overall); - for (int i = 0; i < 10; i++) - leds[i + 40] = color; + // visualize leds to the beat + CRGB color = CRGB::Blue; + color.nscale8_video(val); + fill_solid(leds, NUM_LEDS, color); - // update leds + // update Leds FastLED.show(); } } diff --git a/examples/MSGEQ7_LED/MSGEQ7_LED.ino b/examples/MSGEQ7_LED/MSGEQ7_LED.ino index 1861245..1eb1c76 100644 --- a/examples/MSGEQ7_LED/MSGEQ7_LED.ino +++ b/examples/MSGEQ7_LED/MSGEQ7_LED.ino @@ -1,44 +1,46 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. - MSGEQ7 Serial example - Output via Led + MSGEQ7 Led example + Output via Led (choose a PWM pin!) - Reads MSGEQ7 IC with 7 different frequencys from range 0-255 + Fast setup to demonstrate functionality + + Reads MSGEQ7 IC with 7 different frequencies from range 0-255 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz */ -//MSGEQ7 -#include -const int pinAnalogLeft = A0; -const int pinAnalogRight = A1; -const int pinReset = A2; -const int pinStrobe = A3; +// MSGEQ7 +#include "MSGEQ7.h" +#define pinAnalog A0 +#define pinReset 6 +#define pinStrobe 4 +#define MSGEQ7_INTERVAL ReadsPerSecond(50) +#define MSGEQ7_SMOOTH true + +CMSGEQ7 MSGEQ7; -// choose a pwm pin! -const int pinLed = 3; +// choose a PWM pin! +#define pinLed 11 void setup() { // this will set the IC ready for reading - MSGEQ7.begin(pinReset, pinStrobe, pinAnalogLeft, pinAnalogRight); + MSGEQ7.begin(); // led setup pinMode(pinLed, OUTPUT); } void loop() { - // read without delay - static long prevMillis = 0; - unsigned long currentMillis = millis(); - if (currentMillis - prevMillis > 20) { - prevMillis = currentMillis; - - // analyze - MSGEQ7.read(); - - // Led output - uint8_t val = MSGEQ7.get(MSGEQ7_BASS); - analogWrite(pinLed, val); + // analyze without delay every interval + bool newReading = MSGEQ7.read(MSGEQ7_INTERVAL); + + // Led output + if (newReading) { + uint8_t input = MSGEQ7.get(MSGEQ7_BASS); + + // output PWM signal via Led to the music beat + analogWrite(pinLed, input); } } diff --git a/examples/MSGEQ7_Serial/MSGEQ7_Serial.ino b/examples/MSGEQ7_Serial/MSGEQ7_Serial.ino index 1687427..778d665 100644 --- a/examples/MSGEQ7_Serial/MSGEQ7_Serial.ino +++ b/examples/MSGEQ7_Serial/MSGEQ7_Serial.ino @@ -1,44 +1,89 @@ /* - Copyright (c) 2014 NicoHood + Copyright (c) 2014-2015 NicoHood See the readme for credit to other people. MSGEQ7 Serial example Output via Serial + Needs no special hardware and displays raw values on the Serial monitor. + Reads MSGEQ7 IC with 7 different frequencys from range 0-255 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz */ -//MSGEQ7 -#include -const int pinAnalog = A0; -const int pinReset = A2; -const int pinStrobe = A3; +// MSGEQ7 +#include "MSGEQ7.h" +#define pinAnalogLeft A0 +#define pinAnalogRight A1 +#define pinReset 6 +#define pinStrobe 4 +#define MSGEQ7_INTERVAL ReadsPerSecond(50) +#define MSGEQ7_SMOOTH false + +CMSGEQ7 MSGEQ7; void setup() { // this will set the IC ready for reading - // note that we only use one input here - MSGEQ7.begin(pinReset, pinStrobe, pinAnalogLeft); + MSGEQ7.begin(); - // Serial setup with fastest baud - Serial.begin(115200); + // Serial setup with faster baud rate gives more FPS (115200) + Serial.begin(9600); Serial.println("Startup"); } void loop() { - // read without delay - static long prevMillis = 0; - unsigned long currentMillis = millis(); - if (currentMillis - prevMillis > 20) { - prevMillis = currentMillis; - - // analyze - MSGEQ7.read(); - - // Serial output - uint8_t val = MSGEQ7.get(MSGEQ7_BASS); - for (int i = 0; i < val / 4; i++) - Serial.print("="); + // analyze without delay every interval + bool newReading = MSGEQ7.read(MSGEQ7_INTERVAL); + + // calculate FPS + uint16_t FPS = getFPS(newReading); + + // Serial raw debug output + if (newReading) { + // all channels together + Serial.print(MSGEQ7.get(MSGEQ7_BASS)); + Serial.print(" "); + + // 1st channel (here: left) + Serial.print(MSGEQ7.get(MSGEQ7_BASS, 0)); + Serial.print(" "); + + // 2nd channel (here: left) + Serial.print(MSGEQ7.get(MSGEQ7_BASS, 1)); + Serial.print(" "); + + // overall volume of all channels + Serial.print(MSGEQ7.getVolume()); + Serial.print(" "); + + // FPS of the reading + Serial.print(FPS); + Serial.print(" "); + + // visualize with characters as bars + uint8_t input = MSGEQ7.get(MSGEQ7_BASS); + for (uint8_t i = 0; i < (input / 4); i++) + Serial.print('='); Serial.println(); } } + +uint16_t getFPS(bool newReading) { + // variables to count FPS and last 1 second mark + static uint16_t prevFPS = 0; + static uint16_t FPS = 0; + static uint32_t m = 0; + + // increase FPS count + if (newReading) + FPS++; + + // if 1 second mark crossed, save new FPS + if ((micros() - m) > 1000000) { + prevFPS = FPS; + FPS = 0; + m = micros(); + } + + return prevFPS; +} diff --git a/keywords.txt b/keywords.txt index 5845bff..903e2bd 100644 --- a/keywords.txt +++ b/keywords.txt @@ -10,16 +10,15 @@ # Methods and Functions (KEYWORD2) ####################################### -MSGEQ7 KEYWORD3 +CMSGEQ7 KEYWORD2 +MSGEQ7 KEYWORD1 reset KEYWORD2 read KEYWORD2 -getLeft KEYWORD2 -getRight KEYWORD2 get KEYWORD2 -peek KEYWORD2 -peekLeft KEYWORD2 -peekRight KEYWORD2 +getVolume KEYWORD2 +map KEYWORD2 + ####################################### # Instances (KEYWORD2) @@ -33,6 +32,13 @@ MSGEQ7_BASS LITERAL1 MSGEQ7_LOW LITERAL1 MSGEQ7_MID LITERAL1 MSGEQ7_HIGH LITERAL1 -MSGEQ7_LEFT_RIGHT LITERAL1 -MSGEQ7_LEFT LITERAL1 -MSGEQ7_RIGHT LITERAL1 \ No newline at end of file +MSGEQ7_0 LITERAL1 +MSGEQ7_1 LITERAL1 +MSGEQ7_2 LITERAL1 +MSGEQ7_3 LITERAL1 +MSGEQ7_4 LITERAL1 +MSGEQ7_5 LITERAL1 +MSGEQ7_6 LITERAL1 +ReadsPerSecond LITERAL1 +ReadsPerSecond1 LITERAL2 +ReadsPerSecond2 LITERAL3 \ No newline at end of file diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..56585d9 --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=MSGEQ7 +version=1.2.0 +author=NicoHood +maintainer=NicoHood +sentence=Library for Musicvisualization with MSGEQ7 +paragraph=Reads MSGEQ7 IC with 7 different frequencies: 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz +category=Signal Input/Output +url=https://github.com/NicoHood/MSGEQ7 +architectures=avr