Low frequency audio level detector using PIC ADC?


Closed Thread
Results 1 to 40 of 69

Hybrid View

  1. #1
    Join Date
    Nov 2007
    Location
    Lake Villa Il.
    Posts
    40


    Did you find this post helpful? Yes | No

    Default Re: Low frequency audio RMS signal level detector using PIC ADC?

    Hi Hank,
    That is great that you got it to work! Is there a chance that you could post a working version in the code examples section for the rest of us? It is still a little foggy to me.......

    Thank you,
    Sneaky-geek

  2. #2
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: Low frequency audio RMS signal level detector using PIC ADC?

    Quote Originally Posted by Sneaky-geek View Post
    Hi Hank,
    That is great that you got it to work! Is there a chance that you could post a working version in the code examples section for the rest of us? It is still a little foggy to me.......

    Thank you,
    Sneaky-geek
    Sure, at the risk of being ridiculed for my elementary coding (I'll always be a n00b!), here you go..

    Code:
    '16F1828 Pin Connections*********************************************
                    ' PIN# NAME  USE & CONNECTION
                    '1   Vdd     +5VDC power supply
    TrisC.3 = 1     '7   RC3     AN7 ADC iN
    TrisB.7 = 0     '10  RB7     HSEROUT pin
                    '20  Vss     Ground
    ''*****************************************************************
    @ __CONFIG _CONFIG1, _FCMEN_OFF & _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF & _CP_OFF & _IESO_OFF & _BOREN_OFF & _PWRTE_OFF & _LVP_OFF
    @ __CONFIG _CONFIG2, _LVP_OFF
    
    Osccon = %01110010      'Osc 8Mhz
    
    DEFINE  OSC 8
    DEFINE  NO_CLRWDT 1   ' PBP doesn't clear WDT automatically
    
    ' HW Serial port setup - 115200 @ 8Mhz***********************************
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    DEFINE HSER_SPBRG 16  ' 115200 Baud @ 8MHz, 2.12%
    SPBRGH = 0
    BAUDCON.3 = 1         ' Enable 16 bit baudrate generator
    '********************************************************************
    
    CM1CON0 = 0   ' COMPARATORS OFF
    CM2CON0 = 0   ' COMPARATORS OFF
    
    ADCON0 = %00011101      'SET AN7 as selected ADC input + ON
    ADCON1 = 0
    
    ANSELA     = 0          ; All Port A ports digital
    ANSELB     = 0          ; All Port B ports digital
    ANSELC     = %00001000  'Analogue pin on RC3 (AN7)
    
    CCP4CON = %0001011     'set CCP4 into special event timer mode
    
    TMR1H = 0       ' set timer1 counter registers to zero            
    TMR1L = 0
    
    CCPR4H = 0       ' preset for timer1 match (MSB register) when timer1 TMR1H & TMR1L match these two regsiters, an ADC sample occurs in hardware
    CCPR4L = 50      ' preset for timer1 match (LSB register)  lower value = higher sampling rate (40Khz here - I think!)
    
    T1CON.0 = 1         ' set timer1 on
    
    count1 var byte
    rolling_peak var BYTE
    present_sample var BYTE
    
    rolling_peak = 0
    present_sample= 0
    count1 = 0
    
    '**********ok that's all the config out the way, let's start***************************************
    
    main:
        count1 = count1 +1                       
        present_sample = ADRESH              'copy the ADC value as taken in the background (by the special event trigger) into a variable
        IF  present_sample < 128 then         'if it's less than 128, then this the waveform has entered the negative part of its cycle.
        present_sample = (127 - present_sample)   'therefore  let's make it positive! (just like a full wave rectifier)
        else 
        present_sample = present_sample -128   ' if it' not in the negative cycle (as checked above), then we're in the positrive part of the cycle, so let's rebase everyting down to 0
        endif
    
        IF present_sample >= rolling_peak THEN 'if the present sample is equal or bigger than the last sample - keep it
        rolling_peak = present_sample
        else                            'if the present sample is not equal or bigger than the last, start decrementing (discharging)
        if count1 =  10 then             ' this count will set the decrement ('discharge') rate (lower is faster)
        rolling_peak = rolling_peak -1   
        count1 = 0
        endif
        endif
        HSEROUT [dec rolling_peak, 13, 10]   'lets make sure everything looks ok on screen
        goto main
    The above sets a 16f1828 up to take ADC samples using the special event trigger ...if using the exact code above, your AC input signal goes in on pin 7 (max 'peak to peak' amplitude being your VCC level - best to amplify your signal for presenting into the pin so that 'max peak to peak' of your incoming signal is as near your VCC voltage as possible - you'll achieve max resolution then) ....your AC signal should be sitting an a DC level of half your PIC's VCC (ie positive cycle go from ADC values of 128->255. negative cycles go from 127->0 - the zero crossing point is an ADC value of about 128)

    I should emphasise that I've not used it in anger yet....there may well be some bugs to flush out - & I'm sure it can be improved (feel free anyone to outline how I can make it slicker anyone!), but it works approx ±1 jitter @7 bits...seems to be reasonably ok upto 20khz...which suggests my sampling frequency in the code is higher than I think it is (btw you lose 1 bit of ADC resolution by flipping the negative cycle up into positive territory...this is a sacrifice worth making as you'll get less 'psuedo ripple' when otherwise the value of the ensuing decrements during the negative cycles would kick in - you can always use 10 bits for your ADC, if so, then you'll lose you one bit, therefore a max 512 values up for grabs) ...

    5V peak to peak @300hz....



    Here's approx 2.5V peak to peak @20khz (a tad more jitter), it should read 64, but I reckon the discrepancy can be accounted for with the DC not being exactly 2.5V that the AC signal sits on (&/or my Chinese USB scope might not be that accurate!)



    One last point - despite the thread title, this detects 'peak' not RMS (& peak is what I need in the end...if you need RMS multiply the result by .707 ....or rather use a workaround for the lack of floating point)
    Last edited by HankMcSpank; - 23rd February 2011 at 02:23.

  3. #3
    Join Date
    Jul 2003
    Location
    USA - Arizona
    Posts
    156


    Did you find this post helpful? Yes | No

    Default Re: Low frequency audio RMS signal level detector using PIC ADC?

    Hats off to you Hank, most excellent project.

  4. #4
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Re: Low frequency audio RMS signal level detector using PIC ADC?

    Nice job Hank. What about writing this project up for the wiki?
    It would be a great addition there.
    Dave
    Always wear safety glasses while programming.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: Low frequency audio RMS signal level detector using PIC ADC?

    Hank,
    Thanks for sharing! You projects always push the limits, so we all learn.

    Regards

  6. #6
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default 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 :-)

  7. #7
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default 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)....



    (thats doesn't look like a good square wave at all!)

    & here's the register I'm setting....

    Code:
    CCP4CON = %0000010



    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.
    Last edited by HankMcSpank; - 23rd February 2011 at 23:59.

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts