CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

ADC does not work with external reference
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
POPE19



Joined: 27 Jun 2017
Posts: 71

View user's profile Send private message

ADC does not work with external reference
PostPosted: Fri Jul 28, 2017 6:40 am     Reply with quote

Hello friends,

I am newbie to this field. I want to use PIC16F914 for ADXL335 (Analog accelerometer). I am using 40-pin PDIP microcontroller. I am using external reference volts VREF+ applied to pin 5 (RA3) as per instruction in datasheet. I am using 20 MHz oscillator as external clock. When I put my accelerometer flat on table i get reading 335 with 5v VREF+, however it doesn't change with VREF+ = 3.3 volt. I am giving external reference volts from a 5/3.3V Voltage regulator. Why is the reading same ? I have also tried applying a potentiometer from the output of 5V voltage regulator and applying VREF+ volts from 4.94 to 2 Volts. But the readings are still same without any changes. I am using CCS PCWH 5.074 compiler.

Below is my code:
Code:

//============================================================================//
//                         Inclinometer                                       //
//                         Date: 7-24-2017                                    //
//                                                                            //
//============================================================================//
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
#define VSS_VREF

//============================================================================================//
//===========================================================================================//
//                                 LCD Configuration                                        //
//==========================================================================================//
// Digit segments  A           B         C          D           E         F         G          DP
//                 b7          b6        b5         b4          b3        b2        b1         b0
#define DIGIT5  COM0+17,   COM1+17,   COM2+17,   COM3+17,   COM2+18,   COM0+18,   COM1+18,   COM3+18
#define DIGIT4  COM0+3,    COM1+3,    COM2+3,    COM3+3,    COM2+2,    COM0+2,    COM1+2,    COM3+2
#define DIGIT3  COM0+1,    COM1+1,    COM2+1,    COM3+1,    COM2+0,    COM0+0,    COM1+0,    COM3+0
#define DIGIT2  COM0+19,   COM1+19,   COM2+19,   COM3+19,   COM2+20,   COM0+20,   COM1+20,   COM3+20
//       ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
//=======================================================================================//
//           character          0    1    2    3    4    5    6    7    8    9  Null
byte const Digit_Map[11]   = {0xFD,0x61,0xDB,0xF3,0x67,0xB7,0xBF,0xE1,0xFF,0xF7,0x01}; //Decimal

byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00}; //no Decimal

//=======================================================================================//
//                          Segments Initialization                                       //
// Seg23 Seg22  ...  Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0 //
//  0/1   0/1   0/1   0/1   0/1   0/1  0/1  0/1   0/1  0/1 0/1   0/1 0/1  0/1  0/1   0/1 //
//  if bit_SegX is 1, SegX is set as Segment Output. Otherwise                           //
////=====================================================================================//

#define Segments 0x1E000F    // Initialize LCD SegmentX

//============================================================================//

#define INTS_PER_SECOND     19      // (20000000/(4*256*256)) (used quarter_seconds)

int int_count=INTS_PER_SECOND;


int count5 = 0;// after decimal
int count_5 = 0;
int count4=0;   // 1st digit
int count_4=0;   // 1st digit
int count3=0;   // 2nd digit
int count_3=0; 
int count2=0;   // 3rd digit
int count_2=0;
long seconds=0;
long reading;

#int_rtcc               //This function is called

