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