View previous topic :: View next topic |
Author |
Message |
beaker404
Joined: 24 Jul 2012 Posts: 163
|
PIC18F87K22 ADC |
Posted: Tue Apr 23, 2019 4:08 pm |
|
|
datasheet says 12ADC. read the device .H file, no config for ADC resolution.
setting up like this:
Code: | setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_0); // set up ADC
setup_adc_ports(sAN0|VSS_VDD); |
and calling like this for AN0:
Code: | set_adc_channel(0);
delay_us(50);
adc_value = read_adc(); |
adc_value is in INT16
ADC seems to be running at 8 bit resolution. for a 0.775V input to AN0, i get a value of 40 decimal returned.
Not clear on how to set the negative side of AN0 to ground, did not see how to do that in the .H file. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Tue Apr 23, 2019 4:09 pm |
|
|
Oh, CCS V5.064
windows 10
pic is running at 40MHz |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 23, 2019 5:59 pm |
|
|
Look in the read_adc() section of the CCS manual. You use a #device
statement to set the number of bits.
Vss is ground.
Quote: | setup_adc_ports(sAN0|VSS_VDD); |
|
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 7:37 am |
|
|
Yep, setting to 12 bit resolved the problem YESTERDAY.
for some reason, I thought 12 Bit was the only option.
today, though, back to getting an 8 bit range number even though adc is set for 12 bit the proper voltage is going to the ADC port too. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 8:14 am |
|
|
ADC is returning -24279 when in 12 bit mode. if I comment out the #device adc=12 line it returns a 41
Code: | setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_0); // set up ADC
setup_adc_ports(sAN0|VSS_VDD); // only AN0 is analog port with range of 0 - 5VDC |
Code: | set_adc_channel(0);
delay_us(50);
adc_value = read_adc();
//value = (int)(((adc_value/4096.0)*5.0)/0.01); // convert ADC to degrees F cast to INT to save space only need INT precision
value = (int)adc_value;
|
commented out line is so I can see the ADC value as it is read in. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Thu Apr 25, 2019 8:58 am |
|
|
-24279. No it isn't....
It is returning an _unsigned_ integer, but you are printing it as signed.
If you use #DEVICE ADC=12
you can't cast this to an 'int'. Casting just forces a byte to be treated 'as if'
it was the target type. It'll truncate the top part and result in numeric errors.
Now you are performing your maths with float. result huge amount of
wasted code size. The maths itself seems 'wrong'. /0.01 is the same as
*100 (which would be faster...), but you have a voltage 0 to 5 feeding
this part of the maths so would get 0 to 500.
The way to do this is work in integer:
Assuming adc_value is declared as an int16 (which it needs to be if
the ADC is set to 12bit output):
value = ((int32)adc_value*500)/4096;
Would give the same result as your current sum, just using int32
arithmetic. You are multiplying by 5, and by 100, and dividing by 4096.
In integer do the multiplications first to avoid working with fractions. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 25, 2019 9:10 am |
|
|
beaker404 wrote: | ADC is returning -24279 when in 12 bit mode. if I comment out the #device adc=12 line it returns a 41 |
What voltage are you applying to the adc input pin, that gives this result ?
beaker404 wrote: | ADC is returning -24279 when in 12 bit mode. if I comment out the #device adc=12 line it returns a 41 |
What method are you using to display the ADC result ?
I don't see a printf statement in your posted code. If you're using printf,
post that line. Are you using the debugger ? If so, what debugger,
hardware or MPLAB Sim ? Also, what version of MPLAB ?
beaker404 wrote: |
//value = (int)(((adc_value/4096.0)*5.0)/0.01); // convert ADC to degrees F cast to INT to save space only need INT precision
value = (int)adc_value;
commented out line is so I can see the ADC value as it is read in. |
If you cast to an 'int', you are casting to an 8-bit value (with the PCH
compiler). The compiler throws away all upper bits. For example, if
your adc result is 0x1234, after a cast to 'int', you will get 0x0034. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 9:13 am |
|
|
I understand your reasoning for the math.
the 0.01 comes into play to scale the voltage calculation to deg F.
still do not understand why I cannot print the ADC counts today and yesterday I could.
Just not getting the same numbers as yesterday. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 9:36 am |
|
|
fprintf(SERIAL,"** DEG F= %Lu#\n\r",adc_value);
prints as 41257
this is the number from the adc_read should be 635 |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 9:52 am |
|
|
no sim or debugger, just running PIC and looking at results on hyperterminal.
MPLAB V 8.91 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 25, 2019 10:06 am |
|
|
beaker404 wrote: | fprintf(SERIAL,"** DEG F= %Lu#\n\r",adc_value);
prints as 41257
this is the number from the adc_read should be 635 |
What is the input voltage (measured on the ADC pin with a scope) that
gives that value ? |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 10:08 am |
|
|
0.775V on the pin and that is the same as from the temperature sensor. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 10:15 am |
|
|
moved voltage to AN1 and get the same result, perhaps the ADC is shot? was working last night when I left, this morning turned it on and this happened.
cleaning people were in the office last night and stuff always gets moved around with them around. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 25, 2019 10:22 am |
|
|
I note that 41257 / 64 = 645. Just a preliminary observation.
Can you post the top several lines of your program ? I want to see the
#device adc statement, and the #fuses, and the #use delay(). |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 25, 2019 10:52 am |
|
|
ye did that math too for the magical 64 number.
Code: | /*
*********************************************************************************************
* INCLUDES and CONTROLLER SETTINGS
*********************************************************************************************
*/
#DEVICE PIC18F87K22
#DEVICE ADC=12
#include <18F87K22.h>
#include <stdlib.h>
#FUSES HSH // UP TO 25MHZ CRYSTAL.
#FUSES NOEBTRB
#FUSES NOEBTR
#FUSES NOWRTD
#FUSES NOWRTB
#FUSES NOPROTECT
#FUSES NOCPB
#FUSES NOCPD
#FUSES NOWRT
#FUSES NODEBUG
#FUSES NOSTVREN
#FUSES NOMCLR
#FUSES NOWAIT
#FUSES NOWDT
#FUSES NOIESO
#FUSES PUT // enable power up timer delay
#FUSES NOBROWNOUT
#FUSES NOFCMEN
#FUSES NOPLLEN
#USE delay(CRYSTAL=10000000, CLOCK=40000000)
#USE rs232(UART1,baud=38400, xmit=PIN_C6,rcv=PIN_C7,STREAM=SERIAL,errors)
#USE SPI(MASTER, MODE=0, SPI1, STREAM=SPI,FORCE_HW)
|
|
|
|
|