Escolar Documentos
Profissional Documentos
Cultura Documentos
Arduino Com Scadabr RS485 PDF
Arduino Com Scadabr RS485 PDF
So Paulo SP Brasil
(11) 3804-0126
Rede Social: http://www.labdegaragem.com.br
Loja Virtual: http://loja.labdegaragem.com.br
Manual do Usurio
Introduo
Descrio do KIT
Caractersticas tcnicas
Teste Inicial
Apndice I
Referncias
Introduo
Descrio do KIT
O shield contm um chip transceiver RS485 que faz o trabalho de converso dos
dados de TTL para RS485 e vice versa, LEDs para indicar o fluxo do trfego na rede,
bornes para ligar os cabos do barramento da rede, jumpers para selecionar uso de
resistores de terminao e bias da rede e jumpers para escolher entre usar uma porta
de comunicao serial fsica do ATmega do Arduino ou usar uma porta soft serial.
Para a comunicao pela hard serial (HS) so utilizados os pinos digitais 0 e 1 do
Arduino. Para a comunicao usando soft serial (SS) so usados os pinos digitais 2 e
3 do Arduino. O pino digital 6 usado para comutao entre os modos de
transmisso e recepo do transceiver do shield.
O conversor USB/RS485 usa o chip FT232RL para criar um dispositivo serial em
qualquer microcomputador (porta COM) que pode ser acessada pelo usurio ou
programas. O conversor tambm possui o mesmo circuito do transceiver RS485 com
os jumpers, resistores, LEDs e bornes presente no shield.
Observaes:
JP1 e JP3 s podem ser ligados em um nico dispositivo da rede e devem ser
selecionados igualmente, os dois abertos ou os dois fechados.
JP2 s pode estar ligado se o dispositivo estiver em uma das duas
extremidades do barramento, devendo obrigatoriamente ficar desligado quando
estiver no meio da rede.
O upload de um sketch sempre deve ser feito pelo canal USB nativo do
Arduino, no sendo possvel fazer-lo pela rede RS485.
Caractersticas tcnicas
Fig. 2: Detalhe dos jumpers e conectores do Shield RS485 encaixado sobre o Arduino.
6. Aps a instalao ser concluda, verifique qual porta foi criada usando o
gerenciador de dispositivos do Windows.
Configurao
O pino digital (6) do Arduino ter funo de enable (EN) que habilita o
conversor RS485/TTL para o modo de transmisso quando estiver em nvel
lgico 1 (5V) ou para modo de recepo quando o pino de enable estiver em
nvel lgico 0 (0V).
Teste Inicial
Para testar o funcionamento correto dos mdulos e a comunicao entre o PC e o
Arduino a forma mais simples usando o SERIAL MONITOR que est disponvel na
IDE do Arduino e montando a aplicao a seguir.
Para esta montagem voc vai precisar de alguns componentes eletrnicos:
a. 1 potencimetro rotativo de 16mm de 10k;
d. 1 protoboard;
f.
Cabo manga para o barramento (na falta deste usar cabo CCI de 2 pares);
g. Voc tambm vai precisar de algumas ferramentas como uma chave de fenda
de 1/8 x 4 e um alicate de bico fino.
10
Fig. 5: Teste de comunicao RS485 entre o Arduino e o PC usando o Serial Monitor da IDE do Arduino.
11
Agora que j testamos a rede vamos mostrar um exemplo de como utilizar a soluo
12
c. 2 resistores de 390.
13
14
11. Inicialmente devemos criar uma data source, que identifica cada
dispositivo na rede.
15
17
18. Para criar o data point que corresponde ao LED ligado no pino digital D5
preencha os campos da janela aberta desta forma:
20. Para criar o data point que corresponde a leitura do potencimetro ligado
na entrada analgica A0 preencha os campos da janela aberta desta
forma:
18
22. Agora voc deve habilitar todos os data points criados, clique no boto
vermelho na na coluna Status de cada data point.
23. A caixa Data Points deve estar parecida com a figura abaixo:
19
27. Clique nas setas dos data points que desejar monitorar, assim eles vo
aparecer na caixa da direita da tela.
20
O data point MB_PINO_5 controla o estado do LED verde ligado no pino digital
5. Clicando em
ser aberta uma caixa onde possvel ligar ou desligar o
LED digitando 1 ou 0 respectivamente.
Representao Grfica
Agora que a aplicao j esta rodando no SCADABR, vamos aprender como
fazer uma tela grfica simples, de modo a ter uma visualizao do sistema de
uma forma mais fcil que do que a que temos na tela watch list.
Siga os passos abaixo:
1. Clique em
21
3. Clique em
8. Clique em
para editar as propriedades grficas do objeto e configure
conforme a figura abaixo e salve as modificaes:
23
24
13. Clique em
para editar as propriedades grficas do objeto e configure
conforme a figura abaixo e salve as modificaes:
18. Clique em
para editar as propriedades grficas do objeto e configure
conforme a figura abaixo e salve as modificaes:
26
27
22. Clique em
alteraes.
28
29
30
Apendice I:
31
32
33
Apendice II:
34
Neste artigo ser discutido apenas o padro RTU que na prtica o mais difundido em
linha serial.
Mensagens MODBUS - RTU
As mensagens em MODBUS so formadas por frames ou quadros e existem apenas
dois tipos chamados de quadro de consulta e quadro de resposta. A figura 11 ilustra
uma transao entre o mestre e o escravo sendo que o quadro da esquerda
representa o frame de solicitao enviado pelo mestre ao escravo e o quadro da
direita frame de resposta enviado ao mestre pelo escravo.
35
CRC composto por dois bytes de verificao de erros, onde feita a checagem dos
dados enviados a fim de se verificar se ocorreu um erro durante a transmisso do
frame.
Consiste em realizar uma operao de diviso sobre o bloco de dados com um divisor
conhecido, utilizando-se o resto da operao como um caracter de verificao. A
diviso feita considerando-se como o dividendo a seqncia de bits que ser
transmitida, sendo que o divisor convenientemente escolhido de modo a controlar o
tamanho em bits do resto da diviso. muito comum a utilizao de CRC de no
mximo 16 bits, o que para a maior parte dos casos fornece uma boa segurana.
Quadro de resposta (resposta do escravo)
No quadro de resposta, o cdigo de funo repetido de volta para o mestre. Os bytes
de dados contm os dados coletados pelo escravo ou o seu estado. Se um erro
ocorre, o cdigo de funo modificado para indicar que a resposta uma resposta
de erro e os bytes de dados contm um cdigo que descrever o erro. A verificao de
erro permite o mestre validar os dados recebidos. Se o escravo no responder dentro
de um tempo pr determinado o mestre entende que foi gerado um erro de time out e
tomar as providncias programadas.
Adress formada por um byte que representa o endereo do escravo que est
respondendo ao mestre.
Function formada por um byte que representa o cdigo da funo ou comando
solicitado pelo mestre.
Data pacote de dados formado por um nmero de bytes varivel conforme o
comando do frame.
CRC composto por dois bytes de verificao de erros, onde feita a checagem dos
dados enviados a fim de se verificar se ocorreu um erro durante a transmisso do
frame.
Durao do Frame RTU
Na figura 12 vemos a formao dos quadros do tipo RTU. Observe primeiramente que
temos um perodo de silncio, onde sempre que as linhas de comunicao ficarem
sem trfego por pelo menos 3.5 caracteres o escravo entende que a rede entrou em
estado de idle, ou seja, em estado de repouso. Para uma rede com taxa de
comunicao 8N1 a 9600bps temos que o tempo de transmisso de 1 bit ser de:
1/9600 = 104us
Como 8N1 representa 1 bit de start, 8 bits de dados, nenhum bit de paridade e 1 bit de
parada temos ao todo 10 bits por caractere transmitido. Agora s multiplicar o tempo
de transmisso de um bit (104us) pelo nmero de bits do caractere para encontrar o
tempo de transmisso de um caractere ou byte, neste caso:
104 x 10 = 1040us ou 1,04ms
Caso a rede fique sem transmitir por:
3,5 x 1.04ms = 3,64ms
Ou seja por se a rede ficar em silencio por 3,5 caracteres temos o estado de idle e a
possibilidade do incio da transmisso de um novo frame.
36
37
Existe uma faixa de endereos destinada aos operandos de cada tipo de dados,
conforme relacionados a seguir:
00001 a 09999 - Coils;
10001 a 19999 - Inputs;
38
Sempre que se for desenvolver um dispositivo que deve ser compatvel com o
protocolo MODBUS deve-se respeitar a distribuio de memria padro estabelecida
pelo protocolo. Porm fica claro que os registros do tipo holding registers podem ser
considerados praticamente coringas e na prtica verifica-se que os fabricantes de
equipamentos so muito criativos no uso destes registros.
39
Concluso
O protocolo Modbus bastante eficiente e confivel, sendo uma maneira
relativamente simples e fcil de implementar a comunicao ou troca de dados entre
dois ou mais dispositivos em sistemas de automao. Por ser um dos primeiros
protocolos abertos e no ser muito exigente no que se refere aos meios fsicos de
transmisso um dos protocolos com menor custo de implantao e ainda hoje, mais
de 30 anos aps o lanamento continua sendo um dos protocolos de maior aceitao
no mercado mundial.
40
41
Apendice III:
Sketch para teste de comunicao RS485 com o Serial Monitor ou Hyper Terminal
/*
Teste de Comunicao Serial com RS485
Este exemplo de domnio pblico
Testado na IDE 1.0.1
*/
int POTENCIOMETRO = 0;
int CHAVE = 0;
int RECEBIDO = 0;
void setup()
{
42
void loop()
{
// Verifica se recebeu algum caracter pela serial
if (Serial.available() > 0) {
// le o byte recebido:
RECEBIDO = Serial.read();
// le a entrada analgica e divide por 4 para caber em um byte (0-255):
POTENCIOMETRO = analogRead(A0)/4;
// le o estado do boto:
CHAVE = map(digitalRead(4), 0, 1, 0, 1);
// envia os valores dos sensores:
digitalWrite(6, HIGH); // coloca o Shield RS485 em modo de transmisso
delay(1);
// aguarda 1 milisegundo
Serial.write("Pino A0 = ");
Serial.print(POTENCIOMETRO);//Serial.println(POTENCIOMETRO, DEC);
Serial.write('\n');
Serial.write("Pino D4 = ");
Serial.print(CHAVE);
Serial.write('\n');
43
// aguarda
}
}
Apendice IV:
/*
Modbus serial - RTU Slave Arduino Sketch
44
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
45
paul@pmcrae.freeserve.co.uk (http://www.pmcrae.freeserve.co.uk)
who wrote a small program to read 100 registers from a modbus slave.
*/
/*
* configure_mb_slave(baud, parity, tx_en_pin)
*
* configurao dos parametros da porta serial.
*
* baud: taxa de transmisso em bps (valores tpicos entre 9600, 19200... 115200)
* parity: seta o modo de paridade:
*
'n' sem paridade (8N1); 'e' paridede impar (8E1), 'o' paridade par (8O1).
*/
void configure_mb_slave(long baud, char parity, char txenpin);
/*
* update_mb_slave(slave_id, holding_regs_array, number_of_regs)
*
* verifica se h qualquer pedido vlido do mestre modbus. Se houver,
* executa a ao solicitada
*
* slave: endereo do escravo (arduino) (1 to 127)
46
* regs: uma matriz com os holding registers. Eles comeam no endereo 1 (mestre ponto de
vista)
* Regs_size: nmero total de holding registers.
* Retorna: 0 se no houver pedido do mestre,
* NO_REPLY (-1) se nenhuma resposta enviada para o mestre
* Caso um cdigo de exceo (1 a 4) em algumas excees de modbus
* O nmero de bytes enviados como resposta (> 4) se OK.
*/
/* paridade */
TXEN = 6
47
enum {
MB_PINO_5,
scadabr)*/
MB_PINO_4,
scadabr)*/
MB_A0,
scadabr)*/
MB_REGS
};
int regs[MB_REGS];
int ledPin5 = 5;
int ledPin13 = 13;
int buttonPin4 = 4;
int buttonState = 0;
/* watchdog */
/* tempo anterior do ltimo comando*/
void setup()
{
48
pinMode(ledPin5, OUTPUT);
pinMode(ledPin13, OUTPUT);
pinMode(buttonPin4, INPUT);
}
void loop()
{
/* verifica se h solicitaes do mestre */
if(update_mb_slave(MB_SLAVE, regs, MB_REGS))
wdog = millis();
tanalogprev = millis();
}
digitalWrite(ledPin13, HIGH);
}
else {
49
digitalWrite(ledPin13, LOW);
switch(regs[MB_PINO_5]) {
case 1:
digitalWrite(ledPin5, HIGH);
break;
default: /* apagado */
digitalWrite(ledPin5, LOW);
}
}
/****************************************************************************
* INICIO DAS FUNES ESCRAVO Modbus RTU
****************************************************************************/
/* variaveis globais */
unsigned int Txenpin = TXEN;
/* Lista de cdigos de funo modbus suportados. Se voc implementar um novo, colocar o seu
cdigo de funo aqui! */
enum {
50
FC_READ_REGS = 0x03,
contguo de registos)
};
/* Funes suportadas. Se voc implementar um novo, colocar seu cdigo em funo nessa
matriz! */
const unsigned char fsupported[] = {
FC_READ_REGS, FC_WRITE_REG, FC_WRITE_REGS };
/* constantes */
enum {
MAX_READ_REGS = 0x7D,
MAX_WRITE_REGS = 0x7B,
MAX_MESSAGE_LENGTH = 256
};
enum {
RESPONSE_SIZE = 6,
EXCEPTION_SIZE = 3,
CHECKSUM_SIZE = 2
};
/* cdigo de excees */
enum {
NO_REPLY = -1,
51
EXC_FUNC_CODE = 1,
EXC_ADDR_RANGE = 2,
EXC_REGS_QUANT = 3,
EXC_EXECUTE = 4
};
/*
CRC
INPUTS:
buf -> Matriz contendo a mensagem a ser enviada para o controlador mestre.
start -> Incio do loop no crc do contador, normalmente 0.
cnt -> Quantidade de bytes na mensagem a ser enviada para o controlador mestre
OUTPUTS:
temp -> Retorna byte crc para a mensagem.
52
COMMENTRIOS:
Esta rotina calcula o byte crc alto e baixo de uma mensagem.
Note que este CRC usado somente para Modbus, no em Modbus PLUS ou TCP.
****************************************************************************/
temp = 0xFFFF;
53
return (temp);
}
/***********************************************************************
*
*
*
*
***********************************************************************/
/*
* Incio do pacote de uma resposta read_holding_register
*/
void build_read_packet(unsigned char slave, unsigned char function,
unsigned char count, unsigned char *packet)
{
packet[SLAVE] = slave;
packet[FUNC] = function;
packet[2] = count * 2;
}
/*
54
/*
* Incio do pacote de uma resposta write_single_register
*/
void build_write_single_packet(unsigned char slave, unsigned char function,
unsigned int write_addr, unsigned int reg_val, unsigned char* packet)
{
packet[SLAVE] = slave;
packet[FUNC] = function;
packet[START_H] = write_addr >> 8;
packet[START_L] = write_addr & 0x00ff;
packet[REGS_H] = reg_val >> 8;
packet[REGS_L] = reg_val & 0x00ff;
55
/*
* Incio do pacote de uma resposta excepo
*/
void build_error_packet(unsigned char slave, unsigned char function,
unsigned char exception, unsigned char *packet)
{
packet[SLAVE] = slave;
packet[FUNC] = function + 0x80;
packet[2] = exception;
}
/*************************************************************************
*
* modbus_query( packet, length)
*
* Funo para adicionar uma soma de verificao para o fim de um pacote.
* Por favor, note que a matriz pacote deve ser de pelo menos 2 campos mais do que
* String_length.
**************************************************************************/
56
/***********************************************************************
*
* send_reply( query_string, query_length )
*
* Funo para enviar uma resposta a um mestre Modbus.
* Retorna: o nmero total de caracteres enviados
************************************************************************/
57
modbus_reply(query, string_length);
string_length += 2;
return i;
/***********************************************************************
*
*
receive_request( array_for_data )
*
* Funo para monitorar um pedido do mestre modbus.
*
* Retorna: Nmero total de caracteres recebidos se OK
* 0 se no houver nenhum pedido
* Um cdigo de erro negativo em caso de falha
***********************************************************************/
58
{
int bytes_received = 0;
return (bytes_received);
}
/*********************************************************************
*
*
modbus_request(slave_id, request_data_array)
*
* Funo que retornada quando o pedido est correto
* e a soma de verificao est correto.
* Retorna: string_length se OK
* 0 se no
* Menos de 0 para erros de exceo
*
* Nota: Todas as funes usadas para enviar ou receber dados via
* Modbus devolver esses valores de retorno.
59
*
**********************************************************************/
response_length = receive_request(data);
if (response_length > 0) {
crc_calc = crc(data, 0, response_length - 2);
recv_crc_hi = (unsigned) data[response_length - 2];
recv_crc_lo = (unsigned) data[response_length - 1];
crc_received = data[response_length - 2];
crc_received = (unsigned) crc_received << 8;
crc_received =
crc_received | (unsigned) data[response_length - 1];
60
/* verificar a ID do escravo */
if (slave != data[SLAVE]) {
return NO_REPLY;
}
}
return (response_length);
}
/*********************************************************************
*
*
*
* Funo para verificar se o pedido pode ser processado pelo escravo.
*
* Retorna: 0 se OK
* Um cdigo de exceo negativa em caso de erro
*
**********************************************************************/
61
if (FC_WRITE_REG == data[FUNC]) {
/* Para a funo de escrever um reg nico, este o registro alvo.*/
regs_num = ((int) data[START_H] << 8) + (int) data[START_L];
if (regs_num >= regs_size)
return EXC_ADDR_RANGE;
return 0;
}
62
return 0;
/************************************************************************
*
*
*
*
* A partir de start_addr.
*
* Retorna: o nmero de registros escritos
************************************************************************/
63
*/
regs[start_addr + i] = temp;
}
return i;
}
/************************************************************************
*
*
* data_array, registers_array)
*
*
*
*************************************************************************/
64
return (status);
}
/************************************************************************
*
* write_single_register(slave_id, write_addr, data_array, registers_array)
*
* Escrever um nico valor inteiro em um nico registo do escravo.
*
*************************************************************************/
65
return (status);
}
/************************************************************************
*
*
* registers_array)
*
* l os registros do escravo e envia para o mestre Modbus
*
*************************************************************************/
66
int packet_size = 3;
int status;
unsigned int i;
unsigned char packet[MAX_MESSAGE_LENGTH];
return (status);
}
67
switch (parity) {
case 'e': // 8E1
UCSR0C |= ((1<<UPM01) | (1<<UCSZ01) | (1<<UCSZ00));
//
break;
case 'o': // 8O1
UCSR0C |= ((1<<UPM01) | (1<<UPM00) | (1<<UCSZ01) | (1<<UCSZ00));
//
break;
case 'n': // 8N1
UCSR0C |= ((1<<UCSZ01) | (1<<UCSZ00));
//
break;
default:
break;
}
return;
}
68
/*
* update_mb_slave(slave_id, holding_regs_array, number_of_regs)
*
* verifica se h qualquer pedido vlido do mestre modbus. Se houver,
* executa a ao solicitada
*/
if (length == 0) {
lastBytesReceived = 0;
return 0;
}
if (lastBytesReceived != length) {
69
lastBytesReceived = length;
Nowdt = now + T35;
return 0;
}
if (now < Nowdt)
return 0;
lastBytesReceived = 0;
70
return read_holding_registers(slave,
start_addr,
query[REGS_L],
regs);
break;
case FC_WRITE_REGS:
return preset_multiple_registers(slave,
start_addr,
query[REGS_L],
query,
regs);
break;
case FC_WRITE_REG:
write_single_register(slave,
start_addr,
query,
regs);
break;
}
}
71
Referncias
Arduino:
http://www.arduino.cc/
SCADABR :
http://www.scadabr.com.br/
72
JPMZOMETA:
https://sites.google.com/site/jpmzometa/arduino-mbrt/arduino-modbus-slave
Frum SCADABR no Laboratrio de Garagem:
http://labdegaragem.com /forum/topics/scadabr
MODBUS:
http://www.modbus.org/docs/Modbus_Application_Protocol_V1_1b.pdf
RS485:
http://www.lammertbies.nl/comm/info/RS-485.html
http://www.maxim-ic.com/app-notes/index.mvp/id/763
Videos no Youtube:
http://www.youtube.com/watch?v=aXcgloY4a80
http://www.youtube.com/watch?v=hHhWS2E2BmQ&feature=player_embedded
http://www.youtube.com/watch?v=nHSG7yrs4JE&feature=channel&list=UL
http://www.youtube.com/watch?v=N4vE0F8A1II&feature=relmfu
http://www.youtube.com/watch?v=j-OW5jYRWYk&feature=relmfu
73