Font Size

Fala galera, tudo bem?! Neste artigo irei lhes apresentar um projeto que realiza a análise de consumo elétrico residencial, utilizando o ESP8266 e scripts Python. A ideia é fornecer uma solução para o controle de energia, permitindo estratégias de economia em sua casa. Gostou da ideia?! Então, vamos nessa!

Entendendo o Cálculo do Consumo Elétrico

As distribuidoras de energia elétrica realizam o cálculo do consumo de acordo com a quantidade de potência gasta por equipamentos elétricos e suas horas de uso, na unidade de medida kWh. O valor da conta é dado por uma tarifa aplicada por cada kWh consumido. Para exemplificar, iremos utilizar os seguintes dados de uma lâmpada incandescente:

Potência Elétrica (W) Horas de Uso Diário Consumo Mensal (kWh) Valor (R$)
40 5 6 Tarifa*6

Assim, o cálculo para estimar o consumo mensal, utilizando a potência em W, é realizado com a seguinte fórmula:

 Consumo = (Potência * Horas * 30)/1000 = (40 * 5 * 30)/1000 = 6 kWh

Dessa forma, conseguimos estimar uma média do consumo mensal e prever o gasto da conta no final do mês. Como pode ser observado, nesta fórmula estimamos um tempo médio diário de uso que nem sempre conseguimos determinar. Mas, e se conseguíssemos analisar em tempo real o consumo de certo equipamento e acompanhar, de forma mais precisa, quanto esse equipamento está gastando?!

Essa é a proposta do projeto apresentado a seguir. Então, vem comigo!

Funcionamento do Sistema

Como mencionado anteriormente, nosso objetivo é conseguir acompanhar o consumo elétrico de determinado equipamento. Para isso, utilizaremos o dispositivo ESP8266 que enviará os dados da potência obtidos do equipamento para o banco de dados relacional MySQL através do script Python sendDatas e o broker MQTT Eclipse.

Em sequência, usaremos outro script Python, analizeDatas, para consultar os dados armazenados e visualizar as atualizações de novas medidas em tempo real. Assim, o esquema descrito pode ser resumido na ilustração a seguir:

Consumo-Eletrico-com-ESP8266-e-Python
Figura 1 – Sistema de Backend para Análise do Consumo Elétrico

Dessa forma, para realização do projeto, necessitaremos de um dispositivo ESP8266 que executará a aquisição dos dados a partir de um sensor de corrente não invasivo conectado ao equipamento.

De acordo com a corrente rms obtida, é calculada a potência elétrica aproximada do equipamento. Assim, o dispositivo enviará as informações aquisitadas para o banco de dados, onde serão armazenadas e processadas pelos scripts em Python.

Com base no esquema apresentado, desenvolveremos, nas próximas seções, o passo a passo para a construção do projeto. A seguir, apresento a lista de itens necessários.

Componentes Necessários

Estes e muitos outros materiais podem ser encontrados em nossa loja.

Montagem do Circuito

Com posse dos componentes essenciais, podemos iniciar a montagem de nosso circuito. Basta realizarmos as seguintes conexões:

Consumo-Eletrico-com-ESP8266-e-Python
Figura 2 – Esquema de ligação ao NodeMCU

Código Detalhado do Dispositivo

/*
    Projeto: Análise de Consumo Elétrico com ESP8266
    Autor: Daniel Fiuza - AutoCore Robótica
    Data: 03/04/2020
    Código de Dominio Público.
*/
//============== Declaração de Bibliotecas ====================
#include <NTPClient.h>    // Biblioteca do NTP.
#include <WiFiUdp.h>      // Biblioteca do UDP.
#include <ESP8266WiFi.h>  // Biblioteca do WiFi.
#include "EmonLib.h"      // Biblioteca do Sensor de Corrente AC.
#include <PubSubClient.h> // Biblioteca para enviar dados MQTT.
#include <ArduinoJson.h>  // Biblioteca para criar mensagem Json.

//============== Definição de Constantes ======================
// Calibração da Corrente. Este valor deve ser obtido com o auxílio de um multímetro, 
// modificando o parâmetro CURRENT_CAL até a coincidência entre o valor medido e o mensurado pela IDE.
#define CURRENT_CAL 8.23
#define WIFI_SSID "sua_rede_wifi"
#define WIFI_PASS  "sua_senha"

