Alguém conhece o scadabr e sabe como usa-lo, caso conheça por favor entre em contato pois preciso de algumas informações.

Uma delas é o protocolo modbus pois queria saber como comunicar um sensor,atuador,etc como o supervisor por meio de um microcontrolador ou coisa paracida, me parece que para poder acionar ou receber informações o supervisorio precisa de um clp (que é caro) ou por um microcontrolador?

se alguém tiver informações sobre como usar e implementar ou pelo menos mostrar o caminho das pedras já agradeço.

adriano

Exibições: 97571

Responder esta

Respostas a este tópico

Wiechert muito obrigado, farei os testes
Abraço

Olá amigo desculpe a demora estava sem acesso a internet , meu projeto é algo simples, estou cursando técnico em automação industrial e nos foi passando um trabalho no qual teríamos dois tanques com água, e que deveríamos manter o nível do primeiro tanque constante independente da vazão com que água sai do primeiro tanque para o segundo.

a ideia inicial seria apenas usar um inversor de frequência, uma bomba, um pressostato que gera de um sinal de 0 a 5 v conforme a quantidade de agua no tanque.

consegui realizar todo o controle do projeto atravez de dois botões um liga e outro desliga como pedia o professor.

configurei o inversor de frequência para que conforme fosse aumentando o nivel do tanque, a bomba fosse desacelerando.

até ai foi cumprido o desejado pela avaliação.

Então decidir inovar( inclusive sou o primeiro aluno das turmas de automação do meu senai a fazer algo do genero), decidir ter um supervisório funcional em meu projeto, com controle para ligar/desligar , fazer o controle do nivel manualmente utilizando o 0 a 5 V do arduino, pois conforme a tensão que aplico no inversor irei aumentar ou diminuir o nivel do tanque,tambem disponibilizei na minha representação gráfica sinalizadores, um gráfico de nivel, um tanque que enche conforme o fisico e alarmes para ações criticas.

hoje não tenho video do projeto funcionando, estou com tudo funcionando, inclusive a variação que eu queria do arduino gerando o sinal de 0 a 5 v.(consegui descobrir como fazer no código do arduino, caso deseje dar uma olhada só me avise)

o que falta para mim é um objeto que eu possa colocar  na representação grafica, no qual eu possa variar o comando que o supervisório envia para o arduino.)

pois atualmente consigo fazer essa variação apesar se eu digitar um valor de 0 a 1023 na opção definir valor de escrita, lá no data point no menu watch list

vou colocar abaixo uma imagem do que desejo.

quero que quando eu mover o indicador , ele defina o valor do datapoint conforme a escala desse slider 

deu para entender ? hehehehe as vezes falo demais e acabo confundindo o pessoal, irei fazer essa pergunta no site oficial do scadabr, caso consiga algum retorno lá eu aviso vocês, segunda feira irei fazer um video e coloco aqui para darem uma olhada

Pessoal, uma duvida cruel, estou me dando bem com o scada e estou tendo os resultados esperados, porem 2 questoes estao me perturbando...

1a, no scada so é possivel criar as enums das entradas do arduino ou posso criar uma variavel la dentro para inserir um texto? o que quero é atraves do recurso de alterar condições de estado no whatchlist enviar um texto para o arduino que sera mostrado num display LCD... os dados dos sensores tanto no scadabr e no lcd estao sendo mostrados perfeitamente, mas gostaria de no scadabr escrever, por exemplo "temperatura" e aparecer no display, sem ter q mexer na IDE.

2a questao, qto ao gifs que representam as condições de sensores, saber se posso acrescentar, pois estou pensando em criar um mostrador no formato abaixo, da mesma forma que fazemos com um display de catodo mas atraves de variaveis mostrar no scadabr... 

e ai pessoal ninguem tem ideia do que fazer nesse meu caso?

Olá,

Estou com um problema em receber o comando (dados) do Scada para o Arduino, porém consigo enviar do arduino para o Scada (ºC de temperatura e magpin on/off). Uso modulo RS232 para comunicação e protocolo MODBUS.

