RSS

Function generator with LDR (PhotoResistive) Optocoupler.

Objective of this project, is to create simple and low cost function generator. Of course, it must have arduino interface (!) to set output frequency. I’ve been considering 4 option:

  • AD98XX;
  • XR2206;
  • Wein bridge.
  • OPA, with triangle – to – sine shaper.

First one, DDS high tech miracle AD98XX, was put aside due high price, and simplicity, there just wouldn’t be any fun in connecting couple wires -);

XR2206 had better chance,  but I decided that minimum 10 V supply voltage is a serious disadvantage for arduino interfaced circuits. Boosting voltage up from 5 to 10 may be not very difficult task, same time interface between low (arduino) / high (IC) sides may present a technical problem, and increase cost substantially.

Moving back in time, next alternative is a Wein Bridge Sinewave (most important waveform for me) Oscillator. Well, it would be possible to create low-distortion generator, using circuits from 80-x with modern single power (+5V) rail-to-rail OPA. The technical complexity I only see, is that in order to cover wide frequency range      ( 1 : 10 000 ), I would have to use a switchable bank of capacitors, (btw, same apply for XR2206). Other things, if I go with 2 digital pots as interface to digital world of arduino (Wein bridge require 2 identical resistors), I’d get frequency quantization issue plus non-linear quantization. Using Photo-Resistive (LDR) optocouplers in design, I resolve this problem, the same time it’s practically impossible to have 2 LDR with parameters close to 1% match. My understanding of Wein bridge oscillator theory, is that you can’t get distortion level you wish to have ( > 0.01 % ) w/o high precision resistors AND capacitors. More over, precise “switchable” capacitors would complicate everything even more, as any switch would introduce temperature dependent error. Probably, it may still be possible, but price tag would jump up well above option #1 (AD98XX) or #2 (XR2206).

And finally, I choose OPA based ( integrator / Schmitt trigger ) topology. Summary:

  • Low price, about 2 $ in basic configuration (w/o user interface);
  • Single power supply +5V (from arduino, no need for separate PS);
  • Wide frequency range 30 Hz – 300.000 kHz;
  • Sine / Triangle / Square outputs;
  • Frequency Lock Loop (FLL) +/- 10 Hz (arduino or standalone AtMega328);
  • Distortion (THD) less than 1 %.

MCP_OPA_PhotoResistive_Coupler_4_simple_c

Details on hardware side of the Function Generator itself, you may see from the schematic above. OPA is Microchip MCP6022, data sheet says: “wide bandwidth (10 MHz), low noise (8.7 nV/√Hz), low input offset voltage and low distortion (0.00053% THD+N)”.  There are many faster OPA, with high slew-rate, but most of them ether require dual power supply +-5V (single more than 10V) or doesn’t have JFET at the input stage, which is important in this design, otherwise it’d not be possible to cover 1:10 000 band span w/o using switchable bank of capacitors, as I mention already. Using MCP6022 with relatively modest 7 V/usec slew-rate, upper frequency limit about 400 – 450 kHz ( with lower integrator’s capacitor value  ) when sine magnitude 2.2 V p-p. To get higher, up to 1 MHz, would be necessary to decrease triangle amplitude to about 1V, and using quad OPA like MCP6024 build additional amplifier stage to drive triangle-to-sine shaper properly. Shaper isn’t optimized, and applying higher voltage with more diodes in the circuits ‘d help to lower distortion level. Only, I decided to put simplicity as factor number 1 for this design.

For “Instructables” – how to do a Photo-Resistive (LDR) optocoupler, look at the pictures:

DSCF0338aDSCF0339a DSCF0341a DSCF0343a DSCF0344a DSCF0346a

In basic configuration circuit doesn’t require user interface = LCD + Mouse, which you can see on a photo, there is always an alternative like serial monitor, or CLI (command line interface) to change settings. If you decided to replicate Function Generator for your home -/- garage lab, than I’d recommend to start with a basic form / structure, of course, to simplify debugging.

MCP_OPA_PhotoResistive_Coupler_4_simple_b

Adjustment.

 There is 1 k pot, to set reference voltage exactly at 1/2  of the power line voltage. You may use an oscilloscope, and simply turn pot till square wave reach 50 % duty cycle. Or you may use any available spectrum analyzer, or even your computer sound card and software version of the SA, and do adjustment based on even number harmonics magnitude. Another constant value resistor 3 k, which installed in series with diode’s shaper, may be trimmed slightly in order to minimize odd harmonics content below 1 %.

Software.

 The essence of this project is Frequency Lock Loop, that implemented around TIMER1 external input counting feature and TIMER2 as a gate clock and PWM driver. Here is code:

ISR (TIMER2_OVF_vect) // Counter < 64 usec
{
   ovf_tick++;
   if( ovf_tick > SET_CLOCK )  
  {
    ovf_tick = 0;
    frq_tmr1 = TCNT1;
    TCNT1 = 0;

   int16_t diffr = set_freq – frq_tmr1; 
   int8_t ln2 = 0, sign = 1;

   if ( diffr < 0 ) sign = -1;
   diffr = abs(diffr);

   while( diffr > acr_freq )
   {
      ln2++;
      diffr >>= 1;
   }

    pwm_tmr2 += (sign * ln2); 

   uint16_t temp = pwm_tmr2 + 32768;
   OCR2A = temp & 0xFF;
   OCR2B = (temp >> 8) & 0XFF;

   sec_tmr1++;
  }
}

