No artigo sobre a medição de turbidez com módulo WiFi LoRa 32(V2) - MEC324 foi mostrado desde os fundamentos e importância da turbidez da água até a como medi-la utilizando um sensor apropriado. Expandindo esta ideia, este artigo mostrará como fazer com que a medição, feito com o módulo citado, pode ser transmitida a outro módulo utilizando a tecnologia LoRa. Desta forma, a distância entre os módulos de medição e módulo de recepção poderão ser grandes (chegando na casa de alguns quilômetros), o que viabiliza aplicações reais e dentro do contexto urbano deste tipo de medição. Ainda, com mais alguns poucos incrementos e modificações, este projeto pode ser facilmente inserido no contexto da Internet das Coisas (IoT), se tornando uma aplicação interessante para projetos na área de cidades inteligentes (Smart Cities).

 

  • Material necessário
  • Para fazer o projeto deste artigo você precisará de:
  • Dois módulos WiFi LoRa 32(V2)
  • Um sensor de turbidez SKU: SEN0189
  • Dois resistores de 18k 1/4W
  • Dois resistores de 2k 1/4W
  • Protoboard de 400 pontos ou maior
  • Jumpers macho-macho
  • Cabo micro-USB
  • Duas fontes chaveadas 5V/2A micro-USB

 

Overview do projeto

O projeto abordado neste artigo consiste na expansão do abordado no artigo de Medição de turbidez com módulo WiFi LoRa 32(V2).

Aqui, um dos módulos WiFi LoRa 32(V2) faz a medição da turbidez da água. Este irá enviar utilizando LoRa (Fazendo uso da topologia ponto-a-ponto, conforme abordado neste nosso artigo) a turbidez medida para outro módulo WiFi LoRa 32(V2), o qual irá exibir a informação recebida em seu display OLED.

Observe o diagrama de funcionamento do projeto na figura 1.

 

Figura 1 - diagrama de funcionamento do projeto
Figura 1 - diagrama de funcionamento do projeto

 

 

Este projeto permite, portanto, o monitoramento a distância / monitoramento remoto da turbidez da água. Isso é algo muito útil em se tratando tanto de ambientes urbanos quanto rurais, onde a água cuja turbidez deve ser monitorada pode estar em local de difícil acesso.

 

Circuito esquemático - módulo medidor

O circuito esquemático do módulo medidor é exatamente igual ao do artigo de Medição de turbidez com módulo WiFi LoRa 32(V2).

Desta forma, monte o circuito esquemático do módulo medidor conforme é mostrado pela figura 2.

 

Figura 2 - circuito esquemático do módulo medidor de turbidez da água
Figura 2 - circuito esquemático do módulo medidor de turbidez da água

 

 

Circuito esquemático - módulo receptor

Como o módulo receptor utilizará apenas recursos de hardware já contidos no módulo WiFi LoRa 32(V2), você não precisa de circuitos externo ao módulo.

Em suma, o próprio módulo WiFi LoRa 32(V2) já é suficiente como módulo receptor.

 

Código-fonte - módulo medidor

O código-fonte do módulo medidor está abaixo. Preste bastante atenção nos comentários para maior entendimento do programa.

Você perceberá que é enviado de segundo em segundo a turbidez da água medida. Além disso, perceberá que o módulo medidor não irá utilizar o display OLED.

 

 

#include <LoRa.h>
#include <SPI.h>
#include <Wire.h>
/* Definicoes para comunicação com radio LoRa */
#define SCK_LORA 5
#define MISO_LORA 19
#define MOSI_LORA 27
#define RESET_PIN_LORA 14
#define SS_PIN_LORA 18
#define HIGH_GAIN_LORA 20 /* dBm */
#define BAND 915E6 /* 915MHz de frequencia */
/* Definições gerais */
#define DEBUG_SERIAL_BAUDRATE 115200
/* Definições do buffer (para filtro de média móvel) */
#define TAMANHO_BUFFER 50
/* Definições da leitura do sensor de turbidez */
#define ADC_MAX 4095 /* ADC do modulo WiFi LoRa 32(V2) tem 12 bits de resolucao */
#define ENTRADA_ANALOGICA_SENSOR_TURBIDEZ 13 /* GPIO 13 => ADC2_CH4 */
#define TENSAO_MAXIMA_SAIDA_SENSOR_TURBIDEZ 5 /* Sensor apresenta saida analogica de 0 a 5V */
#define FATOR_DIVISOR_TENSAO 10 /* No projeto, para serem respeitados os limites de operação do 
ADC e fazer com que a tensão do sensor excursione corretamente em
todo seu range, ha um divisor resistivo para que a tensão lida pelo
canal do ADC utilizado seja igual a 10% da tensão real de saída do sensor. 
Portanto, no cálculo da tensão real, este fator é utilizado
para se recuperar corretamente este valor */
#define NUM_LEITURAS_OVERSAMPLING 512 
/* Variáveis globais */
float buffer_tensao_sensor_turbidez[TAMANHO_BUFFER];
/* Protótipos */
bool init_comunicacao_lora(void);
float le_tensao_sensor_turbidez_sem_filtro(void);
float le_tensao_sensor_turbidez_com_filtro(void);
float le_turbidez_da_agua(void);
/* Função: inicia comunicação com chip LoRa
* Parâmetros: nenhum
* Retorno: true: comunicação ok
* false: falha na comunicação
*/
bool init_comunicacao_lora(void)
   {
      bool status_init = false;
      Serial.println("[Modulo medidor] Tentando iniciar comunicacao com o radio LoRa...");
      SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA);
      LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN);
