Hi,
I meant 50 us is for the total time taken for one sample of ADC. 20 us of acquisition time is more than enough, since your source impedance is so low. The conversion time (which is the time taken for the conversion of 10 bits result, the time where you wait for the GO bit to be cleared) takes approximately 12*Tad. Since your Tad is set to 2 us, the conversion time is 24 us. With the acquisition time of 20 us, the total time for one sample is 44 us (excluding the other instruction cycles), that's why I said it is around 50 us.
As I said before, use subtraction and check the carry bit after the conversion. You may need to enable AD interrupt to make life easier, but the time taken for saving and restoring the registers should also be counted, so it takes longer time.
Thanks a lot Pommie and bananasiong for your valuable advice.
Pommie, I was a bit confused about using that instruction [ movf ADRESH,PEAK] just because I was using the 18F PIC sometime ago so I mistakenly used the 18F movff instruction. Sorry about that.
Just a quick question on sampling rate as it's making my life hell. I need to have at least + or - 5 degree accuracy in my phase detection. That implies I have to have 360 deg/5 =72 levels in one cycle. Thus for 1kHz signal, I will be looking to sample at 72kHz. My knowledge about sampling rate is the amount of delay between the two samples. However I am very confused when bananasiong advised me to reduce the delay. If I reduce the delay, wouldn't it affect my phase detection part?
I apologise for asking you guys these silly questions.
You will not be able to sample that fast. The fastest you can sample two channels is 80uS (12.5kHz).
Maybe you should approach this in a different way, if you use a diode and feed a capacitor it will charge to the peak voltage. You will need a largish resistor to slowly discharge it. You can also amplify the waveforms and feed them via resistors into port pins. As the waveform crosses zero it will cause the pin to go high, you can use this signal to work out the phase relationship. You could even use the comparators to detect the waveforms crossing the 2.5V point.
Hi,
The minimum time taken for one sample is 44 us, somehow you still need to do other instructions in between that causes some delay time as well.
44 us is obtained by:
20 us of acquisition time
2 us * 12 = 24 us for the 10 bits data conversion
You can't improve the speed much by using higher oscillator. It is because the AD clock is from 1.6 us to 6 us. Anyway around 12 cycles of Tad needed for the conversion. Higher oscillator frequency can only improve the time for the instructions.
*EDIT: bolded
With 20 MHz, the ADC time can be improved a little by setting the Tad to be 1.6 us. Hence the minimum time for one sample will be 40 us.
Hi,
The minimum time taken for one sample is 44 us, somehow you still need to do other instructions in between that causes some delay time as well.
44 us is obtained by:
20 us of acquisition time
2 us * 12 = 24 us for the 10 bits data conversion
You can't improve the speed much by using higher oscillator. It is because the AD clock is from 1.6 us to 6 us. Anyway around 12 cycles of Tad needed for the conversion. Higher oscillator frequency can only improve the time for the instructions.
*EDIT: bolded
With 20 MHz, the ADC time can be improved a little by setting the Tad to be 1.6 us. Hence the minimum time for one sample will be 40 us.
I have been struggling to do this task for the last 3-4 hours.
Even though I have used your bit of code, it's still not working. I know I have done a silly mistake somewhere in using your code.
The weird thing is when I am loading my code into PIC, all the LEDs [PORTC] are ON and they remain ON even when I am giving 1 kHz [2V half wave rectified] signal at RA0.
Your main code is falling through to your delay routine,
This is what I think you need to do,
Code:
Main
call Delay ;wait for acquision time (20us)
bsf ADCON0,GO ;Start A/D conversion
Wait
btfsc ADCON0,GO ;Wait for conversion to complete
goto Wait
movfw ADRESH ;get ADC result
subwf Peak,W ;do Peak-ADC
btfss STATUS,C ;C set if ADC>Peak
goto DoneMax ;not higher
movfw ADRESH ;is higher
movwf Peak ;so copy to peak
[COLOR="Blue"] ;removed goto Main ;do it again![/COLOR]
DoneMax
movf ADRESH,W ;Write **AMPLITUDE** result to PORTC
movwf PORTC ;LEDs
[COLOR="blue"] ;removed clrf Peak
goto Main ;added [/COLOR]
I see you have the conversion clock at Fosc/8. If you are running at 20MHz then this is too fast. Check the table on page 131 of the datasheet.
The reason your LEDs stay on is probably because they are changing so fast you cannot see when they are off. Try putting a pot an A0 and move it slowly to see the effect.
Your main code is falling through to your delay routine,
This is what I think you need to do,
I see you have the conversion clock at Fosc/8. If you are running at 20MHz then this is too fast. Check the table on page 131 of the datasheet.
The reason your LEDs stay on is probably because they are changing so fast you cannot see when they are off. Try putting a pot an A0 and move it slowly to see the effect.
Thank you very much for your kind suggestion Mike.
One last thing. I am still puzzled about the LEDs. I thought the LEDs will only light when the max value is detected? If my input is 2V halfwave, shouldn't the LEDs show 102?
I just downloaded the program but nothing happend !
After changing the last part of my code i.e.
Code:
DoneMax
movf Peak,W ;Write **AMPLITUDE** result to PORTC
movwf PORTC ;LEDs
goto Main
to
movf ADRESH,W ; changed again
The code seems to work [I am using a pot rather than AC signal]. I don't know why its not showing me the value using Peak,W instruction!!
I am a bit concerned about the
Code:
subwf Peak,W ; do Peak-ADC
. Here we are doing Peak-ADC, but in the beginning of the code I have set Peak as 0 by clrf instruction. I may sound stupid but wouldn't it be wrong doing 0 - some value ?
I used clrf Peak just after the following instruction :
Code:
movf Peak,W ;Write **AMPLITUDE** result to PORTC
movwf PORTB ;LEDs
clrf Peak
goto Main
Still it's not showing me anything on PORTC.
I am a bit concerned about the
code
Code:
subwf Peak,W ; do Peak-ADC
Here we are doing Peak-ADC, but in the beginning of the code I have initialize Peak as 0 by clrf instruction. I may sound stupid but wouldn't it be wrong when the very first sample value will be substracted from 0 ?
I sincerely apologise for troubling you over this.
I missed your clrf Peak at the beginning of your code.
The instruction,
Code:
subwf Peak,W ;do Peak-ADC
When Peak is 0 and the ADC value is say 10 then, Peak-ADC is 0-10=-10 and a borrow is required and so the Carry bit is cleared.
From the above you can see I got the carry bit the wrong way around.
It should be,
Code:
Main
call Delay ;wait for acquision time (20us)
bsf ADCON0,GO ;Start A/D conversion
Wait
btfsc ADCON0,GO ;Wait for conversion to complete
goto Wait
movfw ADRESH ;get ADC result
subwf Peak,W ;do Peak-ADC
btfs[COLOR="Red"]c[/COLOR] STATUS,C ;C clear if ADC>Peak
goto DoneMax ;not higher
movfw ADRESH ;is higher
movwf Peak ;so copy to peak
DoneMax
movf ADRESH,W ;Write **AMPLITUDE** result to PORTC
movwf PORTC ;LEDs
goto Main
I don't know what is wrong. It's been 8 hours since I've been trying and it's 6.00 am in the morning. I might come back after a while and try it again.
I really appreciate your help and please let me know if you find any more corrections or ideas to solve this!
I have made a few changes and it seems to work with DC. I would like you to bare with me for a couple of minutes and would like you to read and advise.
I think I know where the problem lies. Its my code for sure. Let me explain in detail and you guys might catch something. [Thanks to Mike for this idea ]
My code does this:
Let say I have a hafwave rectified wave of 2 V. So the samples [assuming] are occurring at 0, 1, 2 back to 1 and 0. Now my code takes an initial value 0 from the Peak register and subtract it from ADRESH value. If the result is positive, then carry bit is set and the ADRESH value is copied to Peak. Now it goes on till the next value is less than the peak and thus carry bit is clear and the max value is display on PORTC.
It works perfect with DC but when I use AC, it gives me a random incorrect value. I think this might be due to the fact that my code ONLY works for the first quarter cycle [from 0-2] and not for the rest of the quarter cycle [2 back to 0]. Thus when the signal arrives with a delay [say it starts from 2,1 to 0] and sampling begins, it might capture the voltage at say 1 and the rest of the values are obviously less than 1. Thus giving me 1 as peak which is totally wrong.
I think this can be sorted out by using some ZERO CROSSING. Thus program will wait for the zero to come and therefore, samples will begin from there after.
Could someone please advise on how to write a simple zero crossing code????
I apologise for writing this long explanation and it just to show what I think I have done wrong.
I have made a few changes and it seems to work with DC. I would like you to bare with me for a couple of minutes and would like you to read and advise.
I think I know where the problem lies. Its my code for sure. Let me explain in detail and you guys might catch something. [Thanks to Mike for this idea ]
Code is:
Code:
Wait btfsc ADCON0,GO ;Wait for conversion to complete
goto Wait
movfw Peak ;get Peak value '0' to w
subwf ADRESH,1 ;do ADC-Peak
btfss STATUS,C ;C set if ADC>Peak
goto DoneMax ;not higher
movfw ADRESH ;is higher
movwf Peak ;so copy to peak
goto Main ;do it again!
DoneMax
movf Peak ;Write **AMPLITUDE** result to PORTC
movwf PORTC ;LEDs
goto loop_abc
loop_abc
clrwdt
goto loop_abc
My code does this:
Let say I have a hafwave rectified wave of 2 V. So the samples [assuming] are occurring at 0, 1, 2 back to 1 and 0. Now my code takes an initial value 0 from the Peak register and subtract it from ADRESH value. If the result is positive, then carry bit is set and the ADRESH value is copied to Peak. Now it goes on till the next value is less than the peak and thus carry bit is clear and the max value is display on PORTC.
It works perfect with DC but when I use AC, it gives me a random incorrect value. I think this might be due to the fact that my code ONLY works for the first quarter cycle [from 0-2] and not for the rest of the quarter cycle [2 back to 0]. Thus when the signal arrives with a delay [say it starts from 2,1 to 0] and sampling begins, it might capture the voltage at say 1 and the rest of the values are obviously less than 1. Thus giving me 1 as peak which is totally wrong.
I think this can be sorted out by using some ZERO CROSSING. Thus program will wait for the zero to come and therefore, samples will begin from there after.
Could someone please advise on how to write a simple zero crossing code????
I apologise for writing this long explanation and it just to show what I think I have done wrong.