Timer1 is pre-configured to count pulses (square) on pin 5.  Timer2 is running on internal clock 16 MHz w/o preselector, to have maximum resolution and highest PWM frequency possible 16 M / 256 / 2 = 31250 kHz. Counting number of overflow interrupts and compare this value to 3124, defines 0.1 seconds time interval, gate or window for Timer1 based frequency measurements. Timer1 (16-bits) never overflows, as at maximum 300 kHz it counts up to 30 000 only. This gives 10 Hz frequency resolution.

Why not 1 Hz, you may ask? To have 1 Hz resolution up to 300 kHz upper limits would require minimum 19 bits, (better 22 – 24 to accommodate high optocoupler’s LED non linearity ) of PWM resolution. Even, there is still Timer0 pin 6 PWM available, I decided not to do it, as it would require better than 5 / 1 000 000 = 5 uVolts (approximately) noise floor on power lines of the arduino, which is obviously, out of reach even I put uCPU to sleep. I’m not sure, if combining 2 PWM outputs of the Timer2 to get 16-bits resolution was such a good idea. Nevertheless, it’s working as a charm!

LDR has pretty high attenuation level at 31 kHz, so FM modulation index is quite low, that may be an issue otherwise, To practically eliminate modulation at all, PWM is filtered by electrolytic capacitors (100 uF) before it reaches LED.

Arduino UNO sketch:    Function Generator with FLL. 

To be continue….?   Probably…

 
Leave a comment

Posted by on June 9, 2013 in Uncategorized

 

Barometric (atmospheric pressure) Arduino project.

front1 side1 side2

All details on hardware side of the project you can see on the pictures above. UNO board.

Software.

 Interface with a sensor based on a manufacturers library and Arduino Wire library. Same with LCD, there is no point to invent a bicycle. I add up simple low pass filtering, 1 seconds interval timer – “tick-er”, and bar-graph on the left side of display.

Each bar represents averaged (Low Pass Filtered) atmospheric pressure for 2-hours period. Bars  move from right to left, so the most “fresh” data show up on the right side, just in front of theirs digital representation. History, consequently, keeps track for last 16 hours. Have fun.

Download Arduino sketch:  Barometric_2a.

 
Leave a comment

Posted by on April 10, 2013 in DIY, Simple projects.

 

Tags: , , , , ,

Power (Energy) Meter – Phase, Power and Energy.

Chapter II. Software.

Part 1. Sampling.

Specific of this project compare to VU meter, is necessity to sample two analog inputs simultaneously. I have a blog, where 4 ! analog inputs processed, only with Arduino – Leonardo. This time UNO, but it’s almost the same. Take one channel sample, than switch input multiplexer, take another and so on.  Here is the subroutine:

ISR(TIMER1_COMPB_vect)
{ 
 int16_t adc_value = ADC - adc_Offst;
 static int16_t last_smpl = 0;

 if ( smpl_Nmbr < SAMPL_P )
 {
  if( smpl_Nmbr & 0x01 )
  {
   ADMUX = 0xC5; // Voltage, pin AN5 
   v_s[smpl_Nmbr >>1] = (last_smpl + adc_value) / 2; //Linear Interpolation
   last_smpl = adc_value; 
  }
  else
  { 
  ADMUX = 0xC4; // Current 3, pin AN4
  c_s[smpl_Nmbr >>1] = adc_value; 
  }
 }
 smpl_Nmbr++;
}

Another things, related exclusively to Power (Energy) Meter, is phase. It has to be the same for both channels, and as Arduino has only one ADC, it requires some efforts. I choose linear interpolation method, as the easiest one. Other option would be phase rotation after FFT processing, which is also quite simple, but not so as with interpolation. The main duty of the sampling subroutine, is to fill up two data arrays, 64 samples each, 128 samples overall. Sampling goes synchronously, read more in the Power Quality Meter blog for details. Frequency = 60 x 128 = 7680 Hz. Or 3840 Hz per channel. According to the Whittaker-Kotel’nikov-Shannon (WKS) sampling theorem it’s well enough up to 1920 Hz of the analog input signal. Calculating in other directing, 64 – bins FFT outputs 32 bins of results, in other words provides 32 harmonics content, and     32 x 60 = 1920. I read somewhere, that for power metering up to 20-th harmonics must be included, so I’m covering more than standard says.

I noticed, that switching input multiplexer of Arduino UNO, ADC occasionally swapped samples. To solve an issue, I increase default ADC preselector frequency 125 kHz up to 250 kHz in setup().

Part 2. Voltage, Current and Phase.

 Sampling flows in background, Real-Time. Each interrupt request at digital pin 2 ( coming from comparator LM311 – look on previous blog-page ) initiates copy procedure of the captured samples from two arrays to another set of two arrays for FFT calculation. To simplify debugging, I assign also two imaginary arrays, even for practical use only one would be sufficient. If memory is an essence in your application, you may eliminate one of them. Interrupt sets a flag “data ready” for main program – loop. In foreground procedure, conveyor belt consists of next stages:

  1. Calculation Real and Imaginary (Quadrature) part for Voltage;
  2. - // – same for Current samples;
  3. Accumulate values for over 32 cycles on main frequency (60 Hz);
  4. Calculate precise Magnitude and Phase for Voltage;
  5. Calculate “estimated” magnitude for Current, and set PGA Gain;
  6. Do precise calculation for Current channel, (subtracting interference, use appropriate gain coefficients);
  7. Calculate Power usage Power = Voltage x Current (Real);
  8. Accumulate Energy summing up Power divided by 1000 (kWatts).

