Arduino + ScadaBR + Sensor Ultrassônico

Prezados,

Estou tentando comunicar um sensor ultrassônico HC-SR04 no ScadaBR, através de um Arduino(Slave em uma rede Modbus RTU). O problema é que, como o arduino é Slave, a programação da rotina do processo é na plataforma scadabr.

Alguém já utilizou algum sensor semelhante? A dúvida é devido o sensor utilizar as portas Echo e Trig nas portas Digitais.

Obrigado.

Olá,

Ainda não utilizei este sensor, mas geralmente quando utilizamos lógicas associadas a controladores (nesse caso arduino), deixamos na comunicação com o controlador apenas setpoints e leituras de dados. A lógica de operação sob os setpoints fica a cargo do controlador (programação CLP, uControlador, Arduino, …)

AKA

PC-ScadaBR < Setpoints e Dados(100ms - hs) > Controlador-Lógica_de_Operação < Com com sensor(us - ms) > Sensor

Entendeu? Programe o ScadaBR só para receber os dados via Modbus, e encarregue o Arduino da comunicação com o HC-SR04 - você está utilizando a lib dele certo?

Abs

Diego,

Inclusive amigo, já estou testando a biblioteca modbus slave com o arduino. Porém surgiu uma questão, não sei se é um bug do ScadaBR ou mesmo um problema entre a cadeira e o declado, rs.

Eis a questão:

Estou usando o serial nativo do arduino com uma biblioteca modbus RTU para se comunicar com o ScadaBR. O arduino comunica com o scadabr e o led acende e apaga perfeitamente com esse Script:

#include <ModbusSlave.h>
/* First step MBS: create an instance /
ModbusSlave mbs;
/
slave registers /
enum {
MB_REG0,
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 asdf=1;
int regs[MB_REGS];
int ledPin = 13;
void setup()
{
/
the Modbus slave configuration parameters /
const unsigned char SLAVE = 1;
const long BAUD = 9600;
const char PARITY = ‘n’;
const char TXENPIN = 1;
/
Second step MBS: configure /
mbs.configure(SLAVE,BAUD,PARITY,TXENPIN);
pinMode(ledPin, OUTPUT);
pinMode(2,INPUT);
}
void loop()
{
asdf=digitalRead(2);
regs[MB_REG0]=asdf;
/
Third and las step MBS: update in loop*/
mbs.update(regs, MB_REGS);
if(regs[MB_CTRL]==1)
{
digitalWrite(ledPin,1);
}
else{
digitalWrite(ledPin,0);
}
}


Até aí ele acende e apaga normalmente.
Porém, quando eu modifico o script dessa forma:

if(regs[MB_CTRL]==1)
{
digitalWrite(ledPin,1);
delay(3000);
digitalWrite(ledPin,0);
delay(3000);
}
else{
digitalWrite(ledPin,0);
}
}

Inicialmente, no watch list mostra normalmente o datapoint, mas, quando eu seto o bit ele entra
no loop e não aceita o “0”, além de mostrar a mensagem “Valor do ponto pode não ser confiável”.

Como se o serial travasse, sei lá.

Você já tentou usar Modbus serial nas tuas aplicações?

Olá,

Utilizamos bastante o Modbus aqui, tanto modelos comerciais (CLP´s, IO´s), como com o Arduino.

Notei que você utiliza um delay de 6s num loop. Quanto é a sua taxa de aquisição no ScadaBR?

A escrita de pontos é feita de modo assincrono, assim, o Arduino vai receber os dados somente na próxima iteração (se não estou enganado). Como o Arduino não é multithread, e ainda não implementamos algo na interrupção da serial, fica meio complicado garantir que ele não vá se perder na comunicação.

Recomendo 2 testes: diminuir o tempo total do loop, e/ou aumentar o intervalo de aquisição.

Veja se ele ainda vai informar que o dado não é confiável… Ainda temos que melhorar a comunicação Modbus do Arduino. Acredito que isso seja um esforço colaborativo, mas que aos poucos podemos chegar numa solução robusta para aplicações de pequeno porte =]

Abs e boa sorte

Grande Diego,

Atendendo teu posto e dica, setei o delay de 1000 ms e o Offset 4000 ms. E isso deu certo, pelo menos a mensagem realmente sumiu. Mas cara, o bendito loop, sinceramente não entendi. Já tentei usar o while, if/else e o switch case, e nada. Estou bem preocupado, pois o trabalho que quero fazer ele terá que se comunicar e controlar 3 sensores iguais a esse, 3 valvulas solenoides e um motor.

