Posts with «audio - music» label

Power Quality Meter.

Arduino UNO project, Power Quality Meter, someone would call it’s PQ Monitor or PQ Analyzer.

I had already published  a blog  devoted RMS measurements on full band  20 – 20 000 Hz  audio signals. ( Following my own style, I’d refer to already published materials whenever it’s possible, to save my time ).  This time measurements performed on single AC Power Grid frequency. ( 60 Hz in Canada. Algorithm would works with 50 Hz as well).

Features:

  • Graphic LCD display 128×64;
  • First 5 harmonics presentation;
  • RMS Voltage Indicator;
  • Frequency Monitoring;
  • THD calculation;
  • Internal data up to 63-d !!! harmonics components in Real-Time;

The Holy Grail of this project, is a method of sampling input waveform. As there is only one main frequency (fundamental) at the input, I came up with idea to do a sampling period VARIABLE. There are at least 2 great advantages in this brilliant ( may I ? ) invention:

  1. It’s completely eliminate necessity of the windowing.
  2. Only ONE period of input waveform is enough for precise calculation.

First of all, windowing is really BAD on metrological side (for accuracy of results), smashing one single frequency bin to over 3 – 5 of it’s neighbors, significantly deteriorating input sensitivity, and plus it’s not able to eliminate limits discontinuity effects well – only attenuate them. Secondly, from software timing performance point of view, introducing windowing in the Real-Time application would automatically require to DOUBLE data throughput, as Overlap – Add procedure would be mandatory.

In it’s essence, I created a software PLL (Phase Lock Loop). Compare to a project with hardware based PLL (IC 74HC4046), no need for external chip this time. Engine is running on Timer1 features – CTC mode and capability to drive ADC Auto trigger. I will go into details in software section.

Hardware.

As you can see on the drawings, circuitry is quite simple, one LCD ( I used SparkFun LCD-00710, could be different ) and one IC, LM311 – comparator. Pay attention, that GEDA doesn’t have a library for such display, all details on LCD configuration, pin numbering etc you can find here.  I haven’t experienced any difficulties with assembling LCD, except soldering bunch of wires and installing control brightness level pot. Thanks author of the GLCD library (great work!), there was no any troubles with software also.

Transformer is doing galvanic isolation, as they say – safety first! There is no part number ( requirements ), anything with primary windings for your local AC main ( 110V,  220V ) and about 10 V on secondary will be o’k.  Values of the resistive voltage divider ( 22k and 2 x 4.7k ) may be adjusted proportionally for transformer with different secondary voltage output. Trick is to keep voltage level close to ~2V AC peak value at the arduino analog input # 5.  There are two caps 2200 pF to filter out RF interference, and one trim pot to adjust comparators threshold ( not strictly necessary, you can replace with constant two resistors voltage divider ). Good decoupling of the +5V power lines should be done if LCD installed on the same board (as I did), otherwise, arduino goes crazy when it’s received a basket of interrupts on pin 2 (INT0).

SOFTWARE.

 I’ve read an article in December’s issue of the Elektor magazine, that actually inspired me on this project. Even I had such idea in my mind for quite awhile, nevertheless Elektor’s publication accelerate this process. Do you still remember I called my method “brilliant”? And this is why: compare to  project published in well known and respectful electronics magazine, my code is running 140 !!! TIMES faster ( compare 5 milliseconds to 700 milliseconds competitors ). I didn’t tweak any optimization. My software is running REAL-TIME in each AC period, keeping load of the microprocessor below 30 %. It’s capable to do a Real-Time monitoring of three phase power line. The only things which is slow down process, is LCD display refreshment. In current version, algorithm averages data over 32 cycles before outputs summary data report  on the display, around 0.53 seconds period ( 1 / 60 / 32). During update display procedure (23 milliseconds or so) which is longer than 16.66 milliseconds period of the AC 60 Hz, one cycle is skipped. Depends on application, the task of updating screen could be split over many sub-frames, so instead of one big chunk of code, 32 smaller size chunks will go unnoticeable in background, fixing an issue of 33-rd lost frame. But I don’t think it’s necessary for monitoring purposes, may be only in Power Energy Meter project? I just can’t imagine, Elektor’s 2100 milliseconds overall time per cycle, when everything could be done in less than 7 milliseconds ( using split display subroutine ). It’s 300 times difference!.

THE MAGIC.

 Software PLL / FLL – Frequency Lock Loop is build on TIMER1 VCO. Well, it’s not quite correct to call it VCO, probably FCO – Frequency Controlled Oscillator. Software adjusts oscillator in such a way, that number of captured samples  per one AC waveform has to be exactly 128 .  Look here:

   if ( smpl_Nmbr > FFT_SIZE ) smpl_Time++;
   if ( smpl_Nmbr < FFT_SIZE ) smpl_Time–; 

    OCR1A = smpl_Time;
    OCR1B = smpl_Time;

