LSM110A - MEDINDO CONSUMO DE ÁGUA E ENVIANDO VIA LoRaWAN PARA TTN
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.
Baseado no Artigo SMART WATER: UM PROTÓTIPO PARA MONITORAMENTO DO CONSUMO DE ÁGUA Matheus Eduardo Hoeltgebaum Pereira, Miguel Alexandre Wisintainer, Aurélio Faustino Hoppe – Orientador
O objetivo geral deste BLOG é demonstrar como é possível programar o módulo WISOL LSM110A110A via RAKWIRELESS e assim utilizá-lo como OPENCPU.
O objetivo específico neste projeto é programar o LSM110A para permitir coletar as medições reais realizadas por um Hidrômetro e via OTAA enviar para um Gateway LoRaWAN da Dragino e finalmente para TTN.
O tradicional sistema de medição de hidrômetros, através de leituristas, apesar de ainda ser amplamente utilizado pelas empresas que prestam serviço de abastecimento de água, tende a se tornar um processo cada vez mais inviável ao longo dos anos, devido ao crescimento urbano. Com o objetivo de buscar uma solução para esta questão, este BLOG apresenta o desenvolvimento de um protótipo para monitorar o consumo de água e uma aplicação que possibilite ao usuário visualizar o seu consumo. O presente blog também discorre sobre questões técnicas em relação a hidrômetros e o funcionamento do hardware e da rede LoRaWAN, detalhando os processos de conversão de pulsos emitidos pelos sensores de fluxo, além da utilização do módulo LSM110A para controle e envio de mensagens através da rede LoRaWAN.
A água é um recurso essencial para os seres humanos, sendo necessária desde a absorção de alimentos até a eliminação de resíduos. Todo ser vivo tem que manter seu suprimento de água próximo do normal, do contrário morre. Um homem pode viver sem alimento sólido por mais de um mês, mas sem água só poderá viver cerca de dois ou três dias.
Hoje, a sociedade tem acesso à água potável devido ao trabalho realizado por empresas responsáveis pelo tratamento e distribuição deste recurso. A Agência Nacional de Águas elaborou um estudo em 2010, para identificar os tipos de empresas que prestavam este serviço de abastecimento. No estudo, verificou-se que a maioria das empresas são companhias estaduais de saneamento, em 69% dos municípios, enquanto em 27% são entidades municipais e, em 4%, empresas do setor privado
Para a água chegar até a população, estando própria para consumo, requer-se todo um processo de obtenção, tratamento, para enfim, possibilitar a distribuição. Primeiramente, deve-se realizar a captura da água em mananciais, os quais podem ser lagos, rios ou água do subsolo, e logo após, realiza-se um processo de tratamento dela, a fim de que se torne pura e própria para o consumo
Estando a água disponível para a população, faz-se necessário realizar um controle sobre o consumo, por parte das distribuidoras, através da obtenção das informações contidas nos hidrômetros das residências. Atualmente, trata-se de um processo manual, necessitando da presença de uma pessoa responsável por visitar a casa dos consumidores e cadastrar o valor contido no hidrômetro. Por se tratar de um procedimento que é realizado através de caminhada, acaba gerando desgaste físico e de tempo, podendo influenciar na qualidade de vida dos funcionários e no atendimento à população.
O sistema tradicional de leitura de hidrômetros, utilizando-se de leituristas, pode até ser aceitável atualmente, entretanto, com o crescimento urbano, tende a se tornar um processo cada vez mais complexo e demorado. Assim, a utilização de microcontroladores podem propiciar o desenvolvimento de soluções que buscam conectar dispositivos em rede, para o gerenciamento de processos industrias e residenciais. Para viabilizar a leitura de hidrômetros em um curto espaço de tempo, desenvolveram-se sistemas de medição remota, reduzindo o tempo de leitura e sem nenhum custo de mão de obra. No Brasil, já existem fornecedores para este novo sistema de medição, embora o seu custo de implantação seja mais caro do que o sistema tradicional.
A questão do desperdício de água tem causado uma elevada preocupação na população mundial, pelo crescimento exorbitante das taxas de desperdício, sendo necessário a utilização de equipamentos que visam evitar que o mesmo aconteça. Desta maneira, demanda-se um ferramental capaz de apresentar ao usuário o seu consumo em tempo real, para que ele possa controlar o seu gasto desnecessário, algo que ainda não está presente no Brasil.
Diante do exposto, este blog apresenta o desenvolvimento de um protótipo para monitoramento automatizado do consumo de água em residências. Acredita-se que ele facilitará o processo de coleta de informações, por parte das empresas que prestam o serviço de distribuição de água e permitirá que o usuário possa acompanhar o seu consumo de água.
Os hidrômetros são aparelhos que servem para as empresas de saneamento básico realizarem a verificação do consumo de água por parte dos moradores. Eles possuem um contador, registrando a quantidade de água consumida. O cálculo é realizado com base na última leitura realizada e a leitura atual.
Os hidrômetros podem ser divididos em duas categorias: residenciais e industriais. Os primeiros tendem a ser mais pequenos, visto que lidam com volumes menores de água, e terem um princípio de funcionamento relativamente simples, geralmente baseado em partes móveis. Os segundos, trabalham e precisam suportar grandes volumes e forças, são geralmente mais robustos e utilizam princípios de funcionamento mais complexos que tendem a não implicar o envolvimento de partes móveis.
Os hidrômetros residenciais podem ter princípios de funcionamento diferentes, no entanto o seu aspecto exterior é bastante semelhante. A Figura abaixo mostra um contador de água residencial típico. Ele é composto por um indicador digital numérico, usualmente exibindo o volume de água consumido, em m3 , e seis totalizadores, ou ponteiros, apresentando o consumo em frações de m3 . Estes ponteiros são mais orientados para o uso do consumidor visto que o operador da companhia fornecedora de água, ao registrar o consumo mensal, registra exclusivamente o indicado valor no mostrador numérico.
Para residências, existem dois tipos principais de hidrômetros: hidrômetros taquimétricos e hidrômetros volumétricos. O hidrômetro taquimétrico realiza a medição da velocidade pela qual a água atravessa, determinando o volume consumido. A água passa pelo hidrômetro, em forma de jato (s) e, ao entrar em contato com uma parte móvel, que pode ser uma turbina, hélice, entre outros, realiza o movimento de rotação. O número de rotações realizadas por esta parte móvel, após determinado tempo, está relacionado com a quantidade de água consumida.
Dentro da classe de hidrômetros taquimétricos, existem dois tipos: 1) monojatos, no qual a parte móvel é atingida por um único jato tangencial de água; 2) multijatos, no qual a parte móvel é atingida por vários jatos tangenciais de água, gerando equilíbrio no movimento de rotação, por atingir pontos igualmente espaçados. Veja a ilustração dos dois tipos de hidrômetros taquimétricos descritos acima
O funcionamento de hidrômetros taquimétricos monojatos parte do princípio que um único jato de água incide sobre uma pá da hélice existente no hidrômetro, aplicando efeito de rotação sobre a hélice. Assim, considera-se que a velocidade de rotação da hélice está diretamente relacionada com o fluxo de água e qualquer alteração sobre o fluxo pode modificar a curva de erro do hidrômetro. Com relação ao funcionamento de hidrômetros taquimétricos multijatos, o princípio deles consiste em distribuir o fluxo de água ao longo da parte móvel do hidrômetro, gerando jatos simétricos de água e mantendo a hélice em um movimento de equilíbrio. O hidrômetro do tipo multijato tem uma melhor sensibilidade, devido a distribuição de jatos que ocorre dentro dele, não se desgastando tão facilmente e por consequência, tendo uma vida útil maior.
Os hidrômetros volumétricos possuem uma câmara, ao qual internamente existe um componente móvel que realiza um movimento periódico sempre que a água passa por ela. O período é proporcional ao volume de água consumido. Este movimento ocorre devido a diferença de pressão antes e depois do hidrômetro, forçando a água a passar. No Brasil, este tipo de hidrômetro não é utilizado em sistemas de saneamento convencionais, devido ao alto custo e a facilidade de alojamento de partículas na câmara interna do hidrômetro, deixando o consumidor sem água. Os dois tipos mais comuns de hidrômetros volumétricos são os de disco oscilante e os de pistão rotativo.
O hidrômetro de disco oscilante possui um disco dentro de sua câmara, na qual a água ultrapassa a câmara apenas quando o disco realizar uma rotação completa. Como o volume para completar esta rotação é conhecido previamente, é necessário apenas saber o número de rotações que foram realizadas pelo disco, para identificar a quantidade de água consumida. Com relação aos hidrômetros de pistão rotativo, eles consistem em um pistão que separa a câmara em dois compartimentos. O movimento da água permite que o pistão execute rotações, uma vez que o cálculo do consumo de água está relacionado com o número de rotações realizadas pelo pistão. A Figura abaixo ilustra o funcionamento dos dois tipos de hidrômetros volumétricos comentados anteriormente.
Estes tipos de hidrômetros tendem a ser muito mais precisos, sendo uma de suas principais vantagens o funcionamento em vazões de água baixas. Entretanto, conforme abordado anteriormente, sua arquitetura torna-os impróprios para a utilização em serviços de abastecimento, por conta de impurezas que podem estar contidas na água, afetando o abastecimento ao consumidor. Contudo, caso estejam instalados em condições favoráveis, eles têm uma vida útil mais longa, além do fato da posição de montagem não ser tão importante quanto nos hidrômetros taquimétricos.
Para realizar o processo de coleta do consumo de cada consumidor, as empresas de saneamento contam com os leituristas, que são profissionais responsáveis por caminharem de residência em residência, identificando os hidrômetros de cada uma e emitir a fatura ao morador, através de um microcomputador, com base na quantidade de água utilizada. Também é de responsabilidade deles verificar a instalação do hidrômetro, prestar informações e conferir os dados de cada domicílio.
REDE LoRaWAN - TTN
A Rede de Coisas é 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 é 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.
CONFIGURAÇÃO AUTENTICAÇÃO NA REDE LoRaWAN
OTAA
• Vantagem: a rede gera e envia as chaves de criptografia; isto torna mais seguro. Devido ao maior nível de segurança, o OTAA é o método mais utilizado em IoT / LoRaWAN.
• AppEUI: Este é um identificador de aplicativo exclusivo usado para agrupar objetos. este
endereço, 64 bits, é usado para classificar os dispositivos periféricos por aplicação. Essa configuração pode seja ajustado.
• DevEUI: Este identificador, configurado de fábrica, torna cada objeto único. Em princípio, esta
configuração não pode ser ajustada.
• AppKey: esta é uma chave secreta compartilhada entre o dispositivo periférico e a rede. É usado para determinar as chaves da sessão. Essa configuração pode ser ajustada.
Concentre-se na OTAA
O Servido de Rede é o componente de software encarregado de estabelecer uma conexão com os objetos e gerenciando o núcleo da rede. Durante a conexão OTAA, e supondo que o dispositivo esteja autorizado a conectar-se a rede, a rede troca chaves de criptografia específicas da sessão com o núcleo da rede. O Servidor de Rede então aloca informações específicas para a sessão e as envia para o aparelho periférico:
• DevAddr: Endereço lógico (equivalente a um endereço IP) que será usado para todos comunicação subseqüente.
• NetSKey (chave de sessão de rede): chave de criptografia entre o objeto e o operador usado para transmissões e para validar a integridade das mensagens.
• AppSKey (chave de sessão do aplicativo): chave de criptografia entre o objeto e operador (através da aplicação) utilizado para as transmissões e para validar a integridade das mensagens
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
https://raw.githubusercontent.com/RAKWireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless.com_rui_index.json
Alterando configurações para ser compatível com o LSM110A
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.
Ok, o ambiente de desenvolvimento está pronto. Configure 3 parâmetros, os quais deve ser obtidos do 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 toda vez que o sensor magnético detectar a passagem do Imã do registro.
TTN
Código Fonte
//https://docs.rakwireless.com/RUI3/Arduino-API/#settimeout
//https://github.com/beegee-tokyo/RUI3-LowPower-Example/blob/main/RUI3-LowPower-Example.ino
//AT+DEVEUI=9ca7653a4a8b7515
//AT+APPKEY=e633867aa4a0d3af1a5166abff3be9b5
//ATZ
#define DEBUGGER_ON 0
#define LOW_POWER_DISABLE 0
#define OTAA_BAND RAK_REGION_AU915
#define OTAA_DEVEUI {0x00,0x80,0xe1,0x15,0x05,0x1f,0xd8,0x0a}
#define OTAA_APPEUI {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
#define OTAA_APPKEY {0xa6, 0x14, 0xd5, 0x99 , 0x63 , 0xa0 , 0x86 , 0x1e , 0xdf , 0x27 , 0x02 , 0xae , 0x6f , 0x0e , 0x1a , 0xd6}
/** Time interval to send packets in milliseconds */
uint32_t g_send_repeat_time = 10000;
uint8_t QNT_LINKCHECK_FAIL = 0;
uint8_t QNT_JOINED_FAIL = 0;
uint16_t maskBuff = 0x0002;
uint8_t buff[16];
#include "app.h"
float BAT;
float intpart; // A variable to store the integer part
float floatpart; // A variable to store the float part
bool LINKCHECK_ERROR = 0;
#define ANALOG_BAT PB3
//ATC+SENDCOUNTER=0
//flash
uint8_t flash_value[4] = {0};
bool wr_result = false;
uint32_t data_to_save = 0;
uint8_t flash_read[4] = {0};
uint32_t flash_data = 0;
/** Packet is confirmed/unconfirmed (Set with AT commands) */
bool g_confirmed_mode = false;
/** If confirmed packet, number or retries (Set with AT commands) */
uint8_t g_confirmed_retry = 0;
/** Data rate (Set with AT commands) */
uint8_t g_data_rate = 3;
/** Counter pulse */
uint32_t g_send_counter = 0;
/** Flag if transmit is active, used by some sensors */
volatile bool tx_active = false;
/** fPort to send packages */
uint8_t set_fPort = 2;
/** Payload buffer */
uint8_t g_solution_data[64];
/**
* @brief Callback after join request cycle
*
* @param status Join result
*/
void joinCallback(int32_t status)
{
// MYLOG("JOIN-CB", "Join result %d", status);
if (status != 0)
{
MYLOG("JOIN-CB", "LoRaWan OTAA - join fail! \r\n");
// To be checked if this makes sense
// api.lorawan.join();
// adicionado por Miguel
}
else
{
MYLOG("JOIN-CB", "LoRaWan OTAA - joined! \r\n");
}
}
/**
* @brief LoRaWAN callback after packet was received
*
* @param data Structure with the received data
*/
void receiveCallback(SERVICE_LORA_RECEIVE_T *data)
{
MYLOG("RX-CB", "RX, port %d, DR %d, RSSI %d, SNR %d", data->Port, data->RxDatarate, data->Rssi, data->Snr);
//number of digits on register
if(data->BufferSize==7) {
flash_data = 0;
flash_data = flash_data + (data->Buffer[0]-'0')*1000000;
flash_data = flash_data + (data->Buffer[1]-'0')*100000;
flash_data = flash_data + (data->Buffer[2]-'0')*10000;
flash_data = flash_data + (data->Buffer[3]-'0')*1000;
flash_data = flash_data + (data->Buffer[4]-'0')*100;
flash_data = flash_data + (data->Buffer[5]-'0')*10;
flash_data = flash_data + (data->Buffer[6]-'0')*1;
Serial.print("New Downlink Flash data: ");
Serial.print(flash_data);
Serial.println();
flash_value[0] = (uint8_t)(flash_data >> 0);
flash_value[1] = (uint8_t)(flash_data >> 8);
flash_value[2] = (uint8_t)(flash_data >> 16);
flash_value[3] = (uint8_t)(flash_data >> 24);
wr_result = api.system.flash.set(0, flash_value, 4);
while (!wr_result)
{
// Retry
wr_result = api.system.flash.set(0, flash_value, 4);
delay(100);
}
//for (int i = 0; i < data->BufferSize; i++)
//{
//Serial.printf("%02X", data->Buffer[i]);
//}
//Serial.print("\r\n");
}
tx_active = false;
}
/**
* @brief LoRaWAN callback after TX is finished
*
* @param status TX status
*/
void sendCallback(int32_t status)
{
MYLOG("TX-CB", "TX status %d", status);
tx_active = false;
}
uint8_t Hall_Sensor = PB8; // pin to measure pulses
void Hydrometer_Pulse()
{
sensor_handler(NULL);
}
/**
* @brief Arduino setup, called once after reboot/power-up
*
*/
void setup()
{
analogReadResolution(12);
Serial.begin(115200);
//Para entrada de comandos apos o reset
delay(10000);
// sensor hall
pinMode(Hall_Sensor, INPUT);
attachInterrupt(Hall_Sensor, Hydrometer_Pulse, CHANGE);
// 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.appkey.get(buff, 16) == true) {
Serial.print("LoRaWan AppKey = 0x");
for(int i = 0; i < 16; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan AppKey get fail");
}
if (!api.lorawan.appkey.set(buff, 16)) {
Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
return;
}
if(api.lorawan.deui.get(buff, 8) == true) {
Serial.print("LoRaWan AppEUI = 0x");
for(int i = 0; i < 8; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan APPEUI get fail");
}
if (!api.lorawan.deui.set(buff, 8)) {
Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.appeui.set(node_app_eui, 8)) {
Serial.printf("LoRaWan OTAA - set application 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.rety.set(1)) {
Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
return;
}
if (!api.lorawan.cfm.set(0)) {
Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
return;
}
if (!api.lorawan.adr.set(0)) {
Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
return;
}
Serial.printf("Set the data rate %s\r\n", api.lorawan.dr.set(2) ? "Success" : "Fail");
Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");
// Setup for LoRaWAN
g_confirmed_mode = api.lorawan.cfm.get();
g_confirmed_retry = api.lorawan.rety.get();
g_data_rate = api.lorawan.dr.get();
// Setup the callbacks for joined and send finished
api.lorawan.registerRecvCallback(receiveCallback);
api.lorawan.registerSendCallback(sendCallback);
api.lorawan.registerJoinCallback(joinCallback);
Serial.printf("RUI3 %s\n", api.system.firmwareVersion.get().c_str());
api.lorawan.linkcheck.set(1);
// Initialize module
Wire.begin();
// Register the custom AT command to get device status
if (!init_status_at())
{
MYLOG("SETUP", "Add custom AT command STATUS fail");
}
// Register the custom AT command to set the send Counter
if (!init_counter_at())
{
MYLOG("SETUP", "Add custom AT command Send Counter fail");
}
// Get saved sending counter from flash
get_at_setting();
// Create a timer.
api.system.timer.create(RAK_TIMER_0, sensor_handler, RAK_TIMER_PERIODIC);
if (g_send_repeat_time != 0)
{
// Start a timer.
api.system.timer.start(RAK_TIMER_0, g_send_repeat_time, NULL);
}
if (g_confirmed_mode)
{
MYLOG("SETUP", "Confirmed enabled");
}
else
{
MYLOG("SETUP", "Confirmed disabled");
}
MYLOG("SETUP", "Retry = %d", g_confirmed_retry);
MYLOG("SETUP", "DR = %d", g_data_rate);
api.system.lpm.set(1);
if (!api.lorawan.join()) // Join to Gateway
{
Serial.printf("LoRaWan OTAA - join fail! \r\n");
return;
}
}
/**
* @brief sensor_handler is a Interrupt function or user call
*/
void sensor_handler(void *)
{
MYLOG("UPLINK", "Start");
//FALLING
if(digitalRead(Hall_Sensor)==LOW)
{
if (api.system.flash.get(0, flash_read, 4))
{
flash_data |= flash_read[0] << 0;
flash_data |= flash_read[1] << 8;
flash_data |= flash_read[2] << 16;
flash_data |= flash_read[3] << 24;
}
flash_data++;
//Overflow Register
if(flash_data==9999999)
flash_data++;
flash_value[0] = (uint8_t)(flash_data >> 0);
flash_value[1] = (uint8_t)(flash_data >> 8);
flash_value[2] = (uint8_t)(flash_data >> 16);
flash_value[3] = (uint8_t)(flash_data >> 24);
wr_result = api.system.flash.set(0, flash_value, 4);
}
// Create payload
char value = 0x31;
for (int idx = 0; idx < 7; idx++)
{
g_solution_data[idx] = value;
value++;
}
// BAT = (analogRead(ANALOG_BAT) * 3.0) / 4096.0; //CR
BAT = (analogRead(ANALOG_BAT) * 3.3) / 4096.0;
Serial.println(BAT);
intpart = floor (BAT); // Get the integer part by rounding down
floatpart = fmod (BAT, intpart); // Get the float part by calculating the remainder
g_solution_data[0] = flash_value[0];
g_solution_data[1] = flash_value[1];
g_solution_data[2] = flash_value[2];
g_solution_data[3] = flash_value[3];
g_solution_data[4] = intpart;
g_solution_data[5] = floatpart*100.0;
g_solution_data[6] = digitalRead(Hall_Sensor);
// Send the packet
send_packet();
}
/**
* @brief Send the data packet that was prepared in
* Cayenne LPP format by the different sensor and location
* aqcuision functions
*
*/
void send_packet(void)
{
Serial.println(flash_data);
if (!api.lorawan.njs.get())
{
MYLOG("UPLINK", "Not joined, skip sending");
QNT_JOINED_FAIL++;
if(QNT_JOINED_FAIL==3)
{
QNT_JOINED_FAIL=0;
//api.system.reboot();
}
return;
}
// Check if it is LoRaWAN
MYLOG("UPLINK", "Sending packet...");
// Send the packet
api.lorawan.linkcheck.set(1);
Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");
if (api.lorawan.send(7, g_solution_data, set_fPort, g_confirmed_mode, g_confirmed_retry))
{
MYLOG("UPLINK", "Packet enqueued, size 7");
tx_active = true;
}
//linkcheck fails 3 times
if(LINKCHECK_ERROR==true)
{
LINKCHECK_ERROR=false;
QNT_LINKCHECK_FAIL++;
if(QNT_LINKCHECK_FAIL==3)
{
QNT_LINKCHECK_FAIL=0;
//api.system.reboot();
}
}
}
/**
* @brief This example is complete Interrupt Sensor (GPIO)
* driven. The loop() does nothing than
* sleep.
*
*/
void loop()
{
api.system.sleep.all();
}
Hardware
O sensor efeito Hall utilizado foi o drv5032, por causa da Tensão de Trabalho e Consumo (Bateria)
Compilação
DOWNLINK para inicalizar contador de PULSOS
Exemplo (BASE64)
MDAwMDExMQ== ---> 0000111 pulsos
/**
* @brief LoRaWAN callback after packet was received
*
* @param data Structure with the received data
*/
void receiveCallback(SERVICE_LORA_RECEIVE_T *data)
{
MYLOG("RX-CB", "RX, port %d, DR %d, RSSI %d, SNR %d", data->Port, data->RxDatarate, data->Rssi, data->Snr);
//number of digits on register
if(data->BufferSize==7) {
flash_data = 0;
flash_data = flash_data + (data->Buffer[0]-'0')*1000000;
flash_data = flash_data + (data->Buffer[1]-'0')*100000;
flash_data = flash_data + (data->Buffer[2]-'0')*10000;
flash_data = flash_data + (data->Buffer[3]-'0')*1000;
flash_data = flash_data + (data->Buffer[4]-'0')*100;
flash_data = flash_data + (data->Buffer[5]-'0')*10;
flash_data = flash_data + (data->Buffer[6]-'0')*1;
Serial.print("New Downlink Flash data: ");
Serial.print(flash_data);
Serial.println();
flash_value[0] = (uint8_t)(flash_data >> 0);
flash_value[1] = (uint8_t)(flash_data >> 8);
Detectado pelo Downlink
LOW POWER
Init
void loop()
{
api.system.sleep.all();
}
Hardware
Fontes:
Dúvidas sobre o código fonte
suporte@smartcore.com.br
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