Author Topic: PIC12 - ADC never returning zero  (Read 6167 times)

0 Members and 1 Guest are viewing this topic.

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
PIC12 - ADC never returning zero
« on: July 25, 2016, 08:53:03 pm »
Hi Everyone,

I am trying to read a 10K (linear) potentiometer using the ADC of a PIC12F1572 (http://ww1.microchip.com/downloads/en/DeviceDoc/40001723D.pdf). The pot-meter is connected directly to the ADC of the PIC using the same VCC and GND that is supplied to the PIC. But for some reason I am getting weird results when I read low voltages.

Reading 'high' voltage (~5V) works great; I get 1023 as expected (using the 'ADC1_GetConversion()' function that was generated by MPlab). And when rotating the pot-meter the ADC result changes accordingly as far as I can see. But when I turn the pot completely down, I only get 44 from the ADC while the voltage on the ADC pin is around 0.1mV according to my (cheap) multimeter. Directly connecting the ADC pin to GND or using a different PIC12F1572 did not make a difference; the ADC still did not go lower as 44.

I've gone through the datasheet and the Code Configurator settings but sofar I have not been able to find anything that would explain this. Is there some additional setting needed when measuring low voltages on a PIC? Or do I need to add something to my test-circuit since it contains only a bare pot-meter at the moment.


ADC settings used:
Code: [Select]
Clock: FOSC/16 (sampling freq. 86.9565 kHz, conversiontime 11.5us)
Alignment: right
Positive reference: VDD
(No triggers or interrupts)

Code (that was generated) to retrieve ADC value:
Code: [Select]
adc_result_t ADC1_GetConversion(adc_channel_t channel)
{
    ADCON0bits.CHS = channel; // select the A/D channel
    ADCON0bits.ADON = 1; // Turn on the ADC module
    __delay_us(ACQ_US_DELAY); // Acquisition time delay
    ADCON0bits.GO_nDONE = 1; // Start the conversion
    while (ADCON0bits.GO_nDONE) // Wait for the conversion to finish
    {
    }
    return ((ADRESH << 8) + ADRESL); // Conversion finished, return the result
}


Edit: changed subject to better reflect question
« Last Edit: July 25, 2016, 10:01:07 pm by SmokyMcToad »
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: PIC12 - ADC never returning zero
« Reply #1 on: July 25, 2016, 10:18:43 pm »
1. Your pot may not go to 0v.
2. Your ADC may have an offset.
3. Your ADC may not read 0v exactly at 0.
...

To check for sure, ground that pin and see what you have.
================================
https://dannyelectronics.wordpress.com/
 
The following users thanked this post: SmokyMcToad

Offline Signal32

  • Regular Contributor
  • *
  • Posts: 234
  • Country: us
Re: PIC12 - ADC never returning zero
« Reply #2 on: July 25, 2016, 10:25:40 pm »
Is your circuit on a breadboard ?
Can you share an exact schematic ?
What are you using as voltage reference for the ADC ?
 

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
Re: PIC12 - ADC never returning zero
« Reply #3 on: July 25, 2016, 10:27:55 pm »
Hi Danny,

I've already tried connecting to ground; ADC still read 44 unfortunately.

But an offset is possible I guess; I will see if I can find some info from Microchip.

Edit:
@Danny
I've checked for offset but sofar it seems to stop at the expected 1023 when 5V is applied; it never reaches 1024 or higher. So for some reason the range seems to be limited to 44-1023 instead of the full 0-1023.
« Last Edit: July 25, 2016, 10:57:08 pm by SmokyMcToad »
 

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
Re: PIC12 - ADC never returning zero
« Reply #4 on: July 25, 2016, 10:36:31 pm »
@Signal32:
Yes, the PIC is mounted on a breadboard. I don't have an schematic around, but I did not connect much to it so hopefully a description of the pins will make my setup clear enough:

- PIN1 is connected to 5V (using a 7805 from a 12V supply)
- PIN2 is not connected
- PIN3 is set to ADC channel 3: this pin is connected to the middle pin of the pot
- PIN4 is not connected
- PIN5 is digital output; I use this to light a led depending on ADC value ('if (ADCresult == 1023) RA2=1' etc.)
- PIN6 is PWM output; not connected, but it is generating a pulse (disabling PWM did not seem to affect the ADC result for 0V)
- PIN7 is not connected
- PIN8 is connected to GND

The first and third pin of the pot are connected to the same 5V and GND as the PIC.
The ADC voltage reference is set to use VDD.

(PS: The pickit3 is also connected to the PIC, but disconnecting it did not seem to help either)


edit: fixed typo
« Last Edit: July 25, 2016, 10:39:16 pm by SmokyMcToad »
 

Offline ludzinc

  • Supporter
  • ****
  • Posts: 487
  • Country: au
    • My Misadventures In Engineering
Re: PIC12 - ADC never returning zero
« Reply #5 on: July 25, 2016, 11:42:40 pm »
Assuming you're using your 5V rail as your reference, 44 ~= 200mV.

What's the voltage at the input pin of your micro with respect to the ground pin on your micro?

What's the voltage of the 'ground' pin of your pot, with respect to the ground pin of the micro?

With a 10k pot, a 200mV offset on your board equates to around 400 ohms of stray impedance.  How good it he ground connection of your micro to your system ground?

 

Offline StillTrying

  • Super Contributor
  • ***
  • Posts: 2408
  • Country: dk
  • Country: Broken Britain
Re: PIC12 - ADC never returning zero
« Reply #6 on: July 26, 2016, 02:08:16 am »
Unlike some others,  :) I realise you're connecting the input to 0V, and you can't get much lower than that.

