PIC18F13K22 ADC Values Below Expected Result

Discussion in 'Embedded Systems and Microcontrollers' started by razor367, Oct 11, 2016.

  1. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    Setup:
    Vdd: +4.75VDC (from USB, 0.1uf across Vcc and GND bridging PIC)
    Vsig: Variable (+3VDC for this example)
    ADCin: Have tested two configurations, direct in from regulated supply and with 4.7ohm resistor in series
    ADC result is 10 point average of measurements taken within 1 second.

    The value returned via debugging for 3VDC is ~27 instead of the expected result of ~647 (Vsig*1024/Vdd). For a reason yet unknown, this value will also return as ~350 and ~515 at the same Vsig on different runs (power cycle the Vsig and make no changes to the program, program state, or circuit). The 500 level value seems to return consistently after several "startup" runs. The value is stable to +-3, but not accurate. I have a multimeter in line with Vsig to verify that the supply is indeed at the correct voltage.

    A full table looks like this (note the result both over and undershoots expected):
    Code (Text):
    1.  
    2. Vsig  Expected  Actual
    3. 0.5   107.79     209
    4. 1.0   215.58     266
    5. 1.5   323.37     324
    6. 2.0   431.16     382
    7. 2.5   538.95     440
    8. 3.0   646.74     500
    9. 3.5   754.53     540
    10.  
    The clock is configured correctly as I have fired LEDs against a watch and the time cycles match. I am thinking that the bias is program related, but the fluctuation is circuit related. I have been teaching myself how to work with microcontrollers, circuits, and programming, but this is the first issue that has really stumped me.

    Below is the functional code, I have omitted averaging to cut down on space usage:
    Code (C):
    1.  
    2. // PIC18F13K22 Configuration Bit Settings
    3. // 'C' source line config statements
    4. // CONFIG1H
    5. #pragma config FOSC = IRCCLKOUT // Oscillator Selection bits (Internal RC oscillator, CLKOUT function on OSC2)
    6. #pragma config PLLEN = OFF      // 4 X PLL Enable bit (PLL is under software control)
    7. #pragma config PCLKEN = ON      // Primary Clock Enable bit (Primary clock enabled)
    8. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
    9. #pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
    10. // CONFIG2L
    11. #pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT disabled)
    12. #pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
    13. #pragma config BORV = 19        // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)
    14. // CONFIG2H
    15. #pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
    16. #pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
    17. // CONFIG3H
    18. #pragma config HFOFST = ON      // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
    19. #pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled, RA3 input pin disabled)
    20. // CONFIG4L
    21. #pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
    22. #pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
    23. #pragma config BBSIZ = OFF      // Boot Block Size Select bit (512W boot block size)
    24. #pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
    25. // CONFIG5L
    26. #pragma config CP0 = OFF        // Code Protection bit (Block 0 not code-protected)
    27. #pragma config CP1 = OFF        // Code Protection bit (Block 1 not code-protected)
    28. // CONFIG5H
    29. #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block not code-protected)
    30. #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
    31. // CONFIG6L
    32. #pragma config WRT0 = OFF       // Write Protection bit (Block 0 not write-protected)
    33. #pragma config WRT1 = OFF       // Write Protection bit (Block 1 not write-protected)
    34. // CONFIG6H
    35. #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers not write-protected)
    36. #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block not write-protected)
    37. #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
    38. // CONFIG7L
    39. #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
    40. #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)
    41. // CONFIG7H
    42. #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)
    43.  
    44. void ConfigureOscillator(void){
    45.     OSCCONbits.HFIOFS   =0b1; //HFINTOSC Frequency Stable Bit unsure pg18
    46.     OSCCONbits.OSTS     =0b0; //Oscillator Start up and time out pg18
    47.     OSCCONbits.IRCF     =0b111; //Internal Oscillator Frequency Select pg18
    48.     OSCCONbits.SCS      =0b00; //clock set to primary clock pg18
    49.     OSCTUNEbits.PLLEN   =0b1;
    50. }
    51.  
    52. /** * Initialize the Analog to Digital Converter. pg213*/
    53. void init_adc(void){
    54.     TRISAbits.TRISA2    =0b1;  // set pin as input
    55.     ADCON0bits.CHS      =0b0010; // set pin as analog
    56.     ADCON1bits.PVCFG    =0b00; // set v+ reference to Vdd
    57.     ADCON1bits.NVCFG    =0b0;  // set v- reference to GND
    58.     //ADCON1bits.CHSN     =0b000; // set negative input to GND
    59.     ADCON2bits.ADFM     =0b1;  // right justify the output
    60.     ADCON2bits.ACQT     =0b110; // 16 TAD
    61.     ADCON2bits.ADCS     =0b101; // use Fosc/16 for clock source
    62.     ADCON0bits.ADON     =0b1;  // turn on the ADC
    63. }
    64.  
    65. /** * Preform an analog to digital conversion. * at Param channel The ADC input channel to use. * at Return The value of the conversion. */
    66. uint16_t adc_convert(uint8_t channel){
    67.     ADCON0bits.CHS      =channel;  // select the given channel
    68.     ADCON0bits.GO       =0b1;      // start the conversion
    69.     while(ADCON0bits.DONE);         // wait for the conversion to finish
    70.     return(ADRESH<<8)|ADRESL;      // return the result
    71. }
    72.  
     
    Last edited by a moderator: Oct 11, 2016
  2. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    I think I have sussed this. You are using the internal clock at 16MHz and have set the ADC conversion clock to Fosc/16 and that would be just fine BUT you also have "OSCTUNEbits.PLLEN=0b1;" which multiplies the clock frequency by four and now the ADC is compromised.
    Replace "ADCON2bits.ADCS =0b101;// use Fosc/16 for clock source" with "ADCON2bits.ADCS =0b110;// use Fosc/64 for clock source".
     
  3. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    I made the suggested change, but it seems my actual vs. expected is still on the low end (off by ~2.5x @ 2.6V, off by ~1.9x @ 3V). Plotted, the response looks like this. The slope is off expected in run 1, and offset in run 2. I am not sure where this variation is coming from.
    upload_2016-10-12_13-37-52.png

    I have checked the connections all the way to the pin and am receiving a constant voltage. Sometimes the reading is steady out of the ADC, sometimes it creeps up between subsequent debugging runs, sometimes the value swings high or low (never during the same run). Not sure what is happening.
     
    Last edited: Oct 12, 2016
  4. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    How are you powering the PIC?
    While running this test what else do you have connected to the PIC?
    Please post all the code.
    See what readings you get with the ADC input connected by a resistor (1k - 10k) to PIC VDD and then to PIC VSS.
     
  5. kubeek

    AAC Fanatic!

    Sep 20, 2005
    4,670
    804
    A schematic please.
     
  6. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    Yeah, that as well :)
     
  7. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    I will get the readings when I have a moment.

    upload_2016-10-12_16-47-41.png
    upload_2016-10-12_16-47-57.png
     
  8. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    And the rest of the code please.
     
  9. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    Code (C):
    1.  
    2. Main.c:
    3.  
    4. #if defined(__XC)
    5.     #include <xc.h>        /* XC8 General Include File */
    6. #elif defined(HI_TECH_C)
    7.     #include <htc.h>       /* HiTech General Include File */
    8. #elif defined(__18CXX)
    9.     #include <p18cxxx.h>   /* C18 General Include File */
    10. #endif
    11.  
    12. #if defined(__XC) || defined(HI_TECH_C)
    13.  
    14. #include <stdint.h>        /* For uint8_t definition */
    15. #include <stdbool.h>       /* For true/false definition */
    16.  
    17. #endif
    18.  
    19. #include "system.h"        /* System funct/params, like osc/peripheral config */
    20. #include "user.h"          /* User funct/params, such as InitApp */
    21. //#include "highpassbutter.h" /* Include file for IIR filter */
    22.  
    23. /******************************************************************************/
    24. /* User Global Variable Declaration                                           */
    25. /******************************************************************************/
    26.  
    27. /* i.e. uint8_t <variable_name>; */
    28.  
    29. /******************************************************************************/
    30. /* Main Program                                                               */
    31. /******************************************************************************/
    32.  
    33. void main(void)
    34. {
    35.     uint16_t adc_value;                 // variable to hold average ADC conversion result in
    36.     uint16_t adc_value1;                // variable to hold 1st ADC conversion result in
    37.     uint16_t adc_value2;                // variable to hold 2nd ADC conversion result in
    38.     uint16_t adc_value3;                // variable to hold 3rd ADC conversion result in
    39.     uint16_t adc_value4;                // variable to hold 4th ADC conversion result in
    40.     uint16_t adc_value5;                // variable to hold 5th ADC conversion result in
    41.     uint16_t adc_value6;                // variable to hold 6th ADC conversion result in
    42.     uint16_t adc_value7;                // variable to hold 7th ADC conversion result in
    43.     uint16_t adc_value8;                // variable to hold 8th ADC conversion result in
    44.     uint16_t adc_value9;                // variable to hold 9th ADC conversion result in
    45.     uint16_t adc_value10;               // variable to hold 10th ADC conversion result in
    46.     uint16_t adc_value_sum;             // variable to hold sum of ADC conversion results in
    47.  
    48.     /* Configure the oscillator for the device */
    49.     ConfigureOscillator();
    50.  
    51.     /* Initialize I/O and Peripherals for application */
    52.     InitApp();
    53.  
    54.     /* TODO <INSERT USER APPLICATION CODE HERE> */
    55.  
    56.     TRISCbits.TRISC0 = 0; // set pin as output
    57.     TRISCbits.TRISC1 = 0; // set pin as output
    58.     TRISCbits.TRISC2 = 0; // set pin as output
    59.     TRISBbits.TRISB4 = 0; // set pin as output
    60.  
    61.     //while(1)
    62.     //{
    63.         LATCbits.LATC0 = 0; // set pin LOW
    64.         LATCbits.LATC1 = 0; // set pin LOW
    65.         LATCbits.LATC2 = 0; // set pin LOW
    66.         LATBbits.LATB4 = 0; // set pin LOW
    67.         wait_ms(500);       // wait 0.5 seconds
    68.         LATCbits.LATC0 = 1; // set pin HIGH
    69.         LATCbits.LATC1 = 1; // set pin HIGH
    70.         LATCbits.LATC2 = 1; // set pin HIGH
    71.         LATBbits.LATB4 = 1; // set pin HIGH
    72.         wait_ms(3000);       // wait 3.0 seconds to test LEDs
    73.         LATCbits.LATC0 = 0; // set pin LOW
    74.         LATCbits.LATC1 = 0; // set pin LOW
    75.         LATCbits.LATC2 = 0; // set pin LOW
    76.         LATBbits.LATB4 = 0; // set pin LOW
    77.     //} //testing loop condition
    78.      
    79.     while(1)
    80.     {
    81.         //adc_value = 25;             //manual override adc_value variable
    82.         adc_value1 = adc_convert(2);
    83.         wait_ms(10);
    84.         adc_value2 = adc_convert(2);
    85.         wait_ms(10);
    86.         adc_value3 = adc_convert(2);
    87.         wait_ms(10);
    88.         adc_value4 = adc_convert(2);
    89.         wait_ms(10);
    90.         adc_value5 = adc_convert(2);
    91.         wait_ms(10);
    92.         adc_value6 = adc_convert(2);
    93.         wait_ms(10);
    94.         adc_value7 = adc_convert(2);
    95.         wait_ms(10);
    96.         adc_value8 = adc_convert(2);
    97.         wait_ms(10);
    98.         adc_value9 = adc_convert(2);
    99.         wait_ms(10);
    100.         adc_value10 = adc_convert(2);
    101.         wait_ms(10);
    102.         adc_value_sum = adc_value1 + adc_value2 + adc_value3 + adc_value4 + adc_value5 + adc_value6 + adc_value7 + adc_value8 + adc_value9 + adc_value10;
    103.         adc_value = adc_value_sum / 10;
    104.         //adc_value = adc_convert(2);
    105.      
    106.         /* check the boolean condition */
    107.         if( adc_value > 501 ) {
    108.         //if( adc_value > 50 ) {
    109.         /*bank0;
    110.         movlw b'00010111';
    111.         movwf PORTC;*/
    112.         LATCbits.LATC0 = 1; // set pin HIGH
    113.         LATCbits.LATC1 = 1; // set pin HIGH
    114.         LATCbits.LATC2 = 1; // set pin HIGH
    115.         LATBbits.LATB4 = 1; // set pin HIGH
    116.      //printf("Value of adc_result is below range" );
    117.         }
    118.     else if( adc_value <= 500 && adc_value >= 430 ) {
    119.     //else if( adc_value <= 50 && adc_value >= 40 ) {
    120.      /*bank0;
    121.         movlw b'00000001';
    122.         movwf PORTC;*/
    123.         LATCbits.LATC0 = 1; // set pin HIGH
    124.         LATCbits.LATC1 = 0; // set pin LOW
    125.         LATCbits.LATC2 = 0; // set pin LOW
    126.         LATBbits.LATB4 = 0; // set pin LOW
    127.       //printf("Value of adc_result is ORANGE" );
    128.         }
    129.     else if( adc_value <= 385 && adc_value >= 360  ) {
    130.     //else if( adc_value <= 39 && adc_value >= 30  ) {
    131.      /*bank0;
    132.         movlw b'00000010';
    133.         movwf PORTC;*/
    134.         LATCbits.LATC0 = 0; // set pin LOW
    135.         LATCbits.LATC1 = 1; // set pin HIGH
    136.         LATCbits.LATC2 = 0; // set pin LOW
    137.         LATBbits.LATB4 = 0; // set pin LOW
    138.       //printf("Value of adc_result is YELLOW" );
    139.         }
    140.     else if( adc_value <= 335 && adc_value >= 305  ) {
    141.     //else if( adc_value <= 29 && adc_value >= 20  ) {
    142.      /*bank0;
    143.         movlw b'00000100';
    144.         movwf PORTC;*/
    145.         LATCbits.LATC0 = 0; // set pin LOW
    146.         LATCbits.LATC1 = 0; // set pin LOW
    147.         LATCbits.LATC2 = 1; // set pin HIGH
    148.         LATBbits.LATB4 = 0; // set pin LOW
    149.       //printf("Value of adc_result is WHITE" );
    150.         }
    151.     else if( adc_value <= 280 && adc_value >= 265  ) {
    152.     //else if( adc_value <= 19 && adc_value >= 10  ) {
    153.      /*bank0;
    154.         movlw b'00010000';
    155.         movwf PORTC;*/
    156.         LATCbits.LATC0 = 0; // set pin LOW
    157.         LATCbits.LATC1 = 0; // set pin LOW
    158.         LATCbits.LATC2 = 0; // set pin LOW
    159.         LATBbits.LATB4 = 1; // set pin HIGH
    160.       //printf("Value of adc_result is RED" );
    161.         }
    162.     else if( adc_value < 265 && adc_value >= 1 ) {
    163.     //else if( adc_value < 50 && adc_value >= 1 ) {
    164.      /*bank0;
    165.         movlw b'00000000';
    166.         movwf PORTC;*/
    167.         LATCbits.LATC0 = 0; // set pin LOW
    168.         LATCbits.LATC1 = 0; // set pin LOW
    169.         LATCbits.LATC2 = 0; // set pin LOW
    170.         LATBbits.LATB4 = 0; // set pin LOW
    171.       //printf("Value of adc_result is above range" );
    172.         }
    173.     else {
    174.      /*bank0;
    175.         movlw b'00000000';
    176.         movwf PORTC;*/
    177.         LATCbits.LATC0 = 0; // set pin LOW
    178.         LATCbits.LATC1 = 0; // set pin LOW
    179.         LATCbits.LATC2 = 0; // set pin LOW
    180.         LATBbits.LATB4 = 0; // set pin LOW
    181.       //printf("Value of adc_result is not in valid window" );
    182.         }
    183.     //printf("Exact value of signal is: %d\1024", adc_result);
    184.     wait_ms(1000);       // wait 1.0 second before updating
    185.     }
    186.  
    187. }
    188.  
    189. user.c:
    190.  
    191. #if defined(__XC)
    192.     #include <xc.h>         /* XC8 General Include File */
    193. #elif defined(HI_TECH_C)
    194.     #include <htc.h>        /* HiTech General Include File */
    195. #elif defined(__18CXX)
    196.     #include <p18cxxx.h>    /* C18 General Include File */
    197. #endif
    198.  
    199. #if defined(__XC) || defined(HI_TECH_C)
    200.  
    201. #include <stdint.h>         /* For uint8_t definition */
    202. #include <stdbool.h>        /* For true/false definition */
    203.  
    204. #endif
    205.  
    206. #include "user.h"
    207.  
    208. /******************************************************************************/
    209. /* User Functions                                                             */
    210. /******************************************************************************/
    211.  
    212. /* <Initialize variables in user.h and insert code for user algorithms.> */
    213.  
    214. /** * Initialize the Analog to Digital Converter. pg213*/
    215. void init_adc(void){
    216.     TRISAbits.TRISA2    =0b1;  // set pin as input
    217.     ADCON0bits.CHS      =0b0010; // set pin as analog
    218.     ADCON1bits.PVCFG    =0b00; // set v+ reference to Vdd
    219.     ADCON1bits.NVCFG    =0b0;  // set v- reference to GND
    220.     //ADCON1bits.CHSN     =0b000; // set negative input to GND
    221.     ADCON2bits.ADFM     =0b1;  // right justify the output
    222.     ADCON2bits.ACQT     =0b110; // 16 TAD
    223.     ADCON2bits.ADCS     =0b110; // use Fosc/64 for clock source
    224.     //ADCON2bits.ADCS     =0b101; // use Fosc/16 for clock source
    225.     ADCON0bits.ADON     =0b1;  // turn on the ADC
    226. }
    227.  
    228. /** * Preform an analog to digital conversion. * [USER=120004]@Param[/USER] channel The ADC input channel to use. * [USER=190411]@Return[/USER] The value of the conversion. */
    229. uint16_t adc_convert(uint8_t channel){
    230.     ADCON0bits.CHS      =channel;  // select the given channel
    231.     ADCON0bits.GO       =0b1;      // start the conversion
    232.     while(ADCON0bits.DONE);         // wait for the conversion to finish
    233.     return(ADRESH<<8)|ADRESL;      // return the result
    234. }  
    235.  
    236. void InitApp(void)
    237. {
    238.     /* TODO Initialize User Ports/Peripherals/Project here */
    239.  
    240.     /* Setup analog functionality and port direction */
    241.  
    242.     /* Initialize peripherals */
    243.     init_adc();
    244.     /* Configure the IPEN bit (1=on) in RCON to turn on/off int priorities */
    245.  
    246.     /* Enable interrupts */
    247. }
    248.  
    249. configuration_bits.c:
    250. #if defined(__XC)
    251.     #include <xc.h>         /* XC8 General Include File */
    252. #elif defined(HI_TECH_C)
    253.     #include <htc.h>        /* HiTech General Include File */
    254. #elif defined(__18CXX)
    255.     #include <p18cxxx.h>    /* C18 General Include File */
    256. #endif
    257.  
    258. // PIC18F13K22 Configuration Bit Settings
    259.  
    260. // 'C' source line config statements
    261.  
    262. // CONFIG1H
    263. #pragma config FOSC = IRCCLKOUT // Oscillator Selection bits (Internal RC oscillator, CLKOUT function on OSC2)
    264. #pragma config PLLEN = OFF      // 4 X PLL Enable bit (PLL is under software control)
    265. #pragma config PCLKEN = ON      // Primary Clock Enable bit (Primary clock enabled)
    266. #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
    267. #pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
    268.  
    269. // CONFIG2L
    270. #pragma config PWRTEN = OFF     // Power-up Timer Enable bit (PWRT disabled)
    271. #pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
    272. #pragma config BORV = 19        // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)
    273.  
    274. // CONFIG2H
    275. #pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
    276. #pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)
    277.  
    278. // CONFIG3H
    279. #pragma config HFOFST = ON      // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
    280. #pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled, RA3 input pin disabled)
    281.  
    282. // CONFIG4L
    283. #pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
    284. #pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
    285. #pragma config BBSIZ = OFF      // Boot Block Size Select bit (512W boot block size)
    286. #pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
    287.  
    288. // CONFIG5L
    289. #pragma config CP0 = OFF        // Code Protection bit (Block 0 not code-protected)
    290. #pragma config CP1 = OFF        // Code Protection bit (Block 1 not code-protected)
    291.  
    292. // CONFIG5H
    293. #pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block not code-protected)
    294. #pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
    295.  
    296. // CONFIG6L
    297. #pragma config WRT0 = OFF       // Write Protection bit (Block 0 not write-protected)
    298. #pragma config WRT1 = OFF       // Write Protection bit (Block 1 not write-protected)
    299.  
    300. // CONFIG6H
    301. #pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers not write-protected)
    302. #pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block not write-protected)
    303. #pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
    304.  
    305. // CONFIG7L
    306. #pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
    307. #pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)
    308.  
    309. // CONFIG7H
    310. #pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)
    311.  
    312. // #pragma config statements should precede project file includes.
    313. // Use project enums instead of #define for ON and OFF.
    314.  
    315. #include <xc.h>
    316.  
    317. interrupts.c:
    318. #if defined(__XC)
    319.     #include <xc.h>         /* XC8 General Include File */
    320. #elif defined(HI_TECH_C)
    321.     #include <htc.h>        /* HiTech General Include File */
    322. #elif defined(__18CXX)
    323.     #include <p18cxxx.h>    /* C18 General Include File */
    324. #endif
    325.  
    326. #if defined(__XC) || defined(HI_TECH_C)
    327.  
    328. #include <stdint.h>         /* For uint8_t definition */
    329. #include <stdbool.h>        /* For true/false definition */
    330.  
    331. #endif
    332.  
    333. /******************************************************************************/
    334. /* Interrupt Routines                                                         */
    335. /******************************************************************************/
    336.  
    337. /* High-priority service */
    338.  
    339. #if defined(__XC) || defined(HI_TECH_C)
    340. void interrupt high_isr(void)
    341. #elif defined (__18CXX)
    342. #pragma code high_isr=0x08
    343. #pragma interrupt high_isr
    344. void high_isr(void)
    345. #else
    346. #error "Invalid compiler selection for implemented ISR routines"
    347. #endif
    348.  
    349. {
    350.  
    351.       /* This code stub shows general interrupt handling.  Note that these
    352.       conditional statements are not handled within 3 seperate if blocks.
    353.       Do not use a seperate if block for each interrupt flag to avoid run
    354.       time errors. */
    355.  
    356. #if 0
    357.  
    358.       /* TODO Add High Priority interrupt routine code here. */
    359.  
    360.       /* Determine which flag generated the interrupt */
    361.       if(<Interrupt Flag 1>)
    362.       {
    363.           <Interrupt Flag 1=0>; /* Clear Interrupt Flag 1 */
    364.       }
    365.       else if (<Interrupt Flag 2>)
    366.       {
    367.           <Interrupt Flag 2=0>; /* Clear Interrupt Flag 2 */
    368.       }
    369.       else
    370.       {
    371.           /* Unhandled interrupts */
    372.       }
    373.  
    374. #endif
    375.  
    376. }
    377.  
    378. /* Low-priority interrupt routine */
    379. #if defined(__XC) || defined(HI_TECH_C)
    380. void low_priority interrupt low_isr(void)
    381. #elif defined (__18CXX)
    382. #pragma code low_isr=0x18
    383. #pragma interruptlow low_isr
    384. void low_isr(void)
    385. #else
    386. #error "Invalid compiler selection for implemented ISR routines"
    387. #endif
    388. {
    389.  
    390.       /* This code stub shows general interrupt handling.  Note that these
    391.       conditional statements are not handled within 3 seperate if blocks.
    392.       Do not use a seperate if block for each interrupt flag to avoid run
    393.       time errors. */
    394.  
    395. #if 0
    396.  
    397.       /* TODO Add Low Priority interrupt routine code here. */
    398.  
    399.       /* Determine which flag generated the interrupt */
    400.       if(<Interrupt Flag 1>)
    401.       {
    402.           <Interrupt Flag 1=0>; /* Clear Interrupt Flag 1 */
    403.       }
    404.       else if (<Interrupt Flag 2>)
    405.       {
    406.           <Interrupt Flag 2=0>; /* Clear Interrupt Flag 2 */
    407.       }
    408.       else
    409.       {
    410.           /* Unhandled interrupts */
    411.       }
    412.  
    413. #endif
    414.  
    415. }
    416.  
    417. #if defined(__XC)
    418.     #include <xc.h>         /* XC8 General Include File */
    419. #elif defined(HI_TECH_C)
    420.     #include <htc.h>        /* HiTech General Include File */
    421. #elif defined(__18CXX)
    422.     #include <p18cxxx.h>    /* C18 General Include File */
    423. #endif
    424.  
    425. #if defined(__XC) || defined(HI_TECH_C)
    426.  
    427. #include <stdint.h>         /* For uint8_t definition */
    428. #include <stdbool.h>        /* For true/false definition */
    429.  
    430. #endif
    431.  
    432. #include <stdio.h>
    433.  
    434. #include "system.h"
    435.  
    436. /* Refer to the device datasheet for information about available
    437. oscillator configurations. */
    438. void ConfigureOscillator(void)
    439. {
    440.     OSCCONbits.HFIOFS   =0b1; //HFINTOSC Frequency Stable Bit unsure pg18
    441.     OSCCONbits.OSTS     =0b0; //Oscillator Start up and time out pg18
    442.     OSCCONbits.IRCF     =0b111; //Internal Oscillator Frequency Select pg18
    443.     OSCCONbits.SCS      =0b00; //clock set to primary clock pg18
    444.     OSCTUNEbits.PLLEN   =0b1;
    445. }
    446.  
    447. /**
    448. * Wait for a given number of milli-seconds using busy waiting scheme.
    449. * [USER=120004]@Param[/USER] time - time in ms to wait.
    450. */
    451. void wait_ms(uint16_t time)
    452. {
    453.     static long timel = 0;
    454.     timel = time * 1000l;
    455.     for( ; timel; timel--);// no initial condition, while time is >0, decrement time each loop
    456. }
    457.  
    458.  
    459. #define SYS_FREQ        16000000L
    460. #define FCY             SYS_FREQ/4
    461.  
    462. /******************************************************************************/
    463. /* System Function Prototypes                                                 */
    464. /******************************************************************************/
    465.  
    466. /* Custom oscillator configuration funtions, reset source evaluation
    467. functions, and other non-peripheral microcontroller initialization functions
    468. go here. */
    469.  
    470. void ConfigureOscillator(void); /* Handles clock switching/osc initialization */
    471.  
    472. void wait_ms(uint16_t);
    473.  
    474. user.h:
    475. void InitApp(void);         /* I/O and Peripheral Initialization */
    476. uint16_t adc_convert(uint8_t);
    477.  
    Moderators note: used code tags for C
     
    Last edited by a moderator: Oct 13, 2016
  10. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    ADC input to Vdd yields 1022, even without averaging. Input to Vss yields 0, dead nuts.
     
  11. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    So it looks like your input signal is the problem - for further proof connect the ADC input to a pot across VDD/VSS and check a few voltages.

    Where is your input from? Is it earthed?
    Have you got the wires wrapped around a mains cable :D

    Incidentally, I don't like it being connected by 4.7Ω though I don't think it is anything to do with the problem. 1k+ would protect the PIC pin if something unexpected happened (for instance, input set to 3.3V but no power on the PIC).
     
  12. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    Actually, it looks like that might have been the issue. My sensor leads had worked their way near enough to some main lines. I replaced the resistor and remeasured using the instrument signal. Looks much nicer. I think I can get away with some simple y-shift in the code to line up the curves. I have to look at what is causing the dog leg around 1.5V.

    upload_2016-10-13_15-38-49.png
     
  13. AlbertHall

    Well-Known Member

    Jun 4, 2014
    1,951
    387
    If you extend the input voltage range up to 5V does the ADC reading catch up again with the expected result?
    If it doesn't then something is still going on with your input signal as we know that with the ADC linked to VDD you get the right answer.
     
  14. razor367

    Thread Starter New Member

    Sep 12, 2016
    26
    0
    After several trials, turns out the instrument was faulty for the voltage dip. I obtained a replacement and the output tracks as expected. Thanks for your help, Albert!
     
Loading...