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

PIC12F683 with VRef in ADC [SOLVED]

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



Joined: 10 Mar 2020
Posts: 6

View user's profile Send private message

PIC12F683 with VRef in ADC [SOLVED]
PostPosted: Tue Mar 10, 2020 8:14 pm     Reply with quote

Hi!
I'm trying to make a code to use the lm35 with pic12f683, using Vref (AN1) = 1.2V (with potentiometer). For testing, I'm just trying to light a led when the temperature exceeds 27C. What could be wrong?

Code:

#include <12F683.h>
#device adc=10
#FUSES NOWDT, INTRC_IO, NOCPD, NOPROTECT, NOMCLR, PUT, NOBROWNOUT, NOIESO, NOFCMEN
#use delay(clock=4000000)

#use FIXED_IO( A_outputs=PIN_A5,PIN_A4,PIN_A3,PIN_A2)

void main(void) {
int aMask = 0x00;
int16 r;
int temp;
setup_adc_ports(sAN0|VSS_VREF);
setup_adc(ADC_CLOCK_INTERNAL);
setup_comparator(NC_NC);
setup_vref(TRUE); //I tried VREF_HIGH too
output_A(0);
while(TRUE){
 set_adc_channel(0);
 delay_us(50);
 r = read_adc();
 delay_us(50);
 temp = ((1,2 * r)/1023)*100;
  if (temp > 27){
  aMask = aMask | 0b00000100;
  output_a(aMask);
  }else{
  aMask = aMask & 0b11111011;
  output_a(aMask);
  }
 }
}


Hardware:

VREF-VSS = 1,2V => AN1
VDD-VSS = 4,77V
Led => AN2
.LM35 => AN0
.AN0-VSS = 0,38V

Thanks for the help!


Last edited by lcs on Thu Mar 12, 2020 6:16 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 10, 2020 11:03 pm     Reply with quote

1. The Vref module in the 12F683 is for the comparator, not the ADC.

2. The ADC allows you to use an External Vref on a pin. You have to
generate it. If your Vdd is constant, then you could just two resistors or
a trimpot to make a voltage divider and get the external Vref from that
circuit.

3. You can't use a Vref of 1.2v with the ADC. The minimum is 2.2v,
and the preferred minimum is 2.7v. See this section in the data sheet:
Quote:
TABLE 15-9: PIC12F683 A/D CONVERTER (ADC) CHARACTERISTICS

12F683 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/41211D_.pdf

4. If you decide to use the comparator instead of the ADC, here is
example code showing how to do that:
http://www.ccsinfo.com/forum/viewtopic.php?t=42946
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Mar 11, 2020 1:39 am     Reply with quote

Start with setup_vref.

This is wrong. This is _not_ for the ADC VREF. This sets up the internal
comparator VREF. This module sets up the comparator Vref as a level
of the supply. If you look in the .h file for the processor, the setup_vref
'mode' settings are VREF_LOW and VREF_HIGH or'ed with a number 0-15.
If you look in the data sheet for the Cvref module. section 8.11, tells you that
the comparator voltage reference has two ranges each with 16 levels. The
VREF_HIGH and VREF_LOW setting gives control of the ranges and the value
0-15 control the levels. However this is completely and totally for the
comparator _not_ the ADC.
So start by getting rid of this setting....

Then the second problem. ADC VREF. If you again check the data sheet
and look in the A/D converter (ADC) Characteristics. you find AD06
'Reference voltage'. This has values of 2.2 and 2.7V 'minimum'.
The value of 2.2v, is the absolute minimum value that the ADC can
use for the Vref. 2.7v is the minimum it can use and retain 1bit
accuracy. So you can not use 1.2v....

I see PCM_programmer has pointed out both problems while I've been
typing..... Smile

As a general 'comment', most of the PIC ADC's require a minimum of
about 2.5v for the Vref.
temtronic



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

View user's profile Send private message

PostPosted: Wed Mar 11, 2020 4:33 am     Reply with quote

along with the other comments....
this line...

setup_adc(ADC_CLOCK_INTERNAL);

is incorrect.
Have a look at table 9-1, ADC clock vc clock frequency...