If during one AC period ( 1 / 60 Hz = 16.66 milliseconds ) timer restarts more often than necessary (FFT_SIZE = 128), smpl_Time variable increasing, so TIMER1 FCO slow down. In opposite case, smpl_Time is decreasing, forcing clock to run faster. Track on quantity of captured samples goes as usual, via indexing input array variable – smpl_Nmbr, which increments every ADC “start conversion” event, triggered via channel B:

   ISR(TIMER1_COMPB_vect)
   { 
     if ( smpl_Nmbr < FFT_SIZE )
       {
         x_r[smpl_Nmbr] = ADC – adc_Offst; // 
       }   
    smpl_Nmbr++;
    }

( Paralleling Timers two  channel A and B was invented here.)  The comparators main duty is to trigger digital pin 2 (INT0) exactly in the same point in time, relatively to input signal periodicity. Not necessary at zero. Synchronization point could be at any voltage level on the input waveform, it’s has nothing to do with zero-crossing. As software calculates complete FFT subroutine, for both REAL and IMAGINARY part (btw, referring link) , adjusting point (via pot) to exactly zero-cross simply push all energy in imaginary part (sine). Bringing this point to 45 degree would splits energy equally between real and imaginary parts. Later on, extracting square root from sum of two squares ( magnitude calculation ) simply annihilate any difference, magnitude is not changing with moving synchronization point up and down at all.

DC offset is adjusted in every cycle based on REAL (cosine) bin-0 magnitude:

  temp = f_r[0];
  if ( temp > 0 ) 
      adc_Offst++;
  if ( temp < 0 ) 
      adc_Offst–;

Rolling Filter, the easiest one to implement and understand, and very efficient against spikes.

Arduino UNO sketch:  download.

To be continue….

6 January, 2013.

I did some “resource  management” in software, because data calculation in each cycle of AC waveform is not really necessary. Let me explain. There are 3 major hardware limits :

  • ADC resolution
  • Memory size / CPU performance
  • Update Rate

In first version, calculation of harmonics magnitude content goes up to 63-rd. But as resolution of the Arduino ADC limited by 10-bits ( 9 plus sign ) it doesn’t make much sense for real world electrical grid, simply because magnitude starting from 5-th  harmonics drops below noise floor –  6.02 x 9 + 1.76 = 55.94 dB (0.16%) There are two way to solved this issue: increase the FFT size, or use oversampling technics. First method is not possible due memory limits. Second one makes update rate too low for practical use.

In this software release, I limit calculation to first 7 harmonics, and show all of them on display (see photo). FFT size is the same, 128. But sampling clock running 8 times lower, so 8 AC cycles necessary to fill up input array with new data. Method – oversampling in time domain. It gives 3-bit gain in resolution, same as have 12-bit ADC, overall dynamic range 6.02 x 12 + 1.76 = 74 dB. (0.02%)

Version 2:  download.


Speech / Voice Recognition – remix.

It’s about right time to release one more “remix” for one of my blog, published almost a year ago. I haven’t got much comments, not many as I was expecting, on a topic. There are some reasons, that would explain this phenomenon, but I would better to start outlining what I did in new release, and some of you who tried old version would be impressed by progress I’ve made!

Basic structure was left almost intact. Essential parts of the project: Filtering 2D and Cross-Correlation are the same, so please read my old post, if you come across this one w/o seen it first. What differs is “preprocessing”, before we get to the filtering stage. In first, I ported a code on Leonardo board.  The easiness of connecting electret mic to Leonardo, just didn’t give me a choice!  I played already with Leonardo ADC – electret mic’s in my previous post, and would assure you, that this guys were designed to work as a team. Uno followers have to solder a pre-amplifier, not big deal, the same time not really interesting.  Code would run on Uno, except Timer and ADC settings, which you could always “copy/paste” from the old version. Feel free, be my guest.

Analog front-end is absolutely the same as I used in Sound Localization project. You would need only one mic here, just reduce the number of electrical components down.

Sampling subroutine based on Timer 4, and arduino Leonardo internal PGA set to gain x40. There are a comments in the code, so you could adjust gain up or down depends on the sensitivity of mic you have.

Windowing LUT is slightly modified Hamming/Hann cosine function,  I’d say my table is an “intermediate” version of both mention inventors.

FFT is my best achievements of this year, RADIX-4.  Compare to old code, about 3x faster. This is why I was able to increase FFT_SIZE up to 128,  still having plenty of time.  Magnitude calculation is based on approximation, very fast, because no square root extraction required. Accuracy, in the worst case scenario ~95%, which is more than enough in this project.

