Today I spent most of my day chasing an anomaly in my project that involved 3 analog inputs on a PIC 16F1847... and to which I had found a workaround, but not sure if it is something I would use when I release my code for production use.
The details:
- - The analog signals come in through channels AN0, AN1 and AN4.
- - The code reads these voltages through component macros (via the built-in GetInt functions) and use their readings to trip safety features in the software (if conditions are right).
- - To get the accuracy I needed I opted to use a 4.096V external reference IC on the VRef+ (AN3) pin of the PIC.
- - During code development I used three, 2D dash panel analog inputs (pots) with the following identical configurations: VRef voltage: 401, VRef option: Vref+, Conversion Speed: FRC, Aquisition cycles: 50, Bit Depth: 10
- - Tested the code using Flowcode's built-in simulation and was happy to see that all seemed to be OK.
- - Next, I downloaded the code to my prototype board and tested the main software features again and that is when I saw a large (20%+) discrepancy between the calculated and actual safety trip points.
So next, I did some calculations on the actual trip points and the voltages they supposed to trip at in real life and found that they correlate to the PIC's supply voltage (VDD), and not the external 4.096V reference. This prompted me to check the C code generated by Flowcode and tried to make some sense out of it all as I really did not know how it all worked behind the scenes.
Did not see anything bad so I have done some more digging, I found a file named "16F1847.fcdx" in the Flowcode package that had the following section in it, relating to the ADC of the 16F1847:
...
...<adc type='23' bits='10' >
<speed >
<option name='Fosc / 2' value='0' />
<option name='Fosc / 8' value='1' />
<option name='Fosc / 32' value='2' />
<option name='FRC' value='3' />
<option name='Fosc / 4' value='4' />
<option name='Fosc / 16' value='5' />
<option name='Fosc / 64' value='6' />
</speed>
<vref>
<option name='VDD' value='0' />
<option name='Vref+' value='2' />
<option name='FVR' value='3' />
</vref>
</adc>
Then, I had located the function call within my project's auto generated C code and saw that it looked strange as it was calling out a non-existing positive voltage reference option of "1", while according to the "16F1847.fcdx" file it should be calling a "2". So I had come to a conclusion that for some reason when I select "Vref+" as an option in the 2D dash panel analog input component, it is really selecting something else.
To figure it out, I reconfigured all three of my analog inputs with different settings and compiled a new C file again in which then I looked to see what pull-down menu options in the analog input component create what option number in the C code. Here are the results:
- AN0 --> 2D Dash Panel Settings --> VRef option: Vref+
Related C code function call: FC_CAL_ADC_Enable(0, 3, 1, 40);
- AN1 --> 2D Dash Panel Settings --> VRef option: VDD
Related C code function call: FC_CAL_ADC_Enable(1, 3, 0, 60);
- AN4 --> 2D Dash Panel Settings --> VRef option: FVR
Related C code function call: FC_CAL_ADC_Enable(4, 3, 2, 50);
The numbers we are interested in are the third ones in the parenthesis, which define the VRef+ option. From this and the code snippet from the file "16F1847.fcdx" above we can see that the two don't match.
In the fcdx file we get: VDD = 0, Vref+ = 2, FVR = 3,
while in the function calls the numbers are: VDD = 0, Vref+ = 1, FVR = 2
To test the theory, I set all three, 2D dash panel analog inputs to: "VRef option: FVR" and ran the code again on my prototype unit. It worked! My PIC was reading the 4.096V external reference IC. So now I know what the issue is and got a workaround, but I still have a couple of concerns that I would like to get some help with.
- 1. I am not exactly sure if I had stumbled onto a bug or if there is something else in my project that does not work properly. Please let me know as I would really like to correct this before my final code release.
- 2. I have also noticed that the input component does not have a pull-down menu for the VRef- setting of the PIC's ADC - which can be tied either to GND (VSS) or to the VRef- (AN2) pin of the chip. Is this something that can be done elsewhere in the code?
Target folder: ########################
Source name: ###########################################_16F1847.fcfx
Title: #########################.
Description:
Device: PIC.16F.16F1847
Generated by: Flowcode v7.2.1.4
Date: Sunday, June 11, 2017 11:29:00
Users: 1
Registered to: #########
Licence key: #########
http://www.matrixtsl.com
Launching the compiler...
C:\Program Files (x86)\Flowcode 7\compilers\pic\bin\xc8.exe --chip=16F1847 “##################_16F1847.c" --MSGDISABLE=359,1273,1388
Microchip MPLAB XC8 C Compiler (Free Mode) V1.41
Build date: Jan 24 2017
Part Support Version: 1.41
Copyright (C) 2017 Microchip Technology Inc.
License type: Node Configuration
. .
Memory Summary:
Program space used 1284h ( 4740) of 2000h words ( 57.9%)
Data space used DAh ( 218) of 400h bytes ( 21.3%)
EEPROM space used 18h ( 24) of 100h bytes ( 9.4%)
Data stack space used 0h ( 0) of 31Eh bytes ( 0.0%)
Configuration bits used 2h ( 2) of 2h words (100.0%)
ID Location space used 0h ( 0) of 4h bytes ( 0.0%)
You have compiled in FREE mode.
Using Omniscient Code Generation that is available in PRO mode,
you could have produced up to 60% smaller and 400% faster code.
See http://www.microchip.com/MPLABXCcompilers for more information.
Launching the linker/assembler...
C:\Program Files (x86)\Flowcode 7\tools\DoNothing\DoNothing.exe
FINISHED
*******************************************************************************
*******************************************************************************
The three dash panel component properties (settings) and the function calls from the project C code:
AN4 Analog Input
2D Dash Panel Settings:
- VRef voltage: 401
- VRef option: FVR
- Conversion Speed: FRC
- Aquisition cycles: 50
- Bit Depth: 10
C Code:
/*=----------------------------------------------------------------------=*\
Use :Blocking call to read the ADC at full bit depth
:
:Returns : MX_UINT16
\*=----------------------------------------------------------------------=*/
MX_UINT16 FCD_08f43_adc_base__GetInt()
{
//Local variable definitions
MX_UINT16 FCR_RETVAL;
FC_CAL_ADC_Enable(4, 3, 2, 50);
FCR_RETVAL = FC_CAL_ADC_Sample(1);
FC_CAL_ADC_Disable();
return (FCR_RETVAL);
}
*******************************************************************************
*******************************************************************************
AN 0 Input:
2D Dash Panel Settings:
- VRef voltage: 401
- VRef option: Vref+
- Conversion Speed: FRC
- &
- Bit Depth: 10
C Code:
/*=----------------------------------------------------------------------=*\
Use :Blocking call to read the ADC at full bit depth
:
:Returns : MX_UINT16
\*=----------------------------------------------------------------------=*/
MX_UINT16 FCD_08f42_adc_base__GetInt()
{
//Local variable definitions
MX_UINT16 FCR_RETVAL;
FC_CAL_ADC_Enable(0, 3, 1, 40);
FCR_RETVAL = FC_CAL_ADC_Sample(1);
FC_CAL_ADC_Disable();
return (FCR_RETVAL);
}
*******************************************************************************
*******************************************************************************
AN 1 Input:
2D Dash Panel Settings:
- VRef voltage: 401
- VRef option: VDD
- Conversion Speed: FRC
- Aquisition cycles: 60
- Bit Depth: 10
C Code:
/*=----------------------------------------------------------------------=*\
Use :Blocking call to read the ADC at full bit depth
:
:Returns : MX_UINT16
\*=----------------------------------------------------------------------=*/
MX_UINT16 FCD_08f41_adc_base__GetInt()
{
//Local variable definitions
MX_UINT16 FCR_RETVAL;
FC_CAL_ADC_Enable(1, 3, 0, 60);
FCR_RETVAL = FC_CAL_ADC_Sample(1);
FC_CAL_ADC_Disable();
return (FCR_RETVAL);
}
*******************************************************************************
*******************************************************************************
Thanks in advance and cheers...