Gostaria de fazer o controle de temperatura enviando um Setpoint e um Range de temperatura para o arduino,  a partir de uma caixa de diálogo no Scada para ligar e desligar o "magpin" que seria meu equipamento. Deixo o código abaixo para ajudar, obrigado.

*Scada recebendo os dados(Valor), mas na hora de enviar o Setpoint e Range dá erro.

code

#include <modbus.h>
#include <modbusDevice.h>
#include <modbusRegBank.h>
#include <modbusSlave.h>
#include <SPI.h>
#include "Adafruit_MAX31855.h"
#define DO 12
#define CS 8
#define CLK 13

int magpin=3; //Pin 3 output
int Setpoint, Range;
Adafruit_MAX31855 thermocouple(CLK, CS, DO);
modbusDevice regBank;
modbusSlave slave;

void setup()
{

regBank.setId(3);
pinMode(magpin, OUTPUT);

//Liga e desliga magpin (saida digital)
regBank.add(3);

//Entrada Setpoint e range (entrada analogica)
regBank.add(30002); 
regBank.add(30003);

//saida da temperatura (saida analogica)
regBank.add(40001);
regBank.add(40010); 
regBank.add(40011);

slave._device = &regBank; 
slave.setBaud(9600);

}

void loop()
{
while(1)
{
regBank.set(40010, Setpoint); 

regBank.set(40011, Range);

Serial.print("Internal Temp = ");
Serial.println(thermocouple.readInternal());

double c = thermocouple.readCelsius();
if (isnan(c)) 
{
Serial.println("Something wrong with thermocouple!");

else {

Serial.print("C = "); 
Serial.println(c);
regBank.set(40001, (double) c);
}

if(c>=Setpoint+Range)
{
digitalWrite(magpin, HIGH); //Desliga magnetron
delay(200);
regBank.set(3, 1); 
}

if(c<=Setpoint-Range)
{
digitalWrite(magpin, LOW); //Liga magnetron
delay(200);
regBank.set(3, 0); 
}
}

slave.run(); 
}
}

Luiz Gustavo,

eu já estou pesquisando isso faz tempo e tenho algumas coisas para te contar.

Essa biblioteca que usou até é melhor, mas temos um problema no modbus com comandos vindos do scadabr.

Existe um conjunto de parâmetros de tempo que o modbus define e que se não atendidos dá erro.

Vou estudar seu código para entender o que quer fazer.

Muito obrigado Sidney, fico no aguardo! Qualquer atualização posto aqui.

Bom dia galera 

estou com dificuldade para passar o código para o arduino esta dando esta mensagem : 

Arduino: 1.6.0 (Windows 8), Placa:"Arduino Mega or Mega 2560, ATmega2560 (Mega 2560)"

sketch_feb22aScadaBR.ino:144:1: error: invalid suffix "Rua" on integer constant
sketch_feb22aScadaBR.ino:191:1: error: stray '\' in program
sketch_feb22aScadaBR.ino:194:1: error: stray '\' in program
sketch_feb22aScadaBR.ino: In function 'void loop()':
sketch_feb22aScadaBR.ino:37:1: error: 'BYTE' was not declared in this scope
sketch_feb22aScadaBR.ino:37:5: error: expected ';' before ')' token
sketch_feb22aScadaBR.ino: In function 'void setup()':
sketch_feb22aScadaBR.ino:142:6: error: redefinition of 'void setup()'
sketch_feb22aScadaBR.ino:9:6: error: 'void setup()' previously defined here
sketch_feb22aScadaBR.ino:147:2: error: expected ';' before 'configure_mb_slave'
sketch_feb22aScadaBR.ino: In function 'void loop()':
sketch_feb22aScadaBR.ino:152:6: error: redefinition of 'void loop()'
sketch_feb22aScadaBR.ino:16:6: error: 'void loop()' previously defined here
sketch_feb22aScadaBR.ino: At global scope:
sketch_feb22aScadaBR.ino:191:6: error: expected '}' before 'u00edguo'
sketch_feb22aScadaBR.ino:191:15: error: expected initializer before 'de'
sketch_feb22aScadaBR.ino:195:1: error: expected declaration before '}' token
Erro compilando.

