The following project involves the creation of a custom prototype that will be used to blink LEDs based on the frequencies of the analog measurements taken from its surroundings using a sound sensor. The MAX32620FTHR board was used due to its low power capabilities, and the fact that it has a powerful embedded FPU (floating point unit) processor.
IntroductionHi everyone, I will be explaining all the stages involved while I was creating this project. It was a long journey from the thought of the idea, to the complete development. Any ideas, suggestions, and commentaries will be welcomed in the comments section. I hope you enjoy this project.
MotivationMy goal with this project is to build a wearable that can be used in dark environments, with loud music (nightclubs, night parties) and it will make you glow. Literally.
I was inspired by the dancing group "Light Balance". While they perform complex dancing routines with a pre-recorded set of lights, it is cool to see how the contrast of really bright LEDs can be displayed while dancing in the dark.
I searched online for similar projects, and I noticed that most of the related projects had a couple of 'issues':
- They often involved the use of a "custom" library, that only works for a limited number of maker boards: this results in a code that is not portable or reusable.
- Some projects with lights reactive to music only used the sound level, and this quite limits the potential of "show off".
- Even in the case of a portable C library, if the code is not well commented it is not possible to understand how everything works.
With this in mind, and after checking that the MAX32620FTHR board included DSP (Digital Signal Processing) functionalities, I decided it was a good idea for an open source project. The main goal of the project is to see the LEDs dancing with the music, keeping as a second goal developing the firmware as reusable as possible.
Planning the Project PartsThe project looked a little straightforward for me at the moment, I just thought "I need a controller for the LEDs, a sound sensor, a boost voltage and, of course, some cool LEDs". I show here a dirty picture of a quick diagram I drew to get all the pieces together on my mind.
I ended up buying a couple of different sound sensors, the brightest (according to some forums) LEDs I could find, a couple of boost voltage regulators. I did not pay too much attention to the details of the project when I decided to buy the parts, and I ended up buying parts that were useless for this project. PRO Tip: Invest a good amount of time investigating the needed components and how these will be used, the time invested at this stage will save you time later (and probably money).
Studying the Board FeaturesAfter I ordered the hardware parts, I took some time to study the MAX32620FTHR features in detail. I took particular interest in understanding the how the ADC (Analog Digital Converter) peripheral measurements would be acquired, and the limitations of it. The MAX32620 ADC max sample rate is about 7.1Khz, which limits the range of frequencies that can be processed effectively, but as a broad range of frequencies was not a goal of the project, It was not a reason to be concerned.
Another important feature of the board is the PMU (Peripheral Management Unit). This is a peripheral that is able to process data from multiple modules of the board without interrupting the main processor. This is an excellent module to allow processing of data in low power modes. For the purposes of this project, the main objective is to take continuously the sound sensor readings without interrupting the main processor (improving the processor time allowed to use DSP functions).
The MAX77650 unit of the board was analyzed as well, specifically, it was necessary to understand the capabilities of the SYS pin. While I thought at first that this pin was a traditional logic pin, this pin is actually intended to draw enough power to use with all the loads of your prototype. After noticing this, and checking that it is configurable to a voltage up to 4.8V, I got the idea that I could build a prototype without using an additional boost regulator.
Testing the Hardware ComponentsSo, I got the parts, what would be the next step? I took some time to play around with the hardware parts: the LEDs, the sound sensors, and the MAX32620FTHR board. I will include the tests made with the main board in another sub-topic to explain in detail my experience with the software environments.
Testing the LEDs
I got a new bunch of LEDs, 50 Piranha Super Bright LEDs, varied colors, for about 2$. I didn't work with this kind of LEDs before, so I really did not have high expectations. I tested them with a multimeter, and these worked OK. I noticed that even when all the colors (white, green, blue, red, orange), had the same form factor, the anode and cathode were inverted in some of these. My advice: test the polarity before soldering these to a perfboard.
As from the page where I got them there was no really datasheets, I had to take the time to test the LEDs voltages. I set up a simple circuit with a 9V supply (coming from a boost regulator), a 330Ohm resistor, and the LED in series. I was gladly surprised when I did that:
After using a good supply, not the one in the multimeter, I found out they do bright A LOT. The voltage rating depends on the LED, varying from 2.1V to 3.4V, and the current required for max brightness being about 20mA. After that, I decided to use the following circuit to control the LEDs:
Where the Vcc voltage will come from the SYS pin of the MAX32620FTHR board, and the control pin is any of the GPIO pins available from the same board. As the maximum voltage drop coming from one of the bought LEDs is about 3.3 volts, 4.8 volts is enough voltage to power the LEDs directly from the SYS pin.
Testing the Sound Sensors
For this project, I bought at least three sound sensors. One based on the LM358 OPAMP (OPerational Amplifier), one based on the LM386 and the last one based on the MAX4466.
The sensor at the left, LM358 amplifier, is the cheapest of these. But, cheap comes at a price, it measures only sound level, so the signal emitted is not good for detecting music as it doesn't include the necessary bias to include the negative peaks on the music signals.
The sensor at the middle gave me a better feeling, the one based on the LM386. I bought it at a discounted price, probably because it has a JST connector and it is difficult to work with it. This had the problem that it required 5V minimum to work correctly. But testing it using an Arduino Mega gave me hopes that it would work. I took the time to remove the JST connector, and later on, to test it with the MAX32620FTHR board, I damaged the sensor by wrongly using -5V as the power source (I matched its Vcc to main board Gnd, and its Gnd to 5V). Welcome to the Maker experience.
After damaging the second board, I had no replacements, as initially I only bought the first two sensors. I took some time to investigate for better candidates, and I got the MAX4466 from a local supplier. It has an excellent power noise supply ratio, and it is an adequate option for detecting music, with configurable gains. Now that I completed the project, I think it's worth buying one with auto gain control (like the MAX98149) to test the result.
Setting Up the Environment to Program the MAX32620FTHRAt this point you have to decide which way to go: program the board using the Mbed tools flow, follow the Arduino IDE configuration for the MAX32620 boards or set up the Eclipse environment. I will describe briefly how I interacted with the three options:
- Mbed compiler: While it looks pretty well configured already, and seems to be the preferred workflow for Maxim Integrated boards, I personally do not like online tools for firmware development.
- Eclipse environment: I tried to configure the Eclipse environment because Arduino IDE lacks a useful "F3 go to function declaration" option to open specific function and files. But after following the standard installation instructions, I had problems linking the MAX32620 libraries with the programming environment. I was not even able to get a hello world example program built.
- Arduino IDE: While this environment is not well supported, the installation using the board manager (Instructions to install max32620fthr support) worked for me out of the box. I followed the instructions and used "MAX32620FTHR (bootloader)" as the programming board.
While it was good to know the Arduino IDE flow worked, it is not cool starting with a board with two RGB LEDs using a program that only blinks a red led. I noticed that the Eclipse environment had a more complex hello world program, that used both RGB LEDs, so I adjusted this program to use it with the Arduino IDE, and I had this program built to start working:
I used a lot of functions that come from the BSP of the MAX32620 board, these can be found at the core Maxim installed on your local Arduino files (Windows users can find it at "user\AppData\Local\Arduino15\packages\Maxim"). I uploaded these libraries to my the code repositories, in case anyone wants to check them more easily: BSP files and examples for a board based on the max32620: EVKit examples
In order to enable serial port configuration, it is mandatory the use of the PICO programmer. The steps required to connect the board with the PICO board can be found here. After the program is downloaded to the board, the bootloader is lost, so you will have to choose MAX32620FTHR when programming using Arduino IDE (instead of the bootloader option). In order to be able of using serial communication using Windows, it is necessary to install a specific driver for mbed devices, the instructions to do this can be found here.
Building the Prototype PlatformBy testing the LEDs, I decided to start working a little board that featured the LEDs in a cool fashion. I had 50 LEDs, but I decided to use a single bakelite board. After playing a little with the LEDs and the bakelite, I decided to arrange the LEDs like this:
After deciding where to place the LEDs, I used Fritzing to layout all the parts on the perfboard. I did not solder the MAX32620FTHR board directly to the perfboard, instead, I soldered female headers to be able of removing it and use the board for other projects. I am not sure how common is this method, but I use grey wires in Fritzing to layout how I will be soldering the perfboard. This allows me to have all the parts in the simulation and, later on, I can solder without worrying about the layout, following the wires routes on the Fritzing program. Here it is shown a comparison of the soldered paths against the Fritzing image (mirrored):
The code is available at the followed link to be downloaded: Funky LEDs code. It includes several files, including CMSIS libraries required for the use of optimized functions. I will describe here the changes needed to be completed to allow building the program using Arduino IDE.
- The driver include file needed to use the PMU module, pmu.h, uses block struct definitions, with members named "and", and the word "and" is a keyword on the Arduino environment. I replaced these variable names with "and_". This file located at: "C:\Users\YourUser\AppData\Local\Arduino15\packages\Maxim\hardware\arm\1.1.0\system\MAX32620PeriphDriver\Include". I attached one copy of the driver file with the changes here.
- Also, the CMSIS drivers included with the MAXIM board seem to be a little outdated. I downloaded CMSIS from this page. I changed only three include files, located at: "C:\Users\YourUser\AppData\Local\Arduino15\packages\Maxim\hardware\arm\1.1.0\system\CMSIS\Include". I uploaded the changed files here.
The CMSIS core is used to complete most of the mathematical functions of the project, and by using it, instead of other custom libraries, allows the code to be ported to any board based on a Cortex Microcontroller. Keep in mind, that if you are going to use another board, you will need to change the "arm_math.h" file, at line 301, to match your board. It is shown the current configuration:
#define ARM_MATH_CM4
Where possible values are: ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0. Or any other family supported by the CMSIS standard library files.
Features of the ProgramAt its core, the MAX32620 processor completes the following set of tasks:
- Check for BOOT button input, to change execution mode. The program features 4 modes: Idle mode, Funky mode, Calibration mode and shut down mode.
- If there is a new batch of ADC measurements (256 samples), process it to convert it into a set of 10 bands.
- Based on the bands' magnitudes, compare them with defined thresholds. If the result is higher, turn on the LED that matches the band, else turn it off.
- The PMU module takes automatically the 256 samples, moves them to the program memory, and triggers an interrupt every time there is new data available to be processed.
The program features a calibration mode to be able of acquiring the environment current sound level, without music, and improve its response to the changes when there is music on. The only requirement to go into the calibration mode is to keep the boot button for a given amount of time. In fact, the times for the different modes can be easily configured at line 66 of the code:
// Times required to hold the boot button in order to change mode
#define TIME_FUNKY 2*SECOND
#define TIME_CALIBRATION 3*SECOND
#define TIME_POWER_OFF 4*SECOND
#define TIME_ARMONICS_TEST 5*SECOND
"Funky mode" is the main mode of the program, that outputs LEDs based on the frequencies taken from the ADC data. Power off turns off the board. "Armonics test" outputs the magnitude of the bands' measurements to the serial port, and it is a mode used to play as a developer, by checking the magnitude outputs for each frequency and configure the music bands ranges.
The concept of separating the sound bands into human ranges, called "Octave bands" is not new, some information can be found here and here. While I tried dividing the bands following a technical approach, I ended up calibrating these by playing reverse engineering the results of the sensor and the magnitude of the Fourier Transform, this is located at line 627 of the code:
/* Calculate RMS of frequency bands
Play with the ranges of bands used for each led
This was calculated by using printing functions on different stages
of the program, and testing, so can be changed for your needs.
If FFT size is changed, these indexes have to be changed accordingly
*/
#ifdef COUPLED_MODE
arm_rms_f32 ( &fft_result_mag[10], 14, &bands[0]);
arm_rms_f32 ( &fft_result_mag[24], 24, &bands[1]);
arm_rms_f32 ( &fft_result_mag[48], 46, &bands[2]);
arm_rms_f32 ( &fft_result_mag[94], 46, &bands[3]);
arm_rms_f32 ( &fft_result_mag[210], 70, &bands[4]);
#else
arm_rms_f32 ( &fft_result_mag[10], 7, &bands[0]);
arm_rms_f32 ( &fft_result_mag[17], 7, &bands[1]);
arm_rms_f32 ( &fft_result_mag[24], 12, &bands[2]);
arm_rms_f32 ( &fft_result_mag[36], 12, &bands[3]);
arm_rms_f32 ( &fft_result_mag[48], 23, &bands[4]);
arm_rms_f32 ( &fft_result_mag[71], 23, &bands[5]);
arm_rms_f32 ( &fft_result_mag[94], 23, &bands[6]);
arm_rms_f32 ( &fft_result_mag[117], 23, &bands[7]);
arm_rms_f32 ( &fft_result_mag[210], 23, &bands[8]);
arm_rms_f32 ( &fft_result_mag[233], 47, &bands[9]);
#endif
The arm_rms_f32 function takes the magnitudes starting at the position indicated, the number of elements and sums the RMS (Root Mean Square) values to save them to a specific band. This part can be calibrated to suit your needs, you may consider only using a specific set of the frequencies for the output, or calibrating the bands for a specific type of music.
Besides that, the code features two possible modes to control the LEDs: a "coupled" mode, and a "not coupled" mode. In the prototype I created, there are two rows of LEDs, totalling 5 different colors, in the coupled mode, the two LEDs of the same color are not independent, having only 5 different outputs; while the non coupled mode controls the 10 LEDs independently (that's why the bands code has two different bands configuration, one calculates 5 music bands while the other calculates only 10). I created the coupled mode because I showed the result to my friends, and they didn't match the output to the sound, and I thought that maybe it is because too many LEDs caused some distraction. Some preferred the coupled mode result, while I personally prefer the original.
/* Use two different modes, one with 10 singular lights
One with 5 "coupled" lights
Comment the following line in order to use the "single use" lights mode
*/
#define COUPLED_MODE 1
The comparison thresholds to control the LEDs are configured manually using the global constants:
/* Constant values used to output music with the bands
* if current value - avg > threshold, turn on led
*/
const float32_t threshold_values[10] = { 10, 10,
10, 10,
10, 10,
10, 10,
10, 10};
/* Constant values used to help the algorithm when the sound is low*/
const float32_t threshold_halves[10] = { 3, 3,
3, 3,
3, 3,
3, 3,
3, 3};
The "threshold_halves" variables are used if "IN_HOUSE_MODE" is defined. If the board did not turn on any led with checking against the set of threshold values, it checks again comparing against the threshold_halves values. This allows the board to hear quiet sounds for songs that have loud sounds in average, but parts with quiet sounds. This is not recommended while dancing at a club, because the sounds will be too loud, and probably all the LEDs will turn on if the thresholds do not pass the first test.
DemonstrationI attached here a couple of videos of the prototype working, all videos configured with the "IN_HOUSE_MODE" and powering the board with a 500mAh battery. I used "No copyrighted music" for the purposes of the video. I wanted to show a video with "Cruel Angel Thesis", "Chop Suey" or "Seek N' Destroy", but I rather not get in any trouble, so I encourage you to test with these songs!
ConclusionsThe MAX32620FHTR it's a pretty convenient platform for developing wearable applications. With this project it has been proved the processing capabilities can be used to realize complex operations, the onboard PMIC can be used to control the power requirements of the prototype and all fits in a wearable size device.
The main goal of the project was to develop a cool device reactive to music sound, and this was achieved successfully. The second goal, creating a reusable code, was completed as well: while it is not completely pure C code, the CMSIS standard is broadly available as Cortex microcontrollers are gaining popularity. The code is commented as much as possible, and the final user is encouraged to defined custom bands ranges (used for the RMS calculation) and custom thresholds for its personal use. The main segment of the code allows for different behaviors to be implemented, the "IN_HOUSE_MODE" is an example of it: you can play with simple logic using the bands' results, like "if this led is on, do not check this one".
While the results are satisfactory, every project has space for improvement, I will briefly describe areas to be explored in further iterations:
- Testing another sound sensor: The sensor used works well for known environments, where it can be calibrated, but for the purpose of the wearable funky LEDs prototype, I think it could be more convenient an auto gain sensor. This remains to be tested.
- Using another set of lights: I am quite satisfied with the LEDs used brightness, I may have used some lenses to improve its angle of view. But there are a lot of different LEDs combinations that can be used for this project, for example using an array of RGB LEDs instead of single color LEDs. Another cool possibility is to adapt the program to use a display matrix like this one. If some company is interested in sending me a shield like that as a sample (cough cough, Maxim Integrated), I will gladly modify the code to use a display like that. I encourage you to test the code with your own funky LEDs!
- Include battery checking: While I wanted to feature this for the competition, I had no time to include a mechanism to check the battery status, and show a specific color blinking using the RGB PMIC LEDs driver. This rather than an improvement is part of my personal "To Do" list.
- Include low power IDLE mode: I included an IDLE mode, that only blinks a LED every now and then (based on a configurable #define option). This mode is intended to be used with a low power mode of the MAX32620. This is also marked as a "To Do" for the project.
- Building it as a wearable: This first prototype is not quite too comfortable to be used as a wearable: it requires a custom pro PCB with all the parts, and probably extensor connectors to make the LEDs part of a jacket like this cool related project.
Please if you liked the project leave me a comment, or let me know if there is anything else you think it could be added/improved on the project, I really hope you enjoyed it. Special thanks to Hackster and to Maxim Integrated for hosting the contest Unleash Invisible Intelligence.
Comments