Now, I would go step by step.

1. Why FFT for Voltage channel, you may ask. If sampling is synchronous process, than calculation of the phase is also not required – it’s defined by threshold voltage of the comparator. First of all, FFT is very efficient High Pass Filter, which is must be implemented in Voltage channel anyway, to suppress DC voltage offset instability and ADC internal non-linearity / inaccuracy. At step 3 – accumulation, bin – 0 (DC) is not summed. I already explained  this here.  Secondly, I draw a Current Phase Indicator ( extended Power Factor -90 +90 degree ), and I need Voltage Phase data in order to draw this correctly. Electrical grid Voltage has  distorted waveform, and it may be shocking or looks like a paradox, but calculating phase of the 32 harmonics sum, phase is never what it’s originally defined by comparator, and there is no way to trim it to “0″. Voltage shape is never exact in each period. It fluctuates. If there was HPF you would not even know, that each harmonics has unique phase, and only FFT could provide crystal clear picture of this phenomenon. Moreover, averaging data for 32 periods, phase “offset” grows up. ( It’s statistic / math, sure you can find nice tutorial on google. -); .  Because of this, Current passing via pure resistive load, always has exactly the same phase “runaway” as Voltage has, and must be subtracted.

2. Ordinary, sum up squares of the 31 bins real and imaginary part, and accumulate. Sign extraction for extended Power Factor indicator based on bin[1], as major player in Current Magnitude. May be not accurate assumption for highly distorted waveform (for example, with thyristor power regulator).  I’m still searching right approach. It would be much easier to show data in 0 – 90 range, but there would not be any difference in capacitive and inductive load, what I want to be visible.

3. Why accumulate? To save on hardware. I did not explain in hardware section, why I choose ~x10 amplification gain per each of two stages, now it is right time.  10 bit arduino ADC could get only 55 dB dynamic range ( 9 bit plus sign, 9 X 6.02 + 1.76 = 55.something ). To have 1% (40 dB) accuracy, stages can’t be spaced more than 15 dB. And if I want 52 dB dynamic range ( 500 : 1, according to standard ), at least 4 amplification steps are required. “Oversampling” data over 32 cycles, more than 2 bits of resolution are additionally obtained, and 11 x 6.02 + 1.76 = 68.almost, providing about 28 dB allowance for spacing, and just 2 cascades of PGA would be enough to cover 52 dB. Gain per stage could be set as high as x25 (28 dB). I pick up x10 and x100 in my “proto-type”, simply to relax on hardware, assembly, wiring, on-board routing etc. You can scale up gain in x20 and x400. One more hardware – software issue, is GLCD library, which in default configuration occupies 5 analog inputs. So I changed config file, moving 3 pins to the other side UNO board, shifting whole pack up from 4 – 11 to 6 – 13 digital pins, and assigning 3 – 5 (digital) to 3 wires that were on analog pins. Doing this way, I have PGA two control lines on AN2 and AN3, Current analog input on AN4, and Voltage on AN5.

 Be careful, change LCD wiring and test different config file running test GLCD application before you wire up Power (Energy) Meter to your Arduino!!!.

4, 5 & 6 – below, in Calibration section.

7. Active Power calculated,  P = V x I – (Real).  The problem, I do not have right equipment to do calibration precisely. In my initial design, I was considering to build two identical boards for voltage and current sensors, so that they would provide precisely match in phase outputs. But as you know, I changed my design, due to unplanned  issue with limited optocoupler interference immunity, and now there is small phase offset between two channels. Current signal is passing more filtering / amplification stages, and it’s not surprising that phase is drifted off. Luckily, not much, approximately 0.05 – 0.15 degree, but I can’t be 100% sure, as my heater I used for testing has build-in electrical motor (inductive load , about -45 degree – watch video clip below ). I will do more tests, and if they confirm noticeable phase offset, I would up-date software with phase rotation subroutine, which would allow to make tiny phase adjustment. Or, as I mention in “sampling” paragraph, may be linear approximation with different proportion would be easier approach.

8. Just for estimation. To get “normalized” value, correct timing would be necessary, as in this design all timing / frequency grid varying with electrical main 60 Hz.

Part 3. Calibration.

 If you successfully ( and safely ! shock hazard ) build all circuits from hardware blog-page, than you are ready to start calibration. In short, this is not “for beginning” project, and I’m not going to teach how to do calibration of the electrical equipment here. You should already know this.

Minimum good DMM with AC current measurement capability required, and a few loads ranging from 200 mA up to 15 A. Use resistive loads, for example, soldering iron, incandescent bulb (100 – 200 W), heater (1 – 2 kW). Set 0.5V voltage offset on analog pins 4 and 5 trimming two 50k pots on main (LCD) board. If you do have an oscilloscope, check peak-to-peak value on input AN5 received from Voltage sensor Board. 600 – 900 mV would be o’k, If not, use your DMM with a capacitor for DC decoupling. Approximately same DC offset 0.5V should be on input 2 of the comparator, adjust using 1k pot. When comparator runs stable pulses at the output, everything else could be adjusted via arduino serial monitor. There are “x” and “f” commands. One prints out raw data pull, another – process data.

4. Printing out process data via “f” on serial monitor, look for Voltage Magnitude and Voltage Phase two lines. Adjusting comparator’s pot, bring phase as close to “0″ as possible. I have around 1.5 degree “phase runaway”, but it would depends on THD of specific electrical network. Next, divide real Voltage value measured with DMM by Magnitude value received on serial monitor. You get scaling coefficient. Square it up (^2) and substitute in this section:

 volt_Real *= 0.002566241; // Calibration coeff. Voltage = ( Real Value / volt_Magn ) ^ 2 !!! 
 volt_Imag *= 0.002566241; //