Este relatório deveria ter mais informações
"Mostrar saída verbosa durante a compilação"
habilitado em Arquivo > Preferências.

Olá,
Procure resolver o problema pelo primeiro erro que conforme a mensagem ocorreu na linha 144 do sketch, olhe a linha anterior. Ao que parece 'Rua' não foi declarada.
Uma dica é corrigir sempre o primeiro erro, compilar e ver o próximo erro, corrigir e compilar. Desta forma você consegue resolver.
Postar o sketch também ajuda a te ajudarem.
Abraço.

/*
Modbus over serial line - RTU Slave Arduino Sketch

By Juan Pablo Zometa : jpmzometa@gmail.com
http://sites.google.com/site/jpmzometa/
and Samuel Marco: sammarcoarmengol@gmail.com
and Andras Tucsni.

These functions implement functions 3, 6, and 16 (read holding registers,
preset single register and preset multiple registers) of the
Modbus RTU Protocol, to be used over the Arduino serial connection.

This implementation DOES NOT fully comply with the Modbus specifications.

This Arduino adaptation is derived from the work
By P.Costigan email: phil@pcscada.com.au http://pcscada.com.au

These library of functions are designed to enable a program send and
receive data from a device that communicates using the Modbus protocol.

Copyright (C) 2000 Philip Costigan P.C. SCADA LINK PTY. LTD.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

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.

The functions included here have been derived from the
Modicon Modbus Protocol Reference Guide
which can be obtained from Schneider at www.schneiderautomation.com.

This code has its origins with
paul@pmcrae.freeserve.co.uk (http://www.pmcrae.freeserve.co.uk)
who wrote a small program to read 100 registers from a modbus slave.

I have used his code as a catalist to produce this more functional set
of functions. Thanks paul.
*/


/*
* configure_mb_slave(baud, parity, tx_en_pin)
*
* sets the communication parameters for of the serial line.
*
* baud: baudrate in bps (typical values 9600, 19200... 115200)
* parity: a single character sets the parity mode (character frame format):
* 'n' no parity (8N1); 'e' even parity (8E1), 'o' for odd parity (8O1).
* tx_en_pin: arduino pin number that controls transmision/reception
* of an external half-duplex device (e.g. a RS485 interface chip).
* 0 or 1 disables this function (for a two-device network)
* >2 for point-to-multipoint topology (e.g. several arduinos)
*/
void configure_mb_slave(long baud, char parity, char txenpin);

/*
* update_mb_slave(slave_id, holding_regs_array, number_of_regs)
*
* checks if there is any valid request from the modbus master. If there is,
* performs the action requested
*
* slave: slave id (1 to 127)
* regs: an array with the holding registers. They start at address 1 (master point of view)
* regs_size: total number of holding registers.
* returns: 0 if no request from master,
* NO_REPLY (-1) if no reply is sent to the master
* an exception code (1 to 4) in case of a modbus exceptions
* the number of bytes sent as reply ( > 4) if OK.
*/

int update_mb_slave(unsigned char slave, int *regs,
unsigned int regs_size);

/* HERE BEGINS THE EXAMPLE CODE */

/* Modbus RTU common parameters, the Master MUST use the same parameters */
enum {
COMM_BPS = 115200, /* baud rate */
MB_SLAVE = 1, /* modbus slave id */
PARITY = 'e' /* even parity */
};

/* slave registers */
enum {
MB_CTRL, /* Led control on, off or blink */
MB_TIME, /* blink time in milliseconds */
MB_CNT, /* count the number of blinks */
MB_REGS /* total number of registers on slave */
};

