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 CCS Technical Support

VREF not working on 16F1936

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
nailuy



Joined: 21 Sep 2010
Posts: 159

View user's profile Send private message

VREF not working on 16F1936
PostPosted: Sat Jul 19, 2014 4:38 am     Reply with quote

Hy team I have problem by setting vref.
I try many sources of vref but not working.
I set value at input pin AN12/ B0: 0,339V and on display show 26 for 8bit, and 106 for 10bit ADC.
I try to change VREF to have better amplifier at this value but I can't.
Can someone help me? to understand why not working, or where is my mistake?
Voltage of VDD to VSS is 4.98V
Version of CCS 4.140.
Best regards.

Code:
void main()
{
   port_E_pullups(0xFF);
   setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12);
//   setup_adc(ADC_CLOCK_DIV_4);   //2,4,8,16,32,64
   setup_adc(ADC_CLOCK_INTERNAL );
   setup_vref(VREF_ADC_1v024);   //1v024, 2v048, 4v096
//   setup_vref(VREF_VDD);
   setup_lcd(LCD_DISABLED);


   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
   setup_oscillator(OSC_1MHZ|OSC_TIMER1|OSC_PLL_OFF,0);

LCD_INIT_1();
//LCD_SEND_C(%u,asd);
//LCD_SEND ("" %,asd);
//printf(LCD_SEND_C,"=%uV",123);

static unsigned int16 TIMER_LED, VAL;

while(TRUE)
{
   TIMER_LED++;

//LCD_SEND_C
output_bit(ONBK,1);
//output_bit(LED,0);

set_adc_channel( 12 );
delay_us(30);
VAL = read_adc();
set_adc_channel( 10 );


switch (TIMER_LED) {
   case 100: output_bit(LED,0);
      break;
   case 300: output_bit(LED,1);
      TIMER_LED=0;
      printf(LCD_SEND_C,"%4Lu",VAL);
      LCD_DATA_3=0;                   
      break;
   default: ;
      break; }


}
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sat Jul 19, 2014 7:53 am     Reply with quote

A lot of things....

First what is the minimum Vref the ADC is rated to use?. Parameter AD06 in the data sheet.

Then, though yours is one of the (few) chips which does not say _not_ to use ADC_CLOCK_INTERNAL, unless the CPU is put to sleep during the reading, you do still get better accuracy using the divided CPU clock. Fosc/2 at your clock rate. You have FOSC/4 selected in a remark, but not used.

Then get out of the habit of declaring variables mid code. This is 'borderline'. CCS accept it, but it is not legal in traditional C, and unfortunately has the habit of leading to 'sneaky' errors.

Then you enable channels 1,2,3,4 & 12 to the multiplexer, but later select adc_channel 10.....

Then the killers with the FVR....
Code:

   setup_adc(ADC_CLOCK_DIV_2|VSS_FVR);   //Reference needs to be used..
   setup_vref(VREF_ADC_2v024|VREF_ON);   //needs to be turned on....
nailuy



Joined: 21 Sep 2010
Posts: 159

View user's profile Send private message

PostPosted: Sat Jul 19, 2014 1:07 pm     Reply with quote

Thank you Ttelmah.

First what is the minimum Vref the ADC is rated to use?. Parameter AD06 in the data sheet.
Let say is 4,096V
Code:
 setup_vref(VREF_ADC_4v096|VREF_ON);   //1v024, 2v048, 4v096

Then, though yours is one of the (few) chips which does not say _not_ to use ADC_CLOCK_INTERNAL, unless the CPU is put to sleep during the reading, you do still get better accuracy using the divided CPU clock. Fosc/2 at your clock rate. You have FOSC/4 selected in a remark, but not used.
Now I use
Code:
setup_adc(ADC_CLOCK_DIV_4|VSS_FVR);

Then you enable channels 1,2,3,4 & 12 to the multiplexer, but later select adc_channel 10.....

I know this I want to use to be sure that conversion exist because if I select this channel 10 result are 0 or 1, this model not support this.

At the final this solution is not working :(
Vref is at VDD, at 255 I have 4,98V on input CH1, or 100 at 1,831V :(
Code:

   setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12);
   setup_adc(ADC_CLOCK_DIV_4|VSS_FVR);   //2,4,8,16,32,64
   setup_vref(VREF_ADC_4v096|VREF_ON);   //1v024, 2v048, 4v096
temtronic



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

View user's profile Send private message

PostPosted: Sat Jul 19, 2014 1:56 pm     Reply with quote

Actually it is working, though without seeing your complete program makes it hard for us to see where you think there is a problem.

1) you've selected a Vref of 4.096 volts,so FSD will be 4.096 volts
2) you supply 5.00 to the ADC and get back 255 bits = 4.98 volts. That's actually a good result as FSD is 4.096, so 5.00 is 'overrange' of the ADC.

3) 100 bits with Vref of 4.096 is about 1.6 volts and you display 1.8. We don't know how you're converting ADC bits to display as 'real volts'.