Reload sketch, and see how accurate voltage readings you get.

5 & 6. Following the same procedure for current channel, you need to get 3 coefficients. Start with high current – minimum PGA amplification settings. You may comment out this section of the code:

 ampr_Magn = sqrt(ampr_Real + ampr_Imag); 
 if((ampr_Magn < 200) && (ampr_Gain < 3)) ampr_Gain++; 
 if((ampr_Magn > 2400) && (ampr_Gain > 1)) ampr_Gain--;

and use “manual” switching of the PGA – there are two CLI commands “u” – up and “d” – down, that I implemented to simplify debugging. High current should be easiest part, as interference practically doesn’t exist when nothing connected to “load”.

What I want to light up, is a method of fighting electrical interference I “invented” working on this project. When PGA is set to high amplification mode (~ 360) essentially it’s picking up surrounding electrical EMI. There are would be bunch of reasons, starting from amateur routing traces on the Current sensor board ( It’s about me, I have no clue how to design this stuff ), or inputs terminal placed too close to high voltage network, bad grounding, not shielded cables, etc. etc. As long as EMI readings stable, you would need to confirm this by printing out “f” – process data array many times, when PGA is in high gain mode and nothing connected as a  load, it’s a piece of cake to subtract this EMI magnitude directly from squared sum of the Real and Imaginary Current values !!! Doesn’t matter how strong this interference, and what phase it has. In my tests, I see capacitive “phantom” load ( obviously coming somewhere at the input stage of the amplifier ) approximately 8 – 12 mA.   Press a button – “s” and arduino would do “zero” settings for you ! Of course, this procedure has to be done after installation, as EMI would change depends on location. Here you are, after zero is set, Power Meter should be good to measure down to  1 mA !!!

Issue with EMI little bit complicate calibration procedure, especially on middle range. You would need to calculate two more coefficients, that scaling down EMI at medium and low gain. Because EMI estimated at high gain settings (PGA-3) first, it has to be divided by ratio ( PGA3 / PGA2 ), and ( PGA3 / PGA1 ), consequently.

Last Touch.

 I remember,  there were black and red painted lines on rotating disk surface of the mechanical power meter installed in our house. When I was a kid, I like to watch on this marks, slowly passing left to right. It moved faster, when my mother did an ironing. I just can’t resist to add this mark animation to the project !

Enjoy the show, Video on youtube would follows shortly.  Done.

LCD config file.       Download

Arduino Uno sketch. Download

 Completed.

 
Leave a comment

Posted by on February 27, 2013 in Advanced projects., FFT series.

 

Tags: , , , , , ,

Power (Energy) Meter – Opto-Isolator.

Chapter I. Hardware.

Part 1.  Analog Front-End. Opto-Isolator.

 Looking at the Power Quality Analyzer display, I was wandering, if there is any error in the measurement results, introduced by transformer. Overall THD picture doesn’t change much, suspiciously drawing same chart in the morning and in the evening, when electrical grid load significantly differs. Obviously, to estimate effect of the transformer, I have to repeat measurements w /o one, than check again if there is something new. It is one reason, why I decided to design my own Analog Opto-isolator.

Thinking of Power Meter project, I realized, that except Voltage Isolator, I’d need Current Isolator as well. Things are easier with Voltage measurements, even I’m not sure at this time if transformer relayed harmonics content proportionally / correctly to  what is has at the input, the same time dynamic range for Voltage is quite narrow. Value is not changing much from default 110V, may be -10 ~ +10 % at the most. But it’s not the case for Current, which may vary over great extent.

Quick search over the i-net for AC current sensors, brings quite disappointing results. Sensors based on Hall Effect IC with optical isolation are expensive. Another category – Current Transformers, using simplest and well developed  for  over 200 years technology is also not cheap. And not accurate. Data sheet specification, what I read, states that liner response of typical current transformer is only in a range 1 – 100 %, or just 40 dB.  Price tag – several dollars and up. Even more expensive, and definitely not for hobbyist budget, most advanced samples have 0.1 – 100 % range,  or 60 dB. And it’s another reason, to develop Analog Optoisolator, which would cost less, and be linear over 90 dB.

 Warning:   Shock Hazard

The meter described in this project connects to high currents and high voltages. High currents and high voltages may be hazardous, even lethal. I’m not taking any responsibility for consequence that may result from the use of this publication or the circuitry described herein.

Opto_Isolator_CV6cV

Don’t turn away, circuit shown above, despite it’s simplicity has outstanding performance:

  • Linearity better than 0.1%
  • Dynamic range more than 100 dB   50 dB.
  • Voltage gain ~25.

As you can guess, the reason not to use OPA and Linear opto-coupler in design, is to bring down overall cost. There is no need for amplifier at the other end, photo-transistor loaded by 4.7 k resistor.  Voltage gain is not required for voltage sensing board, but it’s must to be in current sensing circuit, as shunt resistor outputs low voltage level, which in next turn limited by dissipated power. For example, assuming 0.25 W for power losses on shunt resistor, voltage would be: V = P / I, and for 20 A load generates only 12.5 mV. Having gain 25,   0.883 V peak-to-peak obtained at the output, which is perfectly match with arduino 1V ADC reference level. There is only one drawback. Circuit, based on Voltage regulator IC ( LM317 – configured as  operational transconductance amplifier – OTA), requires manual adjustment / balancing for THD level.  Good news, you have to do it only ones.

