|
|
View previous topic :: View next topic |
Author |
Message |
jojos
Joined: 30 Apr 2007 Posts: 64
|
16F688 and A/D converter problem |
Posted: Tue Apr 08, 2008 7:20 am |
|
|
Hello.I am using compiler version 3.249 with the PIC 16F688.My project is to measure an analog sine signal 50 Hz .To test my Pcd board I used A/D converter to measure the Vp-p of the signal by searching for the max and the low part of the signal. So I have the A.D result and when the result is bigger then a value e.g. 750 I say to the microcontroller to turn on a led and when is below this point to turn off the led. So here we are.When the signal is bigger than the setpoint the led stays on as it should be.But when I get below the setpoint the led flashed on and off. I used the the RS232 port to see the analog data to the Hyperterminal. In Hyperterminal I saw that the A/D converter apart from reading lets say the correct value of the signal ,in this case 750 (the 750 value is the Vp-p 3,717V value that I am seeing the oscilloscope )
it reads values in the range of 900.So this is the reason that the led is not turning off as it should be below the setpoint but it flashes.I checked my analog signal and I it doesn’t have any noise. After an amount of checks I decided to change the microcontroller with a new one,but same things happened. Then I decided to change to a new type of microcontroller. I took the 18F2420 to see what would happened. I made the changes that should be done for the new controller and then I saw that with this controller I didn’t had the problem I mentioned before.I could see in the Hyperterminal that the analog value from the A/D converter was stable without any picks on the area of 900.So here is my question: Is there something that I should take in account when I am using PIC 16F688 ?Also in the datashhet I saw that PIC 16F688 doesn’t have any option of choosing –Vref for the A/D. Fot the +Vref there is the otion of choosing VDD or Vref pin as reference but for the –Vref there isn’t any option. I imagine that by default it chooses Vss for the –Vref.
I want to mention that I didn’t change nothing on my pcb when I changed the type of the microcontroller.I just made the appropriate changes (supply signals ,reset pin e.t.c.).So the pcb remained the same. Here is my code for both microcontrollers.
For PIC 16F688
Code: |
#include "16f688.h"
#fuses INTRC_IO,NOWDT,NOPROTECT,NOIESO,NOFCMEN,NOPUT,NOBROWNOUT //INTERNAL OSCILLATOR NO CLOCK
#use delay(clock=4000000)
#use rs232(baud=9600, parity=N,xmit=PIN_C4 ,rcv=PIN_C5,bits=8)
#use fast_io(A)
#use fast_io(C)
//#bit relay =7.4
//#bit Led1 =7.5
#bit Led1 =5.5
#define trimmer_ 1
#define nobutton_ 0
#define asymetry 3
#define ON 1
#define OFF 0
void init(void);
unsigned int16 a2d(char ch,char mode);
////////////////////////////////////////////////////////////
////////////////////////VARIABLES//////////////////////////
//////////////////////////////////////////////////////////
unsigned int16 P1,P2,P3,P4,temp22;
unsigned char low,high;
unsigned int16 kl,pot;
void main(void)
{
init();
disable_interrupts(GLOBAL);
while(1)
{
kl=a2d(7,nobutton_);
temp22=kl;//-515;
delay_ms(10);
printf("Analog= %lu\n\r",temp22);
if(temp22>=787)
Led1=ON;
else
if(temp22<787)
Led1=OFF;
}
}
void init(void)
{
TRISA=0b00010111;
PORTA=0;
TRISC=0b00101111;
PORTC=0;
ADCON1=0b00010000;
ANSEL=0b11110111; //all analog inputs
ADCON0=0X80; //initialize a/d
return;
}
///////////////////////////////////////////////////////////////////////
int16 a2d(char ch,char mode)
{
unsigned int hi,lo;
int16 i=0;
unsigned int16 Adres=0,sum=0,max=0,low=0xFFFF,d_sample=0;
SET_ADC_CHANNEL(ch);
ADON=1;
WaitAdc:
GO=1;
delay_cycles(100);
Wait:
while(GO!=0); //Wait until conversion finishes
//goto Wait;
lo=ADRESL;
hi=ADRESH;
Adres = make16(hi,lo); //Create a 16 bit number
//Show_Values();
/*
if(mode==asymetry)
{
ADON=0;
return(Adres);
}
*/
if(mode==trimmer_)
{
while(!(i==63))
{
sum+=Adres;
i++;
goto WaitAdc;
//Read ADCH
}
i=0;
sum/=64;
Adres=sum;
}
if(mode==nobutton_)
{
while(i<600) //Points the times to accept ADC Result
//while(!(i==31))
{
if(Adres>=max)
max=Adres;
if(Adres<=low)
low=Adres;
i++;
goto WaitAdc;
//Read ADCH
}
//i=0;
//sum/=64;
Adres=max-low;
}
//Adres=sum;
//sum=0;
Adout2:
ADON=0;
//bit_clear(ADCON0,0);
return(Adres);
}
|
For the 18F2420
Code: |
#include "18F2420.h"
#include <string.h>
#include <stdlib.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOSTVREN,NOFCMEN,NOPBADEN //INTERNAL OSCILLATOR NO CLOCK //INTRC_IO
#use delay(clock=8000000)
#use rs232(baud=9600, parity=N,xmit=PIN_C6 ,rcv=PIN_C7,bits=8,ERRORS)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#define button_ 1
#define nobutton_ 0
#define asymetry 3
#define left 1
#define right 0
#bit relay =0xF81.7
#bit Led1 =0xF81.6
#bit Led2 =0xF81.5
#define UP_L 1
#define DOWN_L 2
#define UP_R 3
#define DOWN_R 4
#define UP 1
#define DOWN 0
#define dispOn 0
#define dispOff 1
#define ON 1
#define OFF 0
#define GREEK 1
void main(void)
{
char x=0;
unsigned int16 butt=0;
delay_ms(500);
init();
/*
disable_interrupts(GLOBAL);
while(1)
{
rms=a2d(2,nobutton_);
if(rms>787)
out1=ON;
else
if(rms<787)
out1=OFF;
}
*/
/*
Asymmetry_Flag=ON;
sd:
goto sd;
*/
//Sequence_Check();
loop:
rms=a2d(8,nobutton_);
Phase1=rms;
if(rms>787)
Led1=ON;
else
Led1=OFF;
printf("Phase1= %lu\n\r",Phase1);
goto loop;
}
//////////////////////////////////////////////////////////////////////////
void init(void)
{
//TRISIO=0;
//GPIO=0;
//CMCON=7;
PORTA=0;
PORTB=0;
PORTC=0;
TRISA=0b00111111;
TRISB=0b00001100; //All output
TRISC=0;
//TRISC=0b10000000; //with Rs 232 mode ON
//setup_adc( ADC_CLOCK_DIV_8 );
ADCON0=0b00000001; //initialize a/d //Για PIC18F2420
ADCON1=0b00000101; //Για PIC18F2420
ADCON2=0b10000101; //Για PIC18F2420
disable_interrupts(global);
return;
}
//////////////////////////////////////
////////////////////////////////////////////
int16 a2d(char ch,char mode)
{
unsigned int hi,lo;
int16 i=0;
unsigned int16 Adres=0,sum=0,max=0,low=0xFFFF;
SET_ADC_CHANNEL(ch);
ADON=1;
//bit_set(ADCON0,0);
//delay_ms(1);
WaitAdc:
GO=1;
//bit_set(ADCON0,2);
//output_high(Start); //Start Conversion
//delay_cycles(10);
Wait:
while(GO!=0); //Wait until conversion finishes
//goto Wait;
lo=ADRESL;
hi=ADRESH;
Adres = make16(hi,lo); //Create a 16 bit number
//Show_Values();
if(mode==button_)
{
while(!(i==63))
{
sum+=Adres;
i++;
goto WaitAdc;
//Read ADCH
}
i=0;
sum/=64;
Adres=sum;
}
if(mode==nobutton_)
{
while(i<600) //Points the times to accept ADC Result
//while(!(i==31))
{
if(Adres>=max)
max=Adres;
if(Adres<=low)
low=Adres;
i++;
goto WaitAdc;
//Read ADCH
}
//i=0;
//sum/=64;
Adres=max-low;
}
//Adres=sum;
//sum=0;
Adout2:
ADON=0;
//bit_clear(ADCON0,0);
return(Adres);
}
//////////////////////////////////////////////////////////////////////////
|
As you can see A/D routines are the same in both controllers. |
|
|
Matro Guest
|
|
Posted: Tue Apr 08, 2008 9:01 am |
|
|
In your codes I can't see nowhere neither a setup_adc_port() nor a setup_adc() - the only want that is present is commented -.
And you are surprised to have problems with ADC module...
Start by adding this "mandatory" setup lines, and please make your code understandable by removing all these carriage returns, and adding indentation and comments.
Matro. |
|
|
Ttelmah Guest
|
|
Posted: Tue Apr 08, 2008 9:55 am |
|
|
The settings are being done as if he was working in assembler....
By hand.
This is the first comment. It is like the man who owns a dog, and yet barks himself. You are using a compiler. Let _it_ do it's job. There is a lot of stuff 'missing' from what is posted, which makes it impossible to be sure what is wrong (none of the declarations for the bits you are using in the control registers etc..). However, the first thing to do, would be to write compiler code, and see what happens. So:
1) Get rid of the fast_io declarations, unless you need them.
2) 'init', then becomes:
Code: |
void init(void) {
setup_adc_ports(ALL_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
setup_comparator(NC_NC_NC_NC);
}
|
Most of the reading code, can be done with simply the read_adc function.....
However there are then the obvious problems:
First, when you change the ADC channel, you _must_ wait for the acquisition time of the chip, before triggering a read. At present, the code changes channel, and then immediately triggers the ADC (GO=1).
This will result in invalid values, depending on what voltage was on the last selected pin. I'd suspect this is part of the problem. This _will_ result in inaccurate readings on both chips.
Second, the code is not turning off the comparator module.
Best Wishes |
|
|
jojos
Joined: 30 Apr 2007 Posts: 64
|
|
Posted: Wed Apr 09, 2008 4:54 am |
|
|
Thank you again for your response.I solved my problem.You were all more than helpful. |
|
|
|
|
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
|