[PRZYKŁAD] Sterowanie serwomechanizmem za pomocą joysticka oraz KA-NUCLEO-F411CE
Po zmontowaniu sprzętu można przejść do części programowej. Pierwszym etapem jest konfiguracja mikrokontrolera STM32 za pomocą programu STM32CubeMX
Szczegółowy opis narzędzia CubeMX znajduje się w artykule:
STM32Cube graficzny konfigurator STM32
Po uruchomieniu narzędzia i wybraniu nowego projektu należy określić, z jakim procesorem będziemy mieć do czynienia. W poszukiwaniach można sobie pomóc wybierając odpowiedni rdzeń (1), serię (2) oraz linię procesora (3) na pasku bocznym. W naszym przypadku jest to model STM32F411CEUx (4). Wybór zatwierdza się przyciskiem Start Project (5).
Po utworzeniu projektu trzeba skonfigurować źródło taktowania procesora i magistrali peryferiów. W tym celu, po rozwinięciu listy RCC, przy ustawieniu High Speed Clock (HSE) należy wybrać Crystal/Ceramic Resonator (1). Następnie można ustawić rolę odpowiednich pinów mikrokontrolera. Dla Joysticka będzie to pin analogowy A1. W tym celu, po rozwinięciu listy ADC1, zaznaczamy opcję IN1 (2). Po tych operacjach piny PH0, PH1 i PA1 powinny zmienić kolor na zielono. Ostatni z nich odpowiada pinowi A1 na płytce.
Teraz należy ustawić rolę pinu D9 jako wyjścia PWM. W tym celu trzeba kliknąć na pin PB7 i wybrać opcję TIM4_CH2. Na panelu bocznym, po rozwinięciu listy TIM4, powinno się oznaczyć opcję Internal Clock a z listy Channel 2 wybrać PWM Generation CH2.
Zakładka Clock Configuration służy do konfiguracji częstotliwości taktowania wewnątrz procesora. Parametr Input Frequency należy ustawić na wartość 8 MHz (1). Źródłem sygnału pętli PLL powinien być sygnał z oscylatora, a więc HSE (2). Częstotliwość zegara HCLK trzeba ustawić na 100 MHZ (3). Prescaler magistrali ABP1 powinno się ustawić na /2 (4).
W tym momencie należy przejść do zakładki Configuration. Po naciśnięciu przycisku ADC1 można ustawić konfigurację przetwornika Analogowo-Cyfrowego. Aby uzyskać najlepszą dokładność i dobrą szybkość przetwarzania powinno się ustawić opcje: Clock prescaler na PCLK2 divided by 4 (1) i Resolution na 12 bits (15 ADC Clock cycles). Resztę opcji można pozostawić domyślnie, jednak należy sprawdzić czy opcja Data Alignment jest ustawiona w stan Right aligment (To ustawienie powoduje naturalne rozłożenie bitów w zwracanej próbce t.j. najmłodszy bit jest po prawej stronie) (3).
W zakładce TIM4 można ustawić parametry sygnału PWM. Sygnał ten powinien mieć częstotliwość 50 Hz i dokładność ustawianego wypełnienia 0,1% (Przy takich parametrach serwomechanizmu daje to rozdzielczość ustawianego kąta ok. 1°). Dokładność można ustawić wpisując wartość do rejestru Counter Period. Wpisujemy tam ilość stopni swobody minus 1, co daje nam wartość 999 (1). Wartość prescalera obliczamy z wzoru:
PSC = (TIM_CLK/((ARR+1)*FREQ)) – 1
Gdzie:
- TIM_CLK – zegar magistrali, w tym przypadku 50 MHz
- ARR – wartość rejestru Counter Period, w tym przypadku 999
- FREQ – wymagana częstotliwość sygnału PWM, w tym przypadku 50 Hz
Obliczona wartość wpisujemy do konfiguratora (2):
PSC = (50000000/((999+1)*50)) – 1 = 999
Po wpisaniu nazwy projektu (1), folderu(2) oraz wyborze środowiska (3) w zakładce Project > Settings, należy wygenerować kod za pomocą opcji Project > Generate Code. W przykładzie wykorzystywane jest środowisko System Workbench for STM32, które w programie CubeMX obecne jest pod nazwą SW4STM32.
Po wygenerowaniu możemy od razu nacisnąć Open Project, aby przejść do uzupełnienia kodu (Cały projekt znajduje się w sekcji „do pobrania”). Na początku należy zaimportować niezbędną bibliotekę math.
/* USER CODE BEGIN Includes */ #include <math.h> /* USER CODE END Includes */
W następnym kroku powinno się zainicjalizować niezbędne zmienne:
/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ uint16_t pomiarADC; int przesuniecie; /* USER CODE END PV */
Po wykonaniu wszystkich funkcji inicjalizujących peryferia, należy je włączyć następującymi poleceniami:
/* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2); HAL_ADC_Start(&hadc1); /* USER CODE END 2 */
W pętli głównej programu z przetwornika ADC pobierana jest próbka danych, a następnie obliczana jest wartość wypełnienia PWM. Wzór wynika z faktu, że maksymalne wychylenie serwa w lewo powinno się osiągnąć dla napięcia na przetworniku 0 V, a w prawo – dla napięcia 3,3 V. Liczba, jaka należy wpisać do rejestru CCR2 jest – dla tych ustawień – stukrotnością długości impulsu w milisekundach. Obliczona wartość znajduje się w zmiennej przesuniecie, której wartość od razu wpisywana jest do rejestru CCR2. Następnie ponownie włączany jest przetwornik ADC, a także wprowadzane jest niewielkie opóźnienie, które jednak nie ma widocznego wpływu na płynność działania.
while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ pomiarADC = HAL_ADC_GetValue(&hadc1); przesuniecie = round(60+pomiarADC*(190.0/4095.0)); TIM4->CCR2 = przesuniecie; HAL_ADC_Start(&hadc1); HAL_Delay(1); } /* USER CODE END 3 */
Działanie programu zostało przedstawione na poniższym filmie: