2013-06-10 05:12 PM
Running the following two ADC3 inputs, channels 11 and 12 (PC1, light sensor and PC2 potentiometer) on STM32F4Discovery, problem is that when I vary the PC2 input, the reading pertaining to PC1 also varyies a bit. ??????
/* using ADC3, channel 11 and 12 for inputs to PC1 and PC2, in independent,
* scan mode with DMA
*/
#include ''stm32f4xx.h'' //includes stdint.h
#include <
stm32f4xx_usart.h
>
#include ''myUSART1.h''
#include <
misc.h
>
#include ''stm32f4xx_adc.h''
char buffer[4];
__IO uint16_t ConvertedValue[2];
#define ADC3_DR_ADDRESS ((uint32_t)0x4001224C) //Ref p. 54; Ref p. 307;
void ADC3_DMA_Config(void);
void my_itoa(int n, char A[]);
void reverse(char A[]);
int main(void){
ADC3_DMA_Config();
init_USART1(19200);
USART_puts(USART1, ''Ready for ADC Conversion'');
USART_puts(USART1, ''\n'');
ADC_SoftwareStartConv(ADC3);
while (1) {
ADC_SoftwareStartConv(ADC3);
my_itoa(ConvertedValue[0], buffer);
USART_puts(USART1, buffer);
USART_puts(USART1, ''\t'');
my_itoa(ConvertedValue[1], buffer);
USART_puts(USART1, buffer);
USART_puts(USART1, ''\n'');
}
return 1;
}
void ADC3_DMA_Config(void){
ADC_InitTypeDef myADC;
ADC_CommonInitTypeDef myComm;
DMA_InitTypeDef myDMA;
GPIO_InitTypeDef myGPIO;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/* DMA2 Stream0 channel 2 configuration **************************************/
myDMA.DMA_Channel = DMA_Channel_2;
myDMA.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
myDMA.DMA_Memory0BaseAddr = (uint32_t)&ConvertedValue;
myDMA.DMA_DIR = DMA_DIR_PeripheralToMemory;
myDMA.DMA_BufferSize = 2;
myDMA.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
myDMA.DMA_MemoryInc = DMA_MemoryInc_Enable;
myDMA.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // u32
myDMA.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
myDMA.DMA_Mode = DMA_Mode_Circular;
myDMA.DMA_Priority = DMA_Priority_High;
myDMA.DMA_FIFOMode = DMA_FIFOMode_Disable;
myDMA.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
myDMA.DMA_MemoryBurst = DMA_MemoryBurst_Single;
myDMA.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &myDMA);
DMA_Cmd(DMA2_Stream0, ENABLE);
/* Configure ADC3 Channel 11 and 12 pin as analog input ******************************/
myGPIO.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
myGPIO.GPIO_Mode = GPIO_Mode_AN;
myGPIO.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &myGPIO);
/* ADC Common Init **********************************************************/
myComm.ADC_Mode = ADC_Mode_Independent;
myComm.ADC_Prescaler = ADC_Prescaler_Div2;
myComm.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //we not using multi mode
myComm.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&myComm);
/* ADC3 Init ****************************************************************/
myADC.ADC_Resolution = ADC_Resolution_12b;
myADC.ADC_ScanConvMode = ENABLE; //more than one input
myADC.ADC_ContinuousConvMode = ENABLE;
myADC.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1;//=0
myADC.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
myADC.ADC_DataAlign = ADC_DataAlign_Right;
myADC.ADC_NbrOfConversion = 2;
ADC_Init(ADC3, &myADC);
/* ADC3 regular channel12 configuration *************************************/
ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_3Cycles);
ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 2, ADC_SampleTime_15Cycles);
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
/* Enable ADC3 DMA */
ADC_DMACmd(ADC3, ENABLE);
/* Enable ADC3 */
ADC_Cmd(ADC3, ENABLE);
}
void my_itoa(int n, char A[])
{
int i =0;
do {
A[i++] = n % 10 + '0';
} while ((n /= 10) > 0); //we divide by ..continue as long as we can divide by 10 with
//integer left over, so stops with one digit
A[i] = '\0'; //this will become last digit once reverse is called
reverse(A);
}
void reverse(char A[])
{
int i, j;
char c;
for (i = 0, j = strlen(A)-1; i<j; i++, j--) {
c = A[i];
A[i] = A[j];
A[j] = c;
}
}
2013-06-10 05:36 PM
Likely relates to how the sample-hold functions (capacitor charge ?) and that your only giving it 3 cycles. If you let it dwell longer the readings will likely interfere less.
2013-06-10 06:01 PM
Well, I tried ADC_SamplingTime_15 cycles for both channels, with same result.
Perhaps a capacitor across the input?2013-06-10 07:02 PM
Perhaps a capacitor across the input?
Probably won't help. Buffer amplifiers on the ADC inputs will probably fix the problem. Cheers, Hal2013-06-10 07:44 PM
Thanks, guys. Following Clive's comments, I changed sample time to 144 cycles and all is now fine, but another day when I pick this up again I'll dig in my box for a dual uA-741 and try the buffer.
I have read also about pullup on the input, but haven't tried yet. Overall, which is more advantageous, changing sampling time or using the electronic method of buffer or perhaps pullup?2013-06-10 11:09 PM
Overall, which is more advantageous, changing sampling time or using the electronic method of buffer or perhaps pullup?
Both. The input impedance (source + S&H) and the S&H capacity form a RC element. Using the common equations, you can estimate the behavior quite properly. The sampling time sets the time the capacitor is allowed to charge up, and an amplifier reduces the input impedance (beside of amplifying/shifting the input signal). Pullup is for binary (digital) signals. In regard to ADCs, forget about that
I'll dig in my box for a dual uA-741 ...
Not the best choice IMHO. These opamps were designed for +/-15V supply, and are far from rail-to-rail. Better find a rail-to-rail type for low/asymmetric supply.
2013-06-11 08:25 PM
From datasheet it seems ADC running 30MHz. Input Z for ADC 6k and the Cap is 4pF. My input circuits add .5 kohm on PC1 and 2.5 kohm on PC2(the culprit). Thus, the offending circuit input has a longer RC than the victim PC1. Also, in both cases 5xRC is the same order of magnitude as the time for my original 3cycle sampling time, thus I was not allowing time for complete capacitor charge turnover, as you had suggested.
So, 144cycles is two orders higher and therefore safer. Thanks again, Clive.