Created Fri, 04 Apr 2014 20:00:55 +0000 by 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
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...
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 << channelNumber);
#endif // defined(PIC32MX1XX) || defined(PIC32MX2XX)
AD1CHS = (channelNumber & 0xFFFF) << 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 & 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.
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 > 65535) {
baseclock = F_CPU / 2;
ps = 1;
}
if (baseclock / f > 65535) {
baseclock = F_CPU / 4;
ps = 2;
}
if (baseclock / f > 65535) {
baseclock = F_CPU / 8;
ps = 3;
}
if (baseclock / f > 65535) {
baseclock = F_CPU / 16;
ps = 4;
}
if (baseclock / f > 65535) {
baseclock = F_CPU / 32;
ps = 5;
}
if (baseclock / f > 65535) {
baseclock = F_CPU / 64;
ps = 6;
}
if (baseclock / f > 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<<15;
return true;
}
extern "C" {
#include <sys/attribs.h>
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 ;)