Rough 'n Ready Audio Frequency extraction with a PIC


Closed Thread
Results 1 to 34 of 34

Hybrid View

  1. #1
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    I've thought about doing something like that too,

    And I think without external hardware and using the comparator, the DFT idea Josuetas was working with a while back might have the best chance at detecting the notes.
    It may even be able to detect multiple notes at the same time (chords).

    I played with the spreadsheet, but didn't try any hardware.

    And whether the resolution will be tight enough to distinguish 9/8, 10/9 and 16/15ths steps, I don't know either.
    It was originally for DTMF tones.

    Might be worth a look though.
    http://www.picbasic.co.uk/forum/show...2606#post42606

    And the original AppNote (AN257) ...
    http://www.microchip.com/stellent/id...pnote=en024294

    <br>
    Last edited by Darrel Taylor; - 7th March 2010 at 23:45.
    DT

  2. #2
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Thanks Darrel....I'll check it out later.

    So here's the ludicrously simple 'get me up & running' setup I have (lifted/edited fromthe Microchip Tips' n trick sheet)



    I put a sawtooth from a sig gen on the comparator input, but get nowt on the output

    Now like I say, I always struggle with the registers - and even then, it's been a while - so try not to laugh...

    Code:
    @MyConfig = _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON  
    @MyConfig = MyConfig & _MCLRE_OFF 
    
    DEFINE OSC 4           ' Internal 4MHz
    
    CMCON0 = %00000001   	'CIN pins are configured as analog, COUT pin configured as Comparator output?
    ADCON0 = %00000000	'ADC disabled?
    ANSEL = %00001111	'All Analogue inputs enabled?
    TRISIO = %111011	'GPIO2 output (Comparator Out)
    
    ' PIN# NAME     USE & CONNECTION
    '  1   Vdd      +5VDC power supply
    '  2   GPIO.5   Debug Port (PicKit2 needs switching from here to pin Pin 7 to allow programming)
    '  3   GPIO.4   
    '  4   GPIO.3   
    '  5   GPIO.2   Comparator Out (GP2)
    '  6   GPIO.1   CIN-  Signal In  (GP1)
    '  7   GPIO.0   CIN+  trigger level (GP0)
    '  8   Vss      Power supply ground
    '-------------------------------------------------------------------------



    EDIT Ok, spotted it..

    Code:
    ANSEL = %00001011		'All Analogue inputs except AN2 enabled
    & here we have an output...



    Now...what to do with the output?!!!
    Last edited by HankMcSpank; - 8th March 2010 at 00:05.

  3. #3
    Join Date
    Jan 2009
    Location
    California, USA
    Posts
    323


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HankMcSpank View Post
    Now...what to do with the output?!!!
    On the rising edge of your square wave, start a timer running. When the next rising edge comes along, grab the timer count so you can calculate the period of the square wave, and reset the timer for the next go around.

    If your waveform is symmetrical you could start the timer on the rising edge and stop on the falling edge and get your frequency in 1/2 cycle.
    Maybe...


    steve

  4. #4
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Well I went for the most simplistic approach first....

    Code:
    temp var byte
    temp = 0
    
    start:
        count  GPIO.4, 100, temp
        DEBUG  "Count = ", DEC temp, 13, 10 
        temp = 0
        GOTO start
    end
    & it works - the count for 100ms is pretty much bang on ...does jitter about by 1 or so at the lower frequencies

    I realise for a 'sig gen' sourcedsine wave this isn't much of a breakthrough (other than it is for me getting all this comparator stuff melarkey working) - I'm sure guitar signal might be a bit more tricky (one for tomorrow night now).

    Here's 659Hz (Top E String fretted at the 12th), the PIC 100mS pule in count for that frequency matches what I'd anticipated on my spreadsheet...

    Last edited by HankMcSpank; - 8th March 2010 at 01:31.

  5. #5
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Time to revisit this old thread of mine, as I now have a cool use for frequency detection in my ongoing guitar project 'X'.

    Basically, I want a PIC on my cct to establish when the same guitar note has been played for 'x' seconds (user configurable) - once this condition has been met, then the PIC will inoke some cool 'stuff' to kick in!

    I parked this 'early exploratory thread' having gotten the comparator/frequency detect to work simply on a basic 12f683 - back then interrupts were fairly new to me...whilst now I don't pretend that I'm interrupt savvy (I don't need to be thanks to Darrel's routines!)...I think it's time to revisit & try to apply to the more advanced PIC I'm using now - a 16F690.

    Now looking at the comparator module on the 16f690 datasheet - wooooaaah.....a bit scary. So a couple of early questions before I have a pop at this tonight.

    Due to the layout of my board, pin 7 looks like a prime candidate for getting my analogue signal into the PIC - could someone please confirm that this is indeed a valid comparator input pin?!!



    Ok, wrt what signal I'm feeding into the comparator - essentially with no guitar signal present the quiescent voltage will be +4V (which is also the PIC rail voltage) - in my cct config, a diode half wave rectifies the guitar signal so when a signal is present ....the PIC will just see negative portions of the signal.

    So, with respect to the voltage to 'flip' the comparator - I guess, I'd need something in the region of +3V? (ie any incoming signal with a negative swing of 1V will flip the comparator). a quick look at the datasheet suggests there are 16 'reference levels' that can be used internally within the PIC - cool, looks like that should be ok (I'll need to have a dabble with the VRCON register)

    Ok, now assuming I get the comparator 'flipping' at the right voltage level .....what to do with it to get the most dependable frequency detection going on.

    Just to reiterate - I would like to to detect when the guitar frequency has NOT changed for 'x' seconds (the' x' being user selectable selectable by a pot - I have this particular bit covered off already)

    I see that DT's interrupts have a comparator interrupt....presumably that can be brought into play here?

    So what would be a good building block here?

    1. Start a countdown timer configured for 'x' seconds. (as mentioned above)
    2. start looping (say a 300ms loop...whatever time window is needed to detect individual fret frequencies for the frequency range of guitar ...approx 70Hz thru 1300khz))
    3. Clear comparator 'count' (a program variable)
    4. Enable comparator interrupts
    5. Start counting comparator interrupts
    6. Stop loop, compare present number of comparator interrupt count with previous ...
    i) if comparator count is 'within limits' then keep repeating (same note has been held held)
    ii) if 'outside limits...then reset step 1 countdown timer (ie a different note detected, so reset & start again)

    7. countdown timer expires - condition therefore met (ie same note held for x seconds)....go and invoke some cool stuff!!


    Any thoughts, problems etc? (I should point out that the guitar has a sustain device onboard, so the note can/will ring on forever - also such a sustained note is pretty sinuisoidal, stable....so the comparator should flip reasonably dependably)
    Last edited by HankMcSpank; - 20th August 2010 at 11:24.

  6. #6
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Well, I got a simple form of frequency detection going on with my 16f690 last night.

    I fed a sine wave into one of the 16f690s comparator input pins & used DT's comparator interrupt routine - the associated handler incremented a count with every comparator flip (interrupt),

    I then simply used timer1 set to overflow at 0.5s - at overflow the comparator count is multiplied by two (to get the equivalent count for 1 second - so the end result was in Hertz).

    I was getting reasonable accurate frequency detection - the 'count' number danced about +/- 2 or 3 (therefore ultimately 2 or 3Hz) ...which I'm pretty sure could probably be averaged out to bring this error down a little).

    I wasn't able to get the 16f690' internal VREF to work (I was using the external VREF pin set at 1/2 VCC)

    This VREF issue aside (which I'll revist soon), what I now need is a 'rolling window' in code, which goes something like thus...

    "If the comparator count hasn't changed - give or take - for the past 1.5 seconds (ie rolling window), then that must mean a note is presently being held, if so ...go & do stuff!"

    Now there are only two timers on the 16f690....and I was really hoping to keep one of them in reserve for flashing LEDS (the LED 'flash rate' depending on the mode), so I'm looking for creative ideas that would allow me to apply the above 'condition' without wasting anther timer!

    Grateful for any input here!
    Last edited by HankMcSpank; - 26th August 2010 at 11:25.

  7. #7
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Ok, I think I have the loose makings of the necessary code for a rolling 1 second window to check whether the frequency has remained the same...

    (the signal to be monitored is fed into comparator1)

    Code:
    INCLUDE "DT_INTS-14.bas"
    INCLUDE "ReEnterPBP.bas"
    INCLUDE "Elapsed_INT.bas"  ; Elapsed Timer Routines
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,  _timer1_interrupt,   PBP,  yes
            INT_Handler   CMP1_INT,  _comparator_interrupt,   PBP,  yes
        endm
        INT_CREATE            ; Creates the interrupt processor
    ENDASM
    
    @   INT_ENABLE  TMR1_INT  ; Enable Timer 1 Interrupts
    @   INT_ENABLE  CMP1_INT  ; Enable comparator1 Interrupts 
    
    nochange_count var word   'count number of 'timer overflows' where frequency hasn't changed
    
    comparator_count var word   'a variable to count number of comparator interrupts (frequency detection)
    
    loop:
    if nochange_count > 3 then     'ie frequency has remained the same for 1 second
    nochange_count = 0 
    gosub dostuff
    endif
    goto loop
    
    
    '---[Timer1 - interrupt handler]--------------------------------------------------
    timer1_interrupt:        'prescaler set for circa 250ms
    if comparator_count = previous_comparator_count then   'needs a 5% 'deviation' allowable error to go here!!
    nochange_count = nochange_count+1   'count how many times frequency has NOT changed
    else
    nochange_count = 0 ' if frequency has changed, then zero counter and start over
    endif
    previous_comparator_count =  comparator_count
    comparator_count = 0
    @ INT_RETURN
    
    '---[Comparator1 - interrupt handler]--------------------------------------------------
    comparator_interrupt:
    comparator_count = comparator_count +1
    @ INT_RETURN
    There may be some syntax errors in there (I'm at work!), but that's the basic framework - what I don't know how to do is the 'deviation' part (bolded in red above).

    How can I have an 'if' condition that checks to establish if present count is 'within 5%' of previous count' (plus or minus), therefore....

    if comparator_count = previous_comparator_count '+ or -' 5%

    Two 'AND'ed ifs?

    Many thanks!
    Last edited by HankMcSpank; - 26th August 2010 at 13:39.

Similar Threads

  1. Measuring change of frequency with PIC
    By Aussie in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 19th July 2007, 01:47
  2. PIC Audio
    By toofastdave in forum mel PIC BASIC Pro
    Replies: 28
    Last Post: - 27th June 2007, 13:49
  3. Pic driven digital audio delay
    By skimask in forum Off Topic
    Replies: 12
    Last Post: - 19th April 2007, 20:42
  4. Audio Encoding and playback in a PIC
    By Rob in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 24th March 2005, 08:56
  5. Frequency Counter using PIC and PicBasic
    By PICtron in forum mel PIC BASIC Pro
    Replies: 31
    Last Post: - 28th January 2005, 06:20

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