if (!LoRa.begin(BAND)) 
   {
      Serial.println("[Modulo medidor] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 
      delay(1000);
      status_init = false;
   }
else
   {
      /* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 
      LoRa.setTxPower(HIGH_GAIN_LORA); 
      Serial.println("[Modulo medidor] Comunicacao com o radio LoRa ok");
      status_init = true;
   }
   return status_init;
}
/* Função: faz a leitura da tensão de saída do sensor de turbidez (sem filtro)
* Parâmetros: nenhum 
* Retorno: tensão de saída (de 0 até 5V)
*/
float le_tensao_sensor_turbidez_sem_filtro(void)
   {
      float tensao_saida_sensor = 0.0;
      int leitura_adc = 0;
      /* Faz a leitura do canal do ADC do modulo que a saida do sensor de turbidez está ligado */
      leitura_adc = analogRead(ENTRADA_ANALOGICA_SENSOR_TURBIDEZ);
      /* converte a leitura do ADC (canal onde está ligada a saída do sensor de turbidez) em uma tensão de leitura de 0 a 5V */
     tensao_saida_sensor = ((leitura_adc/(float)ADC_MAX)*(float)TENSAO_MAXIMA_SAIDA_SENSOR_TURBIDEZ);
     Serial.print("[Modulo medidor] Tensao de saida (no divisor): ");
     Serial.print(tensao_saida_sensor);
     Serial.println("V");
     tensao_saida_sensor = tensao_saida_sensor*FATOR_DIVISOR_TENSAO; /* Corrige a leitura com base no divisor resistivo utilizado */
     return tensao_saida_sensor;
   }
/* Função: faz a leitura da tensao de saida do sensor de turbidez (com filtro)
* Parâmetros: nenhum 
* Retorno: tensão de saída (de 0 até 5V)
*/
float le_tensao_sensor_turbidez_com_filtro(void)
   {
       float tensao_saida_sensor = 0.0;
       int leitura_adc = 0;
       long soma_leituras_adc = 0;
       int i = 0;
      float soma = 0.0;
      float tensao_filtrada = 0.0;
      /* Faz a leitura do canal do ADC do modulo que a saída do sensor de turbidez está ligado */
     /* Para amenizar efeitos de leituras ruidosas / com oscilações, um oversampling é feito */
      soma_leituras_adc = 0;
   for (i=0; i<NUM_LEITURAS_OVERSAMPLING; i++)
        soma_leituras_adc = soma_leituras_adc + analogRead(ENTRADA_ANALOGICA_SENSOR_TURBIDEZ);
    leitura_adc = soma_leituras_adc/NUM_LEITURAS_OVERSAMPLING;
    /* converte a leitura do ADC (canal onde está ligada a saída do sensor de turbidez) em uma tensão de leitura de 0 a 5V */
    tensao_saida_sensor = ((leitura_adc/(float)ADC_MAX)*(float)TENSAO_MAXIMA_SAIDA_SENSOR_TURBIDEZ);
     Serial.print("Counts de ADC: ");
     Serial.println(leitura_adc);
     Serial.print("[Modulo medidor] Tensao de saida (no divisor): ");
     Serial.print(tensao_saida_sensor);
     Serial.println("V");
     tensao_saida_sensor = tensao_saida_sensor*FATOR_DIVISOR_TENSAO; /* Corrige a leitura com base no divisor resistivo utilizado */
    /* Desloca para a esquerda todas as medidas de tensão já feitas */
   for(i=1; i<TAMANHO_BUFFER; i++)
      buffer_tensao_sensor_turbidez[i-1] = buffer_tensao_sensor_turbidez[i];
   /* Insere a nova medida na última posição do buffer */
   buffer_tensao_sensor_turbidez[TAMANHO_BUFFER-1] = tensao_saida_sensor;
   /* Calcula a média do buffer (valor da média móvel, ou valor filtrado) */
   soma = 0.0;
   tensao_filtrada = 0.0;
   for(i=0; i<TAMANHO_BUFFER; i++)
      soma = soma + buffer_tensao_sensor_turbidez[i];
  
   tensao_filtrada = soma/TAMANHO_BUFFER;
   return tensao_filtrada;
}
/* Função: faz a leitura da turbidez da agua
* Parâmetros: nenhum 
* Retorno: turbidez da água (em NTU)
*/
float le_turbidez_da_agua(void)
   {
      float turbidez_agua = 0.0;
      float tensao_filtrada = 0.0;
      float primeiro_fator = 0.0;
      float segundo_fator = 0.0;
      float terceiro_fator = 0.0;
      /* Faz a leitura da tensão filtrada do sensor de turbidez */
      tensao_filtrada = le_tensao_sensor_turbidez_com_filtro();
      /* Limita a tensão a máxima permitida pelo sensor */
      if (tensao_filtrada > 4.2)
          tensao_filtrada = 4.2;
      Serial.print("[Modulo medidor] Tensao de saida do sensor de turbidez: ");
      Serial.print(tensao_filtrada);
      Serial.println("V");
      /* Calcula a turbidez */
      primeiro_fator = ((-1)*(1120.4) * tensao_filtrada * tensao_filtrada);
      segundo_fator = (5742.3 * tensao_filtrada);
      terceiro_fator = ((-1)*4352.9);
      turbidez_agua = primeiro_fator + segundo_fator + terceiro_fator;
 
      return turbidez_agua; 
   }
/* Função de setup */
void setup() 
   { 
      int i;
     Serial.begin(DEBUG_SERIAL_BAUDRATE);
     /* Configura ADC em sua resolução máxima (12 bits) */
     analogReadResolution(12);
     /* Inicializa buffer de leituras de tensão do sensor de turbidez  (para inicializar o buffer do filtro de média móvel)*/
     for(i=0; i<TAMANHO_BUFFER; i++)
        buffer_tensao_sensor_turbidez[i] = le_tensao_sensor_turbidez_sem_filtro(); 
 
     while (!Serial);
      /* Tenta, até obter sucesso, comunicação com o chip LoRa */
     while(init_comunicacao_lora() == false); 
 }
/* Programa principal */
void loop() 
   {
      float turbidez_da_agua = 0.0;
      long inicio_medicoes = 0;
 
      /* Faz a leitura da turbidez da água (em NTU) */
      inicio_medicoes = millis();
     while ((millis() - inicio_medicoes) < 1000)
      {
           turbidez_da_agua = le_turbidez_da_agua();
      }
     /* Envia a turbidez da água medida */
     LoRa.beginPacket();
     LoRa.write((unsigned char *)&turbidez_da_agua, sizeof(float));
     LoRa.endPacket();
     /* aguarda um segundo para nova leitura e envio */
     delay(1000); 
   }

 

 

Código-fonte - módulo receptor

O código-fonte do módulo receptor está abaixo. Preste bastante atenção nos comentários para maior entendimento do programa.

Será exibido no display OLED o valor de turbidez da água medido no módulo medidor.

 

#include <LoRa.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/* Definicoes para comunicação com radio LoRa */
#define SCK_LORA 5
#define MISO_LORA 19
#define MOSI_LORA 27
#define RESET_PIN_LORA 14
#define SS_PIN_LORA 18
#define HIGH_GAIN_LORA 20 /* dBm */
#define BAND 915E6 /* 915MHz de frequencia */
/* Definicoes do OLED */
#define OLED_SDA_PIN 4
#define OLED_SCL_PIN 15
#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
#define OLED_ADDR 0x3C 
#define OLED_RESET 16
/* Offset de linhas no display OLED */
#define OLED_LINE1 0
#define OLED_LINE2 10
#define OLED_LINE3 20
#define OLED_LINE4 30
#define OLED_LINE5 40
#define OLED_LINE6 50
/* Definicoes gerais */
#define DEBUG_SERIAL_BAUDRATE 115200
/* Variaveis e objetos globais */
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
/* Local prototypes */
void display_init(void);
bool init_comunicacao_lora(void);
/* Funcao: inicializa comunicacao com o display OLED
* Parametros: nenhnum
* Retorno: nenhnum
*/ 
void display_init(void)
	{
	if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) 
		{
			Serial.println("[Modulo receptor] Falha ao inicializar comunicacao com OLED"); 
		}
	else
		{
			Serial.println("[Modulo receptor] Comunicacao com OLED inicializada com sucesso");
			/* Limpa display e configura tamanho de fonte */
			display.clearDisplay();
			display.setTextSize(1);
			display.setTextColor(WHITE);
		}
	}
/* Funcao: inicia comunicação com chip LoRa
* Parametros: nenhum
* Retorno: true: comunicacao ok
* false: falha na comunicacao
*/
bool init_comunicacao_lora(void)
{
	bool status_init = false;
	Serial.println("[Modulo receptor] Tentando iniciar comunicacao com o radio LoRa...");
	SPI.begin(SCK_LORA, MISO_LORA, MOSI_LORA, SS_PIN_LORA);
	LoRa.setPins(SS_PIN_LORA, RESET_PIN_LORA, LORA_DEFAULT_DIO0_PIN);
	if (!LoRa.begin(BAND)) 
	{
		Serial.println("[Modulo receptor] Comunicacao com o radio LoRa falhou. Nova tentativa em 1 segundo..."); 
		delay(1000);
		status_init = false;
	}
	else
	{
		/* Configura o ganho do receptor LoRa para 20dBm, o maior ganho possível (visando maior alcance possível) */ 
		LoRa.setTxPower(HIGH_GAIN_LORA); 
		Serial.println("[Modulo receptor] Comunicacao com o radio LoRa ok");
		status_init = true;
	}
	return status_init;
}
/* Funcao de setup */
void setup() 
{
	/* Configuracao da I²C para o display OLED */
	Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN);
	/* Display init */
	display_init();
	/* Print message telling to wait */
	display.clearDisplay(); 
	display.setCursor(0, OLED_LINE1);
	display.print("Aguarde...");
	display.display();
	Serial.begin(DEBUG_SERIAL_BAUDRATE);
	while (!Serial);
	/* Tenta, até obter sucesso, comunicacao com o chip LoRa */
	while(init_comunicacao_lora() == false); 
}
/* Programa principal */
void loop() 
	{
	char byte_recebido;
	int packet_size = 0;
	float turbidez_recebida = 0;
	char str_turbidez_agua[30] = {0};
	char * ptTurbidezRecebida = NULL; 
	/* Verifica se chegou alguma informação do tamanho esperado */
	packet_size = LoRa.parsePacket();
	if (packet_size == sizeof(float)) 
	{
		Serial.print("[Modulo receptor] Há dados a serem lidos");
		/* Recebe turbidez enviada */ 
		ptTurbidezRecebida = (char *)&turbidez_recebida; 
		while (LoRa.available()) 
		{
			byte_recebido = (char)LoRa.read();
			*ptTurbidezRecebida = byte_recebido;
			ptTurbidezRecebida++;
		}
		/* Cria uma string do valor da turbidez da água lida (com 2 casas decimais) */
		sprintf(str_turbidez_agua, "%.2fNTU", turbidez_recebida);
		/* Exibe a turbidez da agua recebida via LoRa no display OLED */
		display.clearDisplay();
		display.setCursor(0, OLED_LINE1);
		display.println("Turbidez da agua:");
		display.setCursor(0, OLED_LINE2);
		display.print(str_turbidez_agua);
		display.display(); 
	}
}

 

 

Projeto em ação!

Veja o projeto em ação no vídeo abaixo:

https://www.youtube.com/watch?v=0BLh68r6kAA&feature=youtu.be

 

Conclusão

Neste artigo vimos como expandir o projeto da Medição de turbidez com módulo WiFi LoRa 32(V2) , de forma a permitir que seja monitorada a turbidez da água à distância, enviando a informação de um módulo WiFi LoRa 32(V2) para outro via LoRa (topologia ponto-a-ponto).

Com este projeto, o leque de aplicabilidade da medição de turbidez de água se multiplica, uma vez que tanto em cenário urbano quanto rural o acesso à água cuja turbidez deve ser monitorada muitas vezes é difícil.

Além disso, este projeto abre possibilidades de inserção da medição de turbidez de água no contexto da Internet das Coisas (IoT), o que pode ser usado em projetos de cidades inteligentes (Smart Cities). Dada a importância da qualidade da água para todo e qualquer ser vivo, este projeto se torna uma interessante ferramenta para medição para a qualidade de vida de cidades inteligentes (em um futuro não tão distante, espero).