Escolar Documentos
Profissional Documentos
Cultura Documentos
Este tutorial será dividido em duas partes. A primeira, sendo esta, irá descrever como
conectar-se ao multimedidor via RS-485 e capturar os dados de interesse lendo o mapa
de memória interno do dispositivo. Na segunda parte iremos detalhar como enviar os
dados apanhados pelo Arduino a um servidor de dados remoto permitindo assim uma
consulta de qualquer local. Este servidor terá o papel de um concentrador de dados para
possíveis decisões que envolvam o controle de demanda de uma planta industrial ou
mesmo o controle do fator de potência da planta como um todo. A figura abaixo ilustra
a montagem do protótipo completa, indicando o módulo Ethernet, a ser apresentado no
próximo tutorial, o módulo MAX485 e o Arduino MEGA 1280.
MATERIAIS
(1x) Arduino Mega 1280 (Atmega 1280);
(1x) Módulo Ethernet com o ENC39J60 e shift Level de 5 p/ 3V3
(1x) Módulo para comunicação serial RS485 com o MAX 485;
(1x) Protoboard;
Cabo com blindagem para comunicação serial em ambiente industrial;
Cabos para ligação em protoboard.
Registradores do Multimedidor
Não será o foco deste tutorial discutir sobre o protocolo RS485 pois o mesmo já foi
abordado em tutoriais anteriores. Abordaremos o mapa de memória do multimedidor e
como interpretar os dados obtidos.
Abaixo são listadas algumas das funções básicas implementadas dentro do mapa de
memória deste dispositivo. São divididas basicamente entre duas áreas de funções sendo
elas as originais do protocolo Modbus, já pré-definidas por padrão e as funções
especiais implementadas pelo fabricante.
* Broadcast – funções que podem ser endereçadas para todos os slaves (endereço 0)
Funções ESPECIAIS:
Config Address (0x42H)
Read Address (0x71H)
Read Partidas (0x75H)
Report Slave Id Kron (0x76H)
Nesta aplicação utilizamos somente a função Read input Register (0x04) para leitura dos
valores das grandezas elétricas. Os respectivos registradores estão indicados na tabela
abaixo, retirada do manual do fabricante Kron.
ESQUEMA DE LIGAÇÃO
O esquema de montagem deste tutorial é o mais simples até o momento, apesar da
grande utilidade deste protótipo. Destacamos somente o módulo com o MAX485 e as
respectivas ligações nas portas do Arduino. A figura abaixo ilustra este módulo.
Esquema de ligação entre o Max e o Arduino
Uma imagem real do módulo utilizado neste tutorial está exposta abaixo.
Algoritmo
O algoritmo que implementa este sistema de obtenção dos dados está destacado abaixo.
É simples mais apresenta alguns detalhes particulares que serão destacados
posteriormente.
/
******************************************************************
*********
Arduino Lab 20 - Leitura de dados de sete multimedidor
trifásico via RS485 Modbus RTU
******************************************************************
**********
-- IDE do Arduino Versão 1.8.3
-- Autor: Eduardo Avelar
-- Blog: easytromlabs.com
-- email: contato@easytromlabs.com
-- Agosto, 2018
******************************************************************
**********/
#include <ModbusMaster.h>
//Data Enable (DE) and Receiver Enable (/RE)
#define MAX485_DE 21
#define MAX485_RE_NEG 22
// Instancia Objeto ModbusMaster
ModbusMaster node;
uint8_t resultMain;
int endereco_Modulos[] {
22, // 0 - TRAFO 1, 1250 KVa, 13800/380 - Subestação 2
//21, // 1 - TRAFO 2, 1000 KVa, 13800/380 - Subestação 2 - Desligado
20, // 2 - TRAFO 3, 1000 KVa, 13800/380 - Subestação 2
23, // 3 - TRAFO 4, 1000 KVa, 13800/380 - Subestação 1
24, // 4 - TRAFO 5, 1000 KVa, 13800/380 - Subestação 1
25, // 5 - TRAFO 6, 500 KVa, 13800/220 - Subestação 1
26, // 6 - TRAFO 7, 1500 KVa, 13800/380 - Subestação 2
};
int vetor_endereco[] {
0x02, // 0 - Tensão Trifásica [V] - UO
0x04, // 1 - Corrente Trifásica [A] - IO
0x06, // 2 - Fator de potencia Trifásico - FP
0x08, // 3 - Potência Aparente Trifásica [VA] - SO
0x0A, // 4 - Potência Reativa Trifásica [VAr] - QO
0x0C, // 5 - Potência Ativa Trifásica [W] - PO
0x0E, // 6 - Frequencia [Hz] - F
0x3E, // 7 - Demanda Ativa [W] - DA
0x42, // 8 - Demanada Aparente [VA] - DS
0x62 // 9 - Contador Parcial - EAP
};
float vetor_resultado[10];
//Union para obter o valor de leitura:
union leitura {
unsigned char vetor[4];
float valorFloat;
} rs485;
void preTransmission() {
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission() {
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup() {
// Atribui pinos como saída
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// inicializa modo de recebimento
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// Atribui velocidade de comunicação (Baud Rate)
Serial.begin(9600);
Serial2.begin(9600, SERIAL_8N2);
// Callbacks - Permite configurar o transeiver RS485 corretamente
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop() {
for ( int i = 0; i < 6; i ++) {
leitura_medidor(endereco_Modulos[i]);
Serial.println("--> Aguarda 30 segundos para proxima leitura ");
delay(30000);
}
}
/*************************************************************
Realiza a leitura dos dados via RS485 do Multimedidor
*************************************************************/
float leitura_medidor(uint8_t deviceID) {
node.begin(deviceID, Serial2);
Serial.println();
Serial.print("lendo dispositivo no endereço: ");
Serial.println(deviceID);
for (int i = 0; i < 10; i ++) {
resultMain = node.readInputRegisters(vetor_endereco[i], 2); // Realiza a leitura
do registrador 9 ate 14 (0x0E)
delay(50);
if (resultMain == node.ku8MBSuccess) {
rs485.vetor[0] = (node.getResponseBuffer(0x00) >> 8) & 0xFF; //Parte
Alta Word 1
rs485.vetor[1] = node.getResponseBuffer(0x00) & 0xFF; //Parte
Baixa Word 1
rs485.vetor[2] = (node.getResponseBuffer(0x01) >> 8) & 0xFF; //Parte
Alta Word 2
rs485.vetor[3] = node.getResponseBuffer(0x01) & 0xFF;; //Parte
Baixa Word 2
}
else {
Serial.println("--> Falha de comunicacao com o medidor");
rs485.vetor[0] = 00; //Parte Alta Word 1
rs485.vetor[1] = 00; //Parte Baixa Word 1
rs485.vetor[2] = 00; //Parte Alta Word 2
rs485.vetor[3] = 00; //Parte Baixa Word 2
}
vetor_resultado[i] = rs485.valorFloat;
Serial.print("Indice: ");
Serial.println(i);
Serial.print("Valor: ");
Serial.println(rs485.valorFloat);
Serial.println("---------------------------------------------------");
}
}