Please show us your current program that gave those results.
Also you should read the raw Vin say 8 times and average it to reduce any 'glitch' or 'erroneous' readings.


hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sat Jul 19, 2014 2:13 pm     Reply with quote

and as one more comment, you risk destroying the chip.

The analog input must not go more than 0.3v above Vref.

Also the accuracy of the internal ref, is only +/-6%, and the ADC, +/-2.5 counts, so for an input of (say) 2.048 volts, you could get readings from different chips/temperatures etc., between 117 counts, and 138 counts. It is also very unlikely that the voltage you measure really 'is' 1.831v, unless you have a better than 0.1% DVM, that has been calibrated in the last few days....
nailuy



Joined: 21 Sep 2010
Posts: 159

View user's profile Send private message

PostPosted: Sat Jul 19, 2014 3:08 pm     Reply with quote

I don't upset anybody but is my code made for LCD and problem is not from there so I can't post.
I copy from LST file.
Code:
....................    setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12);
022A:  BCF    1E.0
022B:  BCF    1E.1
022C:  BCF    1E.2
022D:  MOVLW  2E
022E:  MOVLB  03
022F:  MOVWF  0C
0230:  MOVLW  01
0231:  MOVWF  0D
....................    setup_adc(ADC_CLOCK_DIV_4|VSS_FVR);   //2,4,8,16,32,64
0232:  MOVLB  01
0233:  BCF    1E.4
0234:  BCF    1E.5
0235:  BSF    1E.6
0236:  BCF    1E.7
0237:  BSF    1D.0
....................    setup_vref(VREF_ADC_2v048|VREF_ON);   //1v024, 2v048, 4v096
0238:  MOVLW  82
0239:  MOVLB  02
023A:  MOVWF  17

I look forward for solution also I search on web and in data sheet for this bug.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Jul 20, 2014 1:45 am     Reply with quote

The parameter in bold is in the wrong place:
Quote:
setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12);
setup_adc(ADC_CLOCK_DIV_4 | VSS_FVR);
setup_vref(VREF_ADC_4v096|VREF_ON);

According to the 16F1936.h file, it's supposed to go in setup_adc_ports(),
like this:
Code:
setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12|VSS_FVR);


However, it doesn't produce the correct ASM code in the .LST file.
So I wrote a macro to replace the built-in setup_adc_ports() function.
See the code below:
Code:

#include <16F1936.H>
#fuses INTRC_IO, BROWNOUT, PUT, NOLVP
#use delay(clock = 4M)
#use rs232(baud=9600, UART1, ERRORS)

//--------------------------------------
// This macro will replace the built-in setup_adc_ports()
// function which is not setting the ADPREF and ADNREF
// bits correctly.  The macro fixes that problem.

#byte ANSELA = getenv("SFR:ANSELA")
#byte ANSELB = getenv("SFR:ANSELB")
#byte ADCON1 = getenv("SFR:ADCON1")
#bit ADPREF0 = ADCON1.0
#bit ADPREF1 = ADCON1.1
#bit ADNREF  = ADCON1.2

#define setup_adc_ports(x)   \
ANSELA = make8(x, 3);        \
ANSELB = make8(x, 1);        \
(make8(x, 0) & 1) ? (ADPREF0 = 1) : (ADPREF0 = 0); \
(make8(x, 0) & 2) ? (ADPREF1 = 1) : (ADPREF1 = 0); \
(make8(x, 0) & 4) ? (ADNREF = 1) : (ADNREF = 0);
//--------------------------------------


//==================================
void main()

setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12|VSS_FVR);

setup_adc(ADC_CLOCK_DIV_4);   
setup_vref(VREF_ADC_2v048|VREF_ON);   

while(1);
}

Try that code and see if it fixes the problem. I don't have time tonight
to test it in hardware. If it doesn't work, I can do that tomorrow.
nailuy



Joined: 21 Sep 2010
Posts: 159

View user's profile Send private message

PostPosted: Sun Jul 20, 2014 4:54 am     Reply with quote

Thank you PCM programmer
I tried today and is working, your asm code is okay, now I try to learn how you do that to understand where is problem with data sheet.
Code:
setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12|VSS_FVR);

This is correct syntax like you posted is written in header file.
Thanks again.
Now let's study this asm code.
If I have future question I will post in this thread.
Best regards.
Nailuy.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Aug 05, 2014 10:53 am     Reply with quote

CCS tech support says it's not actually a bug. Instead, the Vref parameter
should be separated from the sANx parameters by a comma. Example:
Code:
setup_adc_ports(sAN1|sAN2|sAN3|sAN4|sAN12, VSS_FVR);

This is in fact documented in the manual.

So, forget my work-around. It's not necessary. Do it as shown above.
nailuy



Joined: 21 Sep 2010
Posts: 159

View user's profile Send private message

PostPosted: Tue Sep 02, 2014 1:28 pm     Reply with quote

Yes is working until now.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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