segunda-feira, 17 de julho de 2023

PROGRAMANDO WISOL LSM110A ( LoRaWAN CLASS A - OTAA) COM VISUINO E ACESSANDO LoRaWAN TTN - MODO ASSÍNCRONO

  

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

Será publicada uma sequência de bytes, via CustomCode (sem inouts e outputs).
{0xde, 0xad, 0xbe, 0xef,0xde, 0xad, 0xbe, 0xef,0xde, 0xad, 0xbe} a cada 60 segundos na rede LoRaWAN TTN (CLASS A, OTAA), no modo ASSÍNCRONO, ou seja, é testado o exemplo SIMPLEASYNC.

Esta biblioteca fornece suporte para comunicação LoRaWAN usando o microcontrolador STM32WL55 (com rádio LoRa embutido) dentro do ambiente de desenvolvimento Arduino (juntamente com o núcleo stm32duino com versão 2.4.0 ou posterior).

A mesma foi modificada para funcionar no LSM110A.


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




VISUINO

Visuino é o mais recente software inovador da Mitov Software. Um ambiente de programação visual que permite programar suas placas Arduino.
Os componentes encontrados no software Visuino representam seus componentes de hardware e você poderá facilmente criar e projetar seus programas arrastando e soltando. Nenhum equipamento ou hardware é necessário para executar o software no modo de design. Depois de concluir o projeto, você pode conectar o upload da placa Arduino e executá-lo.
Para aquelas pessoas que não são fortes em escrever código, projetar, compilar e criar programas Arduino nunca foi tão fácil! Por que perder tempo codificando quando todo o trabalho duro é feito para você? Você tem sua placa Arduino e um ótimo design de hardware, coloque-a em funcionamento em minutos, não em horas!


LSM110A e VISUINO (STM32DUINO)

LSM110A é baseado em STM32WL55.  No Arduino STM32DUINO existe este core e o VISUINO utiliza o STM32DUINO

LIB STM32LoRaWAN

No github


Baixe em formato ZIP


Adicione ao Arduino IDE (se você tiver o Arduino instalado) ou descompact na pasta de Libraries do Arduino.


Pronto


Altere Placa para STM32WL series, Modelo Generic WL55JCLx


Ok, o ambiente de desenvolvimento está pronto. Abra Projeto Visuino abaixo  e configure 3 parâmetros para LoRaWAN_OTAA os quais deve ser obtidos no servidor TTN.


No CustomCode, Declarations