O uC tem dois estágios - Setup e Loop

Setup, o nome diz tudo, inicialização.

No Loop, vc configura o que ele vai realizar de tempo em tempo (tempo geral de execução)
Quando disse que tinhas um delay de 6s no loop <- esse loop é o ciclo de execução =]

então não precisa de while, for, etc… é só confiar que o a cada ciclo de execução vc leia os sensores e controle os motores e valvulas, garantir que o ciclo seja bem menor que a taxa de aquisição e utilizar as escritas via modbus como setpoints.

Até

Entendo Diego,

Mas e no caso de um efeito Blink? O loop do sketch não é suficiente, tem que colocar ele em uma condição. Até pq o sensor emite pulsos em microsegundos, e no caso eu enviaria um comando “ler sensor de nível” e outro para sair da leitura, e o problema está sendo essa saída, é como se ele entrasse na condição e não obedecesse a mudança do parâmetro.

Tudo bem, desde que o evento de blink ocorra num período inferior ao de aquisição.

Eu não estou conseguindo enxergar de forma clara teu problema… desenha ai pra gente =]

Abs

Olá Diego,

Tudo belezinha?

Então, abaixo segue script. Hoje de manhã consegui sincronizar o sensor ultrassonico com o scadabr, precisão perfeita!! Porém, segue abaixo a minha dúvida:

#include “Ultrasonic.h”
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo
//iniciando a função e passando os pinos
Ultrasonic ultrasonic(12,13);

void configure_mb_slave(long baud, char parity, char txenpin);
int update_mb_slave(unsigned char slave, int regs,
unsigned int regs_size);
/
Modbus RTU common parameters, the Master MUST use the same parameters /
enum {
MB_SLAVE = 1, /
modbus slave id /
};
/
slave registers example /
enum {
MB_REG0, /
Condição para LER sensor /
MB_REG1, /
Leitura da distancia /
MB_REGS /
total number of registers on slave */
};

int regs[MB_REGS]; /* this is the slave’s modbus data map */

void setup()
{
/* Modbus setup example, the master must use the same COM parameters /
/
115200 bps, 8N1, two-device network */
configure_mb_slave(115200, ‘n’, 0);
pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
}

void loop()
{
/* This is all for the Modbus slave */
update_mb_slave(MB_SLAVE, regs, MB_REGS);
if(regs[MB_REG0] == 1)
{
//seta o pino 12 com um pulso baixo “LOW” ou desligado ou ainda 0
digitalWrite(trigPin, LOW);
// delay de 2 microssegundos
delayMicroseconds(2);
//seta o pino 12 com pulso alto “HIGH” ou ligado ou ainda 1
digitalWrite(trigPin, HIGH);
//delay de 10 microssegundos
delayMicroseconds(10);
//seta o pino 12 com pulso baixo novamente
digitalWrite(trigPin, LOW);
// função Ranging, faz a conversão do tempo de
//resposta do echo em centimetros, e armazena
//na variavel distancia
int distancia = (ultrasonic.Ranging(CM));

regs[MB_REG1] = distancia;

delay(1000); //espera 1 segundo para fazer a leitura novamente
}
else{
regs[MB_REG1]==0;
}

}

Como você pode ver ao obedecer a primeira condição, entra-se em um IF, para mandar os pulsos do sensor (por esse motivo que eu estava falando do blink, era apenas uma analogia).

Enfim, ele entra no IF e quando seto o 0 pelo scadabr ele simplesmente não obedece. E com certeza não é biblioteca, já testei com todas existentes e o problema permanece.

Estou usando o serial nativo do arduino.

Bem, espero que possa me ajudar.

Obrigado

abço

Olá Relri,

Da uma conferida no teu else:

“MB_REG1 == 0”

Não é isso? revisei o resto e não vi nada de estranho.

Abs

O pior é que não é,rs. Continua não conseguindo atribuir o valor “0”. Mas tá valendo a correção, realmente, dei a rateada.

Galera,
Enfim, consegui!
Para quem não acompanhou o sufoco, leia os posts anteriores. O perrengue foi ao sincronizar um sensor ultrassônico com o scadabr (usando a biblioteca Modbus RTU). Enfim, resumo da opera, reduzi o baud rate, retirei os delays do script, através de um script que encontrei na internet para esse modelo e pronto…UFAAA…