PQM_Analog_OptoIsolator

DC level matching to switch On internal 1V reference is not finished, work in progress. Would require 2 resistors and two caps in minimum configuration, may be voltage regulator / reference for filtering.

Same with ripple voltage (shown ~28 mVp-p on first drawings), probably, will add up LM7809 later on.

Two photo-transistors of the optocouplers loaded asymmetrically, 1k and 4.7k, in order to have maximum voltage gain. Plus,  they have different collector voltage, so current passing via one LED has to be reduced. The easiest way to make initial adjustment, is to power up circuit from 12V insulated power source ( any cheap wall-wart / wall-mart is o’k), than apply sine waveform at the upper side of trim (50 k – adjustment pin LM317) pot. Next, measure THD level at the output using any available spectrum analyzer. I used my computer sound card and JAAA software.   In this test, output may be powered from the same power source (better not, especially with wall-wart / wall-mart) or using arduino +5V.

First things to do, is get approximately 2.5V DC ( for +5V power source ) level at the output, tweaking another 50 k pot, which is in parallel to optocouplers photo-diode. Than do a fine tunning using 1k. Objective is to minimize THD level. 3-rd and 2-nd harmonics are most noticeable,  but there is a chance, that “optimum” settings for them would be slightly different. If so, reduce input, and see that you have K-3 lower than -60dB, than make adjustment till K-2 drops to same or close level. Repeat a few times. Basically,  technics is similar to balancing audio PA.

60a 230a 1000aHz

Distortion level goes up at higher frequencies, but as primary function for this opto-isolator is power metering application, I don’t care much, as long as THD stay below 0.5% at 20-th harmonics, or 1200 Hz for 60 Hz electrical grid.  Same apply for linearity of the frequency response over specified range, as long as magnitude linearly declining no more than 1.5 dB. What is interesting,  LM317 has “build-in” anti-aliasing filter, which attenuates frequencies above 1.5 – 2 kHz.

Real life test, Power Quality Meter project running with new Voltage Opto-Isolator board.

DSCF0312a DSCF0317a DSCF0318a

to be continue, next – current sensor…

Part 2-1.  Current Board Opto-Isolator.

 Replicating simple circuit based on LM317 and MCT6 optocoupler, I stumbled across one serious issue. I can’t get desirable dynamic range due high noise / interference level. As voltage from shunt resistor is ~12.5 mV only at maximum, decreasing load current to a few milliamps drops voltage level to just a few microvolts !!! Changing values of resistors, de-coupling capacitors,  and adding up LM7805 regulator, I had almost no progress for a couple of days. Here is the drawings:

Opto_Isolator_Current_board

It’s working, and may be useful for AC current monitoring in a range 40 mA – 20 A.  But it’s not what I wanted. My goal is to have a minimum measurable AC current at least 2 mA, better 0.2 mA. Which implies 80-100 dB dynamic range. I came to conclusion, that problem is in high level of interference seen by optocoupler from electrical grid. Taking in equation ~ 25 V, optocoupler must have 140 – 160 dB common mode transient
immunity (CMTI). Opto-isolator used in design can’t provide such high CMTI.

BTW, circuit above could find application in high side DC current measurements, where interference isn’t an issue at all, and could be easily filtered out.

 To be continue…

Part 2-2.  Current Board Opto-Isolator with PGA.

 As I described earlier, low price version of the analog opto-isolator doesn’t work well with the current sensor, due high noise / interference level. It’s not shown on the drawings, but there was an amplifier with gain x400, I used in my experiments, to bring up very low signal level I got in small current tests. In order to solve an issue, I moved amplifier on sensor board. Basically, this is well known technics of using compressor / expander to lower dynamic range of the system. In my case, “bottle neck” is optocoupler, and compressor has to be on sensor board ( Programmable Gain Amplifier is nothing else than compressor ). It’s ad up cost of 74HC4066 and one more MCT6 optocoupler to the project, but it did the trick.  Current sensor in this version has dynamic range more than 90 dB, which was my objective I state in the beginning for this Power (Energy) Meter project.

Opto_Isolator_Current_PGA_2

And here Shunt Board, Main Board, and Voltage Sensor Board (practically, intact from posted above).

Opto_Isolator_Shunt_PGA_2PQM_Analog_OptoIsolator_PGA_2Opto_Isolator_Voltage_PGA_1

Couple after-words, before I moved to the software section on next blog-page. For safety reason, better to use two optocouplers instead of one shown on the drawings in analog path. In current configuration, there is very little spacing between high / low voltage sides, as input and output routed to the same side of the optocoupler. This concerns both sensor boards, for Voltage and Current. 

Now, when hardware part is complete, I’d start to work on software. Of course, FFT would be there -);

to be continue…, on next page..

 
1 Comment

Posted by on February 8, 2013 in Advanced projects., FFT series.

 

Tags: , , , , , ,

MOSFET Tracer.

Having different type of MOSFET transistors in stock,  it’s always bugs me to read data sheet specification again and again, whenever I need to be sure, I can use one at specific voltage / amperage level.  What is make it even more problematic, is ambiguous definition of “logic level” type, as there is different type of “logic” itself, for example 3.3V or 5.0V.   Lets say, non of my transistors in this category. Some of them specified at 6V gate-source voltage, some at 10V. Does it mean, I shouldn’t use any of them with my arduino (5V) ?   Nothing of the kind. Vast majority of the N-channel Power MOSFET transistors would be perfectly happy with G-S voltage as low as 4V, in some occasions just 3V.  With only two conditions, temperature is not at the extreme levels -55 C or +150 C,  and current is less than adequate 2 – 5 A. Which is the case, for practically, any hobbyist project.Tracer_MOSFET_b