Sure the osc is at 16MHz and not 32MHz.
Even at 16Mhz conversiontime 11.5us is right on the limit, so you might have to try FOSC/32 even if it's just for testing.
Double or treble ACQ_US_DELAY just for testing.
ANSELx set correctly.
Page 112 says something about:
Analog input functions, such as ADC and comparator
inputs, are not shown in the priority lists. These inputs
are active when the I/O pin is set for Analog mode using
the ANSELx registers. Digital output functions may
control the pin when it is in Analog mode with the
priority shown below in Table 11-2.


Can't think of any others why you can't get below 44.
« Last Edit: July 26, 2016, 03:41:59 am by StillTrying »
CML+  That took much longer than I thought it would.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 2293
  • Country: gb
Re: PIC12 - ADC never returning zero
« Reply #7 on: July 26, 2016, 12:50:23 pm »
Unlike some others,  :) I realise you're connecting the input to 0V, and you can't get much lower than that.

Except that 0v is not always 0v;  a potential difference of 200mV on a cheap breadboard is not difficult to achieve, assuming the OP has used one.  If he has literally connected the ADC pin directly to the PIC Vss pin (i.e. not some random point of the circuit that eventually connects to the Vss pin) and got the same result then it's time to look at the ADC code.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 1803
  • Country: fi
  • Embedded SW/HW.
Re: PIC12 - ADC never returning zero
« Reply #8 on: July 26, 2016, 01:00:43 pm »
Have you tried increasing the acquisition time delay?

Code: [Select]
__delay_us(ACQ_US_DELAY); // Acquisition time delay
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 1803
  • Country: fi
  • Embedded SW/HW.
Re: PIC12 - ADC never returning zero
« Reply #9 on: July 26, 2016, 01:05:20 pm »
Have you tried to put the chip into a low power mode during the ADC measurement? Atmega328p device have noise issues unless the device is put into a low power mode during ADC operation. This may be applicable to the PIC's too, but not sure though. Just an idea.
 

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
Re: PIC12 - ADC never returning zero
« Reply #10 on: July 26, 2016, 04:41:36 pm »
@Ludzinc & MikerJ
Thanks for the suggestions; I've now measured the resistance and this appears to be around 0.2Ohm from the groundingpoint to the actual ground on the powersupply. As you suggested I've also connected the ADC pin directly to the GND pin, but the adc result was still 44.

@Kalvin
Thanks; I've checked the acquisition delay but after setting it to FOSC/64 with ACQ_US_DELAY*4 there was no difference in the output.



I've also tried using another pin (PIN7 which is connected to adc channel 0) and here I get 40 as lowest value from the ADC (while PIN3 gives 44). The same code was used, so I wondering if this is simply the lowest adcResult I can get on this batch of chips (since another chip I tried (same type) had the same issue). Is it possible for PIC chips to have these kind of 'offset' issues in the ADC peripheral itself?

 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 2573
  • Country: it
Re: PIC12 - ADC never returning zero
« Reply #11 on: July 26, 2016, 05:18:24 pm »
There should be the gain/offset error also with INL and DNL on the electrical specification section of the datasheet... but 44 of offset error is A LOT.
are you able to carefully apply a negative voltage at the analog input? (with a current limiting resistor) and see wether you can get to 0

PAGE 278 for the ADC characteristic

Anyways as it was already stated i would increase the sampling time.. try and substitute that with like __delay_us(1000), a millisecond or so.. not too much, but not too little.

something that could happen... your 5V is happily oscillating because you are in a breadboard so your voltage reference is NOT stable.
Using the FVR and test if with a stable reference you can get to 0V

