terça-feira, 21 de fevereiro de 2023

PROGRAMANDO WISOL LSM110A ( LoRaWAN CLASS A - OTAA) COM ARDUINO E ACESSANDO LoRaWAN TTN - RAK LIB

   

O objetivo deste BLOG é demonstrar como é possível programar o módulo WISOL LSM110A via ARDUINO e assim utilizá-lo como OPENCPU.

Será publicada Test na rede LoRaWAN TTN (CLASS A, OTAA) a cada 60 segundos.


LSM110A Starter KIT
Módulo

O LSM110A é um módulo de última geração que integra o STMicroelectronics STM32WL. É muito menos consumo atual para o dispositivo IoT para estender a vida útil da bateria. E, também suporta ambas as tecnologias – Sigfox e LoRa – com o próprio módulo LSM110A.

Você pode trocar Sigfox ou LoRa com ele para que você também possa reduzir o custo. É altamente otimizado para solução de IoT (Alto Consumo de Energia, Baixo Custo)

BREAKOUT para testes


Esquema Elétrico - últimas correções





PLACA MONTADA



CONEXÃO COM ST-LINK V2 E UART



TTN
The Thing Network

A Rede de Coisas (TTN) é uma iniciativa iniciada pela sociedade civil holandesa. O objetivo é ter redes LoRaWAN instaladas em todas as cidades do mundo. Ao interconectar essas redes locais, a TTN quer construir uma infra-estrutura mundial para facilitar uma Internet das Coisas (IoT) pública.

A The Things Network (TTN) é o servidor IoT na nuvem utilizado nesse projeto. É um dos servidores gratuitos para LoRaWAN mais utilizados, com mais de 90 mil desenvolvedores, mais de 9 mil gateways de usuários conectados à rede ao redor do mundo e mais de 50 mil aplicações em funcionamento.

A TTN comercializa nós e gateways LoRa e provê treinamento individual e coletivo para empresas e desenvolvedores que desejam utilizar o LoRa. Possui uma comunidade bem ativa nos fóruns, sempre colaborando e ajudando a resolver problemas, além de prover diversos meios de integrar a TTN com a aplicação que se deseja usar. Possui integração nativa com diversas aplicações como: Cayenne, Hypertext Transfer Protocol (HTTP), permitindo ao usuário realizar uplink para um gateway e receber downlink por HTTP, OpenSensors e EVRYTHNG . Caso o usuário queira criar sua própria aplicação, a TTN disponibiliza Application Programming Interface (API) para uso com Message Queuing Telemetry Transport (MQTT) e diversos Software Developer Kits (SDK) para uso com as linguagens Python, Java , Node.Js , NODE-RED e Go

A rede TTN utiliza o protocolo LoRaWAN objetivando uma cobertura em longo alcance para os dispositivos da rede, caracterizando-a assim com uma Wide Area Network (WAN). Devido ao baixo consumo de energia e ao uso da tecnologia LoRa, é chamada de LPWAN (Low Power Wide Area Network). O grande diferencial da TTN é seu estabelecimento como uma rede aberta (open-source) e colaborativa (crowd-sourced), onde qualquer usuário pode contribuir instalando um gateway em sua residência.

Os elementos da TTN são classificados como: 

• Endpoints (nós): Os dispositivos responsáveis pela camada de sensoriamento da rede, o endpoint LoRaWAN. Podem coletar informações através de sensores e também acionar dispositivos/máquinas via atuadores. São configurados através de uma das três classes distintas do protocolo LaRaWAN; 

• Gateways: Elementos responsáveis por concentrar e processar as informações enviadas pelos endpoints. Os gateways em geral estão conectados a internet, seja por WiFi/Ethernet ou 3G/4G em locais remotos. Mesmo que uma mesma rede LoRaWAN tenha diferentes objetivos, baseados em aplicações distintas, os gateways possuem o objetivo comum de fornecer a maior área de cobertura possível; 

• Aplicações: Conectar e interligar os diferentes dispositivos da rede TTN para o fornecimento de informações gerais sobre a coleta de dados dos dispositivos.


LSM110A e ARDUINO (RAKWIRELESS)

LSM110A é baseado em STM32WL55.  No Arduino RAKWIRELESS existe o core similar, o qual deve ser modificado para ser compatível com LSM110A

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

Altere radio_board_if.c para

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
































Altere radio_board_if.h para

#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()

Altere Cristal para uso de frequênciais (BAND) mais altas (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;
}

Altere Placa para RAK3272-SIP, compile



Grave com o STM32 Programmer o BOOTLOADER no LSM110A 

Assim, pode-se transferir o programa via Serial, através dos pinos PA2 e PA3 do LSM110A.



Ok, o ambiente de desenvolvimento está pronto. Abra Projeto Arduino LORAWAN_OTA.INOconfigure 3 parâmetros para LoRaWAN_OTAA os quais deve ser obtidos no servidor TTN.

#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}

Transferindo


Executando

Uma vez gravado o Software, o LSM110A fará o JOIN na LoRaWAN enviará o pacote Test a cada 60 segundos.


TTN



Neste exemplo, será transmitido para LoRaWAN (TTN) os dados

Segue código final

/***

    This example shows LoRaWan protocol joining the network in OTAA mode, class A, region AU915.

    Device will send uplink every 20 seconds.

***/



#define OTAA_PERIOD   (20000)

/*************************************



   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,0xe1,0x15,0xXX,0x1f,0xXX,0x4c}

#define OTAA_APPEUI   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}

#define OTAA_APPKEY   {0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6,0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c}



/** 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("------------------------------------------------------");



  if (api.lorawan.nwm.get() != 1)

  {

    Serial.printf("Set Node device work mode %s\r\n",

                  api.lorawan.nwm.set(1) ? "Success" : "Fail");

    api.system.reboot();

  }



  // 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.rety.set(1)) {

    Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");

    return;

  }

  if (!api.lorawan.cfm.set(0)) {

    Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");

    return;

  }



  if (!api.lorawan.adr.set(0)) {

    Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");

    return;

  }

  

  Serial.printf("Set the data rate  %s\r\n", api.lorawan.dr.set(2) ? "Success" : "Fail");



  uint16_t maskBuff = 0x0002;

  Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");



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

  }



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


Montagem


DOWNLINK message


Fontes:

Dúvidas

FORUM

Sobre a SMARTCORE

A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.

Mais detalhes em www.smartcore.com.br

Nenhum comentário:

Postar um comentário