Though, here is simple MOSFET Tracer, to make a quick test:

For now, only N-channel transistors could  be evaluated, but it’s not too complicated to re-design circuitry in order to trace P-channel, following same approach.

Device print out V-threshold voltage and  R-ds(ON) values on the LCD screen. Plus, transfer characteristic “zoom” in between 2.6 and 5.0V.  As I told, there is no “logic level” transistor in my pile, and LCD size limited to 120 pixels,  so I made 0.2 V / div. resolution on the X axis. To be precise,

5V * 120-screen_x / 255-pwm / 12-grid = 0.196 V.

Full range 0 to 5 V scan data available over serial monitor, using debug “x” command.  Resolution along Y axis – 1 V / div, or 0.25 A / div when R = 4 Ohm and V(power supply) = 5 V. Command Line Interface accepts two more commands, “w” – wipe screen and “a” – auto-cleaning screen after each trace. They are handy, if you want to compare 2 or more transistors simply replacing them when scan is continue to run.

Look at the pictures.

306a 307a 308a 309a 310a

 Download sketch (UNO).

 
Leave a comment

Posted by on February 5, 2013 in Uncategorized

 

TRUE ANALOG AUDIO VOLUME CONTROL (T.A.A.V.C.).

 

More:   Video1   and   Video2

Now my Arduino can precisely measure audio input (VU meter),   and obviously, next thing that comes to mind right after measurements, is regulation or control. There are many different ways how to electronically adjust audio volume or level of AC signal.  I’ll name a few:

  • Specifically design IC, Digital potentiometers.
  • Mechanical potentiometers, driven by servo / motors.
  • Vacuum tubes amplifiers in “variable-mu” configuration.
  • Resistive opto-isolators.