I remember having a simillar problem like 6-7 years ago but i can't remember how i solved the problem
« Last Edit: July 26, 2016, 09:29:18 pm by JPortici »
 

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
Re: PIC12 - ADC never returning zero
« Reply #12 on: July 26, 2016, 05:43:04 pm »
@JPortici
Thanks; tested it immediately and the results are definitely interesting; at FVRx4 (4.096Vref) I get around 51 and at FVRx1 (1.024Vref) it jumps a bit between 211 and 212.

So it keeps measuring a value of around 200mV although I don't have a clue yet where this voltage is coming from.

Edit:
Unfortunately I don't have any reliable negative voltage available to test with.
« Last Edit: July 26, 2016, 05:45:42 pm by SmokyMcToad »
 

Offline Signal32

  • Regular Contributor
  • *
  • Posts: 234
  • Country: us
Re: PIC12 - ADC never returning zero
« Reply #13 on: July 26, 2016, 06:14:29 pm »
Unfortunately I don't have any reliable negative voltage available to test with.[/i]
You only need a battery(or any floating power supply) + a pot to create a negative voltage.
Connect the + of the battery to the ground of your circuit.
Then connect both of the ends of the pot to the ends of the battery.
The center of the pot is now your negative adjustable voltage.

PS You wouldn't want to apply more than -0.3v of voltage to the pin.
« Last Edit: July 26, 2016, 06:21:56 pm by Signal32 »
 

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
Re: PIC12 - ADC never returning zero
« Reply #14 on: July 26, 2016, 06:39:10 pm »
@Signal32 & JPortici:
Thanks for the negative voltage tips!! Used a 1.5V battery and now the ADC goes down completely :) I had to apply around -0.218V so that seems to fit my earlier measurements.

But does this mean the internal negative Vref of the PIC is not working correctly? Or can my breadboard still be the cause? (Would adding a trim-pot to the GND of the PIC help?)

Edit:
Adding a pot to the GND of the PIC did work; turning it till I got a voltage difference of around 200mV and the ADC started returning 0. But I guess this is not a great solution as I would need to 'raise' the GND pins of all connected devices. Is there any other way to get a (small) negative voltage without using a battery? Or would I need to use a LM317 (or similar) for that?
« Last Edit: July 26, 2016, 07:36:23 pm by SmokyMcToad »
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 2293
  • Country: gb
Re: PIC12 - ADC never returning zero
« Reply #15 on: July 26, 2016, 09:29:27 pm »
Do you have a second PIC to test?  It seems possible you have a faulty device as the offset is far higher than I would expect.
 

Offline JPortici

  • Super Contributor
  • ***
  • Posts: 2573
  • Country: it
Re: PIC12 - ADC never returning zero
« Reply #16 on: July 26, 2016, 09:35:48 pm »
I think i got it

http://www.microchip.com/forums/m905272.aspx
reply #16

you might have the pullups enabled and those would raise the voltage enough to cause your error, or at least some part of it
(i don't think it was what happened to me that one time, as it happened with an ages old 16f876a)
 
The following users thanked this post: SmokyMcToad

Offline Bruce Abbott

  • Frequent Contributor
  • **
  • Posts: 616
  • Country: nz
    • Bruce Abbott's R/C Models and Electronics
Re: PIC12 - ADC never returning zero
« Reply #17 on: July 26, 2016, 09:42:19 pm »
Quote from: SmokyMcToad
I've checked for offset but sofar it seems to stop at the expected 1023 when 5V is applied; it never reaches 1024 or higher.
The ADC only has 10 bits, so it can't go higher than 1023. Turn the pot until it just gets to 1023. Is the analog input voltage now exactly equal to Vdd, or significantly lower?

Set the DAC output to 0 Volts and measure it internally via ADC channel 30. What do you get?
 

Offline StillTrying

  • Super Contributor
  • ***
  • Posts: 2408
  • Country: dk
  • Country: Broken Britain
Re: PIC12 - ADC never returning zero
« Reply #18 on: July 27, 2016, 03:29:17 pm »
using a different PIC12F1572 did not make a difference; the ADC still did not go lower as 44.

It seems odd for 2 to have exactly the same problem.
When you swapped ICs, are you sure you didn't somehow manage to put the same one back in. I somehow managed it once.
CML+  That took much longer than I thought it would.
 

Offline SmokyMcToad

  • Contributor
  • Posts: 12
  • Country: nl
Re: PIC12 - ADC never returning zero
« Reply #19 on: July 27, 2016, 04:17:17 pm »
@StillTrying:
Yep; the new one was not programmed yet so it would not even blink the led when i plugged it in.

@Bruce:
Correct; but I was testing to see if some offset was applied that increased the adc-result with 44 across the whole range. But nothing exceeded 1023 so I knew there was no general offset applied.

@Jportici:
You Sir are my hero!!  :clap:
(And now I also know what 'WPU' means in the code configurator)

After disabling the weak pullup the adcResult was jumping between 0 and 1 when directly connected to GND :)   :-+