int regs[MB_REGS];
int ledPin = 13;
unsigned long wdog = 0; /* watchdog */
unsigned long tprev = 0; /* previous time*/

void setup()
{
/* configure modbus communication
* 115200 bps, 8E1, two-device network */
configure_mb_slave(COMM_BPS, PARITY, 0);

pinMode(ledPin, OUTPUT);
}


void loop()
{
/* check for master requests*/
if(update_mb_slave(MB_SLAVE, regs, MB_REGS))
wdog = millis();

if ((millis() - wdog) > 5000) { /* no comms in 5 sec */
regs[MB_CTRL] = 0; /* turn off led */
}

/* the values in regs are set by the modbus master */
switch(regs[MB_CTRL]) {
case 0:
digitalWrite(ledPin, LOW);
break;
case 1:
digitalWrite(ledPin, HIGH);
break;
default: /* blink */
if (millis() - tprev > regs[MB_TIME]) {
if (LOW == digitalRead(ledPin)) {
digitalWrite(ledPin, HIGH);
/* this is how you change your holding registers
so the master can read values from the slave */
regs[MB_CNT]++;
} else {
digitalWrite(ledPin, LOW);
}
tprev = millis();
}
}
}

/****************************************************************************
* BEGIN MODBUS RTU SLAVE FUNCTIONS
****************************************************************************/

/* global variables */
unsigned int Txenpin = 0; /* Enable transmission pin, used on RS485 networks */


/* enum of supported modbus function codes. If you implement a new one, put its function code here ! */
enum {
FC_READ_REGS = 0x03, //Read contiguous block of holding register
FC_WRITE_REG = 0x06, //Write single holding register
FC_WRITE_REGS = 0x10 //Write block of contiguous registers
};

/* supported functions. If you implement a new one, put its function code into this array! */
const unsigned char fsupported[] = { FC_READ_REGS, FC_WRITE_REG, FC_WRITE_REGS };

/* constants */
enum {
MAX_READ_REGS = 0x7D,
MAX_WRITE_REGS = 0x7B,
MAX_MESSAGE_LENGTH = 256
};


enum {
RESPONSE_SIZE = 6,
EXCEPTION_SIZE = 3,
CHECKSUM_SIZE = 2
};

/* exceptions code */
enum {
NO_REPLY = -1,
EXC_FUNC_CODE = 1,
EXC_ADDR_RANGE = 2,
EXC_REGS_QUANT = 3,
EXC_EXECUTE = 4
};

/* positions inside the query/response array */
enum {
SLAVE = 0,
FUNC,
START_H,
START_L,
REGS_H,
REGS_L,
BYTE_CNT
};


/*
CRC

INPUTS:
buf -> Array containing message to be sent to controller.
start -> Start of loop in crc counter, usually 0.
cnt -> Amount of bytes in message being sent to controller/
OUTPUTS:
temp -> Returns crc byte for message.
COMMENTS:
This routine calculates the crc high and low byte of a message.
Note that this crc is only used for Modbus, not Modbus+ etc.
****************************************************************************/

unsigned int crc(unsigned char *buf, unsigned char start,
unsigned char cnt)
{
unsigned char i, j;
unsigned temp, temp2, flag;

temp = 0xFFFF;

for (i = start; i < cnt; i++) {
temp = temp ^ buf[i];

for (j = 1; j <= 8; j++) {
flag = temp & 0x0001;
temp = temp >> 1;
if (flag)
temp = temp ^ 0xA001;
}
}

/* Reverse byte order. */
temp2 = temp >> 8;
temp = (temp 8) | temp2;
temp &= 0xFFFF;

return (temp);
}


/***********************************************************************
*
* The following functions construct the required query into
* a modbus query packet.
*
***********************************************************************/

/*
* Start of the packet of a read_holding_register response
*/
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;
}

