Digilent Pmod i STM32 (cz. 5) – PmodCLS, PmodDPG1 i PmodISNS20
PmodISNS20
Ostatnim z prezentowanych w artykule modułów jest PmodISNS20, czyli moduł do pomiaru prądu oparty o czujnik ACS722. Czujnik ten jest w stanie mierzyć prąd stały lub zmienny o maksymalnej wartości 20 A. Układ posiada wyjście analogowe, z którego można odczytać napięcie proporcjonalne do mierzonego natężenia prądu. Czułość pomiaru wynosi 66 mV/A, a maksymalny błąd pomiaru 3%. Układ ACS722 umożliwia wybór pasma sygnału wyjściowego na 80 kHz, lub 20 kHz – jego zmiana jest możliwa za pomocą zworki JP2. Dodatkowo moduł PmodISNS20 pozwala na włączenie filtra analogowego, ograniczającego pasmo do 120 Hz – służy do tego zworka JP1. 12-bitowy przetwornik analogowo-cyfrowy ADCS7476 z interfejsem SPI mierzy napięcie wyjściowe. Przetwornik omówiono już przy okazji opisu modułu PmodDPG1.
Fotografia 6. Moduł PmodISNS20
Podobnie jak w przypadku dwóch poprzednich modułów omówionych w artykule, PmodISNS20 powinien zostać podłączony do złącza Pmod-SPI znajdującego się na płytce KAmeleon, tak jak na fotografii 7. Połączenia pinów mikrokontrolera z pinami modułu są zgodne z wymienionymi w tabeli 1.
Fotografia 7. Moduł PmodISNS20 podłączony do zestawu KAmeleon
Konfiguracja interfejsu SPI
Konfiguracja SPI dla ADCS7476, przedstawiona na listingu 8 i zaimplementowana w pliku src/PmodISNS20.c, wygląda podobnie jak w przypadku modułu PmodDPG1, jednak w tym przypadku pokażemy programową kontrolę linii CS.
Listing 8. Inicjalizacja interfejsu SPI dla PmodISNS20
SPI_HandleTypeDef pmodIsns20Spi; void PmodISNS20_Config(void) { // Configure the SPI connected to the Pmod module. Only the MISO line is required. pmodIsns20Spi.Instance = SPI1; pmodIsns20Spi.Init.Mode = SPI_MODE_MASTER; pmodIsns20Spi.Init.Direction = SPI_DIRECTION_2LINES_RXONLY; pmodIsns20Spi.Init.DataSize = SPI_DATASIZE_16BIT; pmodIsns20Spi.Init.CLKPolarity = SPI_POLARITY_HIGH; pmodIsns20Spi.Init.CLKPhase = SPI_PHASE_1EDGE; pmodIsns20Spi.Init.NSS = SPI_NSS_SOFT; pmodIsns20Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; pmodIsns20Spi.Init.FirstBit = SPI_FIRSTBIT_MSB; pmodIsns20Spi.Init.TIMode = SPI_TIMODE_DISABLE; pmodIsns20Spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; pmodIsns20Spi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; HAL_SPI_Init(&pmodIsns20Spi); }
Ze względu na różnicę w konfiguracji SPI, zmianie musi też ulec konfiguracja GPIO, w której pin PB0, odpowiadający sygnałowi CS, działa jako wyjście z rezystorem podciągającym. Widać to na listingu 9.
Listing 9. Inicjalizacja pinów interfejsu SPI dla PmodISNS20
// Initialize GPIO used by the SPI2 peripheral. The CS is configured by the software (PB0 pin). __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; GPIO_InitStruct.Pin = GPIO_PIN_1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_14; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pin = GPIO_PIN_0; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
Odczyt i konwersja danych
Ostatnia z funkcji, pokazana na listingu 10, odczytuje wartość napięcia z przetwornika analogowo-cyfrowego. Następnie dokonuje jego konwersji na natężenie prądu mierzone przez czujnik ACS722. Transfer SPI należy wykonać dwukrotnie, ponieważ za pierwszym razem przetwornik dokonuje konwersji, a za drugim odczytywana jest zmierzona wartość. Konwersję na natężenie prądu zaimplementowano zgodnie z zależnością:
Listing 10. Odczyt i konwersja wartości różnicy ciśnienia
int32_t PmodISNS20_GetValue(void) { uint16_t adcValue = 0; HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_SPI_Receive(&pmodIsns20Spi, (uint8_t*)&adcValue, 1, 100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); HAL_SPI_Receive(&pmodIsns20Spi, (uint8_t*)&adcValue, 1, 100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // The current value in [mA] is calculated according to the formula given in the PmodISNS20 // reference manual. return (int32_t)(((int16_t)adcValue - 2048) * 1000.0 / 89.95); }
Przykładowy program dokonuje pomiaru natężenia prądu co pół sekundy. Zmierzoną wartość kod wypisuje na port szeregowy LPUART1 obsługiwany przez funkcje zaimplementowane w pliku src/serial.c.