//============== Criação de Instâncias ========================
WiFiUDP udp; // Cria um objeto "UDP".
NTPClient ntp(udp, "0.br.pool.ntp.org", -3 * 3600, 60000); // Cria um objeto "NTP".
WiFiClient wifiClient; // Cria o objeto wifiClient
PubSubClient client(wifiClient); // Cria objeto MQTT client.
EnergyMonitor emon1; // Cria objeto emon1 para obter dados do sensor.

//============= Declaração de Variáveis Globais ===============
int hour; // Armazena o horário obtido do NTP.
int last_hour; // Armazena horário da última medida realizada.
int diff_hour; // Armazena diferença em segundos entre duas medidas.
unsigned long last_time; // Armazena intervalo de tempo entre medidas.
int status = WL_IDLE_STATUS; // Obtém status de conexão Wifi.

//============ Configuração da função void setup() ============
void setup()
{
   Serial.begin(115200);//Inicia a comunicação serial.
   emon1.current(A0, CURRENT_CAL); // Inicializa parâmetros do sensor de corrente.
   client.setServer("mqtt.eclipse.org", 1883); // Configura conexão MQTT.
   WiFi.begin(WIFI_SSID, WIFI_PASS);
   while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
   }
   ntp.begin(); // Inicia o cliente NTP.
   ntp.forceUpdate();  // Força o Update.
   last_hour = ntp.getEpochTime(); // Armazena primeira medida com a hora atual.
}

//============ Configuração da função void loop() ============
void loop(){
   if ( !client.connected() ) {
    reconnect();  // Conecta-se ao broker MQTT.
   }
   client.loop(); // Mantém conexão MQTT aberta.
   // Atualiza novas medidas a cada 1s.
   if ( millis() - last_time > 1000 ) {
    emon1.calcVI(40,500); // Calcula Corrente AC.
    float Current = emon1.Irms; // Obtém valor da corrente calculado.
    float Power = Current * 220.00; // Calcula valor aproximado da Potência Aparente.
    ntp.update();
    hour = (int) ntp.getEpochTime(); // Obtém horário em épocas.

    // Atualiza diferença entre horários em segundos.
    if(last_hour != hour){
      diff_hour = hour - last_hour;
      last_hour = hour;
    }
    
    // Devido as oscilações iniciais, limitamos a corrente em uma margem.
    if(Current < 0.019) {
      Current = 0.00;
      Power = 0.00;
    }
    
    // Envia dados do sensor ao Broker MQTT no formato Json
    StaticJsonDocument<200> datas;
    datas["Irms"] = Current;
    datas["Power"] = Power;
    datas["Hour"] = hour;
    datas["Diff_hour"] = diff_hour;
    String payload;
    serializeJson(datas, payload);
    client.publish("energymeter/send", payload.c_str()); // Publica mensagem MQTT
    last_time = millis();
   } 
}

//============ Configuração da função void reconnect() ============
void reconnect() {
  while (!client.connected()) {
    status = WiFi.status();
    // Caso não esteja conectado ao wifi, inicia conexão
    if ( status != WL_CONNECTED) {
      WiFi.begin(WIFI_SSID, WIFI_PASS);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("Conectado ao AP");
    }
    Serial.print("Conectando-se ao Broker MQTT ...");
    // Inicia conexão MQTT
    if ( client.connect("ESP8266 Device") ) {
      Serial.println( "[MQTT DONE]" ); // Conexão MQTT estabelecida.
    } else {
      Serial.print( "[MQTT FAILED] [ rc = " ); // Conexão MQTT falhou.
      Serial.print( client.state() );
      Serial.println( " : retrying in 5 seconds]" );
      // Aguarda 5 segundos antes de se reconectar
      delay( 5000 );
    }
  }
}

Configurando Banco de Dados

Como informado anteriormente, iremos salvar os dados obtidos do dispositivo no banco de dados relacional MySQL. Para isso, você precisará tê-lo instalado localmente ou em algum serviço em nuvem.

Em seguida, iremos criar o banco e a tabela onde iremos armazenar os dados. Dessa forma, execute o comando:

CREATE DATABASE energy_meter;

Como pode ser observado, ele cria o banco de dados que iremos utilizar. Após isso, adicionaremos a tabela datas de acordo com o comando a seguir:

