BETA BETA BETA BETA BETA BETA BETA BETA
O objetivo deste BLOG é demonstrar como é possível programar o módulo WISOL LSM110A via ARDUINO e assim utilizá-lo como OPENCPU.
Será publicada a temperatura obtida pelo sensor BME680 na rede LoRaWAN TTN (CLASS A, OTAA) a cada 60 segundos.
Temp xx.xx
BETA BETA BETA BETA BETA BETA BETA BETA
LSM110A Starter KIT
Módulo
O LSM110A é um módulo de última geração que integra o STMicroelectronics STM32WL. É muito menos consumo atual para o dispositivo IoT para estender a vida útil da bateria. E, também suporta ambas as tecnologias – Sigfox e LoRa – com o próprio módulo LSM110A.
Você pode trocar Sigfox ou LoRa com ele para que você também possa reduzir o custo. É altamente otimizado para solução de IoT (Alto Consumo de Energia, Baixo Custo)
BREAKOUT para testes
Esquema Elétrico - últimas correções
PLACA MONTADA
CONEXÃO COM ST-LINK V2 E UART
BME680
O BME680 é o primeiro sensor de gás que integra sensores de gás, pressão, umidade e temperatura de alta linearidade e alta precisão. É especialmente desenvolvido para aplicações móveis e wearables, onde o tamanho e o baixo consumo de energia são requisitos críticos. O BME680 garante - dependendo do modo de operação específico - um consumo otimizado, estabilidade a longo prazo e alta robustez EMC.
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.
BME680 LIB
LSM110A e ARDUINO (RAKWIRELESS)
LSM110A é baseado em STM32WL55. No Arduino RAKWIRELESS existe o core similar, o qual deve ser modificado para ser compatível com LSM110A
Baixar RAKWIRELESS Arduino
Versão: 3.5.1
https://raw.githubusercontent.com/RAKWireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless.com_rui_index.json
Pronto
Altere radio_board_if.c para
int32_t RBI_ConfigRFSwitch(RBI_Switch_TypeDef Config)
{
switch (Config)
{
case RBI_SWITCH_OFF:
{
/* Turn off switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET);
break;
}
case RBI_SWITCH_RX:
{
/*Turns On in Rx Mode the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET);
break;
}
case RBI_SWITCH_RFO_LP:
{
/*Turns On in Tx Low Power the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET);
break;
}
case RBI_SWITCH_RFO_HP:
{
/*Turns On in Tx High Power the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET);
break;
}
default:
break;
}
return 0;
}
Altere radio_board_if.h para
#define RF_SW_CTRL1_PIN GPIO_PIN_12
#define RF_SW_CTRL1_GPIO_PORT GPIOB
#define RF_SW_CTRL1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define RF_SW_CTRL1_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()
/* official version */
#define RF_SW_CTRL2_PIN GPIO_PIN_13
#define RF_SW_CTRL2_GPIO_PORT GPIOC
#define RF_SW_CTRL2_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define RF_SW_CTRL2_GPIO_CLK_DISABLE() __HAL_RCC_GPIOA_CLK_DISABLE()
Altere Cristal para uso de frequênciais (BAND) mais altas (board.c)
uint8_t BoardGetHardwareFreq(void)
{
uint8_t hardwareFreq = 0;
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin : PB12 */
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hardwareFreq = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12);
hardwareFreq = 1;
HAL_GPIO_DeInit(GPIOB,GPIO_PIN_12);
return hardwareFreq;
}
Grave com o STM32 Programmer o BOOTLOADER no LSM110A
Assim, pode-se transferir o programa via Serial, através dos pinos PA2 e PA3 do LSM110A.
RAK3272-SiP_latest_final.hex
Ok, o ambiente de desenvolvimento está pronto. Abra Projeto Arduino LORAWAN_OTA.INOconfigure 3 parâmetros para LoRaWAN_OTAA os quais deve ser obtidos no servidor TTN.
#define OTAA_BAND RAK_REGION_AU915
#define OTAA_DEVEUI {0x00, 0x80, 0xE1, 0xXX, 0x05, 0xXX, 0xXX, 0x0A}
#define OTAA_APPEUI {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99}
#define OTAA_APPKEY {0xFF, 0x9F, 0x13, 0x8B, 0x40, 0x18, 0x0A, 0xA4, 0x5D, 0x68, 0x46, 0xE0, 0xA0, 0x14, 0x69, 0x54}
Transferindo
Executando
Uma vez gravado o Software, o LSM110A fará o JOIN na LoRaWAN enviará o pacote Test a cada 60 segundos.
TTN
Neste exemplo, será transmitido para LoRaWAN (TTN) os dados
Segue código final
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME680 bme; // I2C
//Adafruit_BME680 bme(BME_CS); // hardware SPI
//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);
#define OTAA_PERIOD (20000)
/*************************************
LoRaWAN band setting:
RAK_REGION_EU433
RAK_REGION_CN470
RAK_REGION_RU864
RAK_REGION_IN865
RAK_REGION_EU868
RAK_REGION_US915
RAK_REGION_AU915
RAK_REGION_KR920
RAK_REGION_AS923
*************************************/
#define OTAA_BAND RAK_REGION_AU915
#define OTAA_DEVEUI {0x88, 0x57, 0xXX, 0xFF, 0xXX, 0xEE, 0x8C, 0xXX}
#define OTAA_APPEUI {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#define OTAA_APPKEY {0x46, 0x28, 0xCB, 0xXX, 0x4F, 0xF9, 0x4B, 0xA5, 0xB0, 0x04, 0xE2, 0xDC, 0x01, 0xXX, 0x89, 0xA2}
/** Packet buffer for sending */
char collected_data[64] = { 0 };
void recvCallback(SERVICE_LORA_RECEIVE_T * data)
{
if (data->BufferSize > 0) {
Serial.println("Something received!");
for (int i = 0; i < data->BufferSize; i++) {
Serial.printf("%x", data->Buffer[i]);
}
Serial.print("\r\n");
}
}
void joinCallback(int32_t status)
{
Serial.printf("Join status: %d\r\n", status);
}
void sendCallback(int32_t status)
{
if (status == 0) {
Serial.println("Successfully sent");
} else {
Serial.println("Sending failed");
}
}
void setup()
{
unsigned status;
Serial.begin(115200, RAK_AT_MODE);
Serial.println("BME680 LoRaWAN");
if (!bme.begin()) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
}
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
// OTAA Device EUI MSB first
uint8_t node_device_eui[8] = OTAA_DEVEUI;
// OTAA Application EUI MSB first
uint8_t node_app_eui[8] = OTAA_APPEUI;
// OTAA Application Key MSB first
uint8_t node_app_key[16] = OTAA_APPKEY;
if (!api.lorawan.appeui.set(node_app_eui, 8)) {
Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.appkey.set(node_app_key, 16)) {
Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
return;
}
if (!api.lorawan.deui.set(node_device_eui, 8)) {
Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.band.set(OTAA_BAND)) {
Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
return;
}
if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
return;
}
if (!api.lorawan.njm.set(RAK_LORA_OTAA)) // Set the network join mode to OTAA
{
Serial.
printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");
return;
}
if (!api.lorawan.join()) // Join to Gateway
{
Serial.printf("LoRaWan OTAA - join fail! \r\n");
return;
}
/** Wait for Join success */
while (api.lorawan.njs.get() == 0) {
Serial.print("Wait for LoRaWAN join...");
api.lorawan.join();
delay(10000);
}
if (!api.lorawan.adr.set(true)) {
Serial.printf
("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
return;
}
if (!api.lorawan.rety.set(1)) {
Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
return;
}
if (!api.lorawan.cfm.set(1)) {
Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
return;
}
/** Check LoRaWan Status*/
Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF"); // Check Duty Cycle status
Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED"); // Check Confirm status
uint8_t assigned_dev_addr[4] = { 0 };
api.lorawan.daddr.get(assigned_dev_addr, 4);
Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]); // Check Device Address
Serial.printf("Uplink period is %ums\r\n", OTAA_PERIOD);
Serial.println("");
api.lorawan.registerRecvCallback(recvCallback);
api.lorawan.registerJoinCallback(joinCallback);
api.lorawan.registerSendCallback(sendCallback);
}
void uplink_routine()
{
/** Payload of Uplink */
uint8_t data_len = 0;
String s = String(collected_data);
data_len = s.length();
Serial.println("Data Packet:");
for (int i = 0; i < data_len; i++) {
Serial.printf("0x%02X ", collected_data[i]);
}
Serial.println("");
/** Send the data package */
if (api.lorawan.send(data_len, (uint8_t *) & collected_data, 2, true, 1)) {
Serial.println("Sending is requested");
} else {
Serial.println("Sending failed");
}
}
void loop()
{
static uint64_t last = 0;
static uint64_t elapsed;
if (! bme.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
Serial.print("Temperature = ");
Serial.print(bme.temperature);
Serial.println(" *C");
sprintf(collected_data,"Temp %f",bme.temperature);
Serial.print("Pressure = ");
Serial.print(bme.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(bme.humidity);
Serial.println(" %");
Serial.print("Gas = ");
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(" KOhms");
Serial.print("Approx. Altitude = ");
Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
Serial.println(" m");
if ((elapsed = millis() - last) > OTAA_PERIOD) {
if(api.lorawan.njs.get() == 1)
uplink_routine();
last = millis();
}
//Serial.printf("Try sleep %ums..", OTAA_PERIOD);
api.system.sleep.all(OTAA_PERIOD);
//Serial.println("Wakeup..");
}
SmartCore - --- SmartCore - tecnico publico - All Documents (sharepoint.com) (Nodes) / LMIC - The Things Network
Dúvidas
FORUM
Atenção:
Com a nova versão da LIB da RAK, a 4.0.0, LIB BME680 da Adafruit gerou estouro de memória ROM.
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