First category (#1) fits nicely for arduino project. But it’s not interesting to me. My apologies to someone, who was searching an example of interface between arduino and digital pot. Other people don’t tolerate semiconductors in audio path ( tube sound lovers ). Third option would make them happy, only (#3) requires high voltage and difficult to accomplish on low hobbyist budget, so I left it out of the scope. Mechanical pot (#2) would be good solution to satisfy Hi-Fi perfectionists and arduino fans. The same time response time of mechanical parts is too slow, verdict – discarded.  (#4) have been in use since 1960s, but would you like your lovely music to be adjusted by highly toxic CdSe / CdS ?  I don’t think so. Wiki says opto-isolators have low THD distortion level, less than 0.1%. Probably true, but apart from technical aspect, there is always psychological, poisonous CdSe affects my perception.

How about variable resistor in it’s simplest form – tungsten wire? Where you can get one? In the electrical bulb. Perfect material for audiophiles – where distortion could get into ? – It’s pure metal ! And here is my design of the “basic cell” – True Analog Audio Volume Control (T.A.A.V.C.)

Analog_Volume_Control_(theory)

As you can see, cell consists of 5 bulbs plus 1 resistor. All elements form 2 attenuation stages, basically – voltage dividers with variable resistors. Resistive values of bulbs proportional to temperature, which is easy to control passing DC current through. To make it work with the biggest possible dynamic range, middle bulb is also heated up by current flow from two differential control lines / phases.

 Hardware prototype / Proof of Concept.

Analog_Volume_Control_double_diff_simple

Differential Power Amplifier (PA) IC LM4863  is used as DC current source for control lines. Circuitry powered from 5V regulated switching power supply (4A).  Bulbs – clear mini lights, 2.5V, approximately 200 mA. Cold state resistance about 1.2 – 1.5 Ohm, hot state resistance is rising up to 15 Ohm.  Volume regulator could be connected to any audio source with output impedance no more than 32 Ohm, for example, headphones output. For test I used second channel of the PA, that shown in “optional” box on the left side. Second channel is a “nice to have” feature  in stereo version of the project, when both channels would drive two separate TAAVC cells, so using it as a “buffer” amplifier may be not an option.

Results.

  Measured attenuation  range of the “basic cell” is  20 dB, or 10 x times.

266c260c 264c

 to be continue…

 Chart, PWM (Voltage) to Attenuation:

chart

 Quite interesting, isn’t it? I was not expecting it’s to be linear, but changing direction surprised me. There is one things, which could explain such abnormality, is that when voltage on the control lines 1 and 2 ( LM4863 outputs ) is approaching power rails, output impedance of the power amplifier is increasing, and consequently, attenuation characteristics of the basic cell deteriorate. It means, that in order to keep attenuation curve gradually declining, more powerful PA necessary. For now, I limited PWM to 0 – 200 range.

I’m thinking, STA540  powered from +12V, and 5 V bulbs would make sense to try next time.  Probably, replacing middle bulb for less current hungry, will increase max attenuation per cell up to 30-35 dB.

 O’K, after I get this data, how could I “straighten it up” for practical use ?  Volume control device, could be linear or logarithmic, but chart doesn’t resemble nether of this. And this is exactly what I need Arduino for.

Linearization.

 If you, by chance, have read this page, than you know how to do this part. Polynomial approximation. Unfortunately,  2-nd degree polynomial I used last time is not enough for VERY non-linear curve like I have. So, I “upgraded” my calibration subroutine (method: LEAST SQUARES) up to 3-rd degree:

void calibrate()
{
 //Least squares 3-rd degree polynomial coefficient calculation
 float arr[10][5] ={{0},{0}}, err[10] = {0}, coeff[10] = {0};

 err[0] = 10;
 for(uint8_t i = 1; i < 7; i++)
 {
  err[i] = 0;
  for(uint8_t j = 0; j < 10; j++)
  {
   err[i] += pow(level_table[j], i);
  }
 }

 for(uint8_t i = 0; i < 4; i++)
 {
  for(uint8_t j = 0; j < 4; j++)
  {
   arr[i][j] = err[i+j];
  }
 }

 for(uint8_t i = 0; i < 4; i++)
 {
  arr[i][4] = 0;
  for(uint8_t j = 0; j < 10; j++)
  {
   if (i==0) arr[i][4] += calibration[j];
   else arr[i][4] += calibration[j] * pow(level_table[j], i);
  }
 }

 for(uint8_t k = 0; k < 4; k++)
 {
  for(uint8_t i = 0; i < 4; i++)
  {
   if ( i != k )
   {
    for(uint8_t j = (k + 1); j < 5; j++)
    {
     arr[i][j] -= ((arr[i][k] * arr[k][j]) / arr[k][k]);
    }
   }
  }
 }

 union split_float {
 uint16_t tegri[2];
 float loatf;
 } sf; 

 for(uint8_t i = 0; i < 4; i++)
 {
  coeff[i] = ( arr[i][4] / arr[i][i]);
  sf.loatf = coeff[i];
  store_entry(( 2 * i ), sf.tegri[0] );
  store_entry(( 1 + (2 * i)), sf.tegri[1] );
 }
}

Procedure takes 10 data samples as input, calculates 4 coefficients and stores them in EEPROM memory.

VU meter based on Arduino UNO ( in minimum configuration Arduino and DC offsetting circuit ) should be connected right to T.A.A.V.C. output. Everything works in automatic mode, with results printed on serial monitor for review. Stable AC input is necessary, which easy to get from any PC sound card based signal generator, recorded media file or lab sine-wave generator. Arduino also provides PWM for T.A.A.V.C       via pin D3 (TIMER2 OCR2B).

TAAVC_Calibration

Link to download Arduino UNO sketch: T.A.A.V.C.

to be continue…audio compressor, .

Last part,

Dynamic Range Compressor.

There are two important parameters defined in the beginning of the sketch:

#define          CMP_THRE                     -10             // Compression Threshold 
#define          CMP_RATE                        4             // Compression Ratio 4 : 1

Threshold and Ratio. I’m not into explaining all bunch of the details about compressors or what for do you need one, rather forward you to this link.  I only want to say, that I didn’t find any evidence that someone ever used electrical bulbs as compressors “engine”. So, this is my idea, and my implementation.

Technical specification of this design is quite modest, having close to 20 dB maximum attenuation and setting ratio to 2:1, threshold couldn’t be set lower than -40 dB. Good news, that for practical use in home environment it’s  really unlikely, that you ‘d need more. It’s also should be enough to solve a problem with annoying TV or Radio commercial / advertisement.

Compare to VU Meter project, I’ve made a few “relaxing” changes to the code, as it appears there are no strict industry standard on Dynamic Range Regulation. I reduce sampling rate down to 10 kHz,  and  split Low Pass Filtering in two sections. One is the same, as in VU Meter, inside sampling interruption subroutine, only with lower time constants. First LPF section is responsible for “shaping” attack and decay timing. Using quite inertial electrical bulbs in the project, reduce importance of this timing. Here attack and release mostly defined  by thermal responsiveness of the bulbs, which isn’t very high. Decreasing software LPF time constants helps to improve sensitivity. Other LPF section included inside LCD drawing function, works to overcome display slowness, suppressing LCD flickering. Other changes from simple VU Meter, is that finally I “scaled” everything correctly,  and “0″ db corresponds exactly to 1.228 V RMS at the input. Threshold level -10 expressed in dB as well. You may see threshold “mark” above the log scale. Indicator “needle” just below it, small 5×2 pixels only, but you can make it bigger if you wish.

275a

I already described calibration procedure, to do it right, you need to connect arduino to output of the TAAVC cell.  Polynomial coefficients and minimum / maximum constants stored in EEPROM, so you don’t have to do this procedure each time after power cycling.  In normal mode arduino getting input measurements from the cell input:

Analog_Volume_Control_Compressor

Finished.  I’ll do a video “on demand” -);  If I had time…

Arduino UNO sketch:  Audio Dynamic Range Compressor. (TAAVC part 3).

 
1 Comment

Posted by on January 22, 2013 in DIY, Simple projects.

 

Tags: , , , , , , , , , ,

Audio VU Meter.

Simple project, some kind of “Arduino-Wiki” for beginners.

VU

How to do measurements right:

  1. Biasing AC input using resistor divider and scaling up / down if necessary;
  2. Sampling fast and accurately using direct access to Control Registers of ADC and Timer1;
  3. Subtract whatever was added at step #1 from result of Analog / Digital conversion and Square;
  4. Average / accumulate, filtering following VU specification;
  5. Sqrt – take square root, Log10 – transform to dB scale;
  6. Display.

 1.   Hope, you follow my advice and hack your cheap USB speakers, to get nice ( pre-assembled ! ) analog “front-end” for this project. If not, than get your soldering iron to work, minimum two resistors and 1 cap would required, assuming you already have display wired up and running.

 First things with AC measurements ( audio in this category ) on Atmel microcontroler is to get rid of negative half-wave of the input signal, and this what front-end circuitry should do. There are at least two option: rectifying AC to DC before voltage could reach arduino analog input, or biasing signal with external DC offset. Rectification, could nicely be done with help of specifically design IC, LM3914 / 15 / 16 for example. But in this article, I’d describe second alternative, as it’d be not fare to ask you to hack your speakers and than tell you to solder another board…. Here is my set-up, slightly modified version from last blog:

