[PRZYKŁAD] STM32 NUCLEO-L476RG i KA-Nucleo-UniExp
Po wygenerowaniu projektu należy uzupełnić kod o niezbędną funkcjonalność.
Na początek należy dołączyć bibliotekę string.h oraz zdefiniować adresy akcelerometru LIS35DE jako stałe.
/* USER CODE BEGIN Includes */ #include <string.h> #define LIS35DE_WRITE_ADDRESS 0x38 #define LIS35DE_READ_ADDRESS 0x39 /* USER CODE END Includes */
Następnie zadeklarowano wszystkie niezbędne zmienne. To, jakie role będą pełnić opisałem w komentarzach do kodu.
/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ uint16_t Temp_raw; // "surowe" wartosci odczytane z sensorow int8_t x_raw, y_raw, z_raw; float temperatura, x_val, y_val, z_val; // przeliczone odczyty czujnikow float z_offset = 0.14; // przesuniecie akcelerometru na osi Z uint8_t Settings = 0x47; // wartosc jaka nalezy wpisac do rejestru CTRL_REG1 akcelerometru char send[50]; // Tablica przechowujaca wysylana wiadomosc char receive[50]; // Tablica przechowujaca wysylana wiadomosc char bufor [10], odczytX[10], odczytY[10], odczytZ[10]; //odczyty w formie tablicy znakow uint16_t size = 0; /* USER CODE END PV */
Następnie znajdują się deklaracje funkcji używanych dalej w programie. Poniżej znajdują się także ich definicje oraz omówienie.
/* USER CODE BEGIN 0 */ void HC05_Send(char* command); //wysyla komendy do modulu Bluetooth void konwertujNaString (char * tekst, float wartosc); //konwertuje wartosc float na lancuch znakow /* USER CODE END 0 */
Funkcja HC05_Send ma za zadanie wysyłać komendę do modułu HC05 za pośrednictwem portu szeregowego. Funkcja dodaje także znaki „\r\n” niezbędne do potwierdzenia końca komendy.
void HC05_Send(char* command) { sprintf(send, "%s", command); strcat(send, "\r\n"); size = strlen (send); HAL_UART_Transmit (&huart1, send, size, 100); }
Funkcja konwertujNaString ma za zadanie konwersję zmiennej typu float na łańcuch znaków. Proces ten jest niezbędny, aby przesłać wartość przez interfejs szeregowy lub np. na ekran LCD. Funkcja jest identyczna jak w innym przykładzie: [PRZYKŁAD] KAmodMMA7361LC – akcelerometr analogowy i KA-NUCLEO-F411CE.
void konwertujNaString (char * tekst, float wartosc) { int t; char temp[2]; itoa (abs((int)wartosc), temp, 10); if (wartosc < 0) // znak liczby strcpy (tekst, "-"); else strcpy(tekst,"+"); strcat(tekst, temp); // czesc calkowita strcat(tekst, "."); // kropka t = abs((int)((wartosc - (int)wartosc)*100)); itoa (t, temp, 10); if (t< 10) strcat(tekst, "0"); // "0" po kropce gdy czesc ulamkowa jest mniejsza niz 0.1 // Funkcja "itoa" go nie wstawia strcat(tekst, temp); //czesc ulamkowa }
W funkcji main, po inicjalizacji peryferiów, program uruchamia przetwornik ADC. Następnie uruchamia akcelerometr wpisując do rejestru CTRL_REG1 (20h) odpowiednią wartość (47h). Po tym do modułu HC-05 wysyłane są komendy AT, które mają za zadanie skonfigurować urządzenie. Przed wysłaniem komendy AT+RESET, pin KEY ustawiany jest w stan niski. W ten sposób, moduł Bluetooth po resecie ustawi się w tryb oczekiwania na połączenie.
/* USER CODE BEGIN 2 */ HAL_Delay(3000); HAL_ADC_Start(&hadc1); HAL_I2C_Mem_Write (&hi2c1, LIS35DE_WRITE_ADDRESS, 0x20, 1, &Settings, 1, 100); // HC05_Send("AT"); //komenda testowa HC05_Send("AT+INIT"); //inicjalizacja modulu HC05_Send("AT+ORGL"); //reset ustawien HC05_Send("AT+NAME=KA-NUCLEO-UniExp"); //zmiana nazwy urzadzenia HC05_Send("AT+PSWD=0000"); //zmiana hasla urzadzenia HAL_GPIO_WritePin(BT_KEY_GPIO_Port, BT_KEY_Pin, 0); HC05_Send("AT+RESET"); //reset urzadzenia /* USER CODE END 2 */
W pętli głównej program pobiera z czujników wartości temperatury oraz przyspieszenia w każdej osi. Następnie oblicza i skaluje je w odpowiednich jednostkach. (temperaturę w stopniach Celsujsza, przyspieszenie w wielokrotnościach przyspieszenia ziemskiego). Za pomocą funkcji konwertujNaString wartości wpisywane są do określonych łańcuchów znaków. Na koniec dane wysyłane są przez port szeregowy do modułu Bluetooth.
/* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) { //odczyt z czujnika temperatury Temp_raw = HAL_ADC_GetValue(&hadc1); HAL_ADC_Start(&hadc1); } temperatura = (1.8663-(3.3/4095.0)*Temp_raw)/0.01169; //konwersja temperatury HAL_I2C_Mem_Read (&hi2c1, LIS35DE_READ_ADDRESS, 0x29, 1, &x_raw, 1, 100); HAL_I2C_Mem_Read (&hi2c1, LIS35DE_READ_ADDRESS, 0x2b, 1, &y_raw, 1, 100); HAL_I2C_Mem_Read (&hi2c1, LIS35DE_READ_ADDRESS, 0x2d, 1, &z_raw, 1, 100); x_val = x_raw*(2.3/127); y_val = y_raw*(2.3/127); z_val = z_raw*(2.3/127) + z_offset; konwertujNaString(&odczytTemp, temperatura); konwertujNaString(&odczytX, x_val); konwertujNaString(&odczytY, y_val); konwertujNaString(&odczytZ, z_val); size = sprintf(send, "temperatura: %s\r\n", odczytTemp); HAL_UART_Transmit(&huart1, send, size, 100); size = sprintf (send, "ACC X:%s g, Y:%s g, Z:%s g\r\n", odczytX, odczytY, odczytZ); HAL_UART_Transmit(&huart1, send, size, 100); HAL_Delay(1000); } /* USER CODE END 3 */
Komunikacja Bluetooth wykorzystana została tu podobnie jak monitor portu szeregowego w Arduino. Wartości, wraz z odpowiednimi opisami, wysyłane są w formie tekstowej. Można je odczytać posiadając zainstalowaną na urządzeniu konsolę Bluetooth. Ja użyłem programu Bluetooth Terminal HC-05 na platformę Android. Umożliwia ona komunikację w formie tekstowej z każdym sparowanym urządzeniem.
Działanie przykładu przedstawiono na poniższym materiale wideo: