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):
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:
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:
Vsig Expected Actual
0.5 107.79 209
1.0 215.58 266
1.5 323.37 324
2.0 431.16 382
2.5 538.95 440
3.0 646.74 500
3.5 754.53 540
Below is the functional code, I have omitted averaging to cut down on space usage:
C:
// PIC18F13K22 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1H
#pragma config FOSC = IRCCLKOUT // Oscillator Selection bits (Internal RC oscillator, CLKOUT function on OSC2)
#pragma config PLLEN = OFF // 4 X PLL Enable bit (PLL is under software control)
#pragma config PCLKEN = ON // Primary Clock Enable bit (Primary clock enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
// CONFIG2L
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 19 // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)
// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config HFOFST = ON // HFINTOSC Fast Start-up bit (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled, RA3 input pin disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config BBSIZ = OFF // Boot Block Size Select bit (512W boot block size)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
// CONFIG5L
#pragma config CP0 = OFF // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 not code-protected)
// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
// CONFIG6L
#pragma config WRT0 = OFF // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 not write-protected)
// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)
// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)
void ConfigureOscillator(void){
OSCCONbits.HFIOFS =0b1; //HFINTOSC Frequency Stable Bit unsure pg18
OSCCONbits.OSTS =0b0; //Oscillator Start up and time out pg18
OSCCONbits.IRCF =0b111; //Internal Oscillator Frequency Select pg18
OSCCONbits.SCS =0b00; //clock set to primary clock pg18
OSCTUNEbits.PLLEN =0b1;
}
/** * Initialize the Analog to Digital Converter. pg213*/
void init_adc(void){
TRISAbits.TRISA2 =0b1; // set pin as input
ADCON0bits.CHS =0b0010; // set pin as analog
ADCON1bits.PVCFG =0b00; // set v+ reference to Vdd
ADCON1bits.NVCFG =0b0; // set v- reference to GND
//ADCON1bits.CHSN =0b000; // set negative input to GND
ADCON2bits.ADFM =0b1; // right justify the output
ADCON2bits.ACQT =0b110; // 16 TAD
ADCON2bits.ADCS =0b101; // use Fosc/16 for clock source
ADCON0bits.ADON =0b1; // turn on the ADC
}
/** * Preform an analog to digital conversion. * at Param channel The ADC input channel to use. * at Return The value of the conversion. */
uint16_t adc_convert(uint8_t channel){
ADCON0bits.CHS =channel; // select the given channel
ADCON0bits.GO =0b1; // start the conversion
while(ADCON0bits.DONE); // wait for the conversion to finish
return(ADRESH<<8)|ADRESL; // return the result
}
Last edited by a moderator:



