Obliczenie FFT na mikrokontrolerze STM32 – #3 – Pomiar trzech przebiegów za pomocą niezależnych przetworników analogowo-cyfrowych z wykorzystaniem DMA i trybu Combined regular simultaneous + alternate trigger mode w celu dokładnego pomiaru przesunięcia fazowego na procesorze STM32F103

Na rozgrzewkę:

Obliczenia zawarte w dwóch poprzednich wpisach z serii dotyczącej FFT wykonane były za pomocą płytki ewaluacyjnej STM32F401C-DISCO, w docelowym projekcie użyłem procesora STM32F103VET6, który dysponuje trzema niezależnymi przetwornikami analogowo-cyfrowymi. Dobierając ten procesor, sprawdziłem, że ma on trzy niezależne przetworniki ADC, lecz nie sprawdziłem, czy każdy z nich dysponuje swoim DMA. W projekcie chciałem mierzyć dokładne przesunięcie fazowe między przebiegami prądu i dwoma przebiegami napięcia stąd zależało mi na pomiarze przebiegów z wykorzystaniem DMA. Po wykonaniu PCB, konfigurując procesor i dalej podczas zgłębiania dokumentacji dowiedziałem się, że jeden z przetworników nie posiada DMA. Dalej przeglądając dokumentację, zastanawiałem się jak rozwiązać problem. Wyczytałem, że jest możliwość pomiaru z wykorzystaniem DMA drugiego przetwornika, kiedy pierwszy przetwornik jest masterem, a drugi slave. We wpisie zajmę się implementacją pomiaru z wykorzystaniem DMA w konfiguracji master i slave.

Jeśli chcesz nabyć płytki deweloperskie lub mikrokontrolery STM32, na których będziesz mógł wykonać projekty związane z przetwarzaniem sygnałów, zapraszam do sklepu msalamon.pl

Sponsorem wpisu jest msalamon.pl
WWW: https://msalamon.pl/
Sklep: https://sklep.msalamon.pl/

Zakres wpisu:

  • Procesor STM32F103VET6
  • Konfiguracja STM32F103VET6 w STM32CubeIDE
  • Program dla STM32F103VET6
  • Działanie programu

Procesor STM32F103VET6:

Do swojego projektu dobrałem procesor STM32F103VET6, który charakteryzuje się następującymi parametrami:

Dobierając ten procesor, zależało mi na następujących aspektach:

  • minimum 3 niezależne przetworniki ADC z DMA,
  • możliwość podłączenia zewnętrznej referencji analogowej (dostępne w obudowie LQFP100),
  • niski błąd przetwornika ADC (Total Unadjusted Error),
  • dwa przetworniki DAC.

Po wykonaniu PCB dowiedziałem się, że ADC2 nie posiada DMA. Znalazłem rozwązanie tego problemu, którego opis przedstawiłem poniżej z Reference Manual STM32F103 [1]:

Konfiguracja STM32F103VET6 w STM32CubeIDE:

Przetworniki ADC1 i ADC2 mogą pracować ze sobą, używając tego samego DMA. Przetwornik ADC1 jest masterem, ADC2 slave. Tryb pracy, o którym wspominam, nazywa się Dual regular simultaneous + alternate trigger mode. Konwersja przetworników ADC1, ADC2 i ADC3 wyzwalana jest za pomocą tego samego timera (Timer 8).

Konfiguracja ADC1:

Istotnym aspektem jest zmiana szerokości przesyłanych danych poprzez DMA z Half Word do Word zarówno po stronie przetwornika, jak i pamięci. Wynika to z tego, że jednocześnie przesyłane są dane z ADC1, jak i ADC2.

Konfiguracja ADC2:

Konfiguracja ADC3:

Program dla STM32F103VET6:

Liczba próbek zbierana przez pierwszy, jak i drugi przetwornik musi być równa, a długość bufora, w którym będą przechowywane próbki, musi być sumą próbek zbieranych przez przetworniki. W moim przypadku zbieram 512 próbek za pomocą ADC1 i 512 próbek za pomocą ADC2, więc bufor powinien mieć długość 1024 próbek.

Poniżej umieszczone są funkcje, które startują przetworniki ADC1, ADC2 oraz ADC3. Przetworniki pierwszy i drugi będą pracowały w trybie master, slave, ADC3 niezależnie.

HAL_ADCEx_MultiModeStart_DMA(&hadc1, (uint32_t*)&Buffer_ADC1_ADC2, BUFFER_SIZE);
HAL_ADC_Start_DMA(&hadc3, (uint32_t*)&Source_Voltage, BUFFER_SIZE);

Kolejnym krokiem będzie rozdzielenie wartości z ADC1 od wartości z ADC2. Wartości z ADC1 przechowywane są w pozycjach parzystych tablicy, a wartości z ADC2 w pozycjach nieparzystych. Rozdzielenie zrealizowałem za pomocą pętli for.

if(Current_FFT_status==1)
{
	for(uint16_t i=0; i<BUFFER_SIZE; i++)
	{
		Current_Value[i]= (Buffer_ADC1_ADC2[i*2]);
	}
}

if(Current_FFT_status==1)
{
	 for(uint16_t i=0; i<BUFFER_SIZE; i++)
	 {
		 Voltage_Value[i]= (Buffer_ADC1_ADC2[i*2+1]);
	 }
}

Informację o zebraniu wymaganej ilości próbek pobierane są z funkcji Callback:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{

	if(hadc->Instance == ADC1)
	{
		Current_FFT_status=1;
	}

	if(hadc->Instance == ADC3)
	{
		Voltage_Source_FFT_status=1;
	}

}

Działanie programu:

Korzystając z programu STMStudio, odczytałem zebrane próbki sprawdzając je. Jak widać na Rys. 10, dane są prawidłowo zebrane oraz występuje przesunięcie fazowe pomiędzy prądem i napięciem. Tak zebrane dane można dalej wykorzystywać do kolejnych operacji, w moim przypadku FFT.

Podsumowanie:

Finalnie moje niedopatrzenie wyszło nawet lepiej z perspektywy projektu, ponieważ przetwornik 1, jak i 2 są wyzwalane z tego samego timera oraz przesyłane do CPU poprzez to samo DMA, wykorzystując jeden bufor. Sytuacja ta daje gwarancję, że nie jest wprowadzane dodatkowe przesunięcie fazowe podczas pomiarów.

[1] Dostep w internecie: https://www.st.com/en/microcontrollers-microprocessors/stm32f103/documentation.html

Autor artykułu
Mateusz Pluta

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.