sábado, 10 de dezembro de 2022

LOM204A - MEDINDO CONSUMO DE ÁGUA

     

LOM204A - MEDINDO CONSUMO DE ÁGUA E ENVIANDO VIA LoRaWAN, para TTN.

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 LOM204A via KEIL C e assim utilizá-lo como OPENCPU.

O objetivo específico neste projeto é programar o LOM204A para permitir coletar oas 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 trabalho 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 LOM204Apara 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 trabalho 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 (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.


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

Configurando  um gateway LoRaWAN

LG308 é totalmente compatível com o protocolo LoRaWAN. Ele usa o legado “Semtech Packet forward” para encaminhar os pacotes LoRaWAN ao servidor. A estrutura é a abaixo.


Informações  do LG308


Gateway ID é específico para cada Gateway

O método para trabalhar com outros servidores LoRaWAN será semelhante.

Passo 1: Obter uma ID do gateway único.

Cada LG308 tem um ID de porta de entrada única. O ID pode ser encontrada na página LoRaWAN do gateway.

O ID de exemplo gateway é: ​a840411b8268ffff

Passo 2: Cadastre-se uma conta de usuário no servidor TTN




Passo 3: Criar um gateway


Clique no ícone Gateways para abrir a página a seguir:


Depois de criar o gateway, você pode ver a informação gateway, como abaixo.


Configurar LG308 para se conectar ao TTN

Agora você pode configurar o LG308 para deixá-lo se conectar à rede TTN.
Verifique se o seu LG308 tem uma conexão com a internet em primeiro lugar.


Passo 1: Configurar LG308 para atuar como despachante de matéria


Passo 2: Entrada de informação do servidor e ID do gateway

Escolha o correto o endereço do servidor e ID gateway.


Resultado da verificação

Depois de fazer as configurações acima, o LG308 deve ser capaz de se conectar ao TTN. Abaixo está o resultado visto de TTN:


Configurar frequência


Depois de fazer as definições acima, o LG308 será capaz de atuar como um gateway LoRaWAN.
 

Adicionar um dispositivo EndDevice LoRaWan










Esta seção mostra como adicionar um dispositivo EndDevice LoRaWAN à uma rede LoRaWAN e ver os dados de TTN no web site.

LOM204A foi utilizado como dispositivo de referência - a configuração para outros dispositivos LoRaWAN será semelhante.

Passo 1​: Criar uma definição de dispositivos no TTN como exemplo "COLETOR XYY"

Três códigos são necessários para definir o dispositivo em TTN: 

DEVEUI - código de identificação único para um dispositivo em particular. 
APPEUI - código de identificação para um aplicativo definido no TTN. 
APPKey - Chave exclusiva para proteger as comunicações com um dispositivo em particular.

Um conjunto destes códigos são armazenados em cada dispositivo pelo fabricante como os códigos padrão para esse dispositivo particular. Cada dispositivo é fornecido com uma etiqueta com o EUI dispositivo padrão como mostrado abaixo.


Nota: Você pode ser capaz de alterar estes códigos em um dispositivo usando uma instalação de configuração do dispositivo, por exemplo o LOM204A utiliza um acesso porta série e uma série de comandos AT. Alterar os códigos podem ser necessárias no caso em que você tem que usar os códigos atribuídos por um servidor WAN Lora.

Para o servidor TTN, você pode usar os códigos estabelecidos no dispositivo como no exemplo a seguir. 

Selecionar ​Adicionar aplicativo ​para abrir a tela abaixo.

Note-se que há uma APPEUI já criado pela TTN, mas esta não é a definida no dispositivo. 


Selecionar ​Devices​ e ​Register Device ​para abrir a tela abaixo.



Nota-se que há uma APP EUI já criado pela TTN, mas esta não é a definida no dispositivo. Para adicionar o APP EUI do dispositivo LOM204A, selecione​ApplicationEUI​ e ApplicationKey​ no aplicativo LoRAWAN_GUI_CUSTOMER (CLI), em seguida, insira o código necessário. Pode ser Hardcoded depois no projeto implementado no KEIL C.


Passo 2: Ligar dispositivo LOM204A e vai juntar-se automaticamente a rede TTN. 

Depois de ingressar com sucesso, ele vai começar a fazer Upload de mensagens para a TTN. Selecione a guia Dados e você vai ver os dados que aparecem no painel.

Note que isso pode levar algum tempo para que os dados do dispositivo para aparecer no visor TTN.


Mais informações sobre TTN (gateway)



Mais informações sobre TTN (aplicação)





  
Testado no STARTER KIT LOM204A e também no Breakout LOM204A




Código Fonte

//---------------------------------------------------------------------------- // Project Name : LoRa WAN //---------------------------------------------------------------------------- // File Name : Main.c //---------------------------------------------------------------------------- // Processor : STM32L071CZY WLCSP // Compiler : uVision V5.20.0.0 // RF Transceiver : SX1276 // Frequency : 917 ~ 928Mhz // Modulation : LoRa // Version : H/W(1.3), LIB(2.02) #define MAIN_C_ #include <stddef.h> #include <string.h> #include "stm32l0xx_hal.h" #include <math.h> #include "board.h" #include "Utilities.h" #include "misc.h" #include "process.h" #include "timer.h" #include "init.h" #include "timer.h" #include "main.h" #include "WISOL_API.h" #include "stm32l0xx_hal_lptim.h" //lptim reference LPTIM_HandleTypeDef hlptim1; //https://community.st.com/s/question/0D53W00000DhAV7/lptimcounterstart-problem void LPTIM1_Init(void) { LPTIM_HandleTypeDef* hlptim = &hlptim1; HAL_NVIC_SetPriority(LPTIM1_IRQn, 2/*0*/, 0); HAL_NVIC_EnableIRQ(LPTIM1_IRQn); hlptim->Instance->CFGR |= LPTIM_CFGR_PRELOAD; /* Enable Autoreload match interrupt */ hlptim->Instance->ICR |= 0x0002; // ARRMCF clear flag __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM); /* Enable the Peripheral */ __HAL_LPTIM_ENABLE(hlptim); /* Load the period value in the autoreload register */ __HAL_LPTIM_AUTORELOAD_SET(hlptim, 65535); //65535 /* Start timer in freerun mode */ __HAL_LPTIM_START_CONTINUOUS(hlptim); } /** * @brief LPTIM1 Initialization Function * @param None * @retval None */ static void MX_LPTIM1_Init(void) { /* USER CODE BEGIN LPTIM1_Init 0 */ /* USER CODE END LPTIM1_Init 0 */ /* USER CODE BEGIN LPTIM1_Init 1 */ /* USER CODE END LPTIM1_Init 1 */ hlptim1.Instance = LPTIM1; hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_ULPTIM; hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1; hlptim1.Init.UltraLowPowerClock.Polarity = LPTIM_CLOCKPOLARITY_FALLING; //<====================== hlptim1.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION; hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH; hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE; hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_EXTERNAL; if (HAL_LPTIM_Init(&hlptim1) != HAL_OK) { __disable_irq(); } } //Uart Para receber LTS UART_HandleTypeDef huart1; static void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ /* USER CODE BEGIN USART1_Init 1 */ /* USER CODE END USART1_Init 1 */ huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart1) != HAL_OK) { __disable_irq(); } /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ } //LTS CONSUMIDOS E INTERVALO DE WAKEUP uint32_t LTS; uint32_t WAKEUP; void LPTIM1_IRQHandler(void) { // HAL_LPTIM_IRQHandler(&hlptim1); // ==> HAL_LPTIM_AutoReloadMatchCallback(&hlptim2); /* Autoreload match interrupt */ if(__HAL_LPTIM_GET_FLAG(&hlptim1, LPTIM_FLAG_ARRM) != RESET) { if(__HAL_LPTIM_GET_IT_SOURCE(&hlptim1, LPTIM_IT_ARRM) != RESET) { /* Clear Autoreload match flag */ //A cada 65536 contagem de LPTIM, incrementa LTS (16-->XX XX XX XX) LTS++; //BYTES MAIS SIGNIFICATIVOS __HAL_LPTIM_CLEAR_FLAG(&hlptim1, LPTIM_FLAG_ARRM); /* Autoreload match Callback */ } } } //Backup litros consumidos na FLASH uint8_t eeprom_cnt=0; uint8_t prt_flag=0; typedef struct _LORA_EEPROM_tag { uint32_t test1; uint32_t test2; } lora_eeprom_t; lora_eeprom_t eeprom; //Para poder mandar em BCD pela TTN unsigned char bcd2int(unsigned char bcd) { return 10 * (bcd >> 4) + (bcd & 0xF); } //CANAIS DE UPLOAD (8) char* opt1 = "FF00"; char* opt2 = "0000"; char* opt3 = "0000"; char* opt4 = "0000"; char* opt5 = "0000"; char* opt6 = "0000"; #if 1 //--------------------------------------------------------------------------------------------------------- // Example // CLASS A mode, Confirmed up data(1234567890) transfer every 20 seconds. // After data transmission , enter sleep mode. // Run User_fn function when waking up. // Get Device EUI and Print //--------------------------------------------------------------------------------------------------------- void User_fn(void) { } //LEITURA DO LPTIM uint16_t Counter; //MENSAGEM PARA SER ENVIADA A TTN unsigned char Msg[32]; //Para não transmitir já quando ligar o LOM204 a primeira vez unsigned char Wake_Up = 0; //Para controlar envio TTN depois de 7 dias unsigned char Days_Flash_Store = 0; //Status da Transmissao do Pacote depois do JOIN! unsigned char Status_Transmit; //Status do JOIN ???? unsigned char Status_JOIN; //Force Send Data immediately unsigned char Force_Send_Message_immediately = 0; //Segundo datasheet leitura nao confiável uint32_t read_count() { uint32_t tmp1, tmp2; tmp1 = HAL_LPTIM_ReadCounter(&hlptim1); // hlptim1 is a global variable while ((tmp2 = HAL_LPTIM_ReadCounter(&hlptim1)) != tmp1) tmp1 = tmp2; return tmp1; } //Para leitura de dados via UART char buff[ 132 ]; //mais null //#define Um_Dia 1*24*3600*1000 //#define Um_Dia 5*1000 #define Um_Dia 3600*1000 //Gravação na FLASH (BACKUP) void Gravando_Flash_LTS(void) { //PRINTF("---LTS %d---\r\n",LTS); sprintf(buff, "---LTS %d---\r\n",LTS); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); //Guarda LTS na variavel test1 para gravação na EEPROM! //PRINTF("---GRAVANDO %d NA FLASH (DESCONTANDO LPTIM)----\r\n",LTS); sprintf(buff,"---GRAVANDO %d NA FLASH (DESCONTANDO LPTIM)----\r\n",LTS); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); eeprom.test1 = LTS; nvm_write_user(NVM_USER + offsetof(lora_eeprom_t, test1),(void *)(&eeprom.test1), 4 ); // NVM_USER Address: 0x08080800 //PRINTF("---GRAVADO %d---\r\n",LTS); sprintf(buff, "---GRAVADO %d---\r\n",LTS); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); } //Gravação na FLASH (BACKUP) void Gravando_Flash_WAKEUP(void) { //PRINTF("---WAKEUP %d---\r\n",WAKEUP); sprintf(buff, "---WAKEUP %d---\r\n",WAKEUP); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); //Guarda WAKEUP na variavel test2 para gravação na EEPROM! //PRINTF("---GRAVANDO %d NA FLASH WAKEUP----\r\n",WAKEUP); sprintf(buff,"---GRAVANDO %d NA FLASH WAKEUP----\r\n",WAKEUP); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); eeprom.test2 = WAKEUP; nvm_write_user(NVM_USER + offsetof(lora_eeprom_t, test2),(void *)(&eeprom.test2), 4 ); // NVM_USER Address: 0x08080800 //PRINTF("---GRAVADO---\r\n",WAKEUP); sprintf(buff,"---GRAVADO %d---\r\n",WAKEUP); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); } //Entra em SLEEP void Sleep() { Enable_enter_stop_mode(); // Setting condition for entry into sleep mode. Device_State_Sleep_Fn(); // GPIO/TImer event check. Enter sleep mode at CLASS A } //Mensagens de Parametros uint8_t LTS_Mens[] = "*****************QUAL A QUANTIDADE DE LITROS NO HIDROMETRO******************\r\n"; uint8_t LTS_Mens_Error[] = "Tamanho pacote invalido, maximo 7 digitos\r\n"; uint8_t WAKEUP_Mens[] = "*****************QUAL INTERVALO PARA WAKEUP (EM SEGUNDOS)******************\r\n"; uint8_t WAKEUP_Mens_Error[] = "Tamanho pacote invalido, maximo 7 digitos\r\n"; uint8_t APP_EUI_Mens[] = "*****************QUAL APPLICATION EUI ******************\r\n"; uint8_t APP_EUI_Mens_Error[] = "Tamanho pacote invalido, tem que ter 16 digitos\r\n"; uint8_t APP_KEY_Mens[] = "*****************QUAL APPLICATION KEY ******************\r\n"; uint8_t APP_KEY_Mens_Error[] = "Tamanho pacote invalido, tem que ter 32 digitos\r\n"; uint8_t TKS_Mens[] = "Obrigado!\r\n"; uint8_t DEVICE_EUI_Info[] = "*****************DEVICE EUI******************\r\n"; uint8_t APP_EUI_Info[] = "*****************APP EUI******************\r\n"; uint8_t APP_KEY_Info[] = "*****************APP KEY******************\r\n"; uint8_t SPLASH[] = "****************Hidrometro****************\r\n*****************Indriya******************\r\n"; uint8_t QNT_LTS_Mens[] = "----LENDO DA FLASH LTS----\r\n"; uint8_t WKP_FLASH_Mens[] = "----LENDO DA FLASH WAKEUP----\r\n"; uint8_t TTN_DOWNLOAD_Mens[] = "----RECEBIDO MENSAGEM LTS VIA TTN PARA FLASH----\r\n"; uint8_t WKP_NOW_Mens[] = "===WAKE UP IMEDIATAMENTE===\r\n"; uint8_t SEND_TTN_Mens[] = "---MANDANDO DADOS TTN---\r\n"; //MAC uint8_t* res; //Acordar para fazer JOIN (rand) uint16_t WAKEUP_JOIN; //Programa Principal int main(void) { //Init Start_Init(); //Configuração LPTIM MX_LPTIM1_Init(); //Configuração LPTIM (Interrupt) LPTIM1_Init(); //Abre UART1 para recebimento LTS MX_USART1_UART_Init(); //Splash //PRINTF("****************Hidrometro****************\r\n"); //PRINTF("*****************Indriya******************\r\n"); HAL_UART_Transmit(&huart1, SPLASH,sizeof(SPLASH), 10); //Verifica se durante o BOOT, o pino WKUP1 esta em NIVEL ALTO //Se sim, já força (APÓS JOIN), pegar algum pacote DOWNLOADING if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==1) Force_Send_Message_immediately = 1; //PRINTF("*****************DEVICE EUI******************\r\n"); HAL_UART_Transmit(&huart1,DEVICE_EUI_Info, sizeof(DEVICE_EUI_Info),10); res = getDeviceEUI(); sprintf(buff,"Dev Eui :%02x%02x%02x%02x%02x%02x%02x%02x\r\n",res[0],res[1],res[2],res[3],res[4],res[5],res[6],res[7]); PRINTF(buff); PRINTF("---- Dev EUI ----\r\n"); HAL_UART_Transmit(&huart1, (uint8_t *) buff,sizeof(buff), 10); memset( buff, 0, 128 ); //preenche com NULL //Lendo Application EUI PRINTF("---- Application EUI %s ----\r\n",getOtaaAppEUI()); //HAL_UART_Transmit(&huart1, APP_EUI_Info,sizeof(APP_EUI_Info), 10); //Lendo Application Key PRINTF("---- Application Key %s ----\r\n",getOtaaPseudoAppKey()); //HAL_UART_Transmit(&huart1, APP_KEY_Info,sizeof(APP_KEY_Info), 10); //Aguarda 5 segundos para receber LTS //Tem que ser 8 digitos! //PRINTF("*****************QUAL A QUANTIDADE DE LITROS NO HIDROMETRO******************\r\n"); HAL_UART_Transmit(&huart1, LTS_Mens,sizeof(LTS_Mens), 10); HAL_UART_Receive( &huart1, (uint8_t *) buff, 32, 5000 ); //pacote nao esta vazio if(!(strlen(buff)==0)) { //tamanho igual até 7 digitos Hidrometro tem 7 digitos if(!(strlen(buff)>7)) { //String para INT LTS = atoi(buff); //Grava Flash Gravando_Flash_LTS(); //Preenche buff com NULL memset( buff, 0, 128 ); } else { //PRINTF("Tamanho pacote invalido, maximo 7 digitos\r\n"); HAL_UART_Transmit(&huart1, LTS_Mens,sizeof(LTS_Mens_Error), 10); } //PRINTF("*****************QUAL INTERVALO PARA WAKEUP (EM SEGUNDOS)******************\r\n"); HAL_UART_Transmit(&huart1, WAKEUP_Mens,sizeof(WAKEUP_Mens), 10); HAL_UART_Receive( &huart1,(uint8_t *) buff, 32, 5000 ); //pacote nao esta vazio if(!(strlen(buff)==0)) { //tamanho igual até 7 digitos Hidrometro tem 7 digitos // 604800 (1 semana) if(!(strlen(buff)>7)) { //String para INT WAKEUP = atoi(buff); //Grava Flash Gravando_Flash_WAKEUP(); //Preenche buff com NULL memset( buff, 0, 128 ); } else { //PRINTF("Tamanho pacote invalido, maximo 7 digitos\r\n"); HAL_UART_Transmit(&huart1, WAKEUP_Mens_Error,sizeof(WAKEUP_Mens_Error), 10); } } //PRINTF("*****************QUAL APPLICATION EUI ******************\r\n"); HAL_UART_Transmit(&huart1, APP_EUI_Mens,sizeof(APP_EUI_Mens), 10); HAL_UART_Receive( &huart1, (uint8_t *) buff, 32, 5000 ); //pacote nao esta vazio if(!(strlen(buff)==0)) { //tamanho igual à 16 caracteres if(!(strlen(buff)<16)) { setOtaaAppEUI( (uint8_t *) buff, 16 ); memset( buff, 0, 128 ); } else { //PRINTF("Tamanho pacote invalido, tem que ter 16 digitos\r\n"); HAL_UART_Transmit(&huart1, APP_EUI_Mens_Error,sizeof(APP_EUI_Mens_Error), 10); } } //PRINTF("*****************QUAL APPLICATION KEY ******************\r\n"); HAL_UART_Transmit(&huart1, APP_KEY_Mens,sizeof(APP_KEY_Mens), 10); HAL_UART_Receive( &huart1, (uint8_t *) buff, 32, 5000 ); //pacote nao esta vazio if(!(strlen(buff)==0)) { //tamanho igual à 16 caracteres if(!(strlen(buff)<32)) { setOtaaPseudoAppKey ((uint8_t *) buff, 32 ); memset( buff, 0, 128 ); } else { //PRINTF("Tamanho pacote invalido, tem que ter 32 digitos\r\n"); HAL_UART_Transmit(&huart1, APP_KEY_Mens_Error,sizeof(APP_KEY_Mens_Error), 10); } } } //PRINTF("Obrigado!\r\n"); HAL_UART_Transmit(&huart1, TKS_Mens,sizeof(TKS_Mens), 10); //Le o ultimo valor Armazenado caso ocorra um RESET para troca de bateria //PRINTF("----LENDO DA FLASH LTS----\r\n"); HAL_UART_Transmit(&huart1, QNT_LTS_Mens,sizeof(QNT_LTS_Mens), 10); nvm_read_user(NVM_USER + offsetof(lora_eeprom_t, test1), (void *)(&eeprom.test1), 4 ); //SE CHEGUEI NESTE PONTO, SIGNIFICA QUE FOI POR RESET, LPTIM ESTARA COM 0000H LTS = eeprom.test1; // //PRINTF("----LIDO %d LTS----\r\n",LTS); sprintf(buff, "----LIDO %d LTS----\r\n", LTS); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 10); //Le o ultimo valor Armazenado caso ocorra um RESET para troca de bateria //PRINTF("----LENDO DA FLASH WAKEUP----\r\n"); HAL_UART_Transmit(&huart1, WKP_FLASH_Mens, sizeof(WKP_FLASH_Mens), 10); nvm_read_user(NVM_USER + offsetof(lora_eeprom_t, test2), (void *)(&eeprom.test2), 4 ); WAKEUP = eeprom.test2; //PRINTF("----LIDO WAKEUP %d SEGUNDOS----\r\n", WAKEUP); sprintf(buff, "----LIDO WAKEUP %d SEGUNDOS----\r\n", WAKEUP); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 10); //Class,Mascara de Canais, OTA setClass( 0 ); // Set CLASS A mode. setChannelMask(opt1, opt2, opt3, opt4, opt5, opt6); //Pegue parte do MAC address e use ele como Seed para Rotina de delay //Mac está em uint8_t* res; srand(res[6]*256+res[7]); WAKEUP_JOIN = (((rand() & 0x0003) + 2) * 10) + (rand() & 0x000F); //2X a 6X segundos antes do primeiro JOIN //PRINTF("----Aguardando %d minuto(s) antes do primeiro JOIN\r\n",WAKEUP_JOIN); sprintf(buff, "----Aguardando %d segundo(s) antes do primeiro JOIN----\r\n",WAKEUP_JOIN); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 10); memset( buff, 0, 128 ); //<====TIVE QUE COLOCAR! //1 Wakeup_Timer(&TxUser,User_fn,WAKEUP_JOIN*1000,0U); // It wakes up after WAKEUP_JOIN seconds before first JOIN Sleep(); //The Stack try N times! JOIN_TIME_START(8); JOIN_START(); // Join start OTA Status_JOIN = getJoinDoneStatus(); //While not Completed the JOIN //Join is complited: 0, Join is not complited : 1, BUSY : 2 while(Status_JOIN > 0) { WAKEUP_JOIN = (((rand() & 0x0003) + 2) * 10) + (rand() & 0x000F) + (read_count() & 0x000F); //2X a 6X segundos antes do primeiro JOIN + LTS //PRINTF("----JOIN FALHOU...AGUARDE %d MINUTO(S)----\r\n",WAKEUP_JOIN); sprintf(buff, "----JOIN FALHOU...AGUARDE %d SEGUNDO(S)----\r\n",WAKEUP_JOIN); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 200); Wakeup_Timer(&TxUser,User_fn,WAKEUP_JOIN*1000,0U); //give a time do TTN bring up <====RANDOM Sleep(); JOIN_TIME_START(7); JOIN_START(); // Join start OTA Status_JOIN = getJoinDoneStatus(); } //PRINTF("Status JOIN %d\r\n",Status_JOIN); sprintf(buff, "Status JOIN %d\r\n",Status_JOIN); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 10); //Loop infinito while(true) { //while(true) //{ Counter = read_count(); // hlptim1 is a global variable //https://www.st.com/resource/en/application_note/dm00290631-lowpower-timer-lptim-applicative-use-cases-on-stm32-microcontrollers-stmicroelectronics.pdf Counter = Counter + 5; //BoardGetBatteryLevel(); //Imprime LTS para DEBUG sprintf(Msg,"%d",LTS+Counter); //PRINTF("\r\nValor no Hidrometro __%s__%d__\r\n\r\n", Msg, Counter); sprintf(buff, "\r\nValor no Hidrometro __%s__%d__\r\n\r\n", Msg, Counter); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 10); //} CLI_Command_Process(); // To receive CLI command through serial port(UART) (Setup via SERIAL com LoRAWAN_GUI_CUSTOMER //Recebe quantidade de LTS registrado no Hidrometro (Analogico) Schedule downlink if( Check_Received_Msg()) // Check for received messages. return value : 1 [SUCCESS], 2: [FAIL], 0: No messages received. { //Atualiza Contador Interno //Como será digitado no TTN XX XX XX XX //Virá 4 bytes (BCD) if(rx_msg.payload_size==4) { //PRINTF("PORT: %d\r\n",rx_msg.port); // Get the port of the received message. //PRINTF("----RECEBIDO MENSAGEM LTS VIA TTN PARA FLASH----\r\n"); HAL_UART_Transmit(&huart1, TTN_DOWNLOAD_Mens, sizeof(TTN_DOWNLOAD_Mens), 10); //78992211 (JÁ EM BCD) 22*100, 99*10000..etc LTS = (bcd2int(rx_msg.mac_payload[0])*1000000) + (bcd2int(rx_msg.mac_payload[1])*10000) + (bcd2int(rx_msg.mac_payload[2])*100) + (bcd2int(rx_msg.mac_payload[3])); //Será somente em Fábrica ? //Desconta o q tem registrado já no LPTIM Timer (o mesmo não se consegue ZERAR) LTS = LTS - read_count(); //Grava Flash Gravando_Flash_LTS(); } } //Para não começar já transmitindo, a nao ser que faça WAKE UP if(Wake_Up==0) { if(Force_Send_Message_immediately==0) { //PRINTF("===WAKE UP DAQUI %d SEGUNDOS===\r\n", WAKEUP); sprintf(buff, "===WAKE UP DAQUI %d SEGUNDOS===\r\n", WAKEUP); HAL_UART_Transmit(&huart1, (uint8_t *) buff, sizeof(buff), 10); Wakeup_Timer(&TxUser,User_fn,WAKEUP*1000,0U); // It wakes up every WAKEUP seconds to FLASH the LTS } else { //PRINTF("===WAKE UP IMEDIATAMENTE===\r\n"); HAL_UART_Transmit(&huart1,WKP_NOW_Mens, sizeof(WKP_NOW_Mens), 10); Wakeup_Timer(&TxUser,User_fn,1*1000,0U); // It wakes up in 1 second Days_Flash_Store = 6; //++ force send Data } Wake_Up = 1; //STATE MACHINE } else { //Pegando LTS e Gravando na FLASH Counter = read_count(); //PRINTF("---GRAVANDO LTS NA FLASH DEPOIS DE %d SEGUNDOS---\r\n",WAKEUP); sprintf(buff, "---GRAVANDO LTS NA FLASH DEPOIS DE %d SEGUNDOS---\r\n",WAKEUP); HAL_UART_Transmit(&huart1,(uint8_t *) buff, sizeof(buff), 10); //Gravando LTS na FLASH eeprom.test1 = LTS + Counter; nvm_write_user(NVM_USER + offsetof(lora_eeprom_t, test1),(void *)(&eeprom.test1), 4 ); // NVM_USER Address: 0x08080800 //PRINTF("---GRAVADO LTS DEPOIS %d DIA---\r\n\r\n",Days_Flash_Store+1); sprintf(buff, "---GRAVADO LTS DEPOIS %d DIA---\r\n\r\n",Days_Flash_Store+1); HAL_UART_Transmit(&huart1,(uint8_t *) buff, sizeof(buff), 10); //Quantas gravações na SEMANA Days_Flash_Store++; //A cada 7 dias wake up para enviar LTS para TTN if(Days_Flash_Store==7) { //PRINTF("---MANDANDO DADOS TTN---\r\n"); HAL_UART_Transmit(&huart1,SEND_TTN_Mens, sizeof(SEND_TTN_Mens), 10); //Sem confirmação! data_Tx(1,0,1,strlen(Msg),Msg); //API DONE: 1, FAIL : 2 Status_Transmit = API_MODE(); // Run LoRa protocol. //Sucesso envio Pacote! if(Status_Transmit == 1) { //PRINTF("===WAKE UP DAQUI %d SEGUNDOS===\r\n",WAKEUP); sprintf(buff, "===WAKE UP DAQUI %d SEGUNDOS===\r\n",WAKEUP); HAL_UART_Transmit(&huart1,(uint8_t *) buff, sizeof(buff), 10); //Sucesso, repete ciclo de 7 dias Days_Flash_Store=0; Wakeup_Timer(&TxUser,User_fn,WAKEUP*1000,0U); // It wakes up every WAKEUP seconds to FLASH the LTS } //Erro envio Pacotes else { //Temos problema com JOIN e DATA SEND, melhor tentar repetir o ciclo... Days_Flash_Store = 6; //++ //Faz um WAKE UP imediatamente para tentar JOIN ou transmissao do pacote, ou seja, 1s Wakeup_Timer(&TxUser,User_fn,1*1000,0U); // Transmit Error, try again imediatly } } else { //Prepara Wake up para o proximo dia! Wakeup_Timer(&TxUser,User_fn,WAKEUP*1000,0U); } } //Entrando em SLEEP, pode sair por Wake up timer ou Wake up externo Sleep(); //Verifica se a saida do SLEEP foi pelo botao WAKEUP //Se sim, já força manda LTS para TTN if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)==1) { Force_Send_Message_immediately = 1; Days_Flash_Store = 6; //++ force send Data } } } #endif //Não mexer void Start_Init(void) { HW_SystemClock_Config(); StartNVInit(); BoardInitPeriph( ); BoardInitMcu( ); Var_Init(); sub_process_init(); // set receive mode for uart TimerInit( &TxNext, Txnext_fn ); // Do not modify nvm_init(); // To read the configuration saved in EEPROM. Clr_BIT2(); LDO_on(); } void Restart_Init(void) { BoardInitPeriph( ); BoardInitMcu( ); Var_Init(); sub_process_init(); // set receive mode for uart TimerInit( &TxNext, Txnext_fn ); // Do not modify nvm_init(); // To read the configuration saved in EEPROM. Clr_BIT2(); LDO_on(); }

Hardware 


O sensor efeito Hall utilizado foi o drv5032, por causa da Tensão de Trabalho e Consumo (Bateria)

Compilação


Altere em seu Gateway  SUB-BAND para 2


//CANAIS DE UPLOAD (8)
char* opt1 = "FF00"; 
char* opt2 = "0000";
char* opt3 = "0000";
char* opt4 = "0000";
char* opt5 = "0000";
char* opt6 = "0000";

Faça a gravação


Pegue Credenciais OTAA na TTN


Execução

A interação é realizada através de 2 UARTS do LOM204A

Caso os parâmetros não sejam digitados...

Pela UART1 vai solicitar a medição no Hidrômetro, Credenciais e Intervalo de Leitura em segundos (Respeitar Tamanho dos Campos) - Gravado em FLASH
#define Um_Dia 3600*1000

Mostrando dados medidos pelo Hidrômetro - No caso foi escolhido a cada 10 segundos
(no intervalo entra em baixo consumo de Bateria)


Pela UART5 mostrar as Credenciais da TTN e STATUS da conexão (Debug) da Publicação  na TTN

POR QUE 5 PULSOS ? SE ZEREI CONTADOR ?
PORQUE LOWPOWER TIME COMEÇA A CONTAR A PARTIR DO 5 PULSO

DOWNLINK para zerar contador de PULSOS

if( Check_Received_Msg()) // Check for received messages. return value : 1 [SUCCESS], 2: [FAIL], 0: No messages received. { //Atualiza Contador Interno //Como será digitado no TTN XX XX XX XX //Virá 4 bytes (BCD) if(rx_msg.payload_size==4) { //PRINTF("PORT: %d\r\n",rx_msg.port); // Get the port of the received message. //PRINTF("----RECEBIDO MENSAGEM LTS VIA TTN PARA FLASH----\r\n"); HAL_UART_Transmit(&huart1, TTN_DOWNLOAD_Mens, sizeof(TTN_DOWNLOAD_Mens), 10); //78992211 (JÁ EM BCD) 22*100, 99*10000..etc LTS = (bcd2int(rx_msg.mac_payload[0])*1000000) + (bcd2int(rx_msg.mac_payload[1])*10000) + (bcd2int(rx_msg.mac_payload[2])*100) + (bcd2int(rx_msg.mac_payload[3])); //Será somente em Fábrica ? //Desconta o q tem registrado já no LPTIM Timer (o mesmo não se consegue ZERAR) LTS = LTS - read_count(); //Grava Flash Gravando_Flash_LTS(); } }

Exemplo de envio do valor BCD 1111 para ser registrado na Flash do LOM204A

BCD (Importante)

Detectado pelo Downlink


LOW POWER TIMER (Contador de Pulsos)

Init

//https://community.st.com/s/question/0D53W00000DhAV7/lptimcounterstart-problem void LPTIM1_Init(void) { LPTIM_HandleTypeDef* hlptim = &hlptim1; HAL_NVIC_SetPriority(LPTIM1_IRQn, 2/*0*/, 0); HAL_NVIC_EnableIRQ(LPTIM1_IRQn); hlptim->Instance->CFGR |= LPTIM_CFGR_PRELOAD; /* Enable Autoreload match interrupt */ hlptim->Instance->ICR |= 0x0002; // ARRMCF clear flag __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM); /* Enable the Peripheral */ __HAL_LPTIM_ENABLE(hlptim); /* Load the period value in the autoreload register */ __HAL_LPTIM_AUTORELOAD_SET(hlptim, 65535); //65535 /* Start timer in freerun mode */ __HAL_LPTIM_START_CONTINUOUS(hlptim); }



static void MX_LPTIM1_Init(void) { /* USER CODE BEGIN LPTIM1_Init 0 */ /* USER CODE END LPTIM1_Init 0 */ /* USER CODE BEGIN LPTIM1_Init 1 */ /* USER CODE END LPTIM1_Init 1 */ hlptim1.Instance = LPTIM1; hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_ULPTIM; hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1; hlptim1.Init.UltraLowPowerClock.Polarity = LPTIM_CLOCKPOLARITY_FALLING; //<====================== hlptim1.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION; hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH; hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE; hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_EXTERNAL; if (HAL_LPTIM_Init(&hlptim1) != HAL_OK) { __disable_irq(); } }

Handler

void LPTIM1_IRQHandler(void) { // HAL_LPTIM_IRQHandler(&hlptim1); // ==> HAL_LPTIM_AutoReloadMatchCallback(&hlptim2); /* Autoreload match interrupt */ if(__HAL_LPTIM_GET_FLAG(&hlptim1, LPTIM_FLAG_ARRM) != RESET) { if(__HAL_LPTIM_GET_IT_SOURCE(&hlptim1, LPTIM_IT_ARRM) != RESET) { /* Clear Autoreload match flag */ //A cada 65536 contagem de LPTIM, incrementa LTS (16-->XX XX XX XX) LTS++; //BYTES MAIS SIGNIFICATIVOS __HAL_LPTIM_CLEAR_FLAG(&hlptim1, LPTIM_FLAG_ARRM); /* Autoreload match Callback */ } } }

Código parcial gerado pelo STM32CubeMX


PC0 - Pino de entrada dos pulos enviado pelo Hidrômetro

Fontes:

SMART WATER: UM PROTÓTIPO PARA MONITORAMENTO DO CONSUMO DE ÁGUA

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