CREATE TABLE datas(
    id int(4) AUTO_INCREMENT,
    current float,
    power float,
    diff_hour int(4),
    hour datetime,
    PRIMARY KEY (id)
);

Feito isso, teremos criado uma tabela com cinco colunas. A coluna current e power armazenaremos os dados medidos da corrente rms e da potência aparente, respectivamente.

O campo diff_hour armazena a diferença de horário entre a medida atual e a anterior. Por fim, o campo hour contém o horário atual em que a medida foi realizada.

Agora, podemos inserir o dados em nosso banco. Para isso, apresentarei a seguir o script em Python que receberá as mensagens do dispositivo por uma conexão MQTT e as enviará ao MySQL.

Enviando Dados Aquisitados ao Banco de Dados

Nesta etapa, criaremos o script sendDatas.py com o seguinte código:

import paho.mqtt.client as mqtt	# Módulo MQTT
import time			# Módulo para trabalhar com tempo e conversões
import pymysql.cursors		# Módulo Mysql (Banco de Dados)
import json			# Módulo Json


################################ FUNÇÕES MYSQL ###############################
# Insere mensagens recebidas no banco de dados.
def send_mysql(msg_vector):
	# Inicia conexão com o Banco de Dados Mysql
	try:
		connection = pymysql.connect(host='localhost',
                             user='nome-de-usuario',
                             password='senha-do-usuario',
                             db='energy_meter',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

	except:
		print("Não foi possível conectar-se ao banco de dados.")
		return 0

	
	try:
		with connection.cursor() as cursor:		
			sql = "INSERT INTO datas (current, power, diff_hour, hour) VALUES(%s, %s, %s, %s)"
			# Executa query Insert
			cursor.execute(sql,( msg_vector[0], msg_vector[1], msg_vector[2], msg_vector[3] ))
		# Confirma a transação realizada
		connection.commit()
		print("Dados inseridos: current = "+str(msg_vector[0])+", power = "+str(msg_vector[1])+" , diff_hour = "+str(msg_vector[2])+", hour = "+str(msg_vector[3]) )
	except:
		print("Falha ao inserir dados no banco de dados.")
	
	finally:
		# Encerra conexão com Mysql
		connection.close()


################################ FUNÇÕES MQTT ################################
# Define função de retorno de chamada ao conectar-se com o Broker.
def on_connect(client, userdata, flags, rc):
	print("Conectado ao broker.")
	# Inscreve-se no tópico para receber mensagens.
	client.subscribe("energymeter/send")

# Define função de retorno de chamada ao receber mensagem. 
def on_message(client, userdata, msg):
	# Converte mensagem em bytes para string
	msg_string=str(msg.payload.decode("utf-8","ignore"))
	# Desserializa string Json para dicionário Python
	dict_json=json.loads(msg_string)
	# Arredonda corrente para duas casas decimais
	Irms = round(dict_json["Irms"], 2)
	# Arredonda Potencia para duas casas decimais
	Power = round(dict_json["Power"],2)
	# Armazena diff_hour
	Diff_hour = int(dict_json['Diff_hour'])
	# Obs: Esta hora está no padrão época
	Hour_epoch = int(dict_json["Hour"])
	# Converte a hora do padrão época para o padrão data e hora do Mysql
	Hour = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(Hour_epoch))
	# Armazena dados formatados no vetor msg_formated
	msg_formated = [Irms, Power, Diff_hour, Hour] 
	# Função que insere os dados no Mysql
	send_mysql(msg_formated)
	

# Define função de retorno de chamada após uma desconexão.
def on_disconnect(client, userdata, rc):
	if rc != 0:
		print("Desconexão MQTT Inesperada.")
	print("Reconectando-se ao Broker em 3 segundos...")
	time.sleep(3)
	client.connect("mqtt.eclipse.org", 1883, 60)

# Instancia cliente MQTT.
client = mqtt.Client()
client.on_connect = on_connect		# Define como callback a função on_connect
client.on_message = on_message		# Define como callback a função on_message
client.on_disconnect = on_disconnect	# Define como callback a função on_disconnect

# Inicia conexão MQTT com o Broker Mosquitto.
client.connect("mqtt.eclipse.org", 1883, 60)

client.loop_forever()

Entendendo o Script de Envio dos Dados

Primeiramente é necessário importar os seguintes módulos para o correto funcionamento do script:

import paho.mqtt.client as mqtt	# Módulo MQTT
import time			# Módulo para trabalhar com tempo e conversões
import pymysql.cursors		# Módulo Mysql (Banco de Dados)
import json			# Módulo Json

Inicialmente, o script instancia o cliente MQTT, definindo suas funções de callback e, em seguida, inicia a conexão. A função client.loop_forever() mantém a conexão aberta, permitindo receber e processar os eventos de callback, como pode ser visto no trecho a seguir:

# Instancia cliente MQTT.
client = mqtt.Client()
client.on_connect = on_connect		# Define como callback a função on_connect
client.on_message = on_message		# Define como callback a função on_message
client.on_disconnect = on_disconnect	# Define como callback a função on_disconnect

# Inicia conexão MQTT com o Broker Mosquitto.
client.connect("mqtt.eclipse.org", 1883, 60)

client.loop_forever()

Ao conectar-se com o broker, a função on_connect() é executada, a qual realiza a inscrição no tópico “energymeter/send”, permitindo receber as mensagens do dispositivo. Essa função é demonstrada a seguir:

def on_connect(client, userdata, flags, rc):
	print("Conectado ao broker.")
	# Inscreve-se no tópico para receber mensagens.
	client.subscribe("energymeter/send")

Após a inscrição no tópico descrito, novas mensagens são recebidas e processadas pela função on_message() que as converte em um dicionário, estrutura equivalente ao vetor em outras linguagens de programação, da seguinte forma:

# Converte mensagem em bytes para string
	msg_string=str(msg.payload.decode("utf-8","ignore"))
	# Desserializa string Json para dicionário Python
	dict_json=json.loads(msg_string)

Depois, os dados formatados são armazenados no vetor msg_formated, o qual é passado como parâmetro da função send_mysql() que enviará os dados para o banco MySQL através da query insert, como visto a seguir:

# Arredonda corrente para duas casas decimais
	Irms = round(dict_json["Irms"], 2)
	# Arredonda Potencia para duas casas decimais
	Power = round(dict_json["Power"],2)
	# Armazena diff_hour
	Diff_hour = int(dict_json['Diff_hour'])
	# Obs: Esta hora está no padrão época
	Hour_epoch = int(dict_json["Hour"])
	# Converte a hora do padrão época para o padrão data e hora do Mysql
	Hour = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(Hour_epoch))
	# Armazena dados formatados no vetor msg_formated
	msg_formated = [Irms, Power, Diff_hour, Hour] 
	# Função que insere os dados no Mysql
	send_mysql(msg_formated)

Entendido o fluxo do script apresentado, demonstrarei, a seguir, o código de visualização dos dados do dispositivo. Sua estrutura é semelhante ao primeiro script, facilitando bastante sua compreensão.

Visualizando os Dados do Consumo Elétrico

Para a visualização dos dados, crie o script analisysMeters.py com o seguinte código:

import matplotlib.pyplot as plt	# Módulo para imprimir gráfico	
import numpy as np		# Módulo para manipular vetores
import paho.mqtt.client as mqtt	# Módulo MQTT
import time			# Módulo para trabalhar com tempo e conversões
import pymysql.cursors		# Módulo Mysql (Banco de Dados)
import json			# Módulo Json
import datetime			# Módulo para manipular datas e strings

# Define estilo do gráfico
plt.style.use('ggplot')

########################## FUNÇÃO PLOTAR GRÁFICO #############################
def live_plotter(x_vec,y1_data,line1,pause_time=0.1):
	if line1==[]:
		# Esta chamada permite plotar o gráfico dinamicamente
		plt.ion()
		fig = plt.figure(figsize=(13,6))
		ax = fig.add_subplot(111)
		# Cria uma variável referente aos dados do gráfico para, posteriormente, atualizá-la
		line1, = ax.plot(x_vec,y1_data,'-o',alpha=0.8)      
		# Atualiza label/title
		plt.ylabel('Potência (W)')
		plt.title('Consumo Elétrico em Tempo Real')
		plt.show()

	# Após a criação da figura, eixo e linha, nós precisamos atualizar o dados do eixo y
	line1.set_ydata(y1_data)
	# Ajusta os limites se novos dados estiverem além destes
	if np.min(y1_data)<=line1.axes.get_ylim()[0] or np.max(y1_data)>=line1.axes.get_ylim()[1]:
		plt.ylim([np.min(y1_data)-np.std(y1_data),np.max(y1_data)+np.std(y1_data)])
	# Pausa os dados para que a figura / eixo possam recuperar o atraso
	plt.pause(pause_time)

	# Retorna a variável line1 para que ela seja atualizada na próxima iteração
	return line1