/*
* Start of the packet of a preset_multiple_register response
*/
void build_write_packet(unsigned char slave, unsigned char function,
unsigned int start_addr,
unsigned char count,
unsigned char *packet)
{
packet[SLAVE] = slave;
packet[FUNC] = function;
packet[START_H] = start_addr >> 8;
packet[START_L] = start_addr & 0x00ff;
packet[REGS_H] = 0x00;
packet[REGS_L] = count;
}

/*
* Start of the packet of a write_single_register response
*/
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;
}


/*
* Start of the packet of an exception response
*/
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)
*
* Function to add a checksum to the end of a packet.
* Please note that the packet array must be at least 2 fields longer than
* string_length.
**************************************************************************/

void modbus_reply(unsigned char *packet, unsigned char string_length)
{
int temp_crc;

temp_crc = crc(packet, 0, string_length);
packet[string_length] = temp_crc >> 8;
string_length++;
packet[string_length] = temp_crc & 0x00FF;
}

/***********************************************************************
*
* send_reply( query_string, query_length )
*
* Function to send a reply to a modbus master.
* Returns: total number of characters sent
************************************************************************/

int send_reply(unsigned char *query, unsigned char string_length)
{
unsigned char i;

if (Txenpin > 1) { // set MAX485 to speak mode
UCSR0A=UCSR0A |(1 TXC0);
digitalWrite( Txenpin, HIGH);
delay(1);
}

modbus_reply(query, string_length);
string_length += 2;

for (i = 0; i < string_length; i++) {
Serial.print(query[i], BYTE);
}

if (Txenpin > 1) {// set MAX485 to listen mode
while (!(UCSR0A & (1 TXC0)));
digitalWrite( Txenpin, LOW);
}

return i; /* it does not mean that the write was succesful, though */
}

/***********************************************************************
*
* receive_request( array_for_data )
*
* Function to monitor for a request from the modbus master.
*
* Returns: Total number of characters received if OK
* 0 if there is no request
* A negative error code on failure
***********************************************************************/

int receive_request(unsigned char *received_string)
{
int bytes_received = 0;

/* FIXME: does Serial.available wait 1.5T or 3.5T before exiting the loop? */
while (Serial.available()) {
received_string[bytes_received] = Serial.read();
bytes_received++;
if (bytes_received >= MAX_MESSAGE_LENGTH)
return NO_REPLY; /* port error */
}

return (bytes_received);
}


/*********************************************************************
*
* modbus_request(slave_id, request_data_array)
*
* Function to the correct request is returned and that the checksum
* is correct.
*
* Returns: string_length if OK
* 0 if failed
* Less than 0 for exception errors
*
* Note: All functions used for sending or receiving data via
* modbus return these return values.
*
**********************************************************************/

int modbus_request(unsigned char slave, unsigned char *data)
{
int response_length;
unsigned int crc_calc = 0;
unsigned int crc_received = 0;
unsigned char recv_crc_hi;
unsigned char recv_crc_lo;

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];

/*********** check CRC of response ************/
if (crc_calc != crc_received) {
return NO_REPLY;
}

/* check for slave id */
if (slave != data[SLAVE]) {
return NO_REPLY;
}
}
return (response_length);
}

/*********************************************************************
*
* validate_request(request_data_array, request_length, available_regs)
*
* Function to check that the request can be processed by the slave.
*
* Returns: 0 if OK
* A negative exception code on error
*
**********************************************************************/