I changed Non-Linear compression algorithm, as now there are more Bins – 64 to pack in 16 Bands. Math is simple, and hope doesn’t need an extensive comments. Packing is necessary due memory limits, 1 sec password in current configuration (16 bands with sampling rate 4 kHz) occupied 1 kByte, full size of EEPROM on Leonardo or Uno boards.

Command Line Interface is preserved. Here is the instructions, how to set everything up and running.

And here how spectrogram looks like in LibreOffice, test phrase “Front right”, (OS Linux Ubuntu, 12.04):

                   

Instructions.

 Get your microphone wired / connected? All checked at least a couple times with multimeter, voltages looks o’k? Good, now you are ready to start! ( Don’t forget to upload a sketch to your arduino / Leonardo -);

1. X. First of all, open serial monitor window, and check boadrate.
Should be 115200. Next, type “x” and Enter. Get some response? Does
it look like a table? Excellent, data you are looking at is “raw” 
sampling data. Probably, just noise, acoustical or electrical. 

2. F. Second test, type “f” - Enter. Again, arduino would print out 
a table. This time data represent “processed” by FFT analog signal. 
Each bin corresponds to frequency range 32 Hz. If you have a signal
generator , it's right time to do a detailed check up microphone, 
wiring, and software. If don't have, you can use your computer's 
sound card and some program, there are plenty of them available 
on-line free of charge. Connect generator to PC USB speackers, and
run a single tone, anything in audible range 16 – 2000 Hz. Check 
again using “f” command, if arduino registers a signal, and it's in
right bin. Due “windowing” function, even pure single tone would 
show up at least in 2-3 neighboring bins. Amplitude depends on 
sensitivity of the mic, and volume of the sound. Sending “x” you can 
confirm, that there is no “clipping” too many “– 511” or “+511”.

3. S. Next, if all goes well till this step, you probably already
notice, that whenever a mic picking-up a sound – yellow on-board LED
lights up. Now, it's better shutdown your TV, iPad, radio. 
Make your environment as quite as possible. Try to say something 
with your own voice, and see if led lighting up when you start 
talking, and than after ~1 sec it goes off. Repeat a few times, 
adjusting a volume and / or distance to the mic, so led goes “on/off”
reliable. Send “s” command when led is off. Don't worry, it should 
be no report on screen, till you say a word. Procedure is simple, 
send “s” - say something. After you talk, and get a printing, look 
carefully. Your objective, is get a “spectrogram” which consist of 
a few spots / blobs of digits, randomly distributed all over the 
“surface”. Repeat a few times with one word, than try another one 
and so on. With short words, very likely reporting data would be 
concentrated at the top ( you may need to scroll up to see the 
beginning), if this is a case, better to choose longer words or talk
in slower tempo. Just remember, there are three dimension, time, 
frequency and volume. You can use a signal generator here again, 
spectrogram should looks like a vertical line, may be 2 - 3 parallel
lines on low frequencies test tones. 
 Changing a frequency, you can even get some curves. What is 
important, the must be no negative numbers. If you see them – 
"overloading" happens, Decrease a volume. Dynamic range is limited 
by 127, more close you can get to this value w/o negatives, 
the better. And last dimension is a frequency. For man, it would 
be a little bit hard to “detach” a spectrogram from the left border.
It's true for everyone, who is not opera singer, me no exceptions.... 

4. R and G. After you practice enough, and received Manny nice 
looking spectrograms, it's time to check with arduino, if it's 
agree with you / thinks similar. Send “r” - recording, and say 
a word you've get your best spectrum with. Wait a few seconds, 
writing to EEPROM takes time. Now send a “g” and say the same word.
In the same manner, tonality and volume. See on the outputs, what 
is the cross-correlation factor you received. More than 50% - very 
good for beginning. Less – try again a few more times sending “g” and
repeating same word, maybe slightly varying pronunciation. Try to 
reach best recognition, “crack” your own password code! 
( note: Negatives number on “G” reports-form must be present.)
If no luck try another password code. Now you know the drill: 
S – repeat, repeat, repeat....., R, G – repeat, repeat, repeat..... 
(joke). Can't get good match? Try your computer's test sounds, 
beeps, horns, clicks, barks – whatever your OS has. It doesn't have
to be shorter than 1 sec, but only 1 second in the beginning 
would be stored / compared. My computer is able to repeat the same 
sound track (speakers test - "front right") with enormously high 
cross-factor 99 % ! I'm not a computer, my best short 86 % so far...

5. P. This command is simply reading the content of the EEPROM, 
so you always can verify, what you stored last time. 
Editing / formatting this data you can store a table in the arduino 
FLASH memory using PROGMEM. About 10 – 15 commands. Of course, 
storing data in external SD card or EEPROM, could greatly increase
the “vocabulary”, the same time design of fast cross-correlation 
algorithm with multiple “pattern”s would be another brain teasing
puzzle -);.

Have fun!

Link to arduino sketch, VOR (VOice Recognition).