ESP32 spectrum analyser VU meter using arduinoFFT and a FastLED matrix

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone i recently decided to have a look at using the esp32 to make a vu meter spectrum analyzer using a fast fourier transform and having a display on a matrix using fast led i also wanted to make it work from both a line in and a microphone and i started by looking at the arduino fft library however the documentation for this is poor to non-existent and the examples are also pretty useless unless you already know what you're doing so i found an example from david at g6ejd who has a great channel with hundreds of short tech tips for all kinds of microcontrollers and sensors and have linked his channel in the description below even using this example i really didn't understand what was going on so i waded into the world of fft so i could hopefully understand a bit more about what was happening i'm not going to explain the mathematics of the fft here as it's fairly complicated and there are many resources out there that do that very well you also don't need to know it to be able to use the library but i'm going to try my best to explain what you do need to know so hopefully you can follow along do be a weather this isn't a my first project kind of thing to make sure you're comfortable with fast lead and writing to led matrixes before you dive into this and i'll show you some of the patterns i wrote towards the end of the video before we look at the code we need to understand a little bit about what a fourier transform is so if we take wave a which has a long wavelength and a large amplitude and add it to wave b with a smaller wavelength and a small amplitude we get wave c we can do this with any number of waves to recreate any wave pattern we like i say almost because to recreate a perfect square wave for example we actually need an infinite number of sine waves added together but let's not get into that an fft is a clever bit of mathematics it does this in addition in reverse so we feed in a complicated looking wave and it spits out the frequencies that it contains and importantly also the amount of each frequency that is present if we feed an audio signal into an fft we can find out the relative strengths of the various frequencies which is perfect for making a spectrum analyze every meter in order to do this we need to use the adc to sample the audio at a high frequency but how fast do we need a sample well another clever bit of maths called the nyquist theorem can tell us let's say we sample the audio at 10 000 times a second or 10 kilohertz what's the maximum frequency of wave that we can record well if we have a two kilohertz wave we're going to be recording five samples per wave so that's all good we can recreate the wave from that if we have a five kilohertz wave at this point we're only recording two samples per wave and this is just about okay so we can still recreate the wave however if we try and sample a 10 kilohertz wave we're now only getting one reading per wave the signal no longer looks like a wave at all and instead looks like a straight line so the nyquist theorem tells us that the maximum frequency you can sample is half the sample rate so we're sampling audio so ideally we want to record frequencies up to 20 kilohertz and that means we need our sample rate to be 40 kilohertz it needs to be double so can the esp32 do that well let's set up a quick test to find out so written a small piece of code here and all it does is read from the adc a million times and then it records the time taken for each reading in microseconds so let's have a look at the serial monitor here and see what our results are so each conversion takes about 9.7 or 9.6 microseconds which gives us a maximum sampling frequency here of 100 kilohertz now that's absolutely fine remember we want uh to sample 20 kilohertz audio that means we need to be sampling at 40 kilohertz because of the the nyquist theorem if you're using an esp8266 or something of the something like that you might find that the sampling rate is a lot slower and i haven't got one of those so i haven't been able to test it unfortunately but run this piece of code and see what results you get let's now move on to how we use the arduino fft library and how we deal with its results we're going to use the arduino fft library here but as of this writing there is a bug in the dc removal function in the version that's downloaded from the arduino ide library manager so instead of installing it from there you want to go here to github i'll put a link to this in description and and download it code and download zip and then add it to the sketch from sketch include library add zip library hopefully that will be fixed at some point soon i have raised an issue on the the github page so we start off with the fft constructor and this path this takes four arguments one two three four uh two double arrays called v real and v imaginary and uh the number of samples we're going to take and the sampling frequency now i've set the number of samples here to 1024 and we said the sampling frequency earlier needs to be 40 000 if we want to detect 20 kilohertz signals now if you're running a slower microcontroller you might have to set this a bit lower but then you'll get fewer frequency bins and we'll talk about what that means in a little bit we now calculate the sampling period and that is how many microseconds there are between each sampling event so the sample rate of 40 kilohertz we need to sample the signal every 25 microseconds and then we get into our loop so the first thing we need to do is to record our samples so sampling the audio pin for each sample we analog read into the the v real array and we set v imaginary to zero we then wait until 25 microseconds is up and then we sample again until we've recorded 1024 samples now our audio will be biased around half of 3.3 volts which i'll talk about when we look at the schematics later so it'll have a dc offset of 1.65 volts so this next line just here will remove that dc offset from the data so the readings now swing around zero instead next we do some fft magic now if you want to know exactly what's happening here you can read the source code for the library on github or look at one of the many many resources available online but it's not necessary to do that in order to use these results now we have our results we need to understand them so each element now in our v real array represents a frequency bin and the value of each element represents the amplitude or the amount of that frequency but what is a frequency bin i hear you grow glad you asked to keep things simple let's say we did an fft with 16 samples instead of 1024 the x-axis here shows the frequency bins and as we have 16 samples we have 16 bins we can also only use the first half of the data so from i equals 0 to i equals 7 as the rest of the values are negative and are meaningless for looking at power i think they used something to do with phase but we're not getting into that it also turns out that the first sample is also unusable as this is swapped by dc so we discard that now what frequencies do these bins represent well if we take our sample rate and divide it by the number of samples that gives the width of each frequency bin if we're sampling at 40 kilohertz and we take 16 samples each bin is two and a half kilohertz wide so everything between zero and two and a half kilohertz is locked into bin zero from two and a half to five kilohertz is in bin one etc all the way up to the seventh bin um it's 20 kilohertz if we wanted to split our segment of three bands to display bass mid and treble for example we'd have to decide which bins to put in which band we might decide that bin one is bass tones uh being two and three are mid-tones and bid four to seven are treble tones in this case the frequencies here don't match up with those descriptions but just bear with me for the minute let's say band one two and three now we wouldn't just split the bins into thirds because we hear pitch in a logarithmic way and all the interesting stuff is down the low end we therefore want more bins or sorry more bands in the low end compared to in the high end so we add together the values of those bins for each band and after some global scaling they become our bar heights now in reality of course we have a thousand and twenty four bins that means 511 of them are usable and we need to decide which of these bins to put in which band so i wrote an excel spreadsheet to help me calculate that first we put in our sample rate which in this case is 40 kilohertz and then we decide that the lowest frequency band is that we want to look at so let's say our lowest frequency band here is going to be 80 hertz let's set our highest frequency band i'm going to put 12 kilohertz in here i know we can sample higher than that but generally we don't get that interesting results beyond about 16 17 kilohertz so let's put the center of the highest frequency band at 12 kilohertz the number of samples we're going to take is 1024 and let's make that into an eight-band vu meter now the table below here shows which bins should map to which bands so the first band band zero is going to be anything lower than uh three band one is going to be bins between three and six band two is going to be bins between six and thirteen band three is going to be bins between 13 and 27 etc etc so let's see how they fit into our code so you can now see how this matches up so if i is less than three that's the first band zero just here and then we've got three and six so if i is greater than three and less than or equal to six the next one says six and thirteen so greater than six less than or equal to thirteen so we just fill this in uh as shown also make sure at the top of your code that you've set the number of bands correctly so we've put the data in here for eight bands so num bands needs to be eight so now we've done that let's do a quick frequency sweep and check everything's working well [Music] okay so that's working well but let's say we have a 16 by 16 matrix like the one i've got here we can actually increase the number of bands to 16. so back to our excel sheet change the number here to 16. and now we can see we've got 16 bands and i've already written in the code just here so i'm just going to uncomment this bit comment out that bit and again don't forget to change numbans at the top to 16 and then we'll upload that and see what that looks like [Music] couple other quick things to know about the code before we take a quick look at the wiring you can increase this noise parameter just here if you find your display is picking up too much noise we've also got the amplitude parameter and that can be used to scale the output so change this if the bars are too big or too small for your display if you're going for more than 16 bands you'll have to increase the size or the number of elements in each of these three arrays here so the number of elements in here always must be greater than or equal to the number of bands if you look at my xy code here this is standard serpentine matrix xy code um the input to my matrix actually in the top left but i've added this line just here what this does is adjusts the y-coordinate um so that we can reference the y-coordinate from the bottom left instead makes it a little bit easier when you're drawing the bars okay a few quick notes here on hardware um you can wire up using either a microphone or using the line in the microphone wiring is much simpler but you get a better frequency response from the line in with the microphone make sure whatever microphone you're using has a built-in gain preferably one with automatic gain control mine doesn't actually but that makes it a little bit easier um ground goes to ground vcc goes to 3.3 volts and the output pin i've got it wired into d35 just here but you can choose whichever pin you like and if your microphone's picking up electrical noise from the uh the leds flashing um stick a large electrolytic capacitor across the ground and vcc lines just here i've got a 470 microfarad uh electrolytic cap across mine at the moment and that seems to work reasonably well if you're using the line in setup just here um first of all i've used a couple of 10k resistors to tie together the left channel the right channel just to mono my input then we go through a dc blocking capacitor just here i used a 100 narrow farad ceramic cap here but i've used everything up to sort of 10 narrow nano farad's electrolytics and that seems to be absolutely fine i haven't really noticed any difference in the frequency response to be honest so maybe try and play about with that and see what you can see an effect it has we've also got two resistors here what this is doing this is across the 3.3 volt and ground connection and these two resistors are biasing your audio signal up to around 1.65 volts because remember the adc of course on the sp 32 will only go as low as zero volts so you can't put negative voltages into it in each case we've got pin d5 here and that's the data out pin for the leds which is going out to the first led in the matrix so we'll finish off with a couple demonstration of some of the patterns i've written so far there's a lot of scope here for making something really interesting so if this is something you'd like to try yourself i'd love to see what you guys come up with [Music] that's all for now i know this one was a bit technical but i hope you found something useful in there if you have please do consider subscribing as it really helps me out and i'll see you next time
Info
Channel: Scott Marley
Views: 87,847
Rating: undefined out of 5
Keywords:
Id: Mgh2WblO5_c
Channel Id: undefined
Length: 14min 3sec (843 seconds)
Published: Sun Jul 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.