int validate_request(unsigned char *data, unsigned char length,
unsigned int regs_size)
{
int i, fcnt = 0;
unsigned int regs_num = 0;
unsigned int start_addr = 0;
unsigned char max_regs_num;

/* check function code */
for (i = 0; i < sizeof(fsupported); i++) {
if (fsupported[i] == data[FUNC]) {
fcnt = 1;
break;
}
}
if (0 == fcnt)
return EXC_FUNC_CODE;

if (FC_WRITE_REG == data[FUNC]) {
/* For function write single reg, this is the target reg.*/
regs_num = ((int) data[START_H] 8) + (int) data[START_L];
if (regs_num >= regs_size)
return EXC_ADDR_RANGE;
return 0;
}

/* For functions read/write regs, this is the range. */
regs_num = ((int) data[REGS_H] 8) + (int) data[REGS_L];

/* check quantity of registers */
if (FC_READ_REGS == data[FUNC])
max_regs_num = MAX_READ_REGS;
else if (FC_WRITE_REGS == data[FUNC])
max_regs_num = MAX_WRITE_REGS;

if ((regs_num < 1) || (regs_num > max_regs_num))
return EXC_REGS_QUANT;

/* check registers range, start address is 0 */
start_addr = ((int) data[START_H] 8) + (int) data[START_L];
if ((start_addr + regs_num) > regs_size)
return EXC_ADDR_RANGE;

return 0; /* OK, no exception */
}

/************************************************************************
*
* write_regs(first_register, data_array, registers_array)
*
* writes into the slave's holding registers the data in query,
* starting at start_addr.
*
* Returns: the number of registers written
************************************************************************/

int write_regs(unsigned int start_addr, unsigned char *query, int *regs)
{
int temp;
unsigned int i;

for (i = 0; i < query[REGS_L]; i++) {
/* shift reg hi_byte to temp */
temp = (int) query[(BYTE_CNT + 1) + i * 2] 8;
/* OR with lo_byte */
temp = temp | (int) query[(BYTE_CNT + 2) + i * 2];

regs[start_addr + i] = temp;
}
return i;
}

/************************************************************************
*
* preset_multiple_registers(slave_id, first_register, number_of_registers,
* data_array, registers_array)
*
* Write the data from an array into the holding registers of the slave.
*
*************************************************************************/

int preset_multiple_registers(unsigned char slave,
unsigned int start_addr,
unsigned char count,
unsigned char *query,
int *regs)
{
unsigned char function = FC_WRITE_REGS; /* Preset Multiple Registers */
int status = 0;
unsigned char packet[RESPONSE_SIZE + CHECKSUM_SIZE];

build_write_packet(slave, function, start_addr, count, packet);

if (write_regs(start_addr, query, regs)) {
status = send_reply(packet, RESPONSE_SIZE);
}

return (status);
}


/************************************************************************
*
* write_single_register(slave_id, write_addr, data_array, registers_array)
*
* Write a single int val into a single holding register of the slave.
*
*************************************************************************/

int write_single_register(unsigned char slave,
unsigned int write_addr, unsigned char *query, int *regs)
{
unsigned char function = FC_WRITE_REG; /* Function: Write Single Register */
int status = 0;
unsigned int reg_val;
unsigned char packet[RESPONSE_SIZE + CHECKSUM_SIZE];

reg_val = query[REGS_H] 8 | query[REGS_L];
build_write_single_packet(slave, function, write_addr, reg_val, packet);
regs[write_addr] = (int) reg_val;
/*
written.start_addr=write_addr;
written.num_regs=1;
*/
status = send_reply(packet, RESPONSE_SIZE);

return (status);
}


/************************************************************************
*
* read_holding_registers(slave_id, first_register, number_of_registers,
* registers_array)
*
* reads the slave's holdings registers and sends them to the Modbus master
*
*************************************************************************/

int read_holding_registers(unsigned char slave, unsigned int start_addr,

unsigned char reg_count, int *regs)
{
unsigned char function = 0x03; /* Function 03: Read Holding Registers */
int packet_size = 3;
int status;
unsigned int i;
unsigned char packet[MAX_MESSAGE_LENGTH];

build_read_packet(slave, function, reg_count, packet);

for (i = start_addr; i < (start_addr + (unsigned int) reg_count);
i++) {
packet[packet_size] = regs[i] >> 8;
packet_size++;
packet[packet_size] = regs[i] & 0x00FF;
packet_size++;
}

status = send_reply(packet, packet_size);

return (status);
}