you'll see that 'internal' is wrong for clk>4MHz.... you have 2 choices, /8 or /16.
I'll assume you used a 'Wizard' to come up with 'setup_adc(ADC_CLOCK_INTERNAL); ' ?
PIC rule #2... Never EVER trust Wizards.
lcs



Joined: 10 Mar 2020
Posts: 6

View user's profile Send private message

PostPosted: Wed Mar 11, 2020 6:53 pm     Reply with quote

Thanks for the answers.
I made some changes to my code, but the led doesn't turn on:

Code:

#include <12F683.h>
#device adc=10
#FUSES NOWDT, INTRC_IO, NOCPD, NOPROTECT, NOMCLR, PUT, NOBROWNOUT, NOIESO, NOFCMEN
#use delay(clock=4000000)

#use FIXED_IO( A_outputs=PIN_A5,PIN_A4,PIN_A3,PIN_A2,PIN_A1)

void main(void) {
int aMask = 0x00;
int16 r;
int temp;
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_adc_ports(sAN0|VSS_VREF);
setup_adc(ADC_CLOCK_DIV_8);
output_A(0);
while(TRUE){
 set_adc_channel(0);
 delay_us(50);
 r = read_adc();
 delay_us(50);
 temp = ((3 * r)/1023)*100;
  if (temp > 27){
  aMask = aMask | 0b00000100;
  output_a(aMask);
  }else{
  aMask = aMask & 0b11111011;
  output_a(aMask);
  }
 }
}


VREF-VSS = 3V => AN1
VDD-VSS = 4,5V
Led => AN2
.LM35 => AN0
.AN0-VSS = 0,30V
-------------
Curiosity:
I tried without VREF, configuring 3V in VDD with potentiometer. I used this code, and it didn't work either:

Code:

#include <12F683.h>
#device adc=10
#FUSES NOWDT, INTRC_IO, NOCPD, NOPROTECT, NOMCLR, PUT, NOBROWNOUT, NOIESO, NOFCMEN
#use delay(clock=4000000)

#use FIXED_IO( A_outputs=PIN_A5,PIN_A4,PIN_A3,PIN_A2,PIN_A1)

void main()
{
int aMask = 0x00;
int16 r;
setup_adc_ports(sAN0|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_16);
while(TRUE)
{
  set_adc_channel(0);
  delay_us(100);
  r=read_adc();
  delay_us(500);
  if (r > 0){
  aMask = aMask | 0b00000100;
  output_a(aMask);
  }else{
  aMask = aMask & 0b11111011;
  output_a(aMask);
  }
 }
}

VDD-VSS = 3V
Led => AN2
.LM35 => AN0
.AN0-VSS = 0,31V

Would it be a good option to try to manually configure the registers?
Thanks!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 11, 2020 8:06 pm     Reply with quote

Quote:
temp = ((3 * r)/1023)*100;

You're using integer math here. If 'r' is less than 341, you'll get 0 as the result.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Mar 12, 2020 1:02 am     Reply with quote

A simple set of maths to give a reasonable answer with your Vref would
be:

temp=(r*30)/100;

For 1C, this will give '1'. For 10C, 10 etc..

So at 20C, 0.2v in. ADC should read 0.2/(3/1024)=68. 68*30=2040. 2040/100
= 20.

Understand the ADC reads 1023, just below it's reference voltage, so the
division needed to get the ADC step is /1024, not /1023.
Use a 2.5v Vref. Then the conversion becomes

temp=(r*25)/100

and the actual resolution will be slightly better.

Also if you need to read below about 2 to 3C, you do need the -ve
pull down resistor on the signal.
lcs



Joined: 10 Mar 2020
Posts: 6

View user's profile Send private message

PostPosted: Thu Mar 12, 2020 5:41 am     Reply with quote

In the last code of my answer, I directly tested the ADC value ... Apparently, read_adc() did not return a value greater than 0. Is the Adc module having problems?
When I get home, I will test the conversion constants that have passed on to me.
temtronic



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

View user's profile Send private message

PostPosted: Thu Mar 12, 2020 6:51 am     Reply with quote

That could mean the LM34/35 sensor is defective or a shorted input to ADC pin.
In 3+ decades of using those LMs, I've never had a defective one.
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Mar 12, 2020 6:55 am     Reply with quote