Many thanks to you all for helping!

edit: typo
 

Offline matseng

  • Frequent Contributor
  • **
  • Posts: 564
  • Country: se
    • My Github
Re: PIC12 - ADC never returning zero
« Reply #20 on: July 27, 2016, 05:17:37 pm »
It's very un-intuitive that pullups aren't automatically disabled for a pin set as analog input....  But there's a lot of gotchas in the world of microcontrollers so one have to read and understand every damn sentence of the datasheets and not make any assumptions at all.
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 4814
  • Country: gb
Re: PIC12 - ADC never returning zero
« Reply #21 on: July 27, 2016, 08:32:03 pm »
In the meantime, I found myself with a bit of time this evening, only to find this has been solved! I have little trust in MCC, every time I use it I find a new bug, so I built up a board and wrote the following.

Another problem with MCC is that it makes source code distribution more painful as even the most trivial blinky project is in half a dozen source files.

My "board" differs from yours in that I use RA5 as the PWM1 output, I used the primary PWM1 pin for the debugger.



Code: [Select]

// PIC12F1572 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = INTOSC    //  (INTOSC oscillator; I/O function on CLKIN pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF      // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOREN = OFF    // Low Power Brown-out Reset enable bit (LPBOR is disabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

#define _XTAL_FREQ 16000000

#include <stdint.h>

static volatile uint16_t _u16ADCResult=0; // volatile to stop optimising out

void main(void)
{
    // Basic chip initialisation
    OSCCONbits.IRCF=0b1111; // 16MHz in INTOSC
    ANSELA=0; // All digital (for now anyway)

    // Setup pins
    TRISAbits.TRISA2=0; // LED
   
    APFCONbits.P1SEL=1; // Send PWM1 to RA5, I'm using the primary pin for debugging
    TRISAbits.TRISA5=0; // PWM, alternate pin
   
    TRISAbits.TRISA4=1; // RA4 == AN3
    ANSELAbits.ANSA4=1; // Analogue in
   
    // ADC setup
   
    ADCON0bits.CHS=0b00011; // 0b00011 -> Ch3
    ADCON1bits.ADFM=1; // 1 -> Right justified
    ADCON1bits.ADCS=0b110; // 0b110 -> Tad == Fosc/64 == 4us
    ADCON1bits.ADPREF=0b00; // 0b00 -> Vrpos == Vdd
   
    ADCON0bits.ADON=1;
   
    // PWM setup
    PWM1PR=1023; // Match ADC range for total period count
    PWM1OF=0; // Offset not used in our case.
    PWM1PH=0; // Start at phase=0
    PWM1DC=0; // For starters, ADC will change this
    PWM1TMR=0; // Initialise to be safe
   
    PWM1CONbits.MODE=0b00; // 0b00 -> Standard PWM
    PWM1CONbits.OE=1; // Output enable
    PWM1CLKCONbits.CS=0b00; // 0b00 -> FOSC
    PWM1CLKCONbits.PS=0b000; // 0b000 -> Prescaler 1:1
   
    PWM1CONbits.EN=1;
           
    while(1)
    {
        __delay_us(5); // Sample time
        ADCON0bits.ADGO=1; // Start conversion

        LATAbits.LATA2=1; // LED on

        while (ADCON0bits.ADGO) // Wait for conversion to finish
        {
            NOP(); // I like NOPs so I can place debugger breakpoints
        }

        LATAbits.LATA2=0; // LED off

        _u16ADCResult=ADRES; // Get the ADC result
       
        PWM1DC=_u16ADCResult; // Set the new duty cycle
        PWM1LDCONbits.LDA=1; // Trigger a PWM reload next period start
    }
 }

 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: PIC12 - ADC never returning zero
« Reply #22 on: July 27, 2016, 11:10:33 pm »
"adcResult was jumping between 0 and 1 when directly connected to GND :)   :-+"

The last bit of an ADC makes a great random number generator.
================================
https://dannyelectronics.wordpress.com/
 

Offline StillTrying

  • Super Contributor
  • ***
  • Posts: 2408
  • Country: dk
  • Country: Broken Britain
Re: PIC12 - ADC never returning zero
« Reply #23 on: July 28, 2016, 01:11:54 am »
I did think of the weak pull-up, but the 210mV would mean that the wpu is installed 1K to 2K up towards the ADC, - doesn't make much sense.
CML+  That took much longer than I thought it would.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8229
  • Country: 00
Re: PIC12 - ADC never returning zero
« Reply #24 on: July 28, 2016, 01:38:28 am »
Quote
doesn't make much sense.

I agree.

especially when you consider that the adc read 44 with the input grounded: hard to imagine any pull-up to overcome a short to ground.
================================
https://dannyelectronics.wordpress.com/
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf