Digilent Pmod i STM32 (cz. 3) – PmodACL i PmodMAXSONAR
PmodMAXSONAR
PmodMAXSONAR jest ultradźwiękowym czujnikiem odległości z modułem MB1010 LV-MaxSonar-EZ1. Urządzenie jest w stanie wykryć odległość od obiektów w zasięgu od 6 do 255 cali, a pomiary są wykonywane z rozdzielczością jednego cala. Wyniki pomiarów są udostępniane za pośrednictwem interfejsu UART, analogowo, a także w postaci sygnału PWM o zmiennym wypełnieniu: stan wysoki trwa 1 ms, a stan niski 147 µs na każdy cal wykrytej odległości od przeszkody. W omawianym przykładzie dane są odczytywane przez UART, natomiast stan pinu PWM jest dodatkowo sygnalizowany przez diodę na płytce KAmeleon.
Fotografia 4. Wygląd modułu PmodMAXSONAR
Połączenie z KAmeleonem
Moduł PmodMAXSONAR dysponuje 6-pinowym interfejsem UART typu 4, jednak zamiast pinów kontroli przepływu CTS i RTS udostępniono odpowiednio piny AN (odczyt analogowy), a także PWM. W przykładzie moduł podłączono do złącza ESP8266/UART na płytce KAmeleon. Złącze to udostępnia interfejs USART2 oraz dodatkowy pin PF11. Listę pinów na złączu PmodMAXSONAR, wraz z odpowiadającymi im pinami złącza ESP8266/UART i pinami mikrokontrolera, przedstawiono w tabeli 3, natomiast podłączony moduł zaprezentowano na fotografii 5.
Tabela 3. Sygnały PmodMAXSONAR oraz odpowiadające im piny złącza ESP8266/UART i piny mikrokontrolera
Sygnał | Numer pinu PmodMAXSONAR | Numer pinu KAmeleon ESP8266/UART | Pin mikrokontrolera |
AN | 1 | – | – |
RX | 2 | 1 (TX/PA2) | PA2 |
TX | 3 | 8 (RX/PA3) | PA3 |
PW | 4 | 6 (PD/PF11) | PF11 |
GND | 5 | 7 (GND) | – |
VCC | 6 | 2 (+3,3V) | – |
Fotografia 5. Moduł PmodMAXSONAR podłączony do płytki KAmeleon
Interfejs UART
Do komunikacji z modułem PmodMAXSONAR używany jest wyłącznie pin PA3, czyli RX po stronie mikrokontrolera. Pin PA2 powinien być na stałe w stanie wysokim. Jest to możliwe, ponieważ moduł PmodMAXSONAR nie wymaga żadnej konfiguracji. Po włączeniu zasilania wykonuje kalibrację i rozpoczyna od razu wysyłać dane pomiarowe przez UART, a także piny AN i PWM. Dane są wysyłane raz na 49 ms. Konfiguracja modułu w prezentowanym przykładzie znajduje się w funkcji PmodMAXSONAR_Config, znajdującej się w pliku src/PmodMAXSONAR.c i przedstawionej na listingu 6.
Listing 6. Konfiguracja interfejsu UART i linii przerwań do komunikacji z modułem PmodMAXSONAR
void PmodMAXSONAR_Config(void) { __HAL_RCC_GPIOF_CLK_ENABLE(); // Configure the interrupts on PF11 (PWM) pin. The interrupts are active on both edges // to show the PWM signal duty cycle. GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pin = GPIO_PIN_11; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0); HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); // The UART interface is used only for data reception. The TX pin should be kept high. pmodMaxsonarUart.Instance = USART2; pmodMaxsonarUart.Init.BaudRate = 9600; pmodMaxsonarUart.Init.WordLength = UART_WORDLENGTH_8B; pmodMaxsonarUart.Init.StopBits = UART_STOPBITS_1; pmodMaxsonarUart.Init.Parity = UART_PARITY_NONE; pmodMaxsonarUart.Init.Mode = UART_MODE_RX; pmodMaxsonarUart.Init.HwFlowCtl = UART_HWCONTROL_NONE; pmodMaxsonarUart.Init.OverSampling = UART_OVERSAMPLING_16; pmodMaxsonarUart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; HAL_UART_Init(&pmodMaxsonarUart); }
Konfiguracja interfejsów w mikrokontrolerze
W pierwszym kroku konfigurowane jest przerwanie na pinie PF11, które będzie informowało o zmianie stanu sygnału PWM. Przerwanie to jest aktywne na obu zboczach sygnału wejściowego. Interfejs UART należy skonfigurować zgodnie z wymaganiami modułu PmodMAXSONAR, czyli 8 bitów danych, 1 bit stopu, brak parzystości i prędkość transmisji 9600 b/s. Podobnie, jak w przypadku innych interfejsów, wywołanie HAL_UART_Init powoduje wywołanie funkcji konfiguracyjnej HAL_UART_MspInit, w której można dokonać dalszej konfiguracji zegara i GPIO.
Z uwagi na to, że w przykładzie wykorzystano dwa interfejsy szeregowe, wspomnianą funkcję zaimplementowano w pliku src/main.c (listing 7). Sprawdza ona, który interfejs ma być konfigurowany i wywołuje odpowiednio funkcję PmodMAXSONAR_HAL_UART_MspInit, lub Serial_HAL_UART_MspInit. Pierwsza z nich, pokazana na listingu 8, ustawia pin PA2 w stanie wysokim, natomiast pin PA3 jako funkcję alternatywną dla interfejsu UART2. Na koniec włączane jest przerwanie od UARTa, które jest potrzebne do odbioru danych pomiarowych.
Listing 7. Konfiguracja interfejsów UART występujących w przykładzie
void HAL_UART_MspInit(UART_HandleTypeDef *huart) { if(huart->Instance == USART2) PmodMAXSONAR_HAL_UART_MspInit(huart); else if(huart->Instance == LPUART1) Serial_HAL_UART_MspInit(huart); }
Listing 8. Konfiguracja pinów do komunikacji z modułem PmodMAXSONAR
void PmodMAXSONAR_HAL_UART_MspInit(UART_HandleTypeDef *huart) { // Enable the clocks for GPIO pins used by the USART2 port (PA2, PA3). __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART2; GPIO_InitStruct.Pin = GPIO_PIN_3; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // The TX pin (PA2) - RX of the PmodMAXSONAR should be left in the high state // and not used for communication. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Pin = GPIO_PIN_2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // Enable the interrupts generated by USART2 port. HAL_NVIC_SetPriority(USART2_IRQn, 1, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); }
Odbiór danych z modułu PmodMAXSONAR
PmodMAXSONAR wysyła dane w określonym formacie: wielka litera ‘R’, zmierzona trzycyfrowa odległość wyrażona w calach (od 006 do 255) i znak powrotu karetki ‘\r’ (0x0D). Funkcję obsługi przerwania UART realizującą odbiór danych przedstawiono na listingu 9. Sprawdza ona czy odebranym znakiem jest ‘\r’. Jeżeli tak, to ustawia globalną flagę dataReady odczytywaną w głównej pętli programu, informując tym samym o gotowych danych. W przeciwnym razie znak dodawany jest do bufora i rozpoczyna się oczekiwanie na kolejny. Oczekiwanie na znak inicjalizuje funkcja PmodMAXSONAR_Read, będąca jedynie wrapperem na funkcję biblioteczną HAL_UART_Receive_IT. Główna pętla programu, znajdująca się w funkcji main, oczekuje na ustawienie flagi dataReady, po czym wysyła otrzymane dane na port szeregowy LPUART1 i inicjalizuje oczekiwanie na kolejne znaki.
Listing 9. Funkcja obsługi przerwania UART
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { // Look for the end of the line and notify the main loop. // Otherwise receive next character. if(dataBuffer.buffer[dataBuffer.index] == '\r') { dataBuffer.index++; dataReady = 1; } else { dataBuffer.index++; PmodMAXSONAR_Read(&dataBuffer.buffer[dataBuffer.index], 1); } }
Sygnał PWM modułu PmodMAXSONAR zgodnie z konfiguracją wywołuje przerwania na pinie PF11 mikrokontrolera. Funkcja obsługująca te przerwania znajduje się również w pliku src/main.c i zmienia stan diody LED0 płytki KAmeleon, dzięki czemu można zaobserwować zmieniające się wypełnienie sygnału PWM wraz ze zmianą odległości czujnika od przeszkody.