Modbus RTU, Sensor ultrassonico, ScadaBR

Fala Galera,

Tudo belezinha?

Então, abaixo segue script. Sincronizei um 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ês podem ver ao obedecer a primeira condição, entra-se em um IF, para mandar os pulsos do sensor.

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 possam me ajudar e com certeza outros que estejam se aventurando no ScadaBR.

Obrigado

Aquele delay(1000) pode explicar muita coisa...

Bubulindo,

Uai, então se eu for usar o Modbus RTU não poderei usar Delay dentro do loop?

Sempre que usas delay() o programa para durante o tempo que indicaste no delay. Durante essa paragem algo pode acontecer (como enviares um valor pelo SCADA) que pode não ser lido (porque o programa está parado).

Existe algum motivo para que pretendas parar o programa por 1 segundo?

Esse delay existe para pequenos intervalos de alguns milisegundos, não para esperar segundos. Altera o programa e tira esse delay e vê o que resulta. Pode ser que funcione. Mesmo que não seja esse o problema, não usares delay é uma boa prática de programação.

Então Bubulindo

Esse um segundo, o script do sensor ultrassônico que estou usando solicita para poder ler novamente. Caso eu tire ele fica muito "louco", medidas totalmente incertas.

O que resolveu um pouco o problema, ou seja, ele conseguiu sair do loop, foi reduzir o delay. Mesmo assim a precisão reduz drasticamente.
Não sei o que acontece, provavelmente a biblioteca do modbus deve solicitar um tempo semelhante e ele deve conflitar nesse momento.

Vc já usou essa biblioteca antes?

Eu não compreendi completamente o problema... mas porque não fazes algo deste género:

unsigned long agora = 0, antes = 0; 


void loop()
{
        /* This is all for the Modbus slave */

   update_mb_slave(MB_SLAVE, regs, MB_REGS);
   agora = millis(); 
if(regs[MB_REG0] == 1 && ((agora - antes) >=1000))
   {
   //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;
   // O DELAY ESTAVA AQUI
   antes = millis();
   }
   else{
     regs[MB_REG1]==0;
   }
}

Isto evita que tenhas problemas com o programa parado e esta parte só é executada de segundo a segundo.
Experimenta se é isso que pretendes.

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..

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

BUBULINDO, obrigado cara, teus posts deram uma grande luz!!! :slight_smile:

}

É para isso que cá estamos. :slight_smile: