2019-08-28 05:21 AM
Hello!
I have found a lot of examples about simple ADC reads, with:
-single channel single conversion
-single channel continuous conversion
-multi channel single conversion
-multi channel continuous conversion
And these with polling, interrupt and DMA.
I need to measure singple phase AC voltage and current.
Hardware built up:
-VDDA 3.3V
-VSSA AGND
-Vref 3V
-PA6-PA7 differential pair AC voltage
-PC4-PC5 differential pair AC current
I need Dual Regular mode plus Differential read.
Hardware side without load (0V AC) on both pair I have 1.5V. For example if there is 100V AC then PA6 bigger than 1.5V, PA7 smaller than 1.5V. This differential value I need to measure.
Right now without success.
In stm32cubeL4 examples have found this: Diff conversion result = mid-range + (channel_high-channel_low)/2
In 16bit case this means: (let's say 1.5V = ~33500)
without load: 32768-65536 + (33500 - 33500) / 2 = -32768 ???
with load: 32768-65536 + (33800 - 33200) / 2 = -32468 ???
I need only the difference: 33800 - 33200 = 600
I don't really know how to do it in right way. Not so much useful examples on web.
The questions:
-How to adjust cubeMX for ADC1 differential pair?
-How to adjust cubeMX for ADC1+ADC2 in dual mode + differential pair?
-How to start and get value with HAL from differential pair?
-How to start and get value with HAL from dual mode + differential pair?
It must be possible.
For start no matter is it polling, interrupt, or DMA
STM32 H743ZI
C
Thanks for every answers
Szilveszter
2019-09-03 07:29 AM
Okey, so I have made it, just not really work how I want it to work. But it works.
The code:
/*
* the example code is from dual interleaved mode configuration. But here below is only Dual regular mode
*/
#define ADCCONVERTEDVALUES_BUFFER_SIZE ((uint32_t) 1) //256 was before /* Size of array containing ADC converted values */
/**
* @brief Computation of ADC master conversion result
* from ADC dual mode conversion result (ADC master and ADC slave
* results concatenated on data register of ADC master).
* @param DATA: ADC dual mode conversion result
* @retval None
*/
#define COMPUTATION_DUALMODEINTERLEAVED_ADCMASTER_RESULT(DATA) \
((DATA) & 0x0000FFFF)
/**
* @brief Computation of ADC slave conversion result
* from ADC dual mode conversion result (ADC master and ADC slave
* results concatenated on data register of ADC master).
* @param DATA: ADC dual mode conversion result
* @retval None
*/
#define COMPUTATION_DUALMODEINTERLEAVED_ADCSLAVE_RESULT(DATA) \
((DATA) >> 16)
ADC_HandleTypeDef hadc1; /* Master */
ADC_HandleTypeDef hadc2; /* Slave */
ALIGN_32BYTES(__IO uint32_t aADCDualConvertedValues[ADCCONVERTEDVALUES_BUFFER_SIZE]); /* ADC dual mode interleaved conversion results (ADC master and ADC slave results concatenated on data register 32 bits of ADC master). */
ALIGN_32BYTES(__IO uint16_t aADCxConvertedValues[ADCCONVERTEDVALUES_BUFFER_SIZE]); /* For the purpose of this example, dispatch dual conversion values into arrays corresponding to each ADC conversion values. */
ALIGN_32BYTES(__IO uint16_t aADCyConvertedValues[ADCCONVERTEDVALUES_BUFFER_SIZE]); /* For the purpose of this example, dispatch dual conversion values into arrays corresponding to each ADC conversion values. */
uint8_t ubADCDualConversionComplete = RESET; /* Set into ADC conversion complete callback */
/* End of conversion interrupt */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc){
uint32_t tmp_index = 0;
/* For the purpose of this example, dispatch dual conversion values */
/* into 2 arrays corresponding to each ADC conversion values. */
for (tmp_index = (ADCCONVERTEDVALUES_BUFFER_SIZE/2); tmp_index < ADCCONVERTEDVALUES_BUFFER_SIZE; tmp_index++)
{
aADCxConvertedValues[tmp_index] = (uint16_t) COMPUTATION_DUALMODEINTERLEAVED_ADCMASTER_RESULT(aADCDualConvertedValues[tmp_index]);
aADCyConvertedValues[tmp_index] = (uint16_t) COMPUTATION_DUALMODEINTERLEAVED_ADCSLAVE_RESULT(aADCDualConvertedValues[tmp_index]);
}
/* ADCCONVERTEDVALUES_BUFFER_SIZE was 256, I have changed it to 1. Right now it's not clear why it was so big buffer */
float32_t ACCurrent = (((uint16_t)aADCxConvertedValues[0] * 6000) / 0xFFFF) - 3000; /* Result value is the difference between to differential wires in mV. It can be also negative value */
float32_t ACVoltage = (((uint16_t)aADCyConvertedValues[0] * 6000) / 0xFFFF) - 3000; /* Result value is the difference between to differential wires in mV. It can be also negative value */
ubADCDualConversionComplete = SET;
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_11);
}
/* Half conversion interrupt */
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc){
uint32_t tmp_index = 0;
/* For the purpose of this example, dispatch dual conversion values */
/* into 2 arrays corresponding to each ADC conversion values. */
for (tmp_index = 0; tmp_index < (ADCCONVERTEDVALUES_BUFFER_SIZE/2); tmp_index++)
{
aADCxConvertedValues[tmp_index] = (uint16_t) COMPUTATION_DUALMODEINTERLEAVED_ADCMASTER_RESULT(aADCDualConvertedValues[tmp_index]);
aADCyConvertedValues[tmp_index] = (uint16_t) COMPUTATION_DUALMODEINTERLEAVED_ADCSLAVE_RESULT(aADCDualConvertedValues[tmp_index]);
}
ubADCDualConversionComplete = RESET;
}
int main(void)
{
HAL_ADCEx_Calibration_Start(&hadc1, ADC_CALIB_OFFSET, ADC_DIFFERENTIAL_ENDED); /* attach differential mode to ADC1 */
HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET, ADC_DIFFERENTIAL_ENDED); /* attach differential mode to ADC2 */
HAL_ADC_Start(&hadc2); /* start in normal mode ADC2 */
HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t *)aADCDualConvertedValues, ADCCONVERTEDVALUES_BUFFER_SIZE); /* start in multimode DMA ADC1 as master */
/*
* these steps are neccessary to start the dual regual adc read in differential mode. ADC1 as master and ADC2 as slave. Internally ADC1 triggering ADC2.
* here are some things what right now i don't really understand, like line-90, that why need to start ADC2 in normal mode.
* Don't forget to use always on the read data this calculation:
* ((adc_value * 6000) / 0xFFFF) - 3000;
* ((adc_value * VrefX2) / resolution in hex) - Vref;
*/
while (1)
{
}
}
Values are good. Printf works in interrupt so I have made some output messages.
The problem again, that the while(1) don't get time to run. For example an printf("hello") will not happen.
What should I do?
Szilveszter