/** * This is a an example of the asynchronous API. This sketch is not * completely asynchronous (see ScheduledAsync.ino for that) and its * flow still follows the LoRa flow, but this sketch shows how some * background work can be done while waiting for the LoRa library to * complete its work. * * Revised BSD License - https://spdx.org/licenses/BSD-3-Clause.html */ HardwareSerial Serial1(PB6, PB7); STM32LoRaWAN modem; static const unsigned long TX_INTERVAL = 60000; /* ms */ unsigned long last_tx = 0; static const unsigned long BLINK_INTERVAL = 1000; /* ms */ unsigned long last_blink = 0; unsigned int payload_size; char payload[1024]; void wait_for_idle() { while (modem.busy()) { // Call maintain() so the lora library can do any // pending background work too. modem.maintain(); } } void send_packet() { uint8_t payload[] = {0xde, 0xad, 0xbe, 0xef}; modem.setPort(10); modem.beginPacket(); modem.write(payload, sizeof(payload)); if (modem.endPacketAsync() == sizeof(payload)) { Serial.println("Queued packet"); } else { Serial.println("Failed to send packet"); return; } wait_for_idle(); Serial.println("Sent packet"); if (modem.available()) { Serial.print("Received packet on port "); Serial.print(modem.getDownlinkPort()); Serial.print(":"); while (modem.available()) { uint8_t b = modem.read(); Serial.print(" "); Serial.print(b >> 4, HEX); Serial.print(b & 0xF, HEX); } Serial.println(); } }
















































No CustomCode, OnInit

while(1) { // Configure join method by (un)commenting the right method // calls, and fill in credentials in those method calls. modem.setAppEui("0000000000000099"); modem.setAppKey("FF9F138B40180XX45DXX46E0A0146954"); modem.setDevEui("0080E505XX1FDXXA"); Serial.println(setAppEuiString); Serial.println(setAppKeyString); Serial.println(setDevEuiString); modem.joinOTAAAsync(); //modem.setDevAddr("00000000"); //modem.setNwkSKey("00000000000000000000000000000000"); //modem.setAppSKey("00000000000000000000000000000000"); //modem.joinABPAsync(); wait_for_idle(); if (modem.connected()) { Serial.println("Joined"); return; } else { Serial.println("Join failed"); while (true) /* infinite loop */; } }


No CustomCode, OnExecute

if (!last_tx || millis() - last_tx > TX_INTERVAL) { send_packet(); last_tx = millis(); }

No CustomCode, Includes

#include <STM32LoRaWAN.h>

Compilando


Transferindo


Executando

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


TTN



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

Segue código final (gerado pelo VISUINO)

//---------------------------------------------- // // Sketch Generated by Visuino // www.visuino.com // //------------------ Source -------------------- // // STM32WL55_VISUINO_LORAWAN_ASYNC_STM32LORAWAN.visuino // //---------------------------------------------- #define VISUINO_STMDUINO #include <OpenWire.h> #include <Mitov.h> #include <STM32LoRaWAN.h> #include <Mitov_CustomCode.h> /** * This is a an example of the asynchronous API. This sketch is not * completely asynchronous (see ScheduledAsync.ino for that) and its * flow still follows the LoRa flow, but this sketch shows how some * background work can be done while waiting for the LoRa library to * complete its work. * * Revised BSD License - https://spdx.org/licenses/BSD-3-Clause.html */ HardwareSerial Serial1(PB6, PB7); STM32LoRaWAN modem; static const unsigned long TX_INTERVAL = 60000; /* ms */ unsigned long last_tx = 0; static const unsigned long BLINK_INTERVAL = 1000; /* ms */ unsigned long last_blink = 0; unsigned int payload_size; char payload[1024]; void wait_for_idle() { while (modem.busy()) { // Call maintain() so the lora library can do any // pending background work too. modem.maintain(); } } void send_packet() { uint8_t payload[] = {0xde, 0xad, 0xbe, 0xef}; modem.setPort(10); modem.beginPacket(); modem.write(payload, sizeof(payload)); if (modem.endPacketAsync() == sizeof(payload)) { Serial.println("Queued packet"); } else { Serial.println("Failed to send packet"); return; } wait_for_idle(); Serial.println("Sent packet"); if (modem.available()) { Serial.print("Received packet on port "); Serial.print(modem.getDownlinkPort()); Serial.print(":"); while (modem.available()) { uint8_t b = modem.read(); Serial.print(" "); Serial.print(b >> 4, HEX); Serial.print(b & 0xF, HEX); } Serial.println(); } } // Custom Code Declarations namespace CustomCode { class TCustomCodeLoraWAN_Stack1 { public: // Outputs Mitov::CustomOutput< Mitov::TextPin_NoImplementation<2 >, // OutputPin Mitov::String // TYPE > Text1; public: // Inputs inline void __Inputs_o_0_o_Receive( Mitov::String AValue ) { payload_size = AValue.length(); AValue.toCharArray(payload,payload_size+1); send_packet(); } public: void SystemInit(); public: void SystemLoopBegin(); }; class TArduinoCustomCodeInputTextElement1 { public: void InputPin_o_Receive( void *_Data ); }; } // CustomCode // Declarations namespace Declarations { namespace Types { typedef CustomCode::TCustomCodeLoraWAN_Stack1 CustomCodeLoraWAN_Stack; // TArduinoCustomCode } // Types namespace Instances { Types::CustomCodeLoraWAN_Stack CustomCodeLoraWAN_Stack; // TArduinoCustomCode } // Instances namespace Types { typedef CustomCode::TArduinoCustomCodeInputTextElement1 TArduinoCustomCodeInputTextElement1; } // Types namespace Instances { Types::TArduinoCustomCodeInputTextElement1 TArduinoCustomCodeInputTextElement1; } // Instances Mitov::CustomOutput< Mitov::TextPin_NoImplementation<2 >, // OutputPin Mitov::String // TYPE > &TArduinoCustomCodeOutputTextElement1 = Declarations::Instances::CustomCodeLoraWAN_Stack.Text1; } // Declarations // Custom Code Implementations namespace CustomCode { void TCustomCodeLoraWAN_Stack1::SystemInit() { Serial.begin(115200); Serial.println("Start"); modem.begin(AU915); while(1) { // Configure join method by (un)commenting the right method // calls, and fill in credentials in those method calls. modem.setAppEui("0000000000000099"); modem.setAppKey("FF9F13XX40180AA45DXX46E0A0146954"); modem.setDevEui("0080EXX5051XX80A"); modem.joinOTAAAsync(); //modem.setDevAddr("00000000"); //modem.setNwkSKey("00000000000000000000000000000000"); //modem.setAppSKey("00000000000000000000000000000000"); //modem.joinABPAsync(); wait_for_idle(); if (modem.connected()) { Serial.println("Joined"); return; } else { Serial.println("Join failed"); while (true) /* infinite loop */; } } } void TCustomCodeLoraWAN_Stack1::SystemLoopBegin() { if (!last_tx || millis() - last_tx > TX_INTERVAL) { send_packet(); last_tx = millis(); } } void TArduinoCustomCodeInputTextElement1::InputPin_o_Receive( void *_Data ) { Declarations::Instances::CustomCodeLoraWAN_Stack.__Inputs_o_0_o_Receive( Mitov::String( ( char *)_Data ) ); } } // CustomCode namespace ComponentsHardware { void SystemUpdateHardware() { } } // ComponentsHardware //The setup function is called once at startup of the sketch void setup() { Declarations::Instances::CustomCodeLoraWAN_Stack.SystemInit(); } // The loop function is called in an endless loop void loop() { Declarations::Instances::CustomCodeLoraWAN_Stack.SystemLoopBegin(); }
Gateway

Montagem

Máscara de canais (Join, Uplink, Downlink)

Ver RegionAU915.h
C:\Users\Usuario\Documents\Arduino\libraries\STM32LoRaWAN-main\src\STM32CubeWL\LoRaWAN\Mac\Region

// Initialize channels default mask #if ( HYBRID_ENABLED == 1 ) RegionNvmGroup2->ChannelsDefaultMask[0] = HYBRID_DEFAULT_MASK0; RegionNvmGroup2->ChannelsDefaultMask[1] = HYBRID_DEFAULT_MASK1; RegionNvmGroup2->ChannelsDefaultMask[2] = HYBRID_DEFAULT_MASK2; RegionNvmGroup2->ChannelsDefaultMask[3] = HYBRID_DEFAULT_MASK3; RegionNvmGroup2->ChannelsDefaultMask[4] = HYBRID_DEFAULT_MASK4; RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000; #else RegionNvmGroup2->ChannelsDefaultMask[0] = 0xFF00; RegionNvmGroup2->ChannelsDefaultMask[1] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[2] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[3] = 0x0000; RegionNvmGroup2->ChannelsDefaultMask[4] = 0x00FF; RegionNvmGroup2->ChannelsDefaultMask[5] = 0x0000; #endif /* HYBRID_ENABLED == 1 */

Altere em radio_board_if.c 
em
C:\Users\Usuario\Documents\Arduino\libraries\STM32LoRaWAN-main\src\BSP

// Supported TX modes (LP/HP or both) #if !defined(LORAWAN_TX_CONFIG) #define LORAWAN_TX_CONFIG RBI_CONF_RFO_HP //MIGUEL#define LORAWAN_TX_CONFIG RBI_CONF_RFO_LP_HP #endif #if !defined(LORAWAN_RFSWITCH_PINS) #define LORAWAN_RFSWITCH_PINS PB12,PC13 #define LORAWAN_RFSWITCH_PIN_COUNT 2 #define LORAWAN_RFSWITCH_OFF_VALUES LOW,LOW #define LORAWAN_RFSWITCH_RX_VALUES HIGH,LOW #define LORAWAN_RFSWITCH_RFO_LP_VALUES HIGH,HIGH #define LORAWAN_RFSWITCH_RFO_HP_VALUES HIGH,HIGH #endif


Gravador (instalação opcional ?)








"Instale" o STM32 Cube Programmer, o Arduino (STM32 PACKAGE) irá reconhecê-lo e então utilizá-lo para programar o LSM110A. O Kit LSM110A possui um "gravador" ST-LINK embarcado.

Neste blog foi utilizado o BREAKOUT e um ST-LINK-V2.


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