cancel
Showing results for 
Search instead for 
Did you mean: 

I'm using 4 ADC channels and sending the data to a DMA buffer. The data from the different channels are interfering with each other and i'm not sure why. The goal is to read from PA0, PA1, PA4, and PA5 at the same time. so i may going about it wrong.

Paulset
Associate II

my data for this looks like the following without giving input

PA0 PA1 PA4 PA5

0 250 216 190

I expect this

PA0 PA1 PA4 PA5

0 0 0 0

and when i start giving channel PA0 data with a sensor all my channels are changing like so

PA0 PA1 PA4 PA5

400 350 290 220

PA0 should be the only one significantly changing but it interferes with the other channels data

Here is how im printing the data

uint16_t adc_dma_buffer[4];

while(1)

{

uint16_t fsr1_data = adc_dma_buffer[0];

uint16_t fsr2_data = adc_dma_buffer[1];

uint16_t fsr3_data = adc_dma_buffer[2];

uint16_t fsr4_data = adc_dma_buffer[3];

// Do every 1s

char buffer[100];

// Print ADC conversion results

sprintf(buffer, "%d\t %d\t %d\t %d\r\n", fsr1_data, fsr2_data, fsr3_data, fsr4_data);

 putty_print("FSR number: ");

  putty_print(buffer);

}

Here is my code for the ADC and DMA

#include "FSRs.h"

#include "stm32f0xx_hal.h"

#include "GPIOs.h"

void FSRs_init() {

// SETTING UP THE PINS

// Enable GPIOA clock

RCC->AHBENR |= RCC_AHBENR_GPIOAEN;

// Configure pin PA0, PA1, PA4 PA5 as analog

GPIOA->MODER &= ~(GPIO_MODER_MODER0 | GPIO_MODER_MODER1 | GPIO_MODER_MODER4 | GPIO_MODER_MODER5);

GPIOA->MODER |= GPIO_MODER_MODER0 | GPIO_MODER_MODER1 | GPIO_MODER_MODER4 | GPIO_MODER_MODER5;

// SETTING UP ADC

// Enable ADC clock

RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;

// Reset ADC configuration

ADC1->CR = 0;

ADC1->CFGR1 = 0;

ADC1->CFGR2 = 0;

ADC1->CHSELR = 0;

// Enable continuous conversion mode

ADC1->CFGR1 |= ADC_CFGR1_CONT;

// 12-bit resolution

ADC1->CFGR1 &= ~ ADC_CFGR1_RES;

// Select PCLK/2 as ADC clock

ADC1->CFGR2 |= ADC_CFGR2_CKMODE_1;

// Set sampling time to 28.5 ADC clock cycles

ADC1->SMPR = 0x03;

// Select channel 0, 1, 4, 5

ADC1->CHSELR |= ADC_CHSELR_CHSEL0 | ADC_CHSELR_CHSEL1 | ADC_CHSELR_CHSEL4 | ADC_CHSELR_CHSEL5;

// SETTING UP DMA

// Start DMA clock

RCC->AHBENR |= RCC_AHBENR_DMA1EN;

// Peripheral is ADC1 DR

DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;

// Memory is adc_dma_buffer

DMA1_Channel1->CMAR = (uint32_t)adc_dma_buffer;

// Set Memory Buffer size

DMA1_Channel1->CNDTR = 4;

// Reset DMA1 Channel 1 configuration

DMA1_Channel1->CCR = 0x00000000;

// Configure DMA1 Channel 1

// Peripheral -> Memory

// Peripheral is 16-bit, no increment

// Memory is 16-bit, increment

// Circular mode

DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0 | DMA_CCR_PSIZE_0 | DMA_CCR_MINC | DMA_CCR_CIRC;

// Enable DMA1 Channel 1

DMA1_Channel1->CCR |= DMA_CCR_EN;

/* (1) Ensure that ADEN = 0 */

 /* (2) Clear ADEN by setting ADDIS*/

 /* (3) Clear DMAEN */

 /* (4) Launch the calibration by setting ADCAL */

 /* (5) Wait until ADCAL=0 */

if ((ADC1->CR & ADC_CR_ADEN) != 0) /* (1) */

{

ADC1->CR |= ADC_CR_ADDIS; /* (2) */

}

while ((ADC1->CR & ADC_CR_ADEN) != 0)

{

/* For robust implementation, add here time-out management */

}

ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN; /* (3) */

ADC1->CR |= ADC_CR_ADCAL; /* (4) */

while ((ADC1->CR & ADC_CR_ADCAL) != 0) /* (5) */

{

/* For robust implementation, add here time-out management */

}

 // START ADC

// Enable ADC DMA Request in circular mode

ADC1->CFGR1 |= ADC_CFGR1_DMACFG | ADC_CFGR1_DMAEN;

// Enable ADC

ADC1->CR |= ADC_CR_ADEN;

// Start conversion

ADC1->CR |= ADC_CR_ADSTART;

}

6 REPLIES 6

Are the ADC inputs fed from low-impedance sources? Show us schematics.

JW

PS. Change your username to a normal nick.

Paulset
Associate II

Each pin is connected to a force sensor and about 3.3 volts. The force sensor is:

Resistors Force Sensing Standard Round Format Connector Housing

Manufacturer #: FSR03CE

Allied Stock #: 71202270

and the specs and features of it are as follows:

Series Features:

Small, thin and light

Largely immune to EMI and water events

Low power

False touch rejection

Cost effective

Highly Durable (>10M activations typical)

Long term drift 1kg for 48hrs, Per log time < 2%

Single part repeatability 100 actuations of 1kg, 1 standard deviation/mean 5%

Part to part repeatability 100 sensors same batch, 1 std. deviation/mean ±10%

Low temp. storage –20°C for 250hrs, Avg. change in resistance of 5 Sensors 2%

High temp. storage +85°C for 250hrs, Avg. change in resistance of 5 Sensors 9%

High humidity storage +85°C/85%RH for 250hrs, Avg. change in resistance of 5 sensors 10%

Lifecycle durability (10M) 1kg force at 3Hz, Avg. change in resistance of 4 sensors 4%

Hysteresis 100 actuations of 1kg, Avg. change in resistance of 100 samples 5%

Operational temp. range 100 cycles at 0.5kg, –20 to +60°C

Linear resistance Resistance between pins 1 & 2, Average of 100 parts same batch:

— FSP01CE: 1.25k, ±15%

— FSP02CE: 0.76k, ±15%

— FSP03CE: ±15%

OK, those are basically variable resistors. How exactly do you have them electrically connected to the ADC inputs?

JW

Paulset
Associate II

they are all connected to a 3.3 volt line from the STM itself

I also found this thread as well, that i think would be useful but the Links given are dead and unhelpful. is there a template showing multiple channels of the ADC using a DMA?

https://community.st.com/s/question/0D50X00009Xkgn8/stm32f072-adc-and-dma-help

You can't measure resistance by connecting resistors one end to VCC and other to ADC input. You'd need to put it as part of a voltage divider and condition the output by an amplifier.

JW