
Originally Posted by
Sneaky-geek
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)
Bookmarks