Abraço e obrigado a todos que cooperaram. Fica aí o scrípt para quem quiser usar ao sincronizar esse sensor.

#include “Ultrasonic.h”
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo
//iniciando a função e passando os pinos
Ultrasonic sensor(12,13);
void configure_mb_slave(long baud, char parity, char txenpin);
int update_mb_slave(unsigned char slave, int *regs,
unsigned int regs_size);

/* Modbus RTU common parameters, the Master MUST use the same parameters /
enum {
MB_SLAVE = 1, /
modbus slave id /
};
/
slave registers example /
enum {
MB_REG0, /
Condição para LER sensor /
MB_REG1, /
Leitura da distancia /
MB_REGS /
total number of registers on slave /
};
int regs[MB_REGS]; /
this is the slave’s modbus data map */
int distancia;

void setup()
{
/* Modbus setup example, the master must use the same COM parameters /
/
9600 bps, 8N1, two-device network */
configure_mb_slave(9600, ‘n’, 0);
pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
}

void loop()
{
/* This is all for the Modbus slave */
update_mb_slave(MB_SLAVE, regs, MB_REGS);

if(regs[MB_REG0] == 1)
{
distancia = sensor.Ranging ( CM );
regs[MB_REG1]=distancia;
delay(30); //Esse delay é fundamental, achei ele na tentativa e erro.
}
else{
regs[MB_REG1]=regs[MB_REG1];
}

}

Galera,
Enfim, consegui!
Para quem não acompanhou o sufoco, leia os posts anteriores. O perrengue foi ao sincronizar um sensor ultrassônico com o scadabr (usando a biblioteca Modbus RTU). Enfim, resumo da opera, reduzi o baud rate, retirei os delays do script, através de um script que encontrei na internet para esse modelo e pronto…UFAAA…

Abraço e obrigado a todos que cooperaram. Fica aí o scrípt para quem quiser usar ao sincronizar esse sensor.

#include “Ultrasonic.h”
#define echoPin 13 //Pino 13 recebe o pulso do echo
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo
//iniciando a função e passando os pinos
Ultrasonic sensor(12,13);
void configure_mb_slave(long baud, char parity, char txenpin);
int update_mb_slave(unsigned char slave, int *regs,
unsigned int regs_size);

/* Modbus RTU common parameters, the Master MUST use the same parameters /
enum {
MB_SLAVE = 1, /
modbus slave id /
};
/
slave registers example /
enum {
MB_REG0, /
Condição para LER sensor /
MB_REG1, /
Leitura da distancia /
MB_REGS /
total number of registers on slave /
};
int regs[MB_REGS]; /
this is the slave’s modbus data map */
int distancia;

void setup()
{
/* Modbus setup example, the master must use the same COM parameters /
/
9600 bps, 8N1, two-device network */
configure_mb_slave(9600, ‘n’, 0);
pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)
pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)
}

void loop()
{
/* This is all for the Modbus slave */
update_mb_slave(MB_SLAVE, regs, MB_REGS);

if(regs[MB_REG0] == 1)
{
distancia = sensor.Ranging ( CM );
regs[MB_REG1]=distancia;
delay(30); //Esse delay é fundamental, achei ele na tentativa e erro.
}
else{
regs[MB_REG1]=regs[MB_REG1];
}

}

Show de bola Relri,

Ficamos felizes em saber que deu certo… Eu já to pensando em usar esse sensor para outras aplicações, e com certeza tua experiência foi interessante pra gente.

Abraços e que venham os próximos projetos!

Diego, quando eu terminar o projeto postarei aqui para apreciação.
O maior desafio vem agora, instalar os outros instrumentos.

Abraço… qualquer coisa, estamos aí!

Amigo,
Você poderia fazer o screenshoot do datasource? Não consegui configura-lo. Obrigado!

Com certeza cara, porém preciso da sua ajuda. Simplesmente não consigo inserir nenhuma imagem.

Aguardo, caso vc saiba.

Abç

Opa, muito obrigado.
Você pode fazer o screnshoot e enivar a imagem para http://www.freeimagehosting.net/.
Depois basta copiar o endereço image Link aqui.
Veleu!

http://www.freeimagehosting.net/maktr

O outro ponto criei um binário comum.

Qualquer coisa estamos na área…

sucesso.

Olá tentei rodar seu código e tive alguns problemas tem me dado erro Ranging ( CM ); … tentei varias bibliotecas e não consegui solucionar o problema … vc tem como disponibilizar a biblioteca ou o arquivo do seu código