################################ FUNÇÕES MYSQL ###############################
# Insere mensagens recebidas no banco de dados.
def get_data_mysql(size, query=''):
	# Inicia conexão com o Banco de Dados Mysql
	try:
		connection = pymysql.connect(host='localhost',
                             user='nome-de-usuario',
                             password='senha-de-usuario',
                             db='energy_meter',
                             charset='utf8mb4',
                             cursorclass=pymysql.cursors.DictCursor)

	except:
		print("Não foi possível conectar-se ao banco de dados.")
		return 0


	try:
		with connection.cursor() as cursor:
			if query == 'get_value': # Obtém o valor em real total até o momento.
				sql = "SELECT SUM(power*diff_hour*0.79857/(1000*3600)) AS valor_total FROM datas;"
			else:		
				sql = "SELECT power, hour FROM datas ORDER BY hour DESC LIMIT "+str(size)+";"
			# Executa query Select
			cursor.execute(sql)
		# Confirma a transação realizada
		connection.commit()
		result = cursor.fetchall()
		# Retorna resultado
		return result
	except:
		print("Falha ao inserir dados no banco de dados.")

	finally:
		# Encerra conexão com Mysql
		connection.close()

#####################################################################################
################################ FUNÇÕES MQTT ################################
# Define função de retorno de chamada ao conectar-se com o Broker.
def on_connect(client, userdata, flags, rc):
	print("Conectado ao broker.")
	# Inscreve-se no tópico para receber mensagens.
	client.subscribe("energymeter/send")

# Define função de retorno de chamada ao receber mensagem. 
def on_message(client, userdata, msg):
	# Converte mensagem em bytes para string
	msg_string=str(msg.payload.decode("utf-8","ignore"))
	# Desserializa string Json para dicionário Python
	dict_json=json.loads(msg_string)
	# Arredonda corrente para duas casas decimais
	Irms = round(dict_json["Irms"], 2)
	# Arredonda Potencia para duas casas decimais
	Power = round(dict_json["Power"],2)
	# Armazena diff_hour
	Diff_hour = int(dict_json["Diff_hour"])
	# Obs: Esta hora está no padrão época
	Hour_epoch = int(dict_json["Hour"])
	# Converte a hora do padrão época para o padrão data e hora do Mysql
	Hour = datetime.datetime.fromtimestamp(float(str(Hour_epoch)))

	# Informa que as seguintes variáveis são globais
	global y_vec, x_vec, valor_total, taxa
	# Elimina primeiro elemento do array e adiciona 0 como último elemento
	y_vec = np.append(y_vec[1:],0.0)
	x_vec = np.append(x_vec[1:],0.0)
	# Substitui último elemento do array pelos valores atualizados
	y_vec[-1] = Power
	x_vec[-1] = Hour
	# Atualiza Gasto total
	valor_total += Power*Diff_hour*taxa
	print("Valor Gasto Atual: R$ "+str(round(valor_total,6)))
	

# Define função de retorno de chamada após uma desconexão.
def on_disconnect(client, userdata, rc):
	if rc != 0:
		print("Desconexão MQTT Inesperada.")
	print("Reconectando-se ao Broker em 3 segundos...")
	time.sleep(3)
	client.connect("mqtt.eclipse.org", 1883, 60)

############################# TRECHO INICIAL ######################################

print("Iniciando script	")
# Instancia cliente MQTT.
client = mqtt.Client()
client.on_connect = on_connect		# Define como callback a função on_connect
client.on_message = on_message		# Define como callback a função on_message
client.on_disconnect = on_disconnect	# Define como callback a função on_disconnect

# Variáveis Globais.
size = 50        # Tamanho da amostra de dados
valor_total = 0  # Valor em real total
line1, y_vec, x_vec = [], [], []  # Arrays usados para elaborar o gráfico
taxa = 0.79857/(1000*3600)	# cálculo de conversão considerando 1s cada amostra

