sábado, 25 de fevereiro de 2023

PROGRAMMING WISOL LSM110A ( LoRaWAN CLASS A - OTAA) WITH ARDUINO AND ACCESSING LoRaWAN TTN - RAKWIRELLES LIB (PORT)

 

The purpose of this BLOG is to demonstrate how it is possible to program the WISOL LSM110A module via ARDUINO and thus use it as OPENCPU.

"Test" will be published on the LoRaWAN TTN network (CLASS A, OTAA) every 60 seconds (FPU).

LSM110A Starter KIT
Module

The purpose of this LSM110A is a state-of-the-art module that integrates the STMicroelectronics STM32WL. It is much less current consumption for the IoT device to extend battery life. And it also supports both technologies – Sigfox and LoRa – with the LSM110A module itself.

You can trade Sigfox or LoRa with it so you can also reduce the cost. It is highly optimized for IoT (High Energy Consumption, Low Cost)BLOG solution is to demonstrate how it is possible to program the WISOL LSM110A module via ARDUINO and thus use it as OPENCPU.

Test will be published on the LoRaWAN TTN network (CLASS A, OTAA) every 60 seconds.

BREAKOUT


|Schematic - updated





Assembled



ST-LINK V2 CONNECTION 



TTN
The Thing Network

The Things Network (TTN) is the IoT server in the cloud used in this project. It is one of the most widely used free LoRaWAN servers, with more than 90,000 developers, more than 9,000 gateways of network-connected users around the world and more than 50,000 applications in operation.


LSM110A AND ARDUINO (RAKWIRELESS)

LSM110A is based on STM32WL55.  In Arduino RAKWIRELESS there is the similar core, which must be modified to be compatible with LSM110A

Download RAKWIRELESS Arduino
https://raw.githubusercontent.com/RAKWireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless.com_rui_index.json

Ready

Change radio_board_if.c to

int32_t RBI_ConfigRFSwitch(RBI_Switch_TypeDef Config) { switch (Config) { case RBI_SWITCH_OFF: { /* Turn off switch */ HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_RESET); HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET); break; } case RBI_SWITCH_RX: { /*Turns On in Rx Mode the RF Switch */ HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET); break; } case RBI_SWITCH_RFO_LP: { /*Turns On in Tx Low Power the RF Switch */ HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET); break; } case RBI_SWITCH_RFO_HP: { /*Turns On in Tx High Power the RF Switch */ HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET); break; } default: break; } return 0; }



































Change radio_board_if.h to

#define RF_SW_CTRL1_PIN GPIO_PIN_12 #define RF_SW_CTRL1_GPIO_PORT GPIOB #define RF_SW_CTRL1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define RF_SW_CTRL1_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE() /* official version */ #define RF_SW_CTRL2_PIN GPIO_PIN_13 #define RF_SW_CTRL2_GPIO_PORT GPIOC #define RF_SW_CTRL2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE() #define RF_SW_CTRL2_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()

Change Crystal to use higher frequencies (BAND) (board.c)

uint8_t BoardGetHardwareFreq(void)
{
    uint8_t hardwareFreq = 0;
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    /* GPIO Ports Clock Enable */
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /*Configure GPIO pin : PB12 */
    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    hardwareFreq  = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12);
hardwareFreq = 1;

    HAL_GPIO_DeInit(GPIOB,GPIO_PIN_12);
    return hardwareFreq;
}

Change Arduino config to RAK3272-SIP and compile


Burn with the STM32 Programmer the BOOTLOADER on the LSM110A 

Thus, you can transfer the program via Serial via the PA2 and PA3 pins of the LSM110A.


RAK3272-SiP_latest_final


Okay, the development environment is ready. Open Arduino project LORAWAN_OTA. INO, configure 3 parameters for LoRaWAN_OTAA must be obtained on the TTN server.

#define OTAA_BAND     RAK_REGION_AU915
#define OTAA_DEVEUI   {0x00, 0x80, 0xE1, 0xXX, 0x05, 0xXX, 0xXX, 0x0A}
#define OTAA_APPEUI   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99}
#define OTAA_APPKEY   {0xFF, 0x9F, 0x13, 0x8B, 0x40, 0x18, 0x0A, 0xA4, 0x5D, 0x68, 0x46, 0xE0, 0xA0, 0x14, 0x69, 0x54}

Transfer


Executing

Once the Software is burned, the LSM110A will join lorawan will send the Test package every 60 seconds.


TTN



In this example, the data will be transmitted to LoRaWAN (TTN)

Follow final code

#define OTAA_PERIOD   (60000)
/*************************************

   LoRaWAN band setting:
     RAK_REGION_EU433
     RAK_REGION_CN470
     RAK_REGION_RU864
     RAK_REGION_IN865
     RAK_REGION_EU868
     RAK_REGION_US915
     RAK_REGION_AU915
     RAK_REGION_KR920
     RAK_REGION_AS923

 *************************************/
#define OTAA_BAND     RAK_REGION_AU915
#define OTAA_DEVEUI   {0x00, 0xXX, 0xXX, 0x15, 0x05, 0xXX, 0xXX, 0x0A}
#define OTAA_APPEUI   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99}
#define OTAA_APPKEY   {0xFF, 0x9F, 0x13, 0x8B, 0x40, 0x18, 0x0A, 0xA4, 0x5D, 0x68, 0x46, 0xE0, 0xA0, 0x14, 0x69, 0x54}

/** Packet buffer for sending */
uint8_t collected_data[64] = { 0 };

void recvCallback(SERVICE_LORA_RECEIVE_T * data)
{
  if (data->BufferSize > 0) {
    Serial.println("Something received!");
    for (int i = 0; i < data->BufferSize; i++) {
      Serial.printf("%x", data->Buffer[i]);
    }
    Serial.print("\r\n");
  }
}

void joinCallback(int32_t status)
{
  Serial.printf("Join status: %d\r\n", status);
}

void sendCallback(int32_t status)
{
  if (status == 0) {
    Serial.println("Successfully sent");
  } else {
    Serial.println("Sending failed");
  }
}

void setup()
{
  Serial.begin(115200, RAK_AT_MODE);

  Serial.println("RAKwireless LoRaWan OTAA Example");
  Serial.println("------------------------------------------------------");

  // OTAA Device EUI MSB first
  uint8_t node_device_eui[8] = OTAA_DEVEUI;
  // OTAA Application EUI MSB first
  uint8_t node_app_eui[8] = OTAA_APPEUI;
  // OTAA Application Key MSB first
  uint8_t node_app_key[16] = OTAA_APPKEY;

  if (!api.lorawan.appeui.set(node_app_eui, 8)) {
    Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.appkey.set(node_app_key, 16)) {
    Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.deui.set(node_device_eui, 8)) {
    Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
    return;
  }

  if (!api.lorawan.band.set(OTAA_BAND)) {
    Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
    Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.njm.set(RAK_LORA_OTAA)) // Set the network join mode to OTAA
  {
    Serial.
printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.join()) // Join to Gateway
  {
    Serial.printf("LoRaWan OTAA - join fail! \r\n");
    return;
  }

  /** Wait for Join success */
  while (api.lorawan.njs.get() == 0) {
    Serial.print("Wait for LoRaWAN join...");
    api.lorawan.join();
    delay(10000);
  }

  if (!api.lorawan.adr.set(true)) {
    Serial.printf
("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.rety.set(1)) {
    Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
    return;
  }
  if (!api.lorawan.cfm.set(1)) {
    Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
    return;
  }

  /** Check LoRaWan Status*/
  Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF"); // Check Duty Cycle status
  Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED"); // Check Confirm status
  uint8_t assigned_dev_addr[4] = { 0 };
  api.lorawan.daddr.get(assigned_dev_addr, 4);
  Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]); // Check Device Address
  Serial.printf("Uplink period is %ums\r\n", OTAA_PERIOD);
  Serial.println("");
  api.lorawan.registerRecvCallback(recvCallback);
  api.lorawan.registerJoinCallback(joinCallback);
  api.lorawan.registerSendCallback(sendCallback);
}

void uplink_routine()
{
  /** Payload of Uplink */
  uint8_t data_len = 0;
  collected_data[data_len++] = (uint8_t) 't';
  collected_data[data_len++] = (uint8_t) 'e';
  collected_data[data_len++] = (uint8_t) 's';
  collected_data[data_len++] = (uint8_t) 't';

  Serial.println("Data Packet:");
  for (int i = 0; i < data_len; i++) {
    Serial.printf("0x%02X ", collected_data[i]);
  }
  Serial.println("");

  /** Send the data package */
  if (api.lorawan.send(data_len, (uint8_t *) & collected_data, 2, true, 1)) {
    Serial.println("Sending is requested");
  } else {
    Serial.println("Sending failed");
  }
}

void loop()
{
  static uint64_t last = 0;
  static uint64_t elapsed;

  if ((elapsed = millis() - last) > OTAA_PERIOD) {
    uplink_routine();

    last = millis();
  }
  //Serial.printf("Try sleep %ums..", OTAA_PERIOD);
  api.system.sleep.all(OTAA_PERIOD);
  //Serial.println("Wakeup..");
}

Gateway


Mounting


DOWNLINK message


References:

Questions

FORUM

About  SMARTCORE

SmartCore provides modules for wireless communication, biometrics, connectivity, tracking and automation.
Our portfolio includes 2G/3G/4G/4G/NB-IoT/Cat.M modem, satellite, WiFi modules, Bluetooth, GNSS/GPS, Sigfox, LoRa, card reader, QR code reader, printing engine, mini-board PC, antenna, pigtail, LCD, battery, GPS repeater and sensors.

More details in www.smartcore.com.br

Nenhum comentário:

Postar um comentário