-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Thanks gents ...but I'm just a guy who has a couple "hmm, I wonder if ....." ideas - & without truly knowing how to arrive at the end destination! (or sometimes how to even start off on the journey!). It's the wealth of knowledge on this forum (& willingness to contribute to my threads) by folks that actually have a clue that makes it all happen.
Re the Wiki - I'd be too mortified/embarrassed that my (sometimes cringeworthy) stuff would actually make it into such a place (like I say, in this instance the program I've knocked up is not that elegant but seems to work...I think!), but to do it justice I'd have to write it up a lot better, do a lot more testing etc ....there's not enough hours in the day blah blah.... but I'm really chuffed though that you thought it was a potential contender though :-)
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
You thought I was done here didn't you?!
Well for this to be 100% dependable, I need to be assured I know what the hell is going 'behind the scenes' with respect to this special event trigger melarkey.specifically whether the sample rate can be easily worked out & dependable.
Firstly...I've accounted for the ADC value 'jitter' - the incoming audio ignal is jittering! (this means it's not a measurement error...but the actual signal itself is varying. This is very heartening as it means this thing has real potential!)
Ok, something troubles me here, this from the datasheet.,..
"The Special Event Trigger output of the CCP occurs immediately upon a match between the TMR1H, TMR1L register pair and the CCPRxH, CCPRxL register pair. The TMR1H, TMR1L"
At 8MHz, therefore a 2MHz instruction clock that presetting 50 for TMR1L to match against would - if I have the maths/theory correct - mean a a 40khz special event trigger rate......but if that were the case, I'd have expected to seen the ADC samples be ing far more erratic at an audio input signal 20khz than what I'm seeing (two samples during the 20Khz waveform would have ADC results all over the place) ...so what's going on?
I looked at the datasheet, and apparently it's possible to get the special event trigger to toggle a pin (as opposed to take an ADC sample) ...at least in that way, I could the put a scope on to the physical pin confirm the observed frequency vs the number preloaded into the CCPRxH, CCPRxL pair. I'll revisit this over the coming evenings, but if anyone has had prior dealings with the special even trigger & specifically getting it to toggle a pin - all top tips greatfully received! Here's what I'm seeing on the CCP4 pin (I've set the pin as an output)....
http://img841.imageshack.us/img841/5582/10641603.jpg
(thats doesn't look like a good square wave at all!)
& here's the register I'm setting....
Also, can someone clear up this ADC uncertainty for me.....Fosc/8 & tads...there's a table on page 149 of the datasheet here http://ww1.microchip.com/downloads/e...Doc/41419A.pdf but it's not clear to me how many tads an 8 bit ADC sample will take (10 bits would appear to be 11.5...therefore 12us?!)....basically I want to know how long an ADC sample takes...as obviously this will dictate the maximum sample rate I can get the special event timer to run at.
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Quote:
At 8MHz, therefore a 2MHz instruction clock that presetting 50 for TMR1L to match against would - if I have the maths/theory correct - mean a a 40khz special event trigger rate......but if that were the case, I'd have expected to seen the ADC samples be ing far more erratic at an audio input signal 20khz than what I'm seeing (two samples during the 20Khz waveform would have ADC results all over the place) ...so what's going on?
I believe you are correct in the math, maybe you are off by a count of 1 for reload or something. The more perplexing part to me is the scope showing 30 Hz!! That really confuses me.
Is the incoming signal comming from a signal generator? if so it is prolly a really nice clean 20K? So if this is the case, it stands to reason the samples are being taken at the same spot maybe? since 20k is half the sample frequency.
What if the signal is 19.367K? (random number)
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Quote:
Re the Wiki - I'd be too mortified/embarrassed that my (sometimes cringeworthy) stuff would actually make it into such a place (like I say, in this instance the program I've knocked up is not that elegant but seems to work...I think!), but to do it justice I'd have to write it up a lot better, do a lot more testing etc ....there's not enough hours in the day blah blah.... but I'm really chuffed though that you thought it was a potential contender though :-)
You do not give yourself enough credit. Who cares if the code is "elegant" as long as it works. I do understand about time though...
Keep up the good work!
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Quote:
Originally Posted by
cncmachineguy
I believe you are correct in the math, maybe you are off by a count of 1 for reload or something. The more perplexing part to me is the scope showing 30 Hz!! That really confuses me.
Is the incoming signal comming from a signal generator? if so it is prolly a really nice clean 20K? So if this is the case, it stands to reason the samples are being taken at the same spot maybe? since 20k is half the sample frequency.
What if the signal is 19.367K? (random number)
That's a good call (as ever) Bert - I shall try it tonight.
Since I can't get to the bottom of ensuring the sample rate *is* what I *hope* it is....last night, I tried the good old 'tried & tested' ...send the max audio frequency I'm interested in (1.5khz) then tweak the TMR 'match against' CCPRxH, CCPRxL registers (sample rate) until I saw static ADC readings. From recollection it was about CCPR4l = 100 (which I think works out at 20khz sampling)...which is 13 samples throughout the waveform ....albeit this was with a slower decrement (pseudo capacaitor discharge rate). As I type this, that doesn't seem enough samples in the light of the stable readings I was seeing. Hmmm.
I really can't figure out what's going on with the toggling CCP4 output pin (the whacky square wave)...30Hz?!!!
Can anyone think of an alternative method of confirming the special event trigger frequency?!!
I've now got a fresh challenge-ette with this method ...the dependency (stability) of it very much depends on the time it takes for my main loop....obviously the ADC register is getting updated at the sample rate (in the background), but if I don't copy the ADRESH register into my my main loop & then process it 'in between' subsequent samples then I'm in trouble - therefore I need to establish a way of seeing exactly how much time my main loop is taking (ie so I know when I've gone past the time allowed between samples) .....how best to approach this? (my immediate thought is a timer count between loops & convert the timer value to human time that I can see onscreen?!!)
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
HankMcSpank , If you have an extra pin available or one you can (borrow) for the test, just set it at the begining and then clear it at the end of the portion of the program you are trying to time. Use a scope or a timer/counter to get the actual timing value.... It works for me... The plus side is the instructions don't add much to offset the timing. (portb.4 = 1).......(portb.4 = 0)
Dave Purola,
N8NTA
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
[QUOTE=HankMcSpank;99190]Actually I think my revised method below will be better....
(VCC is 5V, AC signal will sit on 2.5V, therefore positive half of cycle samples @10 bits will be between 512 & 1024, negative parts of the cycle will be between 0 & 512)
1. Setup a timer to interrupt at a rate of 20khz
2. In the timer interrupt routine take an ADC sample into a variable
3. Compare the ADC sample to the last sample - if it's higher keep it, if it's smaller ignore it.
4. If the sample reads below 512 (half VCC - the signal's zero cross), then the highest sample from step 3 is signal 'peak', now zero the variable ready for the next positive cycle (ie samples above 512)
5. Run a bit of maths to convert peak voltage sample to RMS (ie multipy peak sample by .707 using some FP workaround)
i agree :)
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Hank, I think something is wrong with the settings. The toggle rate seems to represent a word timing out. For instance timer1 is 16 bit, full count is 65535. 65535*.0000005 = 32.7675mSec. that sure looks like your toggle rate!
So I would guess TMR0 is not clearing on a match!
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
[QUOTE=tony45;99536]
Quote:
Originally Posted by
HankMcSpank
Actually I think my revised method below will be better....
(VCC is 5V, AC signal will sit on 2.5V, therefore positive half of cycle samples @10 bits will be between 512 & 1024, negative parts of the cycle will be between 0 & 512)
1. Setup a timer to interrupt at a rate of 20khz
2. In the timer interrupt routine take an ADC sample into a variable
3. Compare the ADC sample to the last sample - if it's higher keep it, if it's smaller ignore it.
4. If the sample reads below 512 (half VCC - the signal's zero cross), then the highest sample from step 3 is signal 'peak', now zero the variable ready for the next positive cycle (ie samples above 512)
5. Run a bit of maths to convert peak voltage sample to RMS (ie multipy peak sample by .707 using some FP workaround)
i agree :)
Tony, Bert - The problem with step 4, is that in the absence of an equal or higher sample arriving (or, as you're proposing, while below zero point) my running peak variable is decremented (remember this code is emulating an analogue peak detect circuit - in such a circuit, the diode only lets through voltage that is higher.....and in the absence of a higher voltage the didoe is reverse biased & the cap starts discharging via a resistor - my running peak variable content decrements in this case).
This will utlimately mean that during the negative portions of the cycle, the running peak I've stored will decrement a fair bit, before the next positive part of the cycle returns & sets the peak high again - this is essentially like half wave rectification vs full wave - the former gives much more ripple, ie half wave ripple....
http://www.m.case.btinternet.co.uk/a...e_Smoothed.gif
...so what I end up with is pseudo ripple (a variable decrementing then being topped up) This is why when the ADC reading goes below zero (ie below 128 on an 8 bit sample), I want to flip the negative cycle up - to be a positive cycle. This greatly reduces any decrementing (pseudo cap disharging)
This diagrams illustrate the end goal in analogue waveform terms...
http://www.eleinmec.com/figures/018_04.gif
The 0V (zero crossing point) in my case is 2.5V (an ADC reading of 128)...I want to flip the negative part of the wave up. It not only reduces ripple...but halfs the amount of time to detect peak etc, leading to less ripple (peak detect fluctuations)
http://images-mediawiki-sites.theful...3847055696.png
I realise 10 bits would be better, but just wanted to keep it all simple while I'm ironing out all the issues.
N8NTA - tks for the tip about measuring the main loop time, I'll do that.
Quote:
Originally Posted by
cncmachineguy
Hank, I think something is wrong with the settings. The toggle rate seems to represent a word timing out. For instance timer1 is 16 bit, full count is 65535. 65535*.0000005 = 32.7675mSec. that sure looks like your toggle rate!
So I would guess TMR0 is not clearing on a match!
Wow Bert - that's a great spot! This from the datasheet...
"The Special Event Trigger output of the CCP occurs immediately upon a match between the TMR1H, TMR1L register pair and the CCPRxH, CCPRxL registerpair. The TMR1H, TMR1L register pair is not reset
until the next rising edge of the Timer1 clock."
As far as I can gather. other than to set the CCP register (to select pin toggle vs special event ADC triggering) ...there's nothing else to be done - not sure how this one can be tackled?!!
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Ok, after some careful reading of the datasheet, I find I am no longer any smarter then I was before I started. I can't find anywhere in the datasheet to say in compare mode timer is reset on a match. It DOES say for the Special event trigger the timer is reset. So I suggest this:
Go back to SET mode (Special Event Trigger).
Enable interrupt on A/D conversion done.
Have the ISR do this:
toggle a pin (for debuging speed)
move A/D results to a variable for later use
Return from INT
With that done, several things are solved for you.
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Hank,
1. why don't you make a full rectifier of your analog signal?
2. is the signal always of the same amplitude?
3. are you after a peak detector or an rms calculator? I am little confused by this thread...
Ioannis
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Quote:
Originally Posted by
Ioannis
Hank,
1. why don't you make a full rectifier of your analog signal?
2. is the signal always of the same amplitude?
3. are you after a peak detector or an rms calculator? I am little confused by this thread...
Ioannis
Hi Ioannis,
Ok, I came into this thinking I needed an RMS detector - I don't (despite the title ....which I'm unable to update/edit)....I really want to track 'peak' of a guitar signal. The incoming signal is of very wildly differing amplitude.....but fortunately it only goes up to 1.5khz max (the max fundamental on a guitar...I don't care about the harmonic content here - I'm only wanting to extract magnitude info, not accurately replicate the waveform digitally)
So why not use conventional analogue components? Well I'm *very* pushed for PCB real estate ...the intended PCB will already have a PIC, but the PIC isn't doing much (basic switching, LED indicators etc) ...so that got me thinking, why not extract peak from the incoming analogue signal using the PIC - just like an analogue full wave rectifier into a peak detector (which is what my code above is doing ....'full wave rectifying a signal' but via code inside the PIC) ...if nothing else, my intention was to learn a little more about sampling an AC signal rapidly .....& like most journeys - you discover other stuff enroute. And that has proved to be the case - the special event trigger - it's been a revelation to me at least.
Not only do I save components (PCB space)...I also avoid the forward voltage drop loss that an analogue peak detector suffers from (this is a relatively small signal I'm monitoring)...but it struck me I can also have on the fly varying 'discharge' rates to suit as my peak detector is now working in the digital domain.
The nut has actually been cracked ....all that's happening here now is a bit of a wash up...trying to get to the bottom of a couple of quirks I'm hitting (specifically the calculations wrt sample rate, etc)
Bert,
Again...great ideas...I'll implement this later to get a handle on the sampling frequency (I concur that the datasheet is a bit scant with the 'meat' here!)
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
The first that comes to mind is to use a DSP or dsPIC for the job as there seems to be a lot of maths.
But then since the max frequency is just 1,5KHz then maybe the PIC used is good enough.
Of course it has the speed to convert the input sample, but do you have time to proceess afterwards?
The other matter is the form of the input signal. You mentioned that it is greatly varying. Are you feeding it directly to the ADC? Any pre-conditioning I thing is necessary (filtering, dc-level bias etc.).
Ioannis
P.S. I changed the thread title hoping you do not have any objection.
-
Re: Low frequency audio level detector using PIC ADC?
Hank, take a look at the Tips & tricks doc (http://ww1.microchip.com/downloads/e...Doc/01146B.pdf). Pay special attention to chapter3 (CCP and ECCP); tips #7 and #11.
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Quote:
Originally Posted by
Ioannis
The first that comes to mind is to use a DSP or dsPIC for the job as there seems to be a lot of maths.
But then since the max frequency is just 1,5KHz then maybe the PIC used is good enough.
Of course it has the speed to convert the input sample, but do you have time to proceess afterwards?
The other matter is the form of the input signal. You mentioned that it is greatly varying. Are you feeding it directly to the ADC? Any pre-conditioning I thing is necessary (filtering, dc-level bias etc.).
Ioannis
P.S. I changed the thread title hoping you do not have any objection.
Actually, that's the beauty here - there's almost no complicated maths....ie just et the special event trigger grabbing ADC samples at a reasonably high sampling rate (& this is all done in the background without any recourse to interrupts etc), then in the main (fast) loop, just compare the present ADC sample to the last sample...if it is the same or bigger, keep it as the 'present peak'....if it's not the same or bigger. start decrementing the variable linearly.
This approach wouldn't be right, if the PIC was already running intensively....but like I say, in my application the PIC isn't being too stressed.
The signal is preconditioned in that it goes through a buffer.....this puts the AC signal on a DC level of half VCC (necessary to full wave rectify the signal inside the PIC).
At the end of the day, I'm really just using the latent (otherwise wasted) power of the in-situ modest PIC to save on a few components (not for cost, but space) - .I don't want to start involving specific specialised ICs for what is after all a simple enough requirement.
oh, btw I've no problem with the title being changed!
Quote:
Originally Posted by
languer
wow...a great doc.....need to digest - thanks!
-
Re: Low frequency audio RMS signal level detector using PIC ADC?
Eeek, even a little bit of code like this....
Code:
main:
toggle PortC.4 'pin 6
'count1 = count1 +1
present_sample = ADRESH
IF present_sample < 128 then
present_sample = (127 - present_sample)
else
present_sample = present_sample -128
endif
IF present_sample >= rolling_peak THEN
rolling_peak = present_sample
else
if count1 = 50 and rolling_peak !=0 then
rolling_peak = rolling_peak -1
count1 = 0
endif
endif
goto main
is only toggling at 16khz - meaning that the main loop is only running at 30khz ...gulp (that's not leaving much room for anything else) bearing in mind I only have a 20khz sample rate going on...I wish the 16f1828 didn't have the ADC iissue about 8Mhz internal clock, becuase the obvious way of winning back por main loop time is to crank the internal clock up.
-
Re: Low frequency audio level detector using PIC ADC?
what is your device ID and REV?
-
Re: Low frequency audio level detector using PIC ADC?
Quote:
Originally Posted by
cncmachineguy
what is your device ID and REV?
I don't know...and it's possible they've fixed the problem for the ones I have (purchased just a couple of weeks ago)
I use a Pickit2 programmer & can't seem to find anything that tells me such device info?
In the light of needing more 'main loop time', I've actually just cranked the Oscillator up to 16Mhz...and the ADC aspect still seems to be working ok.
-
Re: Low frequency audio level detector using PIC ADC?
Per the errata, they have fixed it for all current stuff. So unless your supplier has old stock, you are prolly good. I didn't think to look at the date on the errata, that may shed some light on if it will work. It sounded like it will either work or not. It didn't sound like it could be interminent.
And remember to change your ccpr values to reflect the faster clock. - unless you want to double the samples :)
-
Re: Low frequency audio level detector using PIC ADC?
Quote:
Originally Posted by
cncmachineguy
Per the errata, they have fixed it for all current stuff. So unless your supplier has old stock, you are prolly good. I didn't think to look at the date on the errata, that may shed some light on if it will work. It sounded like it will either work or not. It didn't sound like it could be interminent.
And remember to change your ccpr values to reflect the faster clock. - unless you want to double the samples :)
Thanks Bert - Actually, I think we're done here would you believe! (Bert sighs in relief!)
I've aborted any attempt to confirm the sampling rate & have reasonable faith in our calculations! I've got the PIC Internal Oscillator running at 16 Mhz, and a special event trigger frequency of of 16Khz (ADC sample rate ), ie Timer1 matching against this....
CCPR4H = 0
CCPR4L = 250
(16Mhz clock, 4Mhz Instruction = 0.00000025sec period, therefore 250 x 0.00000025 = 0.0000625 sec .....so 1/0.0000625 sec= 16Khz)
....I've integrated the 'peak detect' code above into the final destination main loop - I've scoped a pin toggling within my my main loop @50khz which means it's looping at 100khz (so plenty of time to do other stuff in the main loop if I so desire). I don't use any interrupts except for switch presses,...and when a switch is pressed, I'm not worried about losing ADC samples.
...just connected it up to my guitar (vs the sig gen I've been testing with)....it's working as expected :)
A *very* happy Hank...thanks for all your input.
-
Re: Low frequency audio level detector using PIC ADC?
Quote:
Originally Posted by
HankMcSpank
Thanks Bert - Actually, I think we're done here would you believe! (Bert sighs in relief!)
No sigh at all Hank, I really enjoy these kinds of threads. Lots of new things learned by all. I don't seem to have the imagination or desire to make such projects, but I LOVE thinking about them.
So Thank YOU and I look forward to your next one. :)
BTW, I agree you should consider making a WIKI of this. Your coding is fine, as Dave said you underestimate yourself. I do get the time aspect of it.
-
Re: Low frequency audio level detector using PIC ADC?
Thumbs up from me too.
Good idea with just a few components and clever programming. To the Wiki absolutely!
Ioannis
-
Re: Low frequency audio level detector using PIC ADC?
Back at post #42 there is a picture of a square wave, (not so square wave) and a comment about how bad it looks. The wave looks like this because it has just passed through a capacitor. (A high pass filter) (DC blocking capacitor)
What are you trying to do? Measure the output of your electric guitar in peak response mode?
For long before I was born, audio has been measured in two modes.
Average mode: Full wave rectify. Then use a 2hz low pass filter. The response time is set to about the spoken syllable rate. (half wave produces little error)
Peak mode: Full wave rectify. Use a filter with an attack time of 1.7mS and a decay time of 660mS. You need the 1.7mS attack time or any very small peak will peg you meter but you ear can not hear that small peak.
Do you want RMS response?
-
Re: Low frequency audio level detector using PIC ADC?
Hi Ron,
Post #52 above explains what I was trying to achieve.....thankfully, it's al sorted now & seems to work ok.
-
3 Attachment(s)
Re: Low frequency audio level detector using PIC ADC?
If you search for VU meter you will find examples of what you are working on.
With out a PIC the two attached pictures show an analog way of getting average and peak readings.
The rectifier is:
if MSB is 1 then shift left to remove that bit.
if MSB is 0 then compliment number +1 then shift left.
The peak detector (analog version):
The meter moves up at a rate set by R18 & C5. (fast)
The meter moves down at a rate set by R17+R18 & C5. (slow)
In software:
If the output of the rectifier > than the meter reading then (meter-rectifier)/x add to meter.
If rectifier is < meter then meter=meter-y.
Where y is a small number that will move the meter from full scale to 0 in about 600mS.
Where x sets the response time. (moving up)
There are several companies (THAT CORP and National see LM3915/16.) that have applications notes on the response of of VU meters. A typical test is to inject a 5khz tone for 10mS then stop. The meter should reach near full scale in 1.7mS and decay in 660mS.
My first try at a VU meter is attached. R2,3 set the input at 1/2 supply.
C1 blocks DC. 1/(2*2.14*50k*C1)=20hz set lowest frequency of intrest.
R1 & C2 makes a low pass filter to block information above 20khz.
R1 is to limit the current going into the PIC if the signal gets above 5 volts or below 0 volts. Could be 1k.
There is several better ways of setting the DC input of the ADC to 2.5 volts. More later.
-
Re: Low frequency audio level detector using PIC ADC?
Quote:
Originally Posted by
ronsimpson
In software:
If the output of the rectifier > than the meter reading then (meter-rectifier)/x add to meter.
If rectifier is < meter then meter=meter-y.
Hi Ron
If you glance at the final code I knocked together - that's essentially what I'm doing ...... 'x' being the AC signal coming in on a PIC pin, 'y' being my pseudo (sw) cap discharge rate (albeit I'm not driving VU meters & I require different attack/release times).
-
Re: Low frequency audio level detector using PIC ADC?
Audio has a large dynamic range. I wanted to get as much range as possible. I needed to “zero” at 512 (10 bit). Resistors at 1% and even 0.1% did not always get me to zero. I also tried resistors to get within 1% of zero and then used the PWM output to move the ˝ voltage point +/- a little. I know in software I could have move the zero point to correct for this error. I wanted to do all the math slightly faster than the ADC could work and there was no time.
-
Re: Low frequency audio level detector using PIC ADC?
Quote:
Originally Posted by
ronsimpson
Audio has a large dynamic range. I wanted to get as much range as possible. I needed to “zero” at 512 (10 bit). Resistors at 1% and even 0.1% did not always get me to zero. I also tried resistors to get within 1% of zero and then used the PWM output to move the ˝ voltage point +/- a little. I know in software I could have move the zero point to correct for this error. I wanted to do all the math slightly faster than the ADC could work and there was no time.
I can live with the 1% (even 2%)....quiescently, I was seeing jitter of just over 1%.(ie readings of 127,127,126,127,17,126, etc)
The accuracy of your ADC 'zero' point is obviously going to be down to how you approach DC biasing your AC signal feeding into the ADC pin - as a late suggestion, have you tried a DC blocking cap between your AC signal input & your chosen ADC pin? Obviously you then have to rebias the ADC pin - but 2 x 1% tolerance resistors between your PIC VCC & Gnd should ...with the the resistor junction connected to your ADC pin, should get you incredibly close to a reading of 512.
-
Re: Low frequency audio level detector using PIC ADC?
127,127,126,127,127,126, etc) APPROX. = 126.67
If you have a voltage =126.66 in 8 bit mode you will likely get 127 and 126 readings.
If I use 1% resistors then the error from resistors could be as great as 2%. Typically under 0.5%
The ADC is not perfect. point 128 may be off a little. Typically it is close but it could be several counts off. I wanted to correct for both resistor and ADC worst case errors.
Yes I have a DC blocking cap.
It appears you read in data in 8 bit mode. After rectificaton you have 7 bit data.
I chose to read in data in 10 bit mode. Rectify to 9 bit data. Loose the LSB to get 8 bit data.
The math is done in 8 bit mode to keep the speed high.
In RMS mode I square the 8 bit number to get a 16 bit number that is averaged.