void configure_mb_slave(long baud, char parity, char txenpin)
{
Serial.begin(baud);

switch (parity) {
case 'e': // 8E1
UCSR0C |= ((1UPM01) | (1UCSZ01) | (1UCSZ00));
// UCSR0C &= ~((1UPM00) | (1UCSZ02) | (1USBS0));
break;
case 'o': // 8O1
UCSR0C |= ((1UPM01) | (1UPM00) | (1UCSZ01) | (1UCSZ00));
// UCSR0C &= ~((1UCSZ02) | (1USBS0));
break;
case 'n': // 8N1
UCSR0C |= ((1UCSZ01) | (1UCSZ00));
// UCSR0C &= ~((1UPM01) | (1UPM00) | (1UCSZ02) | (1USBS0));
break;
default:
break;
}

if (txenpin > 1) { // pin 0 & pin 1 are reserved for RX/TX
Txenpin = txenpin; /* set global variable */
pinMode(Txenpin, OUTPUT);
digitalWrite(Txenpin, LOW);
}

return;
}

/*
* update_mb_slave(slave_id, holding_regs_array, number_of_regs)
*
* checks if there is any valid request from the modbus master. If there is,
* performs the action requested
*/

unsigned long Nowdt = 0;
unsigned int lastBytesReceived;
const unsigned long T35 = 5;

int update_mb_slave(unsigned char slave, int *regs,
unsigned int regs_size)
{
unsigned char query[MAX_MESSAGE_LENGTH];
unsigned char errpacket[EXCEPTION_SIZE + CHECKSUM_SIZE];
unsigned int start_addr;
int exception;
int length = Serial.available();
unsigned long now = millis();

if (length == 0) {
lastBytesReceived = 0;
return 0;
}

if (lastBytesReceived != length) {
lastBytesReceived = length;
Nowdt = now + T35;
return 0;
}
if (now < Nowdt)
return 0;

lastBytesReceived = 0;

length = modbus_request(slave, query);
if (length < 1)
return length;

exception = validate_request(query, length, regs_size);
if (exception) {
build_error_packet(slave, query[FUNC], exception,
errpacket);
send_reply(errpacket, EXCEPTION_SIZE);
return (exception);
}


start_addr = ((int) query[START_H] 8) +
(int) query[START_L];
switch (query[FUNC]) {
case FC_READ_REGS:
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;
}
}

Olá pessoal, depois de muito tempo trago uma boa nova.

Conclui hoje uma biblioteca Modbus para Arduino que suporta RS-232, RS-485 e IP. Atualmente a biblioteca permite que o arduino opere como Slave (Mestre em desenvolvimento). 

Há muito tempo atrás fiz uma extensão da biblioteca ModbusSlave do Juan Pablo mas apesar de funcional ela nunca foi muito usada (eu acho) e também não muito divulgada.

Dessa vez (eu acho que) fiz a coisa certa:

- Pesquisei cinco bibliotecas Modbus para Arduino e criei uma que certamente vai facilitar as coisas pois a forma de utilização ficou bem simplificada mas com flexibilidade. Bom, isso é o que eu acho mas quem vai dizer mesmo são vocês :).

- Coloquei o o código no GitHub o que está ajudando um bocado, fixando um local de fácil download (É só clicar no botão para baixar o zip).

- Fiz 4 exemplos de uso para Modbus Serial e 4 para Modbus IP.

- Coloquei ainda um README em inglês e português que explica tudo sobre a biblioteca.

- Fiz diversos testes com o ScadaBR

Agora passo a bola pra vocês, se puderem testar, apontar erros e contribuições seria ótimo!

Ela foi testada somente no Uno e no Nano. No Mega deve funcionar também, quem pode testar?


http://github.com/andresarmento/modbus-arduino

Abraços a todos.

Boa noite! André

Estou fazendo um TCC para a faculdade de redes de computadores e queria fazer o monitoramento da rede elétrica e da temperatura da sala de no-break com o ScadaBr + Arduino, você tem alguma coisa para mim ajudar.

Wilton Feitosa

wilton-f-b@hotmail.com

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço