I am using ChibiOS/RT v. 2.6.2 on Lisa M 2.0 board with Paparazzi autopilo (STM32F105 chip, pinout and some info about the board and the autopilot here http://paparazzi.enac.fr/wiki/Lisa/M_v2.0).
There are 4 ADC channels available plus the CPU temperature sensor. I use ADC1 (only ADC available for this chip) in circular buffer mode. I noticed, that no matter what is the order of the channels, voltage change in one channel affects measured voltage in the next channel in the sequence.
For example, my sequence is ADC13, ADC11, ADC10, ADC14. If I connect ADC13 to Vref, I can see voltage increase also on ADC11. If I connect ADC10 to Vref, then voltage on ADC14 jumps up. I am pretty sure that I am reading buffer from the callback correctly.
Different timing settings or buffer size has no effect on this behavior.
A workaround seems to be to include "dummy" channels in the sequence (i.e. ADC13 - DUMMY - ADC11 - DUMMY - ADC10 - DUMMY - ADC14). Then the next measurement in the sequence shows correct value. Disadvantage is that you have to use twice as much memory and time to do the conversion.
My code:
Code: Select all
#define ADC_NUM_CHANNELS 9
#define ADC_BUF_DEPTH 32
#define ADC_V_REF_MV 3300
#define ADC_12_BIT_RESOLUTION 4096
static adcsample_t adc_samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH] = {0};
struct adc_buf {
uint32_t sum; /* Sum of samples in buffer (avg = sum / av_nb_sample) */
uint16_t values[MAX_AV_NB_SAMPLE]; /* Buffer for sample values from ADC */
uint8_t head; /* Position index of write head in buffer */
uint8_t av_nb_sample; /* Number of samples to use in buffer (used for avg) */
};
static struct adc_buf * adc1_buffers[ADC_NUM_CHANNELS] = {NULL};
void adc1callback(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
if (adcp->state != ADC_STOP) {
for(uint8_t channel = 0; channel < ADC_NUM_CHANNELS; channel+=2) {
if (adc1_buffers[channel/2] != NULL) {
adc1_buffers[channel/2]->sum = 0;
adc1_buffers[channel/2]->av_nb_sample = n;
for (uint8_t sample = 0; sample < n; sample++) {
adc1_buffers[channel/2]->sum += buffer[channel + sample*ADC_NUM_CHANNELS];
}
adc1_buffers[channel/2]->sum = (adc1_buffers[channel/2]->sum)*ADC_V_REF_MV/ADC_12_BIT_RESOLUTION;
}
}
}
}
static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) {
chSysLockFromIsr();
adcp_err = adcp;
adc_error_flag = err;
chSysUnlockFromIsr();
}
/*
* Conversion config for ADC
* @note: Continuous conversion
* Including Temp sensor, Ts = 7 + 12.5 = 19.5us
* ADCCLK = 14 MHz
* Rest of ADcs Ts = 41.5c + 12.5c = 54.0us
*/
static const ADCConversionGroup adcgrpcfg = {
TRUE,
ADC_NUM_CHANNELS,
adc1callback,
adcerrorcallback,
0, ADC_CR2_TSVREFE,
ADC_SMPR1_SMP_AN10(ADC_SAMPLE_41P5) | ADC_SMPR1_SMP_AN11(ADC_SAMPLE_41P5) |
ADC_SMPR1_SMP_AN13(ADC_SAMPLE_41P5) | ADC_SMPR1_SMP_AN14(ADC_SAMPLE_41P5) | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_7P5),
0,
ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
ADC_SQR2_SQ9_N(ADC_CHANNEL_SENSOR) |ADC_SQR2_SQ7_N(ADC_CHANNEL_IN14),
ADC_SQR3_SQ5_N(ADC_CHANNEL_IN11) | ADC_SQR3_SQ3_N(ADC_CHANNEL_IN10) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN13)
};
then in my thread I run:
Code: Select all
adcStart(&ADCD1, NULL);
adcStartConversion(&ADCD1, &adcgrpcfg, adc_samples, ADC_BUF_DEPTH);
Do you have any idea what might be wrong? Might it be HW issue?
Regards
Michal