Low frequency audio level detector using PIC ADC?


Results 1 to 40 of 69

Threaded View

  1. #29
    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 01:23.

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