terça-feira, 21 de fevereiro de 2023

PROGRAMANDO WISOL LSM110A ( LoRaWAN CLASS A - OTAA) COM VISUINO E ACESSANDO LoRaWAN TTN - STM32 LORAWAN LIB

  

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

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

Dados serão obtidos do BME280, via I2C.

Fui utilizado CUSTOM CODE do VISUINO para inclusão de código Arduino da LIB STM32 LoRaWAN.

Portado o exemplo Basic.ino, mas atenção, ele trabalha no modo Blocking.

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)

BEAKOUT para testes

Esquema Elétrico - últimas correções





PLACA MONTADA



CONEXÃO COM ST-LINK V2 E UART


BME280

- O Sensor de Pressão BME280 é um exclusivo modelo capaz de realizar a medição de pressão atmosférica, umidade e temperatura, também conhecido como barômetro é um módulo digital de alta capacidade e resolução, utilizado nas mais diversas aplicações junto a microcontroladores, entre eles, o Arduino.
- Utilizado em projetos de estações meteorológicas e aperfeiçoamento de navegação GPS, ele apresenta grande potencial e mostra ser um produto de grande auxílio para projetistas que procuram um exclusivo produto capaz de executar as três funcionalidades principais sem ocupar muito espaço.
- Através de seu padrão de conexão por I2C, o Sensor de Pressão BME280 aumenta a sua praticidade de utilização, além de contribuir na maior precisão da obtenção de resultados.
- Desenvolvido com base no sensor Bosh ME280, o Sensor possui design simplificado com pequenas dimensõe que tornam este pequeno módulo um produto de fácil adaptação nos mais diversificados projetos, além de contar com 2 exclusivos furos para melhorar a fixação do mesmo junto aos mais diversificados projetos.


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!
Como executar o código Visuino no PICSIMLAB?
Baixe e instale o PICSIMLAB
PICSimLab - Prog. Laboratório de Simulação IC. Baixar | SourceForge.net
(EMULADOR DE ARDUINO)

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 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.



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.visuino // //---------------------------------------------- #define VISUINO_STMDUINO #include <OpenWire.h> #include <Mitov.h> #include <Mitov_StandardSerial.h> #include <STM32LoRaWAN.h> #include <Mitov_CustomCode.h> #include <Mitov_FormattedText.h> #include <Mitov_BinaryGenerators.h> HardwareSerial Serial1(PB6, PB7); bool connected; void text1(String Txt); void Connected_LoRaWAN(); void send_packet(); char SPRINTF[1024]; char payload[1024]; unsigned int payload_size; String payload_concat; STM32LoRaWAN modem; static const unsigned long TX_INTERVAL = 60000; /* ms */ unsigned long last_tx = 0; // Shared Component Member Variables namespace ComponentVariables { class { public: bool Value1 : 1; bool Value2 : 1; bool Value3 : 1; bool Value4 : 1; } BitFields; class Variable1 { public: inline static bool GetValue() { return BitFields.Value1; } inline static void SetValue( bool AValue ) { BitFields.Value1 = AValue; } }; class Variable2 { public: inline static bool GetValue() { return BitFields.Value2; } inline static void SetValue( bool AValue ) { BitFields.Value2 = AValue; } }; class Variable3 { public: inline static bool GetValue() { return BitFields.Value3; } inline static void SetValue( bool AValue ) { BitFields.Value3 = AValue; } }; class Variable4 { public: inline static bool GetValue() { return BitFields.Value4; } inline static void SetValue( bool AValue ) { BitFields.Value4 = AValue; } }; } // ComponentVariables // Arduino Constant Declarations namespace VisuinoConstants { class FloatValue0 { public: inline static constexpr float GetValue() { return 0.200000002980232; } }; class FloatValue1 { public: inline static constexpr float GetValue() { return 0; } }; class TextValue0 { public: inline static constexpr const char *GetValue() { return "MIGUELITO"; } }; } // VisuinoConstants // Pin Call Declarations namespace PinCalls { class PinCallerReceive0 { public: void Notify( void *_Data ); }; class PinCallerReceive1 { public: void Notify( void *_Data ); }; class PinCallerReceive2 { public: void Notify( void *_Data ); }; class PinCallerReceive3 { public: void Notify( void *_Data ); }; } // PinCalls // Call Chains namespace CallChains { class Processed1 { public: inline static constexpr uint32_t Count() { return 0; } static void Call(); }; class CanProcess1 { public: inline static constexpr uint32_t Count() { return 0; } static void Call( bool & AResult ); }; class Process1 { public: inline static constexpr uint32_t Count() { return 1; } static void Call( Mitov::String &AText ); }; } // CallChains // Arduino Board Declarations namespace BoardDeclarations { namespace Types { typedef Mitov::SerialSTM32Port< SERIAL_TYPE, // 0_T_TYPE Serial, // 1_C_OBJECT Mitov::ConstantProperty<4, uint32_t, 0 >, // AfterSendingDelay Mitov::ConstantProperty<7, uint32_t, 8 >, // DataBits Mitov::ConstantProperty<2, bool, true >, // Enabled Mitov::ConstantProperty<14, uint32_t, 0 >, // FEndTime Mitov::ConstantProperty<12, bool, false >, // FSending Mitov::GenericPin_NoImplementation<5 >, // OutputPin Mitov::ConstantProperty<9, Mitov::TArduinoStandardSerialParity, Mitov::spNone >, // Parity Mitov::ConstantProperty<10, uint32_t, 3 >, // RXPin Mitov::DigitalPin_NoImplementation<3 >, // SendingOutputPin Mitov::ConstantProperty<6, uint32_t, 115200 >, // Speed Mitov::ConstantProperty<8, uint32_t, 1 >, // StopBits Mitov::ConstantProperty<11, uint32_t, 2 > // TXPin > SerialPort0; } // Types namespace Instances { Types::SerialPort0 SerialPort0; } // Instances } // BoardDeclarations // Custom Code Declarations namespace CustomCode { class THARDWARE_SERIAL_INTERRUPT1 { }; class TCustomCodeLoraWAN_Stack1 { public: // Outputs Mitov::CustomOutput< Mitov::TextPin_EmbeddedPinImplementation<2, ::PinCalls::PinCallerReceive0 >, // OutputPin Mitov::String // TYPE > Text1; Mitov::CustomOutput< Mitov::DigitalPin_EmbeddedPinImplementation<2, ::PinCalls::PinCallerReceive1 >, // OutputPin bool // TYPE > Connected; 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 SystemStart(); }; class TArduinoCustomCodeInputTextElement1 { public: void InputPin_o_Receive( void *_Data ); }; } // CustomCode // Declarations namespace Declarations { namespace Types { typedef Mitov::ArduinoSerialInput_String<BoardDeclarations::Types::SerialPort0, BoardDeclarations::Instances::SerialPort0, char *> SerialPort0_Input_IOWStringStream_1; } // Types namespace Instances { Types::SerialPort0_Input_IOWStringStream_1 SerialPort0_Input_IOWStringStream_1; } // Instances namespace Types { typedef CustomCode::THARDWARE_SERIAL_INTERRUPT1 HARDWARE_SERIAL_INTERRUPT; } // Types namespace Instances { Types::HARDWARE_SERIAL_INTERRUPT HARDWARE_SERIAL_INTERRUPT; } // Instances namespace Types { typedef CustomCode::TCustomCodeLoraWAN_Stack1 CustomCodeLoraWAN_Stack; } // Types namespace Instances { Types::CustomCodeLoraWAN_Stack CustomCodeLoraWAN_Stack; } // Instances namespace Types { typedef CustomCode::TArduinoCustomCodeInputTextElement1 TArduinoCustomCodeInputTextElement1; } // Types namespace Instances { Types::TArduinoCustomCodeInputTextElement1 TArduinoCustomCodeInputTextElement1; } // Instances Mitov::CustomOutput< Mitov::TextPin_EmbeddedPinImplementation<2, ::PinCalls::PinCallerReceive0 >, // OutputPin Mitov::String // TYPE > &TArduinoCustomCodeOutputTextElement1 = Declarations::Instances::CustomCodeLoraWAN_Stack.Text1; Mitov::CustomOutput< Mitov::DigitalPin_EmbeddedPinImplementation<2, ::PinCalls::PinCallerReceive1 >, // OutputPin bool // TYPE > &TArduinoCustomCodeOutputDigitalElement1 = Declarations::Instances::CustomCodeLoraWAN_Stack.Connected; namespace Types { typedef Mitov::FormattedText_Fixed< true, // Clock_IsConnected 0, // Elements Mitov::EmbeddedCallChain<CallChains::CanProcess1 >, // Elements_CanProcess ::CallChains::Process1, // Elements_Process Mitov::EmbeddedCallChain<CallChains::Processed1 >, // Elements_Processed Mitov::ConstantProperty<88, bool, true >, // FModified Mitov::TextPin_EmbeddedPinImplementation<3, ::PinCalls::PinCallerReceive2 > // OutputPin > FormattedText1; } // Types namespace Instances { Types::FormattedText1 FormattedText1; } // Instances Mitov::TFormattedTextStringItemText< ::VisuinoConstants::TextValue0> _o_FormattedText1_o_Indexed0; namespace Types { typedef Mitov::PulseGenerator< Mitov::ConstantPropertyFloat<8, float, ::VisuinoConstants::FloatValue1 >, // Asymmetry Mitov::TypedVariableValue<4, bool, ::ComponentVariables::Variable2, true >, // Enabled Mitov::ConstantPropertyFloat<17, float, ::VisuinoConstants::FloatValue1>, // FPhase Mitov::TypedVariable<15, bool, ::ComponentVariables::Variable3 >, // FValue Mitov::ConstantPropertyFloat<7, float, ::VisuinoConstants::FloatValue0 >, // Frequency Mitov::ConstantProperty<5, bool, false >, // InitialValue Mitov::DigitalPin_EmbeddedPinImplementation<3, ::PinCalls::PinCallerReceive3 >, // OutputPin Mitov::ConstantPropertyFloat<9, float, ::VisuinoConstants::FloatValue1 >, // Phase Mitov::NestedProperty<14, Mitov::TArduinoGeneratorWhenDisabled< Mitov::ConstantProperty<13, bool, false >, // CompleteCycle Mitov::ConstantProperty<12, bool, true >, // FCycleCompleted Mitov::ConstantProperty<11, bool, false > // Reset > > // WhenDisabled > PulseGenerator1; } // Types namespace Instances { Types::PulseGenerator1 PulseGenerator1; } // Instances } // Declarations // Custom Code Implementations namespace CustomCode { void TCustomCodeLoraWAN_Stack1::SystemInit() { Serial.begin(115200); text1("Start"); modem.begin(AU915); // Configure join method by (un)commenting the right method // call, and fill in credentials in that method call. connected = modem.joinOTAA(/* AppEui */ "0000000000000099", /* AppKey */ "FF9F138B40180AA45D6846E0A0146954", /* DevEui */ "00XXE11XX51FD8XX"); //bool connected = modem.joinABP(/* DevAddr */ "00000000", /* NwkSKey */ "00000000000000000000000000000000", /* AppSKey */ "00000000000000000000000000000000"); if (connected) { text1("Joined"); } else { text1("Join failed"); while (true) /* infinite loop */; } } void TCustomCodeLoraWAN_Stack1::SystemStart() { Connected_LoRaWAN(); } void TArduinoCustomCodeInputTextElement1::InputPin_o_Receive( void *_Data ) { Declarations::Instances::CustomCodeLoraWAN_Stack.__Inputs_o_0_o_Receive( Mitov::String( ( char *)_Data ) ); } } // CustomCode // Type Converters namespace TypeConverters { Mitov::Convert_BinaryToClock<Mitov::TypedVariable<0, bool, ::ComponentVariables::Variable4 > > Converter0; } // TypeConverters // Bindings namespace Bindings { inline void PulseGenerator1_EnabledInputPin_o_Receive( void * ___PTR___, bool __AOriginalValue__ ) { bool ___A_VALUE___ = *(bool *)___PTR___; if( __AOriginalValue__ == ___A_VALUE___ ) return; Declarations::Instances::PulseGenerator1.Enabled() = ___A_VALUE___; Declarations::Instances::PulseGenerator1.UpdateEnabled(); } } // Bindings // Call Chains namespace CallChains { void Processed1::Call() { } void CanProcess1::Call( bool & AResult ) { } void Process1::Call( Mitov::String &AText ) { Declarations::_o_FormattedText1_o_Indexed0.Process( AText ); } } // CallChains // Pin Call Declarations namespace PinCalls { void PinCallerConverterReceive1( void *_Data ); } // PinCalls // Pin Call Implementations namespace PinCalls { void PinCallerReceive0::Notify( void *_Data ) { Declarations::Instances::SerialPort0_Input_IOWStringStream_1.InputPin_o_Receive( _Data ); } void PinCallerReceive1::Notify( void *_Data ) { bool __Value_PulseGenerator1_EnabledInputPin__ = Declarations::Instances::PulseGenerator1.Enabled().GetValue(); ::Bindings::PulseGenerator1_EnabledInputPin_o_Receive( _Data, __Value_PulseGenerator1_EnabledInputPin__ ); } void PinCallerReceive2::Notify( void *_Data ) { Declarations::Instances::TArduinoCustomCodeInputTextElement1.InputPin_o_Receive( _Data ); } void PinCallerReceive3::Notify( void *_Data ) { TypeConverters::Converter0.Convert( _Data, PinCallerConverterReceive1 ); } void PinCallerConverterReceive1( void *_Data ) { Declarations::Instances::FormattedText1.ClockInputPin_o_Receive( _Data ); } } // PinCalls namespace ComponentsHardware { void SystemUpdateHardware() { } } // ComponentsHardware void send_packet() { modem.setPort(10); modem.beginPacket(); modem.write(payload, payload_size); if (modem.endPacket() == payload_size) { text1("Sent packet"); } else { text1("Failed to send packet"); } if (modem.available()) { payload_concat=""; text1("Received packet on port "); sprintf(SPRINTF,"%d",modem.getDownlinkPort()); payload_concat=payload_concat+SPRINTF+":"; while (modem.available()) { uint8_t b = modem.read(); sprintf(SPRINTF,"%x",b >> 4); payload_concat=payload_concat+SPRINTF; sprintf(SPRINTF,"%x",b & 0xF); payload_concat=payload_concat+SPRINTF; } text1(payload_concat); } } void text1(String Txt) { Declarations::Instances::CustomCodeLoraWAN_Stack.Text1.Send(Txt); } void Connected_LoRaWAN() { Declarations::Instances::CustomCodeLoraWAN_Stack.Connected.Send(connected); } //The setup function is called once at startup of the sketch void setup() { BoardDeclarations::Instances::SerialPort0.SystemInit(); Declarations::Instances::CustomCodeLoraWAN_Stack.SystemInit(); Declarations::Instances::CustomCodeLoraWAN_Stack.SystemStart(); Declarations::Instances::FormattedText1.SystemStart(); Declarations::Instances::PulseGenerator1.SystemStart(); } // The loop function is called in an endless loop void loop() { Declarations::Instances::PulseGenerator1.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



Adicionando BME280


Execução




Projeto


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