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.
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:
SmartCore - --- SmartCore - tecnico publico - All Documents (sharepoint.com) (Nodes) / LMIC - The Things Network
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