STM32_01.SteringOtherModulesLoraDisplay

LoRa Display Control System

System controlling devices over LoRa with local display. Implementation of radio communication and status presentation.

STM32F4CHALLoRaDisplayMulti-module systemI2CLCD

Project facts

  • Repository: STM32_01.SteringOtherModulesLoraDisplay
  • Board / area: STM32F401CCU6 / LoRa / Display
  • Category: Wireless / display
  • Status: Public repository

Technical description

  • The firmware combines LoRa communication, the local LCD display and commands for external actuator modules.
  • The system consists of a main module (STM32F401CCU6), actuator modules, LoRa messages, operating states and a local 16x2 LCD screen.
  • The firmware handles JSON data frames, command reactions and status presentation on the LCD display.
  • The logic covers a small distributed system, not only a single microcontroller.
  • The radio layer needs explicit data frames and link-state diagnostics to make communication loss with actuator modules easier to detect.
  • The module handles LoRa communication using the LoRa library and receives data from other modules in JSON format.
  • Data is presented on an LCD 16x2 display via I2C interface.

What happens in the code

Selected key mechanisms from the project code. This is not a full repository dump, but an analysis of the parts responsible for the main firmware logic.

  • The main module communicates with other modules via LoRa and displays data on an LCD display.
  • It uses the cJSON library to parse JSON data received over LoRa.
  • LoRa communication is handled through SPI using the SX1276 module.
  • The 16x2 LCD display is controlled via I2C interface with the liquidcrystal_i2c library.
  • The firmware handles various message types: temperature, voltage, car status and other data from other modules.
  • The module supports buttons for navigation and system interaction.

Key code excerpts

The code is shortened to the parts that matter for understanding the project.

Receiving and processing LoRa messages

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;

					}
	  			}
			}
		}

The function receives LoRa data, processes it as JSON and displays appropriate information on the LCD. It handles different message types: car status, temperature and voltage.

LoRa and display initialization

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);

The function initializes the timer, LCD display and buttons. Then it initializes the LoRa module for data reception.

LoRa communication with cJSON library

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 */
}

The function packs data into JSON format for LoRa transmission. It uses the cJSON library to create a JSON structure with the data.