Well the concept seems to work, but would you believe the thing that's hampering me is getting the timer1 interrupt frequency set right....I'm chasing an interrupt (ADC Sample) frequency of about 30khz.
I seem to be getting an interrupt frequency of just 1Khz, which means only low frequency sine waves that I'm sampling are stable from an ADC perspective, what am I doing wrong....
here's the top bit of my code (setting up the timer1)
Code:
' Timer1 Registers:
' Prescaler=1:1; TMR1 Preset=65503; Freq=30,303.0303Hz; Period=33,000 ns
T1CON.5 = 0 ' bits 5-4 Prescaler Rate Select bits
T1CON.4 = 0
T1CON.3 = 1 ' bit 3 Timer1 Oscillator Enable Control: bit 1=on
T1CON.2 = 1 ' bit 2 Timer1 External Clock Input Synchronization Control bit: 1=Do not synchronize external clock input
T1CON.1 = 0 ' bit 1 Timer1 Clock Source Select bit: 0=Internal clock (FOSC/4) / 1 = External clock from pin T1CKI (on the rising edge)
T1CON.0 = 1 ' bit 0 enables timer
TMR1H = $FF ' preset for timer1 MSB register
TMR1L = $DF ' preset for timer1 LSB register
& below is my (DT) interrupt handler (feel free to suggest better way of writing this ...I'm a kludger at heart & I've not really a clue how to code well!)
zero_cross is just a variable to track whether the signal wave/cycle is above zero (the signal zero point = 128....ie 1/2 my supply of 5V)
signal_in is a variable to store the sample (previous_sample + peak_sample are too!).
Code:
'---[TMR1 - interrupt handler]--------------------------------------------------
@ INT_DISABLE TMR1_INT ; diable Timer 1 interrupts
T1CON.0 = 0 ' disables timer1
ADC_Sample:
ADCIN 8, Signal_In 'sample the incoming signal
IF SIGNAL_IN > 130 THEN 'a level of 128 is the zero crossing point (130 adds a bit of margin for error)
zero_cross = 1 'a simple toggle/flag to track whether signal is above or below the 'zero point (ADC val of 128)
IF SIGNAL_IN > PREVIOUS_SAMPLE THEN previous_sample = signal_in ; if this latest incoming sample is bigger than the last sample, then it supercedes the previous value
GOTO INTERRUPT_END
ENDIF
if signal_in < 126 and zero_cross = 1 then 'if sample is 128 or less, then we're at the zero cross point, (126 adds some margin for error) therefore we've finished trying to sample peak
peak_sample = previous_sample ' our peak sample is therefore whatever value is in the variable 'previous_sample' from above
previous_sample = 0 'zero it, ready for when the waveform goes into positive territory again.
zero_cross = 0 ' toggle the above zero/below zero flag
endif
INTERRUPT_END:
LOOP_COUNT1 =LOOP_COUNT1+1 'this section just allow me to divide the interrupt rate down for onscreen display (else the serial port would bottleneck & PIC would likely restart)
if loop_count1 = 1000 then 'I'm seeing about 1 update onscreen per second, which suggest the interrupt frequency is 1kHz & not the required 30khz!
hserout [dec peak_sample,13, 10]
loop_count1 = 0
endif
TMR1H = $FF ' preset for timer1 MSB register
TMR1L = $f0 ' preset for timer1 LSB register
T1CON.0 = 1 ' bit 0 enables timer
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts
@ INT_RETURN
end
100hz, 2.5Vp signal - extracted 'peak' sample is circa 255....

100Hz, 1.25Vp signal - extracted 'peak' sample should be circa 192 (remember here that the signal's zero crossing point is ADC=128)

Ok, now you start seeing the problem...up to 300Hz, the ADC readings are fairly stable at +/- 1 sample, but if I now take the audio frequency up to 400Hz, the ADC 'samples' start getting choppy, which suggests the interrupt rate isn't high enough...

So what am doing wrong wrt getting the timer1 interrupts to interrupt at a 30Khz?!!!
Bookmarks