VUM_ver2pWhen AC input signal is mixed with DC offset, so it stays always in positive area, ( think about sine, which defined betseen -1 and +1, if I add +1 it always would be positive ), I only save arduino life, preventing it from destruction by negative voltage. When arduino ADC completes conversion from analog to digital form, I don’t need DC offset anymore, and it should be subtracted.

  NOTE: DC voltage was added just to pass audio through arduino ADC. 

2. Sampling subroutine is running at 40 kHz, that is more than enough for ANY application. You may decrease sampling rate to lower CPU load, with current settings VU metering consumes more than 50%. Higher sampling rate gives better linearity / precision over wide band, the same time with regular audio content even 10 kHz sampling would provide better than 1 dB accuracy. All input capture process goes in Interruption subroutine, which is configured in setup. Two channels of Timer 1 Configured to run in parallel, “A” is responsible to keep clock at 40 kHz sharp, and “B” fires start conversion event to ADC with the same speed. Restarting new conversion via hardware provides lowest phase noise compare to any other way of doing this.

     ADCSRB = ((1<<ADTS2)| // Sets Auto Trigger source – Timer/Counter1 Compare Match B
                       (0<<ADTS1)|
                       (1<<ADTS0));

/* Set up TIMER 1 – ADC sampler */
       TCCR1A = ((1<<WGM11) | (1<<WGM10)); // Mode 15, Fast PWM
       TCCR1B = ((1<<WGM13) | (1<<WGM12)); // Mode 15, Fast PWM

       TCCR1B |= (1<<CS10); // clk/1 prescaling.
       OCR1A = SMP_TMR1;
       OCR1B = SMP_TMR1;

      TIFR1 |= (1<<OCF1B); 
      TIMSK1 |= (1<<OCIE1B);

3 .  As you can see in a code snipped below, adc_Offst is subtracted from new ADC result. Quite simple, value of DC offset ( adc_Offst ) was obtained in setup() during start up, using Arduino IDE “analogRead”. The only problem with this simple solution, is that no audio should be present at this moment ( start up ) at input, otherwise all measurements would be erroneous.

 ISR(TIMER1_COMPB_vect)
   {  
      int32_t temp = ADC – adc_Offst; 
                 temp = temp * temp;
      if ( temp > ppm_Level ) ppm_Level = ((ppm_Level * 255) + temp) >> 8;
      else ppm_Level = (ppm_Level * 16383) >> 14; 
   }  

4. The same piece of code includes VU filtering algorithm. I was trying to get as close to standard as possible, but tough timing requirements ( 25 usec ! ) doesn’t allow get full satisfaction. Attack time is very close to specification, 3 milliseconds or so. Decay, I’d estimate in 200 milliseconds, which is less than recommended 650 milliseconds for Peak Program Meter (PPM), and also less than 300 milliseconds for regular VU.  The limits come from 32-bit integer math, from one side, and high sampling rate from another.

updated:

This comparison operator     if ( temp > ppm_Level )  separates attack – when new value is bigger than stored, and decay – when new value is smaller. Now, lets me explain what this line of code does:

     ppm_Level = ((ppm_Level * 255) + temp) >> 8;
Rewriting it to:  ppm_Level = ((ppm_Level * 255) + temp) / 256;

and than:          ppm_Level = ppm_Level *  ( 255 / 256 ) + temp * ( 1 / 256 );

reveals:            ppm_Level = ppm_Level *  0.99609375 + temp * 0.00390625;

Which is simple, single pole Low Pass Filter. For more details on recursive filtering I’d refer to this book. Equation 19.2.   Trick with right shift operator (>>8) is just to improve speed of calculation. Remind you, that Arduino doesn’t have floating point CPU, and any mathematics work with floating point coefficient very slow.

Same with filtering decay process, the difference is only in coefficient value.

( >> 14) is the same as 1 / 16384,   and so   16383 / 16384 = 0.999938965.

5.   Read comments, please:

    int32_t temp;

     temp = ppm_Level;                        // Take a copy, so Real Value not affected by calculation.
     temp = sqrt(temp);

    rms_Level = 20.0 * log10(temp +1); // Calculated, available over Serial

6. Last part, drawing VU indicator on graphical display. Ones again, referring you to short hardware description of using model.  There is not much to say, all display interface based on GLCD library. The only “tweak” from my side, is that I added “if” condition in front of drawing needle subfunctions:

      if ( abs(st1 – st2) > 3 )                          //  ~1/3 dB

I discovered, that DrawLine is quite slow, 4 calls ( 2 – erase, 2 – draw, all double – to make needle thicker ) take 125 milliseconds, so it make sense not to draw anything if there is not big difference between old and new needle position. At least, new position has to be off by width of the needle itself.

Link to Arduino (UNO) sketch: download.

 
9 Comments

Posted by on January 9, 2013 in DIY, Simple projects.

 

Tags: , , , ,

 
Follow

Get every new post delivered to your Inbox.

Join 26 other followers