In your original code, there is a major issue, you are setting the Vref pin
as an output. No. It needs to be an input. Input, and 3v.
Honestly get rid of the #use fixed_IO, and just use output_high/ output_low
on PIN_A2 for your test. It should always be high with the code as posted,
since unless the ADC input is totally shorted to 0v, you will always see
a value above 0.
Honestly better to use

#use delay(INTERNAL=4MHz)
lcs



Joined: 10 Mar 2020
Posts: 6

View user's profile Send private message

PostPosted: Thu Mar 12, 2020 6:16 pm     Reply with quote

The code finally worked! I thank everyone for their help and the time they spent helping me.
The changes:

Code:

#include <12F683.h>
#device adc=10
#FUSES NOWDT, INTRC_IO, NOCPD, NOPROTECT, NOMCLR, PUT, NOBROWNOUT, NOIESO, NOFCMEN
#use delay(INTERNAL=4MHz)

int16 r;
int temp;

void main()
{
set_tris_a(0b00000011);
setup_adc_ports(sAN0|VSS_VREF);
setup_adc(ADC_CLOCK_DIV_8);
while(TRUE)
{
  setup_adc_ports(sAN0|VSS_VREF);
  delay_us(100);
  r=read_adc();
  temp=(r*25)/100;
  delay_ms(500);
  if (temp > 27){
  output_high(pin_A2);
  }else{
  output_low(pin_A2);
  }
 }
}


Hardware:
VDD-VSS => 4,8V
AN0 => LM35 output
AN1 = 2,5V
AN2 =>Led

This experience added knowledge and now I can continue with the project. Thank you all!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 14, 2020 3:54 am     Reply with quote

Your code still has several problems:

1. You forgot to set the adc channel. You got away with it because the
channel select register bits default to 0. But it should be set.

2. There should be a 5us delay after setting the channel. This in the
12F683 data sheet in this section:
Quote:
EQUATION 9-1: ACQUISITION TIME EXAMPLE

3. You don't need to call setup_adc_ports() in the while() loop, because
it only needs to be called once, and you did that above the loop.

4. There is no reason to put a 100us delay after calling setup_adc_ports().
The delay should be done after calling set_channel_adc() as shown below in bold:
lcs wrote:
#include <12F683.h>
#device adc=10
#FUSES NOWDT, INTRC_IO, NOCPD, NOPROTECT, NOMCLR, PUT, NOBROWNOUT, NOIESO, NOFCMEN
#use delay(INTERNAL=4MHz)

int16 r;
int temp;

void main()
{
set_tris_a(0b00000011);
setup_adc_ports(sAN0|VSS_VREF);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0); // *** Add this line
delay_us(5); // *** Add this line

while(TRUE)
{
setup_adc_ports(sAN0|VSS_VREF); // *** Delete this line
delay_us(100); // *** Delete this line
r=read_adc();
temp=(r*25)/100;
delay_ms(500);
if (temp > 27){
output_high(pin_A2);
}else{
output_low(pin_A2);
}
}
}
temtronic



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

View user's profile Send private message

PostPosted: Sat Mar 14, 2020 4:27 am     Reply with quote

I'd also delete this line....
set_tris_a(0b00000011);


and let the compiler handle the I/O configuration.

Unless you NEED very,very fast I/O just use 'standard I/O, the compiler default.
In 3 decades of programming PICs, I've only needed set_tris.. and fast_io... 2 or 3 times. In each case is was early and for a custom interface with propriatory I/O. Once the 20MHz barrier was broken, 'speed' hasn'y been a problem.

Also
try to get into the habit of adding comments at the end of each line. While code looks obvious, now, for you... 3 days,or months from now you or a friend will wonder WHAT is this suppose to do ??
Comments don't take up any codespace and as long as you can type are easy to add.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 14, 2020 9:37 am     Reply with quote

I agree it's not necessary for his program to work, but one reason for
including that line is if he doesn't want floating inputs on the unused pins.

He is not setting the output level for each pin, but the GPIO register bits
default to 0 at power-up, except pin A3 (input-only) and pin A5.
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