用户工具

站点工具


knowledge:electronic:2019032101

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
knowledge:electronic:2019032101 [2019/03/21 12:48]
弘毅
knowledge:electronic:2019032101 [2019/03/21 12:51] (当前版本)
弘毅
行 220: 行 220:
 </​code>​ </​code>​
  
 +So now with proper module and calibration you can measure sound level of different events or devices and compare them one to the other.
  
 +===== Frequency analysis with FHT =====
 +
 +What if you want to “break” the sound into individual frequencies and measure or visualize each individual frequency? Can this be done with Arduino? The answer is that it can be done relatively easily thanks to some existing libraries. To turn signals from a time domain to a frequency domain you would generally use a Fourier transform. Such transforms are used for signals of different types, sound, images, radio transmissions,​ etc. Each signal type has its own properties and the transform that best suits a sound signal is the Discrete Hartley Transform (DHT). DHT will work with discrete, real values which form our waveform. To implement DHT we will use Fast Hartley Transform (FHT) and specifically the ArduinoFHT library.
 +
 +The Arduino FHT library works with vectors of 16 to 256 samples. This size is denoted as N. In this project I will be using N=256 to achieve maximum resolution, but you may use smaller values if you are short on memory or processing power.
 +
 +First, the algorithm takes N real numbers and results in N/2 complex numbers. Then we can pass the data to another function to calculate the magnitude of the complex numbers to get N/2 bins. In the end we get N/2 bins, each covering a frequency range of sampling_rate/​N Hz. The highest value of the last bin will be sampling_rate/​2 . The reasons for this relate to signal processing theory, specifically aliasing and Nyquist law. In practice, if you want to avoid any strange effects, such as higher frequencies “folding” over lower frequencies,​ you will need to make sure to use a sampling rate that is twice the highest frequency you expect to have in the sound signal. Otherwise you are not sampling fast enough. You should also not over sample, as it will result in low ADC accuracy and wasting of FHT bins on ranges that don’t appear in the signal. I found the value of 20Khz to be a good upper frequency based on the range of my microphone and on the range of typical human hearing. As a result the, sampling at 38.4Khz (divider=32) seemed optimal.
 +
 +So for N=256 and sampling_rate=38.4Khz we get 128 150hz bins with the first been holding the magnitude value of 0-150hz and the last bin holding the magnitude value of 19050-19200hz. We can now focus on specific bins that interest us, send the values of all the bins over serial connection, store the values, display them in some way, etc.
 +
 +One of the fun ways to use the data, especially when troubleshooting and developing is to visualize with an analyser. Load the following FHT example code to the Arduino or adapt it to your needs. It gets the samples, runs FHT on the data and sends it in binary form over serial. Your Arduino should be connected to a computer running Processing development environment. In Processing, load the “FHT 128 channel analyser” project. I had to make a change to the project to make it compatible with Processing 3.0 . To do so, move the call to “size” function from within the “setup” function to a new function called “settings”.
 +
 +{{:​knowledge:​electronic:​pasted:​20190321-124951.png|Analyzer}}
 +
 +Another way to analyze the data is for the Arduino to send it over serial in textual form, let it run for some time, then copy it from the serial monitor and paste it in a spreadsheet. For example using a code that is similar to this:
 +
 +<​code>​
 +void MeasureFHT()
 +{
 +    long t0 = micros();
 +    for (int i = 0; i < FHT_N; i++) { // save 256 samples
 +        while (!(ADCSRA & /​*0x10*/​_BV(ADIF)));​ // wait for adc to be ready (ADIF)
 +        sbi(ADCSRA, ADIF); // restart adc
 +        byte m = ADCL; // fetch adc data
 +        byte j = ADCH;
 +        int k = ((int)j << 8) | m; // form into an int
 +        k -= 0x0200; // form into a signed int
 +        k <<= 6; // form into a 16b signed int
 +        fht_input[i] = k; // put real data into bins
 +    }
 +    long dt = micros() - t0;
 +    fht_window();​ // window the data for better frequency response
 +    fht_reorder();​ // reorder the data before doing the fht
 +    fht_run(); // process the data in the fht
 +    fht_mag_log();​
 + 
 +    // print as text
 +    for (int i = 0; i < FHT_N / 2; i++)
 +    {
 +        Serial.print(FreqOutData[i]);​
 +        Serial.print(','​);​
 +    }
 +    long sample_rate = FHT_N * 1000000l / dt;
 +    Serial.print(dt);​
 +    Serial.print(','​);​
 +    Serial.println(sample_rate);​
 +}
 +</​code>​
 +
 +Then you can format the data in a spreadsheet,​ such as Excel, as a “3-D Surface” mesh graph. For example, see a graph of a Frequency Sweep from 1hz to 5000hz as captured and analyzed by the Arduino and FHT:
 +
 +{{:​knowledge:​electronic:​pasted:​20190321-125044.png|Mesh of FHT frequency sweep}}
 +
 +===== Summary =====
 +
 +My code for this project can be found at github for you to experiment with.
 +
 +The Arduino can be used for relative sound level measurement and for frequency analysis/​visualization. One just needs a microphone to match the use case, an Arduino, some coding and optionally the FHT library. Have fun and let me know in the comments if you make something nice using such a setup.
  
 https://​blog.yavilevich.com/​2016/​08/​arduino-sound-level-meter-and-spectrum-analyzer/​ https://​blog.yavilevich.com/​2016/​08/​arduino-sound-level-meter-and-spectrum-analyzer/​
  
  
knowledge/electronic/2019032101.txt · 最后更改: 2019/03/21 12:51 由 弘毅