STM32_01.SteringOtherModulesLoraDisplay

LoRa Display Control System

System sterowania urządzeniami przez LoRa z lokalnym wyświetlaczem. Implementacja komunikacji radiowej i prezentacji statusu.

STM32F4CHALLoRaDisplayMulti-module systemI2CLCD

Informacje

  • Repozytorium: STM32_01.SteringOtherModulesLoraDisplay
  • Płytka / obszar: STM32F401CCU6 / LoRa / Display
  • Kategoria: Wireless / display
  • Status: Public repository

Opis techniczny

  • Firmware łączy komunikację LoRa, lokalny wyświetlacz LCD i komendy dla zewnętrznych modułów wykonawczych.
  • System składa się z modułu głównego (STM32F401CCU6), modułów wykonawczych, komunikatów LoRa, stanów pracy i lokalnego ekranu LCD 16x2.
  • Firmware obsługuje ramki danych JSON, reakcję na komendy LoRa oraz prezentację statusu na wyświetlaczu LCD.
  • Logika dotyczy całego małego systemu rozproszonego, a nie tylko pojedynczego mikrokontrolera.
  • Warstwa radiowa wymaga jednoznacznych ramek danych oraz diagnostyki stanu połączenia, aby łatwiej wykrywać utratę komunikacji z modułami wykonawczymi.
  • Moduł obsługuje komunikację LoRa z użyciem biblioteki LoRa i odbiera dane z innych modułów w formacie JSON.
  • Dane są prezentowane na wyświetlaczu LCD 16x2 za pomocą interfejsu I2C.

Co dzieje się w kodzie

Wybrane najważniejsze mechanizmy z projektu.

  • Moduł główny komunikuje się z innymi modułami przez LoRa i prezentuje dane na wyświetlaczu LCD.
  • Używa biblioteki cJSON do parsowania danych JSON otrzymanych przez LoRa.
  • Komunikacja LoRa odbywa się za pomocą SPI z użyciem modułu SX1276.
  • Wyświetlacz LCD 16x2 jest obsługiwany przez interfejs I2C z biblioteką liquidcrystal_i2c.
  • Firmware obsługuje różne typy komunikatów: temperaturę, napięcie, status samochodu i inne dane z innych modułów.
  • Moduł obsługuje przyciski do nawigacji i interakcji z systemem.

Kluczowe fragmenty kodu

Kod jest skrócony do części istotnych dla zrozumienia projektu.

Odbiór i przetwarzanie komunikatów LoRa

Core/Src/main.c
if(LoRaIsReceived == 1)// received somethig
		{
			uint8_t  local_buf[RX_MAX];
			uint16_t local_len;

			local_len = RxLen;
			for (uint16_t i = 0; i < local_len; ++i)local_buf[i] = RxBuffer[i];
			LoRaIsReceived = 0;

			local_buf[local_len] = '';
			trim_crlf((char*)local_buf, &local_len);

			memset((uint8_t*)RxBuffer, 0, sizeof RxBuffer);

			if(UnpackMessage((const char*)local_buf, (Message*)&receivedMessageStruct) == true)
			{
	  			if(receivedMessageStruct.DestinationDevID == MyDevID)
	  			{
					switch (receivedMessageStruct.mt)
					{
						case MT_CarStatus:
							PrintCarStatusHD44780(receivedMessageStruct.DeviceID, receivedMessageStruct.u.car.status);
							break;
						case MT_Temperature:
							PrintTempHD44780(receivedMessageStruct.DeviceID, receivedMessageStruct.u.temp.value);
							break;

						case MT_Volt:
							PrintVoltageHD44780(receivedMessageStruct.DeviceID, receivedMessageStruct.u.volt.value);
							break;

						default:
						break;

					}
	  			}
			}
		}

Funkcja odbiera dane LoRa, przetwarza je jako JSON i wyświetla odpowiednie informacje na LCD. Obsługuje różne typy komunikatów: status samochodu, temperaturę i napięcie.

Inicjalizacja LoRa i wyświetlacza

Core/Src/main.c
// wawero Start Timer 10 ustawiony na 1000 (10msek)
  if (HAL_TIM_Base_Start_IT(&htim10) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }
  // wawero Start Timer 3 ustawiony na 1sek
  if (HAL_TIM_Base_Start_IT(&htim3) != HAL_OK)
  {
    /* Starting Error */
    Error_Handler();
  }

  HD16x2Status = Initialize_HD44780();
  HD16x2Backlight =LCD_BACKLIGHT_ON;
  HD44780_NoCursor();

  FirstButtonConfig.GPIOx = BUTTON_0_GPIO_Port;
  FirstButtonConfig.GPIO_Pin = BUTTON_0_Pin;

  SecondButtonConfig.GPIOx = BUTTON_1_GPIO_Port;
  SecondButtonConfig.GPIO_Pin = BUTTON_1_Pin;

  GetHandleToButtons(&FirstButtonConfig, &SecondButtonConfig);

  updateLevel_0();
  LoRa_stat = InitializeMyLoRa(&myLoRa);

Funkcja inicjalizuje timer, wyświetlacz LCD i przyciski. Następnie inicjalizuje moduł LoRa do odbioru danych.

Komunikacja LoRa z użyciem biblioteki cJSON

Core/Src/CommunicationMessagesV2.c
int PackMessage(const Message* m, char *out_json, size_t out_cap)
{
    if (!m || !out_json || out_cap == 0) return -1;

    int ret = -1;
    cJSON *root = cJSON_CreateObject();
    if (!root) return -1;

    add_common_fields(root, m);

    switch (m->mt) {
        case MT_Volt:
            cJSON_AddNumberToObject(root, "Voltage", m->u.volt.value);
            break;
        case MT_Temperature:
            cJSON_AddNumberToObject(root, "Temperature", m->u.temp.value);
            break;
        case MT_CarStatus:
            cJSON_AddNumberToObject(root, "CarStatus", m->u.car.status);
            break;
        // ... more cases
    }

    char *printed = cJSON_PrintUnformatted(root);
    if (printed) {
        /* BEZPIECZNIE – kopiujemy jako tekst */
        int n = snprintf(out_json, out_cap, "%s", printed);
        if (n >= 0 && (size_t)n < out_cap) ret = n;
        cJSON_free(printed);
    }

    cJSON_Delete(root);
    return ret; /* długość JSON lub -1 */
}

Funkcja pakuje dane do formatu JSON dla transmisji LoRa. Używa biblioteki cJSON do tworzenia struktury JSON z danymi.