//============================================================================//
void clock_isr()
{                       //every time the RTCC (timer0)
                        //overflows (255->0)
                        //For this program this is apx
                        //31 times per second.

   if(--int_count==0)
   {
      seconds++;
      int_count=INTS_PER_SECOND;
   }
}
//============================================================================//
void Disp_num()
{
   if(reading < 10)
   {
      count_5=reading;
      count_2=11;
      count_3=11;
      count_4=11;
   }
   
   if(10<= reading < 100)
   {
     count_5=reading%10;
     count_4=reading/10;
     count_3=11;
     count_2=11;
   }
   
   if(100 <= reading <999)
   {
     count_5=reading%10;
     count_4=reading%100/10;
     Count_3=reading%1000/100;
     count_2=11;
   }
   if(1000 <= reading < 1024)
   {
     count_5=reading%10;
     count_4=reading%100/10;
     Count_3=reading%1000/100;
     count_2=reading%10000/1000;
   }
   if(reading >= 1024)
   {
       count_5=11;
       count_4=11;
       count_3=11;
       count_2=11;
   }
}
//=============================================================================//
void sec_disp()
{
   count4=count_4;
   count5=count_5;
   count2=count_2;
   count3=count_3;
   
}
//============================================================================//
void Display()
{
   lcd_symbol (Digit_Map_1[count5], DIGIT5);
   lcd_symbol (Digit_Map[count4], DIGIT4);
   lcd_symbol (Digit_Map_1[count3], DIGIT3);
   lcd_symbol (Digit_Map_1[count2], DIGIT2);
     
}
//============================================================================//
void Digit()
{
      if(seconds>=1)
      {
     
         reading = read_adc();
         
         seconds=0;
      }
}
//===========================================================================//
void main()
{
   set_tris_a (0xdf);
   set_tris_b (0xc0);
   set_tris_c (0x07);
   
   setup_adc_ports(sAN0);
   setup_adc (ADC_CLOCK_INTERNAL);
   set_adc_channel (0);

   set_rtcc(0);
   setup_counters (RTCC_INTERNAL, RTCC_DIV_256);

   enable_interrupts (INT_RTCC);
   
   enable_interrupts(GLOBAL);
   
   setup_lcd(LCD_MUX14|LCD_STOP_ON_SLEEP,3, Segments); // set segments
 
   count5 = 8;
   count4 = 8;
   count3 = 8;
   count2 = 8;
 
   Display ();
   
   delay_ms (1000);
 
     
   while (TRUE)  /* Modify on 9/19/2012 */
   {
       
      digit();     
      Disp_num();
      sec_disp();
      display();
     
    }

   
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 7:19 am     Reply with quote

Code:

   setup_adc_ports(sAN0 | VSS_VREF);
//You are not selecting to use the Vref...
//This is the setting to use Vref+, with Vss for the -
   setup_adc (ADC_CLOCK_DIV_32);
//Internal is not recommended above 1MHz, unless you put
//the chip to sleep for the conversion....
   set_adc_channel (0);


Wrong ADC clock, and you are not selecting to use the Vref
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 7:39 am     Reply with quote

Quote:
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
#define VSS_VREF
Also, remove the line in bold above. That constant is defined in the
16F914.h file. You should not #define it in your own program.
And, since you have defined it to be nothing, you will get this error:
Quote:
*** Error 51 A numeric expression must appear here
Remove that line.


Quote:

#int_rtcc //This function is called

//==========================================//
void clock_isr()
{ //every time the RTCC (timer0)
//overflows (255->0)
//For this program this is apx
//31 times per second.

if(--int_count==0)
{
seconds++;
int_count=INTS_PER_SECOND;
}
}

The #int_rtcc line should not be floating around above the isr routine.
It's an integral part of the routine and should be placed above the
isr function declaration, like this:
Code:

//============================================//
#int_rtcc               
void clock_isr()
{                       //every time the RTCC (timer0)
                        //overflows (255->0)
                        //For this program this is apx
                        //31 times per second.

   if(--int_count==0)
   {
      seconds++;
      int_count=INTS_PER_SECOND;
   }
}
POPE19



Joined: 27 Jun 2017
Posts: 71

View user's profile Send private message

ADC does not work with external reference
PostPosted: Fri Jul 28, 2017 9:22 am     Reply with quote

thanks Ttelmah & PCM Programmer

I have made recommended correction. Here is what i observed the ADC reading does not change. i.e analog output of ADXL 335 is 1.637 volt. Now if we convert it with 5V ref then we should get 334 ADC value which i am getting 331.

If i select VREF+ = 3.3 volts i should get around 559 ADC value, which i am not.
Also the Datasheet on page 177 says for ADC clock period (TAD) to select ADC Clock Source. I have selected FRC because page 183 says that TACQ (acquisition time) should be greater than 4.67 us. Am i missing something? Please enlighten.

My modified code is as follows
Code:

//============================================================================//
//                         Inclinometer                                       //
//                         Date: 7-24-2017                                    //
//                                                                            //
//============================================================================//
#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)



//============================================================================================//
//===========================================================================================//
//                                 LCD Configuration                                        //
//==========================================================================================//
// Digit segments  A           B         C          D           E         F         G          DP
//                 b7          b6        b5         b4          b3        b2        b1         b0
#define DIGIT5  COM0+17,   COM1+17,   COM2+17,   COM3+17,   COM2+18,   COM0+18,   COM1+18,   COM3+18
#define DIGIT4  COM0+3,    COM1+3,    COM2+3,    COM3+3,    COM2+2,    COM0+2,    COM1+2,    COM3+2
#define DIGIT3  COM0+1,    COM1+1,    COM2+1,    COM3+1,    COM2+0,    COM0+0,    COM1+0,    COM3+0
#define DIGIT2  COM0+19,   COM1+19,   COM2+19,   COM3+19,   COM2+20,   COM0+20,   COM1+20,   COM3+20
//       ComX+Y is combination of Backplan0-3 and Segment0-SegmentXX
//=======================================================================================//
//           character          0    1    2    3    4    5    6    7    8    9  Null
byte const Digit_Map[11]   = {0xFD,0x61,0xDB,0xF3,0x67,0xB7,0xBF,0xE1,0xFF,0xF7,0x01}; //Decimal

byte const Digit_Map_1[11] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0x00}; //no Decimal

//=======================================================================================//
//                          Segments Initialization                                       //
// Seg23 Seg22  ...  Seg12 Seg11 Seg10 Seg9 Seg8 Seg7 Seg6 Seg5 Seg4 Seg3 Seg2 Seg1 Seg0 //
//  0/1   0/1   0/1   0/1   0/1   0/1  0/1  0/1   0/1  0/1 0/1   0/1 0/1  0/1  0/1   0/1 //
//  if bit_SegX is 1, SegX is set as Segment Output. Otherwise                           //
////=====================================================================================//

#define Segments 0x1E000F    // Initialize LCD SegmentX

//============================================================================//

#define INTS_PER_SECOND     76      // (20000000/(4*256*256))

int int_count=INTS_PER_SECOND;


int count5 = 0;// after decimal
int count_5 = 0;
int count4=0;   // 1st digit
int count_4=0;   // 1st digit
int count3=0;   // 2nd digit
int count_3=0; 
int count2=0;   // 3rd digit
int count_2=0;
long seconds=0;
long reading;


//============================================================================//

#int_rtcc               //This function is called
void clock_isr()
{                       //every time the RTCC (timer0)
                        //overflows (255->0)
                        //For this program this is apx
                        //31 times per second.

   if(--int_count==0)
   {
      seconds++;
      int_count=INTS_PER_SECOND;
   }
}
//============================================================================//
void Disp_num()
{
   if(reading < 10)
   {
      count_5=reading;
      count_2=11;
      count_3=11;
      count_4=11;
   }
   
   if(10<= reading < 100)
   {
     count_5=reading%10;
     count_4=reading/10;
     count_3=11;
     count_2=11;
   }
   
   if(100 <= reading <999)
   {
     count_5=reading%10;
     count_4=reading%100/10;
     Count_3=reading%1000/100;
     count_2=11;
   }
   if(1000 <= reading < 1024)
   {
     count_5=reading%10;
     count_4=reading%100/10;
     Count_3=reading%1000/100;
     count_2=reading%10000/1000;
   }
   if(reading >= 1024)
   {
       count_5=11;
       count_4=11;
       count_3=11;
       count_2=11;
   }
}
//=============================================================================//
void sec_disp()
{
   count4=count_4;
   count5=count_5;
   count2=count_2;
   count3=count_3;
   
}
//============================================================================//
void Display()
{
   lcd_symbol (Digit_Map_1[count5], DIGIT5);
   lcd_symbol (Digit_Map[count4], DIGIT4);
   lcd_symbol (Digit_Map_1[count3], DIGIT3);
   lcd_symbol (Digit_Map_1[count2], DIGIT2);
     
}
//============================================================================//
void Digit()
{
      if(seconds>=1)
      {
     
         reading = read_adc();
         
         seconds=0;
      }
}
//===========================================================================//
void main()
{
   set_tris_a (0xdf);
   set_tris_b (0xc0);
   set_tris_c (0x07);
   
   setup_adc_ports(sAN0 | VSS_VREF);
   setup_adc (ADC_CLOCK_DIV_32);
   set_adc_channel (0);

 
   set_rtcc(0);
   setup_counters (RTCC_INTERNAL, RTCC_DIV_256);

   enable_interrupts (INT_RTCC);
   
   enable_interrupts(GLOBAL);
   
   setup_lcd(LCD_MUX14|LCD_STOP_ON_SLEEP,3, Segments); // set segments
 
   count5 = 8;
   count4 = 8;
   count3 = 8;
   count2 = 8;
 
   Display ();
   
   delay_ms (1000);
 
     
   while (TRUE)  /* Modify on 9/19/2012 */
   {
       
      digit();     
      Disp_num();
      sec_disp();
      display();
     
    }

   
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 11:19 am     Reply with quote

Tacq, is the period between selecting the channel, and taking a reading, or the time between successive readings. The 'acquisition time'.
It's the time the internal capacitor takes to charge to within 0.5bit of the actual value.
It's not Tad, which is the clock rate of the ADC.

What is your compiler version number?.

Need to check if your version is correctly selecting the Vref option.

334 Vs 331, may well be that the 5v on the chip is not actually 5v, or a little noise.
POPE19



Joined: 27 Jun 2017
Posts: 71

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 11:27 am     Reply with quote

i am using CCS PCWH Compiler version 5.074
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 12:34 pm     Reply with quote

Quote:
setup_adc_ports(sAN0 | VSS_VREF);

According to the 16F914.h file, a comma should be used as the separator
between those two parameters, as shown below:
Code:
setup_adc_ports(sAN0, VSS_VREF);

However, that didn't fix it for me. I'm testing with a 16F917. I'm getting
334 with a 3.3v Vref+, and a 1.64v input voltage on AN0. That's incorrect.

I then stuck in a 16F1937 and it worked. I got 501 with 1.64v input
with a 3.3v Vref+.

I'm still working on it. Not sure what to try next.
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 12:56 pm     Reply with quote

Yes, but it doesn't make any difference.

The | syntax was the old syntax (before the days of CCS supporting overloaded functions). For many dozens of compiler versions now, they have supported the use instead of an optional second parameter (as you show). However for 'reverse compatibility', they still support the | syntax as well.

I looked into this a while ago, and keep trying to remember to switch to the new syntax, but still tend to type the older form... Embarassed

Have you tried going back to an older compiler?. If not, I'll try this later. Have used this chip, and am sure it was working, but it was a while ago. Have a nasty feeling that something has got missed in an upgrade.
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 2:00 pm     Reply with quote

OK.

It's incorrectly setting the VCFG bits....
With VSS_VREF selected it should give 10 in these bits. Instead it gives 01...

The two defines are reversed in the .h file.
Code:

#include <16F914.h>
#device ADC = 10
#fuses HS, MCLR, NOWDT, PUT, NOIESO, BROWNOUT, NOFCMEN
#use delay(clock=20000000)
#use RS232 (UART1, baud=9600, ERRORS)
#undef VSS_VREF
#undef VREF_VDD
#define VSS_VREF              0x4000    //| Range 0-VrefH
#define VREF_VDD              0x2000    //| Range VrefL-Vdd
//===========================================================================//
void main()
{
 
   setup_adc_ports(sAN0 ,VSS_VREF);
   setup_adc (ADC_CLOCK_DIV_32);
   set_adc_channel (0);
     
   while (TRUE)  /* Modify on 9/19/2012 */
   {
     
      delay_us(500); 
      printf("ADC=%ld\r\n", read_adc());
     
   } 
}

Set up to do a simple serial test, this gives the correct readings.
POPE19



Joined: 27 Jun 2017
Posts: 71

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 2:29 pm     Reply with quote

Ok I will give a try and will let you know once I test it. Thanks again Ttelmah.
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 3:15 pm     Reply with quote

What is amusing, is that nobody has spotted this before!...
I went back about 10 versions and it is still wrong. :(
temtronic



Joined: 01 Jul 2010
Posts: 9102
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 4:35 pm     Reply with quote

too many PICs,
too many pins,
too many peripherals.....
I can understnad why it hasn't been caught until now....

sigh, life is too short to try everything on every PIC !!
Very Happy
POPE19



Joined: 27 Jun 2017
Posts: 71

View user's profile Send private message

PostPosted: Fri Jul 28, 2017 4:46 pm     Reply with quote

Quick question .

I think the header file is right because according to data sheet if you look to page 180 it says that VCFG1 is (1 for VREF+ and 0 for Vss ) & VCFG0 is ( 1- for VREF- & 0 for VSS ).

In my case I am choosing VREF+ as positive peak and VSS as ground reference. In that case won't the bit B5 is 1 (VCFG0) & bit B6 is 0 (VCFG1) make it 0x2000 ?

Please suggest
Ttelmah



Joined: 11 Mar 2010
Posts: 19219

View user's profile Send private message

PostPosted: Sat Jul 29, 2017 1:12 am     Reply with quote

You want VCFG1 to be for Vref+. So '1'. VCFG0 to be for Vss, so '0'.
10 in the two bits.

I tested with the change, and the voltage read correctly.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 29, 2017 5:01 am     Reply with quote

I tested it on a 16F917 and it didn't work for me.

The 16F917 data sheet shows that VCFG1 is for the Vref- pin.

PIC16F913/914/916/917/946
DS41250F-page 180
http://ww1.microchip.com/downloads/en/DeviceDoc/41250F.pdf

From page 180 (page 182 in the Adobe reader):
Code:

REGISTER 12-1: ADCON0: A/D CONTROL REGISTER 0

bit 6 VCFG1: Voltage Reference bit
1 = VREF- pin
0 = VSS

bit 5 VCFG0: Voltage Reference bit
1 = VREF+ pin
0 = VSS
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
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