I think the Fast Average section might be modified so that instead of jumping to the spurious noise point, it will reject the sample entirely.
That should only take commenting 1 line from the original code.
I think the Fast Average section might be modified so that instead of jumping to the spurious noise point, it will reject the sample entirely.
That should only take commenting 1 line from the original code.
DT
I've broke the breadboard circuit up ....so can't test right yet. But this sounds cool.
How does the averging code decide whether what's coming in is spurious...or in fact the beginning of a new stream of samples (eg a new frequency arriving, which will generate a different comparator count - with it's own spurious counts).
I guess what I really need issome form of 'trigger' (or 'change' threshold) so that my program then knows that a new frequency is coming in (& is not just a spurious reading)...
For example, red test below is spurious count, blue is new frequency arriving (therefore count changes and starts coming in at around that new level)
5000,4999,5000,5001, 3956,5000,5001,5000,4999,5000,3789, 2570,2571,2569,2570,2571,18912569,2571....
Last edited by HankMcSpank; - 20th October 2010 at 23:00.
Hank, It seems to me you need to set some rules, or rather conditions. something like this:
1) samples must be +- 10 of a target number to be included in the average
2) numbers outside the +- 10 will need to have 2 more samples within the new samples range to be considered a good sample.
That seems like it would weed out the rouge numbers. Now of course I have chosen random numbers. The 10 and 3. I don't really know what the numbers represent (I assume gutiar notes). Nor do I have a feel for how long a note will last. thats what drives the 10 number.
-Bert
The glass is not half full or half empty, Its twice as big as needed for the job!
http://foamcasualty.com/ - Warbird R/C scratch building with foam!
We choose to go to the moon. We choose to go to the moon in this decade and do the other things, not because they are easy, but because they are hard, because that goal will serve to organize and measure the best of our energies and skills, because that challenge is one that we are willing to accept, one we are unwilling to postpone, and one which we intend to win, and the others, too.
John F. Kennedy
Notice in the image that all spurious samples were rejected.
And where the samples changed from 6798 to 3899, the average caught up after 2 samples (adjustable with a constant).
Code:DEFINE OSC 20 DEFINE LCD_DREG PORTB 'LCD data port DEFINE LCD_DBIT 0 'LCD data starting bit 0 or 4 DEFINE LCD_RSREG PORTB 'LCD register select port DEFINE LCD_RSBIT 4 'LCD register select bit DEFINE LCD_EREG PORTB 'LCD enable port DEFINE LCD_EBIT 5 'LCD enable bit DEFINE LCD_BITS 4 'LCD bus size 4 or 8 DEFINE LCD_LINES 2 'Number lines on LCD DEFINE LCD_COMMANDUS 2000 'Command delay time in us DEFINE LCD_DATAUS 50 'Data delay time in us DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1 DEFINE HSER_SPBRG 129 ' 9600 Baud @ 20MHz, 0.16% DEFINE HSER_CLROERR 1 ' Clear overflow automatically '----[Averaging Options]------------------------------------------------------------------ AvgCount CON 16 ' Number of samples to average FAspread CON 50 ' Fast Average threshold +/- Reject CON 2 ' Spurious Rejection level ;----[Variables]-------------------------------------------------------------------------- Value VAR WORD RejCount VAR BYTE ADavg VAR WORD ;----[Initialize]------------------------------------------------------------------------- RejCount = 0 ADavg = 0 ;----[Main Program Loop]------------------------------------------------------------------ Main: HSERIN [wait($FF),DEC Value] ; get a sample HSEROUT ["Smpl= ",DEC Value] LCDOUT $FE,$80,"Smpl= ",DEC Value," " GOSUB Average ; average it HSEROUT [" Avg= ",DEC ADavg] ; ," Avg2= ",DEC ADavg2,13,10] IF RejCount > 0 THEN HSEROUT [" Rejected"] ; indicate if rejected HSEROUT [13,10] LCDOUT $FE,$C0,"Avg = ",DEC Value," " LCDOUT $FE,$94,"FC = ",DEC RejCount," " GOTO Main ' -=-=-=-=-=-= Average Sample values -=-=-=-=-=-=-=-=-=-= Average: IF Value = ADavg Then RejCount = 0 : RETURN ; NoChange IF ABS (Value - ADavg) > FAspread OR Value < AvgCount Then FastAvg IF ABS (Value - ADavg) < AvgCount Then RealClose ADavg = ADavg - (ADavg/AvgCount) ADavg = ADavg + (Value/AvgCount) RejCount = 0 GoTo AVGok FastAvg: RejCount = RejCount + 1 IF RejCount = Reject + 1 THEN ADavg = Value RejCount = 0 ENDIF GoTo AVGok RealClose: RejCount = 0 ADavg = ADavg - (ADavg/(AvgCount/4)) ADavg = ADavg + (Value/(AvgCount/4)) AVGok: Value = ADavg ' Put Average back into Value NoChange: Return
DT
Thanks Ioannis.
And I'll say ... cncmachineguy's rules were pretty darn close to how I modified the averaging routine.![]()
DT
Wow...what can I say?!!
DT you truly rock...and without a doubt you're my most favouritiest E-personage on the whole of this global network!
I'll give this runout at the weekend...once again, thanks....just brilliant!!
cnc machine guy - great input too ...many thanks.. re the arriving frequencies (or more importantly, what the PIC sees for incoming signal frequency - comparator 'count'), well, on a std tuned guitar, the lowest note is 82.4Hz...which @20Mhz clock gives a comparator interrupt 'count' of about 60700 per 82.4Hz period' ...the highest note on a guitar is about 1.4Khz & gives a comparator count of about 3500 1.4khz 'period'. Each musical note has about 5% difference...but the problem with guitar 'pitch detection' is you can bend a note, which will obviously fall somewhere in between the 5% between notes.
I'd like to be able to eventually get the PIC discern not just which note is being played but also when it is s being bent - but for that I need good solid incoming samples to process...and these spurious samples were really screwing me up - hence I relish having a dabble with what DT has just posted!
Last edited by HankMcSpank; - 21st October 2010 at 15:57.
Bookmarks