IMPORTANTE: Opção NÃO OFICIAL da WISOL, indicamos uso do KEIL C
VERSÃO BETA - SPI 2 não implementado
O objetivo deste BLOG é demonstrar como é possível programar o módulo WISOL LOM204A02 via VISUINO e assim utilizá-lo como OPENCPU (atualmente programado com o KEIL C).
IMPORTANTE: Opção NÃO OFICIAL da WISOL, indicamos uso do KEIL C
O exemplo gerará 3 COORDENADAS (x,y,z) (simulando um acelerômetro) a cada 20 segundos e então fará a publicação do Payload (formato Cayenne) no servidor loraWAN TTN e então encaminhado para um servidor myDevices para visualização. No exemplo, foi utilizado o KIT LOM204A02 da Wisol, e como gateway LoraWAN um Dragino modelo LG308 e servidor TTN.
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 (utilizado nesse trabalho), 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.
VISUINO
O Visuino é o mais recente software inovador da Mitov Software. Um ambiente de programação visual que permite programar suas placas Arduino.
O 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á criar e projetar facilmente seus programas usando arrastar e soltar. Nenhum equipamento ou hardware é necessário para executar o software no modo de design. Depois de ter concluído o design, você pode conectar o upload da placa Arduino e executá-lo.
Para aquelas pessoas que não são fortes em escrever código, em seguida, projetar, compilar e criar programas Arduino nunca foi tão fácil! Por que perder tempo criando código quando já se faz todo o trabalho duro para você? Você tem sua placa Arduino e um ótimo design de hardware, veja-a rodando em minutos, não em horas!
A missão da empresa é simplificar o mundo conectado, fornecendo ferramentas que permitam a criação de soluções de IoT agnósticas de dispositivos e conectividade para edifícios inteligentes, agricultura inteligente, rastreamento de ativos e outras verticais de IoT. MyDevices está sediada em Los Angeles, CA. Para mais informações, visite www.myDevices.com
Formato Cayenne
CayenneLPP é um formato projetado por myDevices para integrar os nódulos LoRaWan em sua plataforma IoT. Ele é usado para enviar dados de sensores de forma embalada para a plataforma The Things Network.
O formato CayenneLPP é uma maneira bastante otimizada de enviar dados de sensores sobre conexão de baixa taxa de bits, como LoRa. Você pode encontrar, provavelmente, uma maneira melhor para o seu projeto específico, mas CayenneLPP é um formato standarized e comprovado que embala dados de forma suficiente.
Enfim, é um formato simplificado de payload para envio para TTN com intuito de usar o menos de Banda de transmissão. No servidor é decodificado este payload e identificado os sensores encapsulados, veja:
CayenneLPP lpp(100);
float Acc_x;
float Acc_y;
float Acc_z;
void printVariables()
{
lpp.reset();
lpp.addAccelerometer(4, Acc_x, Acc_y, Acc_z);
}
PS: código 4 = Coordenadas X,Y,Z de um acelerômetro.
O Cayenne Low Power Payload (LPP) fornece uma maneira conveniente e fácil de enviar dados sobre redes LPWAN, como LoRaWAN. O Cayenne LPP está em conformidade com a restrição de tamanho de carga, que pode ser reduzida para 11 bytes, e permite que o dispositivo final envie vários dados de sensor ao mesmo tempo.
Para usar o CayenneLPP Payload Formatter, o dispositivo deve enviar cargas binárias compatíveis com Cayenne. Para placas compatíveis com Arduino, a documentação sobre a alteração do seu Esboço Arduino para codificar dados com CayenneLPP pode ser encontrada na Documentação Cayenne da The Things Network. Informações gerais sobre a Carga De Carga CayenneLPP estão disponíveis no Repositório De Github CayenneLPP.
Uma vez configurado seu dispositivo para enviar cargas compatíveis com CayenneLPP, habilitar o CayenneLPP Payload Formatter adicionará um decoded_payload objeto a mensagens de uplink do seu dispositivo.
Por exemplo, os seguintes dados binários:
[0x3, 0x67, 0x01, 0x10, 0x05, 0x67, 0x00, 0xFF] produzirá as seguintes uplink_message:
{
"uplink_message": {
"f_port": 8,
"f_cnt": 113,
"frm_payload": "A2cBEAVnAP8=",
"decoded_payload": {
"temperature_3": 27.200000762939453,
"temperature_5": 25.5
},
}
}
Biblioteca
Inclui decodificador totalmente invertido em JavaScript, adequado para implementações com NodeRED ou TTN, por exemplo.
Ao usar o decodificador, você deve instalar a biblioteca ArduinoJson 6.X. Você pode encontrá-lo tanto nos gerentes de bibliotecas Arduino.
Como utilizar LoRaWAN no VISUINO ?
Através do Custom Code do Visuino você pode incluir código em C/C++
Baixe o VISUINO PRO e instale
Foi Criado, não oficialmente , um VCOMP (Virtual Component) para o LOM204, o qual pode ser baixado aqui.
Copie para a PASTA
C:\Users\Usuario\Documents\Arduino\libraries\Mitov\Visuino
Agora baixe o projeto
Abra o projeto!
Atenção, o VISUINO instalará o SDK "STM32" em
C:\Users\Usuario\AppData\Local\Arduino15\packages
Podes apagar, deixe o baixado pela IDE do Arduino, para que faça referência ao SDK oficial do STM32.
C:\Users\Usuario\AppData\Local\Arduino15\packages\STMicroelectronics
Configurando Credenciais do TTN
LMIC LoRaWAN Stack
Aqui você pode incluir o LMIC LoRaWAN Stack (colocado junto com as funções do programa Arduino)
//Cayenna PAYLOAD
CayenneLPP lpp(100);
//
// For normal use, we require that you edit the sketch to replace FILLMEIN
// with values assigned by the TTN console. However, for regression tests,
// we want to be able to compile these scripts. The regression tests define
// COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non-
// working but innocuous value.
//
#ifdef COMPILE_REGRESSION_TEST
# define FILLMEIN 0
#else
# warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!"
# define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN)
#endif
static osjob_t sendjob;
//Trick
uint8_t mydata[128];
char mydata_Aux[128];
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 20;
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = RADIO_NSS,
.rxtx = RADIO_ANT_SWITCH_HF,
.rst = RADIO_RESET,
.dio = {RADIO_DIO_0, RADIO_DIO_1, RADIO_DIO_2},
};
float Acc_x;
float Acc_y;
float Acc_z;
void printVariables()
{
lpp.reset();
lpp.addAccelerometer(4, Acc_x, Acc_y, Acc_z);
}
void printHex2(unsigned v) {
v &= 0xff;
if (v < 16)
Serial.print('0');
Serial.print(v, HEX);
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch(ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
{
u4_t netid = 0;
devaddr_t devaddr = 0;
u1_t nwkKey[16];
u1_t artKey[16];
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
Serial.print("netid: ");
Serial.println(netid, DEC);
Serial.print("devaddr: ");
Serial.println(devaddr, HEX);
Serial.print("AppSKey: ");
for (size_t i=0; i<sizeof(artKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(artKey[i]);
}
Serial.println("");
Serial.print("NwkSKey: ");
for (size_t i=0; i<sizeof(nwkKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(nwkKey[i]);
}
Serial.println();
}
// Disable link check validation (automatically enabled
// during join, but because slow data rates change max TX
// size, we don't use it in this example.
LMIC_setLinkCheckMode(0);
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_RFU1:
|| Serial.println(F("EV_RFU1"));
|| break;
*/
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.print(F("Received "));
Serial.print(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_SCAN_FOUND:
|| Serial.println(F("EV_SCAN_FOUND"));
|| break;
*/
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println(F("EV_TXCANCELED"));
break;
case EV_RXSTART:
/* do not print anything -- it wrecks timing */
break;
case EV_JOIN_TXCOMPLETE:
Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
Serial.print(F("Unknown event: "));
Serial.println((unsigned) ev);
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
printVariables();
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
Aqui foi necessário referenciar os #include do LMIC LoRaWAN Stack (incluido no Topo do código Arduino)
#include <lmic.h>
#include <hal/hal.h>
#include <ArduinoJson.h>
#include <CayenneLPP.h>
Aqui algumas inicializações do LMIC LoRaWAN Stack (modifique conforme sua BAND)
(Chamadas no Setup() do código Arduino)
//LOM204
pinMode(RADIO_TCXO_VCC_PIN,OUTPUT);
digitalWrite(RADIO_TCXO_VCC_PIN,HIGH);
//LOM204
Serial.begin(9600);
Serial.println(F("Starting"));
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
LMIC_selectSubBand(1); //FSB2 start in 0
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
Algumas configurações extras de GPIOS do LOM204 (Chamadas no Setup() do código Arduino)
pinMode(RADIO_TCXO_VCC_PIN,OUTPUT);
digitalWrite(RADIO_TCXO_VCC_PIN,HIGH);
pinMode(RADIO_ANT_SWITCH_PIN_RX,OUTPUT);
digitalWrite(RADIO_ANT_SWITCH_PIN_RX,HIGH);
Acc_x = AValue;
Acc_y = AValue;
Acc_z = AValue;
Finalmente a inclusão no Loop() do Arduino
os_runloop_once();
Abaixo o código completo
//----------------------------------------------
//
// Sketch Generated by Visuino
// www.visuino.com
//
//------------------ Source --------------------
//
// lorawanDynamicCayenne.visuino
//
//----------------------------------------------
#define VISUINO_STMDUINO
HardwareSerial Serial1(PB4, PB3);
#include <OpenWire.h>
#include <Mitov.h>
#include <Mitov_StandardSerial.h>
#include <lmic.h>
#include <hal/hal.h>
#include <ArduinoJson.h>
#include <CayenneLPP.h>
#include <Mitov_Text.h>
#include <Mitov_BinaryGenerators.h>
#include <Mitov_Counter.h>
#include <Mitov_RandomGenerator.h>
//Cayenna PAYLOAD
CayenneLPP lpp(100);
//
// For normal use, we require that you edit the sketch to replace FILLMEIN
// with values assigned by the TTN console. However, for regression tests,
// we want to be able to compile these scripts. The regression tests define
// COMPILE_REGRESSION_TEST, and in that case we define FILLMEIN to a non-
// working but innocuous value.
//
#ifdef COMPILE_REGRESSION_TEST
# define FILLMEIN 0
#else
# warning "You must replace the values marked FILLMEIN with real values from the TTN control panel!"
# define FILLMEIN (#dont edit this, edit the lines that use FILLMEIN)
#endif
static osjob_t sendjob;
//Trick
uint8_t mydata[128];
char mydata_Aux[128];
// Schedule TX every this many seconds (might become longer due to duty
// cycle limitations).
const unsigned TX_INTERVAL = 20;
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = RADIO_NSS,
.rxtx = RADIO_ANT_SWITCH_HF,
.rst = RADIO_RESET,
.dio = {RADIO_DIO_0, RADIO_DIO_1, RADIO_DIO_2},
};
float Acc_x;
float Acc_y;
float Acc_z;
void printVariables()
{
lpp.reset();
lpp.addAccelerometer(4, Acc_x, Acc_y, Acc_z);
}
void printHex2(unsigned v) {
v &= 0xff;
if (v < 16)
Serial.print('0');
Serial.print(v, HEX);
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch(ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
{
u4_t netid = 0;
devaddr_t devaddr = 0;
u1_t nwkKey[16];
u1_t artKey[16];
LMIC_getSessionKeys(&netid, &devaddr, nwkKey, artKey);
Serial.print("netid: ");
Serial.println(netid, DEC);
Serial.print("devaddr: ");
Serial.println(devaddr, HEX);
Serial.print("AppSKey: ");
for (size_t i=0; i<sizeof(artKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(artKey[i]);
}
Serial.println("");
Serial.print("NwkSKey: ");
for (size_t i=0; i<sizeof(nwkKey); ++i) {
if (i != 0)
Serial.print("-");
printHex2(nwkKey[i]);
}
Serial.println();
}
// Disable link check validation (automatically enabled
// during join, but because slow data rates change max TX
// size, we don't use it in this example.
LMIC_setLinkCheckMode(0);
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_RFU1:
|| Serial.println(F("EV_RFU1"));
|| break;
*/
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.print(F("Received "));
Serial.print(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
/*
|| This event is defined but not used in the code. No
|| point in wasting codespace on it.
||
|| case EV_SCAN_FOUND:
|| Serial.println(F("EV_SCAN_FOUND"));
|| break;
*/
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
case EV_TXCANCELED:
Serial.println(F("EV_TXCANCELED"));
break;
case EV_RXSTART:
/* do not print anything -- it wrecks timing */
break;
case EV_JOIN_TXCOMPLETE:
Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept"));
break;
default:
Serial.print(F("Unknown event: "));
Serial.println((unsigned) ev);
break;
}
}
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
printVariables();
LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
// This should also be in little endian format, see above.
//88 57 1D FF FE EE 8C 64
static const u1_t PROGMEM DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
//48 4F 68 92 5E 6E 4C 82 E0 6C 9A EF CA 37 86 EA
static const u1_t PROGMEM APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
// Shared Component Member Variables
namespace ComponentVariables
{
class
{
public:
bool Value1 : 1;
bool Value2 : 1;
bool Value3 : 1;
bool Value4 : 1;
bool Value5 : 1;
bool Value6 : 1;
int32_t Value7 : 32;
bool Value8 : 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; }
};
class Variable5
{
public:
inline static bool GetValue() { return BitFields.Value5; }
inline static void SetValue( bool AValue ) { BitFields.Value5 = AValue; }
};
class Variable6
{
public:
inline static bool GetValue() { return BitFields.Value6; }
inline static void SetValue( bool AValue ) { BitFields.Value6 = AValue; }
};
class Variable7
{
public:
inline static int32_t GetValue() { return BitFields.Value7; }
inline static void SetValue( int32_t AValue ) { BitFields.Value7 = AValue; }
};
class Variable8
{
public:
inline static bool GetValue() { return BitFields.Value8; }
inline static void SetValue( bool AValue ) { BitFields.Value8 = AValue; }
};
} // ComponentVariables
// Arduino Constant Declarations
namespace VisuinoConstants
{
class FloatValue2
{
public:
inline static constexpr float GetValue() { return 0.5; }
};
class FloatValue0
{
public:
inline static constexpr float GetValue() { return 0.0500000007450581; }
};
class FloatValue1
{
public:
inline static constexpr float GetValue() { return 0; }
};
class TextValue0
{
public:
inline static constexpr const char *GetValue() { return "Count: "; }
};
} // 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 );
};
class PinCallerReceive4
{
public:
void Notify( void *_Data );
};
class PinCallerReceive5
{
public:
void Notify( void *_Data );
};
} // PinCalls
// Call Chains
namespace CallChains
{
class Processed1
{
public:
inline static uint32_t Count() { return 1; }
static void Call();
};
class CanProcess1
{
public:
inline static uint32_t Count() { return 1; }
static void Call( bool & AResult );
};
class Process1
{
public:
inline static 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_TYPE
Mitov::ConstantProperty<4, uint32_t, 0 >, // AfterSendingDelay
Mitov::ConstantProperty<7, uint32_t, 8 >, // DataBits
Mitov::ConstantProperty<3, bool, true >, // Enabled
Mitov::ConstantProperty<51, uint32_t, 0>, // FEndTime
Mitov::ConstantProperty<50, bool, false>, // FSending
Mitov::GenericPin_NoImplementation<5 >, // OutputPin
Mitov::ConstantProperty<9, Mitov::TArduinoStandardSerialParity, Mitov::spNone >, // Parity
Mitov::ConstantProperty<10, uint32_t, 10 >, // RXPin
Mitov::DigitalPin_NoImplementation<2 >, // SendingOutputPin
Mitov::ConstantProperty<6, uint32_t, 9600 >, // Speed
Mitov::ConstantProperty<8, uint32_t, 1 >, // StopBits
Mitov::ConstantProperty<11, uint32_t, 9 > // TXPin
> SerialPort0;
} // Types
namespace Instances
{
Types::SerialPort0 SerialPort0;
} // Instances
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 Mitov::SerialPort<
SERIAL_TYPE, // 0_T_TYPE
Serial1, // 1_C_TYPE
Mitov::ConstantProperty<4, uint32_t, 0 >, // AfterSendingDelay
Mitov::ConstantProperty<7, uint32_t, 8 >, // DataBits
Mitov::ConstantProperty<3, bool, true >, // Enabled
Mitov::ConstantProperty<51, uint32_t, 0>, // FEndTime
Mitov::ConstantProperty<50, bool, false>, // FSending
Mitov::GenericPin_NoImplementation<5 >, // OutputPin
Mitov::ConstantProperty<9, Mitov::TArduinoStandardSerialParity, Mitov::spNone >, // Parity
Mitov::DigitalPin_NoImplementation<2 >, // SendingOutputPin
Mitov::ConstantProperty<6, uint32_t, 9600 >, // Speed
Mitov::ConstantProperty<8, uint32_t, 1 > // StopBits
> SerialPort1;
} // Types
namespace Instances
{
Types::SerialPort1 SerialPort1;
} // Instances
namespace Types
{
typedef Mitov::ArduinoSerialInput_String<BoardDeclarations::Types::SerialPort1, BoardDeclarations::Instances::SerialPort1, char *> SerialPort1_Input_IOWStringStream_1;
} // Types
namespace Instances
{
Types::SerialPort1_Input_IOWStringStream_1 SerialPort1_Input_IOWStringStream_1;
} // Instances
} // BoardDeclarations
// Custom Code Declarations
namespace CustomCode
{
class TCustomCodeLoraWAN_Stack1
{
public: // Inputs
inline void __Inputs_o_0_o_Receive( Mitov::String AValue )
{
AValue.toCharArray(mydata_Aux,128);
for(uint8_t i=0;i<AValue.length();i++)
mydata[i] = mydata_Aux[i];
//String S = String(mydata_Aux);
//Serial.println(S);
}
inline void __Inputs_o_1_o_Receive( int32_t AValue )
{
Acc_x = AValue;
}
inline void __Inputs_o_2_o_Receive( int32_t AValue )
{
Acc_y = AValue;
}
inline void __Inputs_o_3_o_Receive( int32_t AValue )
{
Acc_z = AValue;
}
public:
void SystemInit();
public:
void SystemStart();
public:
void SystemLoopUpdateHardware();
};
class TArduinoCustomCodeInputTextElement1
{
public:
void InputPin_o_Receive( void *_Data );
};
class TArduinoCustomCodeInputIntegerElement1
{
public:
void InputPin_o_Receive( void *_Data );
};
class TArduinoCustomCodeInputIntegerElement2
{
public:
void InputPin_o_Receive( void *_Data );
};
class TArduinoCustomCodeInputIntegerElement3
{
public:
void InputPin_o_Receive( void *_Data );
};
class TCustomCodeLoraWAN_Setup_Globals1
{
};
} // CustomCode
// Declarations
namespace Declarations
{
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
namespace Types
{
typedef CustomCode::TArduinoCustomCodeInputIntegerElement1 TArduinoCustomCodeInputIntegerElement1;
} // Types
namespace Instances
{
Types::TArduinoCustomCodeInputIntegerElement1 TArduinoCustomCodeInputIntegerElement1;
} // Instances
namespace Types
{
typedef CustomCode::TArduinoCustomCodeInputIntegerElement2 TArduinoCustomCodeInputIntegerElement2;
} // Types
namespace Instances
{
Types::TArduinoCustomCodeInputIntegerElement2 TArduinoCustomCodeInputIntegerElement2;
} // Instances
namespace Types
{
typedef CustomCode::TArduinoCustomCodeInputIntegerElement3 TArduinoCustomCodeInputIntegerElement3;
} // Types
namespace Instances
{
Types::TArduinoCustomCodeInputIntegerElement3 TArduinoCustomCodeInputIntegerElement3;
} // Instances
namespace Types
{
typedef Mitov::FormattedText_Fixed<
true, // Clock_IsConnected
1, // 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::PinCallerReceive0 > // OutputPin
> FormattedText1;
} // Types
namespace Instances
{
Types::FormattedText1 FormattedText1;
} // Instances
namespace Types
{
typedef Mitov::FormattedTextElementInteger<
Declarations::Types::FormattedText1, // 0_TYPE_OWNER
Declarations::Instances::FormattedText1, // 1_NAME_OWNER
Mitov::ConstantProperty<5, int32_t, 10 >, // Base
Mitov::ConstantProperty<88, bool, true >, // FModified
Mitov::ConstantProperty<3, char, ' ' >, // FillCharacter
Mitov::VariableProperty<6, int32_t, 0 >, // InitialValue
Mitov::ConstantProperty<2, uint32_t, 0 > // Length
> TArduinoFormattedTextElementInteger1;
} // Types
namespace Instances
{
Types::TArduinoFormattedTextElementInteger1 TArduinoFormattedTextElementInteger1;
} // Instances
Mitov::TFormattedTextStringItemIndexed<
::VisuinoConstants::TextValue0,
Declarations::Types::TArduinoFormattedTextElementInteger1,
Declarations::Instances::TArduinoFormattedTextElementInteger1
> _o_FormattedText1_o_Indexed0;
namespace Types
{
typedef Mitov::PulseGenerator<
Mitov::ConstantPropertyFloat<8, float, ::VisuinoConstants::FloatValue1 >, // Asymmetry
Mitov::ConstantProperty<4, bool, true >, // Enabled
Mitov::ConstantPropertyFloat<17, float, ::VisuinoConstants::FloatValue1>, // FPhase
Mitov::TypedVariable<15, bool, ::ComponentVariables::Variable4 >, // FValue
Mitov::ConstantPropertyFloat<7, float, ::VisuinoConstants::FloatValue0 >, // Frequency
Mitov::ConstantProperty<5, bool, false >, // InitialValue
Mitov::DigitalPin_EmbeddedPinImplementation_ChangeOnly<3, ::PinCalls::PinCallerReceive1, Mitov::TypedVariable<0, bool, ::ComponentVariables::Variable3 > >, // 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
namespace Types
{
typedef Mitov::PulseGenerator<
Mitov::ConstantPropertyFloat<8, float, ::VisuinoConstants::FloatValue1 >, // Asymmetry
Mitov::ConstantProperty<4, bool, true >, // Enabled
Mitov::ConstantPropertyFloat<17, float, ::VisuinoConstants::FloatValue1>, // FPhase
Mitov::TypedVariable<15, bool, ::ComponentVariables::Variable5 >, // FValue
Mitov::ConstantPropertyFloat<7, float, ::VisuinoConstants::FloatValue2 >, // Frequency
Mitov::ConstantProperty<5, bool, false >, // InitialValue
Mitov::DigitalPin_DirectBoardPinImplementation<PA2 >, // 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
> PulseGenerator2;
} // Types
namespace Instances
{
Types::PulseGenerator2 PulseGenerator2;
} // Instances
namespace Types
{
typedef CustomCode::TCustomCodeLoraWAN_Setup_Globals1 CustomCodeLoraWAN_Setup_Globals;
} // Types
namespace Instances
{
Types::CustomCodeLoraWAN_Setup_Globals CustomCodeLoraWAN_Setup_Globals;
} // Instances
namespace Types
{
typedef Mitov::Counter<
Mitov::ConstantProperty<4, bool, true >, // Enabled
Mitov::TypedVariable<32, int32_t, ::ComponentVariables::Variable7>, // FCount
Mitov::ConstantProperty<6, int32_t, 0 >, // InitialValue
Mitov::NestedProperty<14, Mitov::CounterLimit<
Mitov::ConstantProperty<13, bool, true >, // RollOver
Mitov::ConstantProperty<12, int32_t, 2147483647 > // Value
> >, // Value_Max
Mitov::NestedProperty<10, Mitov::CounterLimit<
Mitov::ConstantProperty<9, bool, true >, // RollOver
Mitov::ConstantProperty<8, int32_t, -2147483648 > // Value
> >, // Value_Min
Mitov::TypedVariable<18, bool, ::ComponentVariables::Variable6 >, // NeedsUpdate
Mitov::TypedPin_EmbeddedPinImplementation<3, ::PinCalls::PinCallerReceive2, int32_t >, // OutputPin
Mitov::ConstantProperty<17, bool, false > // Reversed
> Counter1;
} // Types
namespace Instances
{
Types::Counter1 Counter1;
} // Instances
namespace Types
{
typedef Mitov::CommonRandomGenerator<
float, // 0_TYPE
Mitov::RandomIntegerGenerator<int32_t>, // 1_BASE
Mitov::ConstantProperty<5, bool, true >, // Enabled
Mitov::ConstantProperty<7, int32_t, 10 >, // Value_Max
Mitov::ConstantProperty<6, int32_t, 0 >, // Value_Min
Mitov::TypedPin_EmbeddedPinImplementation<3, ::PinCalls::PinCallerReceive3, int32_t >, // OutputPin
Mitov::ConstantProperty<8, int32_t, 0 > // Seed
> RandomIntegerGeneratorX;
} // Types
namespace Instances
{
Types::RandomIntegerGeneratorX RandomIntegerGeneratorX;
} // Instances
namespace Types
{
typedef Mitov::CommonRandomGenerator<
float, // 0_TYPE
Mitov::RandomIntegerGenerator<int32_t>, // 1_BASE
Mitov::ConstantProperty<5, bool, true >, // Enabled
Mitov::ConstantProperty<7, int32_t, 10 >, // Value_Max
Mitov::ConstantProperty<6, int32_t, 0 >, // Value_Min
Mitov::TypedPin_EmbeddedPinImplementation<3, ::PinCalls::PinCallerReceive4, int32_t >, // OutputPin
Mitov::ConstantProperty<8, int32_t, 0 > // Seed
> RandomIntegerGeneratorY;
} // Types
namespace Instances
{
Types::RandomIntegerGeneratorY RandomIntegerGeneratorY;
} // Instances
namespace Types
{
typedef Mitov::CommonRandomGenerator<
float, // 0_TYPE
Mitov::RandomIntegerGenerator<int32_t>, // 1_BASE
Mitov::ConstantProperty<5, bool, true >, // Enabled
Mitov::ConstantProperty<7, int32_t, 10 >, // Value_Max
Mitov::ConstantProperty<6, int32_t, 0 >, // Value_Min
Mitov::TypedPin_EmbeddedPinImplementation<3, ::PinCalls::PinCallerReceive5, int32_t >, // OutputPin
Mitov::ConstantProperty<8, int32_t, 0 > // Seed
> RandomIntegerGeneratorZ;
} // Types
namespace Instances
{
Types::RandomIntegerGeneratorZ RandomIntegerGeneratorZ;
} // Instances
} // Declarations
// Custom Code Implementations
namespace CustomCode
{
void TCustomCodeLoraWAN_Stack1::SystemInit()
{
pinMode(RADIO_TCXO_VCC_PIN,OUTPUT);
digitalWrite(RADIO_TCXO_VCC_PIN,HIGH);
pinMode(RADIO_ANT_SWITCH_PIN_RX,OUTPUT);
digitalWrite(RADIO_ANT_SWITCH_PIN_RX,HIGH);
}
void TCustomCodeLoraWAN_Stack1::SystemStart()
{
//LOM204
pinMode(RADIO_TCXO_VCC_PIN,OUTPUT);
digitalWrite(RADIO_TCXO_VCC_PIN,HIGH);
//LOM204
Serial.begin(9600);
Serial.println(F("Starting"));
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
LMIC_selectSubBand(1); //FSB2 start in 0
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
}
void TCustomCodeLoraWAN_Stack1::SystemLoopUpdateHardware()
{
os_runloop_once();
}
void TArduinoCustomCodeInputTextElement1::InputPin_o_Receive( void *_Data )
{
Declarations::Instances::CustomCodeLoraWAN_Stack.__Inputs_o_0_o_Receive( Mitov::String( ( char *)_Data ) );
}
void TArduinoCustomCodeInputIntegerElement1::InputPin_o_Receive( void *_Data )
{
Declarations::Instances::CustomCodeLoraWAN_Stack.__Inputs_o_1_o_Receive( *( int32_t *)_Data );
}
void TArduinoCustomCodeInputIntegerElement2::InputPin_o_Receive( void *_Data )
{
Declarations::Instances::CustomCodeLoraWAN_Stack.__Inputs_o_2_o_Receive( *( int32_t *)_Data );
}
void TArduinoCustomCodeInputIntegerElement3::InputPin_o_Receive( void *_Data )
{
Declarations::Instances::CustomCodeLoraWAN_Stack.__Inputs_o_3_o_Receive( *( int32_t *)_Data );
}
} // CustomCode
// Type Converters
namespace TypeConverters
{
Mitov::Convert_BinaryToClock<Mitov::TypedVariable<0, bool, ::ComponentVariables::Variable8 >> Converter0;
} // TypeConverters
// Call Chains
namespace CallChains
{
void Processed1::Call()
{
Declarations::Instances::TArduinoFormattedTextElementInteger1.Processed();
}
void CanProcess1::Call( bool & AResult )
{
Declarations::Instances::TArduinoFormattedTextElementInteger1.CanProcess( 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 )
{
BoardDeclarations::Instances::SerialPort0_Input_IOWStringStream_1.InputPin_o_Receive( _Data );
BoardDeclarations::Instances::SerialPort1_Input_IOWStringStream_1.InputPin_o_Receive( _Data );
Declarations::Instances::TArduinoCustomCodeInputTextElement1.InputPin_o_Receive( _Data );
}
void PinCallerReceive1::Notify( void *_Data )
{
TypeConverters::Converter0.Convert( _Data, PinCallerConverterReceive1 );
}
void PinCallerConverterReceive1( void *_Data )
{
Declarations::Instances::FormattedText1.ClockInputPin_o_Receive( _Data );
Declarations::Instances::Counter1.InputPin_o_Receive( _Data );
}
void PinCallerReceive2::Notify( void *_Data )
{
Declarations::Instances::TArduinoFormattedTextElementInteger1.InputPin_o_Receive( _Data );
}
void PinCallerReceive3::Notify( void *_Data )
{
Declarations::Instances::TArduinoCustomCodeInputIntegerElement1.InputPin_o_Receive( _Data );
}
void PinCallerReceive4::Notify( void *_Data )
{
Declarations::Instances::TArduinoCustomCodeInputIntegerElement2.InputPin_o_Receive( _Data );
}
void PinCallerReceive5::Notify( void *_Data )
{
Declarations::Instances::TArduinoCustomCodeInputIntegerElement3.InputPin_o_Receive( _Data );
}
} // PinCalls
namespace ComponentsHardware
{
void SystemUpdateHardware()
{
Declarations::Instances::CustomCodeLoraWAN_Stack.SystemLoopUpdateHardware();
}
} // ComponentsHardware
//The setup function is called once at startup of the sketch
void setup()
{
BoardDeclarations::Instances::SerialPort0.SystemInit();
BoardDeclarations::Instances::SerialPort1.SystemInit();
Declarations::Instances::CustomCodeLoraWAN_Stack.SystemInit();
Declarations::Instances::Counter1.SystemInit();
Declarations::Instances::CustomCodeLoraWAN_Stack.SystemStart();
Declarations::Instances::FormattedText1.SystemStart();
Declarations::Instances::TArduinoFormattedTextElementInteger1.SystemStart();
Declarations::Instances::PulseGenerator1.SystemStart();
Declarations::Instances::PulseGenerator2.SystemStart();
Declarations::Instances::Counter1.SystemStart();
Declarations::Instances::RandomIntegerGeneratorX.SystemStartGenerate();
Declarations::Instances::RandomIntegerGeneratorY.SystemStartGenerate();
Declarations::Instances::RandomIntegerGeneratorZ.SystemStartGenerate();
}
// The loop function is called in an endless loop
void loop()
{
Declarations::Instances::PulseGenerator1.SystemLoopBegin();
Declarations::Instances::PulseGenerator2.SystemLoopBegin();
Declarations::Instances::RandomIntegerGeneratorX.SystemLoopBegin();
Declarations::Instances::RandomIntegerGeneratorY.SystemLoopBegin();
Declarations::Instances::RandomIntegerGeneratorZ.SystemLoopBegin();
ComponentsHardware::SystemUpdateHardware();
}
Conectando EndDevices com myDevices(TTN )
Conta cayenne (vincular EnDevice)
Certifique-se que LOM204 e programador estejam selecionados, bem como demais parâmetros e então compile.
Transfira o programa (sempre reset antes o LOM204)
Execução
STM32Programmer
Uma boa opção se tiveres problemas com drivers é instalar.
Fontes:
Dúvidas
suporte@smartcore.com.br
Download
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