chipKIT® Development Platform

Inspired by Arduino™

ADC automatic readings read the wrong analog input

Created Fri, 04 Apr 2014 20:00:55 +0000 by wheresbicki


wheresbicki

Fri, 04 Apr 2014 20:00:55 +0000

It appears my readADC function is shifting the analog signal each time I display onto my LCD module. A0 is AN3 when it should be AN2, A1 is AN5 when it should be AN4...etc

Here is my readADC code.

#include "globdefs.h" #include "globvars.h" #include "lcd.h" #include "model.h" #include "pot_reader.h" #include <p32xxxx.h>

// initialize the ADC for single conversion, select input pins void initADC( int amask) //initADC

int readADC( int ch) // readADC


majenko

Fri, 04 Apr 2014 20:35:20 +0000

I guess you're not using MPIDE then? So no nice simple analogRead() function...?

Why not take a look at the core in MPIDE for the analogRead() function and see what that does and how it all works - you may spot something...


wheresbicki

Sat, 05 Apr 2014 20:02:05 +0000

Thank you for the suggestion! This is what I found in the wiring_analog.c in the MPIDE library.

/* In the other PIC32 devices, all of the analog input capable pins are
**  in PORTB, and the AD1PCFG register is used to set the pins associated
**  with PORTB to analog input or digital input mode. Clear the appropriate
**  bit in AD1PCFG.
*/
AD1PCFGCLR = (1 &lt;&lt; channelNumber);

#endif // defined(PIC32MX1XX) || defined(PIC32MX2XX)

AD1CHS = (channelNumber &amp; 0xFFFF) &lt;&lt; 16;
AD1CON1	=	0; //Ends sampling, and starts converting

/* Set up for manual sampling*/
AD1CSSL	=	0;
AD1CON3	=	0x0002;	//Tad = internal 6 Tpb
AD1CON2	=	analog_reference;

/* Turn on ADC*/
AD1CON1SET	=	0x8000;

/* Start sampling*/
AD1CON1SET	=	0x0002;

/* Delay for a bit*/
delayMicroseconds(2);

/* Start conversion*/
AD1CON1CLR	=	0x0002;

/* Wait for conversion to finish*/
while (!(AD1CON1 &amp; 0x0001));

/* Read the ADC Value*/
analogValue	=	ADC1BUF0;
return (analogValue);

I was using automatic sampling in the PIC32, but I decided to manually force the conversion after sampling and a short delay like in this file. It worked using those changes.


majenko

Sat, 05 Apr 2014 21:07:21 +0000

Here's some high speed ADC code I use for taking block samples. It's timer controlled, and you can set it to run at a specific frequency.

const int dataSize = 512;

int32_t data[dataSize];

void setup() {
    configureADC(192000);
    AD1CON1bits.ON = 1;
}

void loop() {
    while (AD1CON1bits.ON == 1);
    // Do something with the data, then start a new sample acquisition
    AD1CON1bits.ON = 1;
    // You can now do other things while it's sampling
}


boolean configureADC(float freq) {
    uint16_t numchans = 1;
    uint16_t enabledChannels = 1;
    float f = freq * (float)numchans;
    uint32_t baseclock = F_CPU;
    uint8_t ps = 0;
   
    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 2;
        ps = 1;
    }

    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 4;
        ps = 2;
    }

    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 8;
        ps = 3;
    }

    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 16;
        ps = 4;
    }

    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 32;
        ps = 5;
    }

    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 64;
        ps = 6;
    }

    if (baseclock / f &gt; 65535) {
        baseclock = F_CPU / 256;
        ps = 7;
    }


    AD1CON1 = 0;
    AD1CON2 = 0;
    AD1CON3 = 0;
    AD1CHS  = 0;

    AD1CON1bits.FORM = 0b101;
    AD1CON1bits.SSRC = 0b010;
    AD1CON1bits.ASAM = 1;
    AD1CON2bits.CSCNA = 1;
    AD1CON2bits.SMPI = numchans-1;
    AD1CON3bits.SAMC = 0b00111;
    AD1CON3bits.ADCS = 0b00000111;
   
    AD1PCFG = ~enabledChannels;
    AD1CSSL = enabledChannels;

    IPC6bits.AD1IP = 6;
    IFS1bits.AD1IF = 0;
    IEC1bits.AD1IE = 1;

    T3CON = 0;
    T3CONbits.TCKPS = ps;
    PR3 = baseclock / f;
    T3CONSET = 1&lt;&lt;15;
    return true;
}

extern "C" {
    #include &lt;sys/attribs.h&gt;
    void __ISR(_ADC_VECTOR, IPL6) _ADCInterrupt() {
        static int x = 0;
        data[x++] = abs(ADC1BUF0);
        if (x == dataSize) {
            x = 0;
            AD1CON1bits.ON = 0;
        }
        IFS1bits.AD1IF = 0;
    }
}

I've just hacked it out of a project, and that I hacked out of another project, so there's bits there that are redundant, and I don't know if I even hacked it out right just now, but you're welcome to take it and do your own hacking with it ;)