|
|
View previous topic :: View next topic |
Author |
Message |
otavio_fisica
Joined: 20 Jul 2006 Posts: 29
|
Problems with ADC in the PIC16F689 |
Posted: Sat Jul 28, 2007 9:49 pm |
|
|
Hi...
I have some problems with the A/D converter of the PIC 16F689. The code I am using is the following:
Code: | long int angulo;
void main()
{
setup_adc_ports(sAN0|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC_NC_NC);
delay_us(50);
while(true){
output_high(PIN_C5); //this is just a led pin.
angulo = 0;
angulo = read_adc(); //reads the adc and then stores the result in the variable angulo
delay_ms(100);
printf("%Lu",angulo); //prints the result through the serial port.
output_low(pin_c5);
}
} |
The problem is that the ADC just doesn't seem to work. When I attach the pin AN0 to the VSS, the result should be 0 and it should be 1024 when the pin is attached to the VCC. But what I got was a 48 for when it is tied to the VSS and a crazy value in the other case.
Can you identify some problem with my code?
Any help would be of great value...
Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 28, 2007 10:44 pm |
|
|
1. Do you have a debugger (ICD-U40, or ICD2) connected to your board
while you are running these tests ?
2. Post all the #fuse, #device, and #use statements for your program.
3. Post your compiler version. |
|
|
Guest
|
Here it is. |
Posted: Sun Jul 29, 2007 7:06 am |
|
|
Oh, sorry. My .h file is the following one.
Code: |
#include <16F689.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOPUT //No Power Up Timer
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B7,rcv=PIN_B5,bits=8,stream=sensor) |
My compiler's version is IDE, PCB, PCM, PCH 4.032.
I thought of some problem in the serial communication, but it is ok. I made the PIC transfer integer numbers to the other one in a FOR loop, and it worked perfectly. I don't know what may be happening. |
|
|
otavio_fisica
Joined: 20 Jul 2006 Posts: 29
|
|
Posted: Sun Jul 29, 2007 7:07 am |
|
|
I also do not have a debugger in my system.
I forgot logging in in the last reply. Sorry. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 29, 2007 5:29 pm |
|
|
Do you have a programmer attached to your board ? It uses the
AN0 pin.
I don't have a 16F689, but I do have a 16F690. I installed vs. 4.032
and compiled your program for the 16F690. I added a 500 ms delay
in your loop, because your loop was too fast.
I put a 5K trimpot on pin 19 (AN0), with the end terminals connected
to +5v and to Ground. I slowly turned the pot from one end to the
other, and it worked:
Quote: | 1023
1023
1023
902
817
787
747
699
625
559
470
362
297
238
168
81
0
0 |
If the debugger (ICD2) is attached, then I get some missing codes.
That's because the AN0 pin is used by the debugger, and the debugger
loads down the pin. (I am using the ICD2 as a programmer).
Quote: | 1023
1022
1022
<== Note missing codes
791
618
504
434
357
161
0
0
0 |
I suggest that you try a different pin which is not used by the debugger.
Try using AN4 instead, on pin 16. Make the changes shown in bold:
Quote: | setup_adc_ports(sAN4 | VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(4); |
|
|
|
otavio_fisica
Joined: 20 Jul 2006 Posts: 29
|
It still does not work |
Posted: Mon Jul 30, 2007 7:13 am |
|
|
I do not have any ICD attached to my system. Yet I tried to change the pin, but the result was the same. After many tests, I tried the following code:
Code: | float media,final;
int16 i, angulo, parcial;
byte ser, a, saida;
int saidera;
while(true){
angulo = 0;
for (i=1;i<=3; i++){
parcial = read_adc();
angulo = angulo + parcial;
delay_ms(200);
}
media = angulo/3;
media = 255*media;
media = media/1023;
saidera=(int8)media;
putc(saidera);
}} |
As you can see, I tried sending the value saidera. The calcullus with media were only tests. They will be different. I tried these ones just to change the scale to a int8 number that will be transmitted through the serial line. The calcullus will be different, but the result will still be a int8 number.
What I got was a 63 for when the analog channel is tied to the VCC and a 0 for when it is tied to the VSS. When it is tied to the system I want to measure, it works fine, but in this strange scale that goes from 0 to 63. According to my code, it should be from 0 to 255.
I tried many different variations of this code in the simulator, and everytime I implement the code in the hardware system, the result is the same.
I don't have any idea of what is happening. |
|
|
otavio_fisica
Joined: 20 Jul 2006 Posts: 29
|
|
Posted: Mon Jul 30, 2007 7:16 am |
|
|
Oh, I forgot... I tried to do it with that delay of 100us and then I changed to 200ms, for PCM said it was too fast. The result was the same for both the delays.
Just one more information.
Thanks for your help. |
|
|
otavio_fisica
Joined: 20 Jul 2006 Posts: 29
|
I tried this other code |
Posted: Mon Jul 30, 2007 9:17 am |
|
|
I tried this other code:
Code: | while(true){
angulo = 0;
for (i=1;i<=3; i++){
putc(i);
delay_ms(200);
parcial = read_adc();
angulo = angulo + parcial;
}
media = (float)4*angulo/3;
media = 255*media;
media = media/1023;
saidera=(int8)media;
putc(saidera);
} |
The variables are of the same type of the ones of the last post.
I tried this because I think the problem was with the convertion of the variable media to a int8 type. I think the compiler was truncating the first two bits of the variable media (which uses only 10 bits). So I tried multipling the variable angulo by 4, so that the first two bits would be 0. During the convertion, the variable saidera would store the correct value of media.
I have difficulties on sending a in16 variable through the serial port to another pic. I mean, with the other pic, I can't get the result correctly to store it in a int16 variable. That's because I want to make all the calcullations before sending the value. If I could send directly the variable angulo, after the for loop, it would also solve my problem. I think it would be a better solution. But, if there's no other possibility, I think it's fine to do what I tried now. Do you agree? Any suggestion? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 30, 2007 12:00 pm |
|
|
Quote: | float media,final;
int16 i, angulo, parcial;
byte ser, a, saida;
int saidera;
while(true){
angulo = 0;
for (i=1;i<=3; i++){
parcial = read_adc();
angulo = angulo + parcial;
delay_ms(200);
}
media = angulo/3;
media = 255*media;
media = media/1023;
saidera=(int8)media;
putc(saidera);
}} |
This code is too complicated for an initial test. Your purpose is to get
the A/D to give a good output. Use the test program that I posted
earlier. Don't do this complex math now. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|