# Obtém os últimos 50 dados do Banco de dados.
result = get_data_mysql(size)

# Insere os dados obtidos do Banco de Dados nos arrays y_vec e x_vec
for x in reversed(result):
	y_vec.append(float(x['power']))
	x_vec.append(x['hour'])

# Obtém o valor total em real até o momento do Banco de dados.
result_valor = get_data_mysql(size,'get_value')

# Atribui o valor recebido do banco de dados à variável valor_total.
for x in result_valor:
	valor_total = float(x['valor_total'])

# Inicia conexão MQTT com o Broker.
client.connect("mqtt.eclipse.org", 1883, 60)

while True:
	# Atualiza constantemente o gráfico
	line1 = live_plotter(x_vec,y_vec,line1)
	# Mantém conexão MQTT aberta
	client.loop_start()

Explicação Detalhada do Script de Visualização

Se você entendeu o script anterior, esse será tranquilo. Além disso, considero esta a parte mais interessante. Então, vamos lá!

Nosso código inicia instanciando o cliente MQTT e definindo suas funções de callback. Até agora, nada de novo. Em seguida, são declarada algumas variáveis globais que serão utilizadas ao longo do nosso script, apresentadas no seguinte trecho:

# Variáveis Globais.
size = 50        # Tamanho da amostra de dados
valor_total = 0  # Valor em real total
line1, y_vec, x_vec = [], [], []  # Arrays usados para elaborar o gráfico
taxa = 0.79857/(1000*3600)	# cálculo de conversão considerando 1s cada amostra

Como pode observar, a variável taxa é uma constante que resulta da tarifa da concessionária de energia dividida pelo valor (1000*3600). Esse termo apenas converte a potência obtida em Ws para KWh, unidade de medida utilizada pelas distribuidoras.

Então, essa taxa será aplicada à potência recebida do dispositivo, obtendo-se o valor em real do consumo elétrico.

Prosseguindo no código, é solicitada, duas vezes, a função get_data_mysql(). A primeira chamada realiza uma query select para obter os últimos 50 valores da potência e seus respectivos horários, armazenando-os nos vetores x_vec e y_vec.

Em seguida, é solicitada novamente, onde se obtém o valor total do consumo elétrico e o armazena na variável valor_total. Isso é referido no trecho:

# Obtém os últimos 50 dados do Banco de dados.
result = get_data_mysql(size)

# Insere os dados obtidos do Banco de Dados nos arrays y_vec e x_vec
for x in reversed(result):
	y_vec.append(float(x['power']))
	x_vec.append(x['hour'])

# Obtém o valor total em real até o momento do Banco de dados.
result_valor = get_data_mysql(size,'get_value')

# Atribui o valor recebido do banco de dados à variável valor_total.
for x in result_valor:
	valor_total = float(x['valor_total'])

Logo após, é iniciada a conexão MQTT e definido o loop while. Então, o código atualizará constantemente o gráfico, mantendo a conexão MQTT aberta.

Ao receber uma nova mensagem do dispositivo, a função on_message() formata os dados e atualiza os vetores do gráfico, assim como, a variável valor_total. Esse trecho é observado a seguir:

# Informa que as seguintes variáveis são globais
	global y_vec, x_vec, valor_total, taxa
	# Elimina primeiro elemento do array e adiciona 0 como último elemento
	y_vec = np.append(y_vec[1:],0.0)
	x_vec = np.append(x_vec[1:],0.0)
	# Substitui último elemento do array pelos valores atualizados
	y_vec[-1] = Power
	x_vec[-1] = Hour
	# Atualiza Gasto total
	valor_total += Power*Diff_hour*taxa
	print("Valor Gasto Atual: R$ "+str(round(valor_total,6)))

Dessa forma, é apresentado o consumo elétrico, em tempo real, do equipamento permitindo monitorá-lo e, até mesmo, realizar estratégias de economia.

Resultado do Projeto

A seguir apresento um vídeo demonstrando o resultado obtido do projeto:

https://youtu.be/zqEEtgiA5-s

Então, gostou do projeto? Espero que ele possa estimular novas propostas e colaborar com o seu desenvolvimento acerca do tema. Caso haja alguma dúvida, comente abaixo. Confira também mais conteúdos em nosso Blog

 

5.00 avg. rating (94% score) - 1 vote