Crear Variables para ACIMUT SCADA

Saludos a toda la comunidad.
Estoy incursionando en Arduino (utilizo una placa MEGA 2560) y me encuentro con la siguiente dificultad.
Mi intención es crear un voltímetro utilizando el conversor AD y que la lectura del mismo se exprese en el Indicador Analógico del ACIMUT.
Bajé un ejemplo que enciende y apaga un led, el cual funciona.
Ahora bien, la variable del ejemplo (MB_CTRL) funciona y es reconocida por el indicador analógico (si la variable pasa a 1, lo indica), pero no consigo que lo haga con ninguna otra, pese a declararlas en el ACIMUT.
La variable funciona, ya que si su valor lo escribo en un pin PWM, conectando un led varía su brillo en función de la posición del potenciómetro que tengo en la entrada.
Lo mejor que logré fue que la aguja del indicador tomase valores al azar (como si dejásemos flotando los cables del instrumento).
Busqué videos, pero hago lo mismo (o al menos eso creo yo) y no logro hacerlo funcionar.

Dejo pegado el sketch (esta basado en el ejemplo del ACIMUT).

Muchas gracias a todos

/* 		
 Modbus over serial line - RTU Slave Arduino Sketch 
 
 By Juan Pablo Zometa : jpmzometa@gmail.com

/* HERE BEGINS THE EXAMPLE CODE */

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

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

int regs[MB_REGS];
int ledPin = 24;
int ledPin1 = 13;
unsigned long wdog = 0;         /* watchdog */
unsigned long tprev = 0;         /* previous time*/
int i = 0;
int sensorPin = A0;
int AOP = 9;
int V = 0;
int OV = 0;

void setup() 
{
        /* configure modbus communication 
         * 19200 bps, 8N1, two-device network */
        configure_mb_slave(COMM_BPS, PARITY, 0);
        
        pinMode(ledPin, OUTPUT);
        pinMode(ledPin1, OUTPUT);
}


void loop() 
{
        V = analogRead (sensorPin);
        OV = map(V, 0, 1023, 0, 255);
  // change the analog out value:
  analogWrite(AOP, OV);
        /* 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 */
        }        
        
        i = i +1;
        if (i > 10000) i=0;
        regs[2] = i;
        
        /* 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
 ****************************************************************************/

Mira, ACIMUT SCADA te permite trabajar de manera muy cómoda con Holding Register o sea enteros.
Entonces si tienes un valor del tipo float lo conveniente es que determines primero con cuantos decimales quieres expresarlo, y que no sean mas de 2 porque para un voltímetro eso ya es exigente.
Supongamos que fuera 1 y que lees como en el caso del Arduino algo entre 0 y 5V. En ese caso tendrás lecturas del tipo 4.324 V
Como muestras eso usando enteros

float valor = 4.324;

Ahora a ese valor lo multiplicas por 1000 y tendrás 4324, dicho valor es el que compartes con Acimut SCADA y cuando el lo lea claramente verá 4324, pero como Acimut se programa en Visual Basic, con suma facilidad puedes modificar dicho valor y hacer que la variable de presentación muestre el registro modbus / 1000.

En un caso como este, ¿no sería más conveniente enviar directamente el valor del ADC y hacer la conversión en la PC de destino en lugar de solo hacer la división para "restituir" los decimales?
Consulto desde la total ignorancia sobre Acimut SCADA.

Saludos

Si, es lo mismo. tal vez mejor tu idea @gatul, mas simple.

Además se obtendría mayor precisión en los cálculos, creo.

Agradezco las respuestas, pero mi problema es más básico.

Yo estoy cargando la variable con el valor directo del ADC (0 a 1023) y el indicador no marca absolutamente nada.
La única variable que reconoce el MB_CTRL que venía en el ejemplo.
Probé con esa sintaxis (ejemplo MB_VOLT) y nada
Probé con la sintaxis "normal" y nada.
Cambié las formas de declararla en ACIMUT y nada.
El sketch compila, la variable esta presente (lo comprobé colocando ese número en el pin PWM y veo como varía el brillo del led al accionar el potenciómetro.
Cambié por el indicador digital y pasa lo mismo.
Idem con el contador.
Probé con otras variables del ejemplo y tampoco las muestra.
La cuestión de resolución la dejo para más adelante.

No veo error en lo que hice, pero evidentemente esta mal porque solo anda con una variable (la que prende y apaga el led).

No veo error en lo que hice

Nosotros tampoco porque todavía no has subido tu código completo. :grin:

/* 		
 Modbus over serial line - RTU Slave Arduino Sketch 
 
 By Juan Pablo Zometa : jpmzometa@gmail.com
 
        COMM_BPS = 19200, /* baud rate */
        MB_SLAVE = 1,	/* modbus slave id */
        PARITY = 'n' /* even parity */
};

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

int regs[MB_REGS];
int ledPin = 24;
int ledPin1 = 13;
unsigned long wdog = 0;         /* watchdog */
unsigned long tprev = 0;         /* previous time*/
int i = 0;
int sensorPin = A0;
int AOP = 9;
int V = 0;
int OV = 0;
int T = 0;

void setup() 
{
        /* configure modbus communication 
         * 19200 bps, 8N1, two-device network */
        configure_mb_slave(COMM_BPS, PARITY, 0);
        
        pinMode(ledPin, OUTPUT);
        pinMode(ledPin1, OUTPUT);
}


void loop() 
{
        V = analogRead (sensorPin);
        OV = map(V, 0, 1023, 0, 255);
        
        
  // change the analog out value:
  analogWrite(AOP, OV);
        /* 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 */
        }        
        
        i = i +1;
        if (i > 10000) i=0;
        regs[2] = i;
        
        /* 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
 ****************************************************************************/

Acá esta, la variable que pretendo leer es "V"
También probé con leer "OV" y tampoco la reconoce.

Ambas están presentes porque tengo salida en el pin correspondiente de PWM
Falta toda la parte de comunicación que es fija y funciona

He hecho algunas correcciones a tu código, que dicho sea de paso no has modificaco en lo mas mínimo. No se como esperabas que ACIMUT SCADA se enterara de algo?

Primero debes crear una variable y actualizarla cosa que haces de este modo

/* slave registers */
enum {        
        MB_CTRL,        /* Led control on, off or blink */
        MB_TIME,        /* blink time in milliseconds */
        MB_CNT,        /* counter */
        MB_V,              // registro dedicado a transferir el valor a ACIMUT SCADA
        MB_REGS		/* total number of registers on slave */
};

CTRL, TIME, CNT estan pintados, en tu objetivo, asi que puedes eliminarlos y todo lo que el programa tiene tambien pero por ahora los dejo.

  V = analogRead (sensorPin);
  regs[MB_V] = V;         // esto hace que tu registro se actual

Esto actualiza a MB_V para que luego pueda leerse en el SCADA.

En ACIMUT Scada debes crear una variable con este nombre o el nombre que gustes pero que tenga el mismo orden. En este caso observa que

MB_CTRL, // regs[0]
MB_TIME, // regs[1]
MB_CNT,   // regs[2]
MB_V,        // regs[3]

Entonces para Acimut SCADA el Holding Register ira de 0 a 3 y 3 en particular será dirección Modbus de la variable que tiene la información del ADC en entero o sea 0-1023.

Con ello verás que la variable con el nombre que gustes se actualizará.

MUCHÍSIMAS GRACIAS !!!!!!!!!!!!!!!!

Ahora funciona !!!!!

A seguir experimentando y leyendo el foro (y aportando donde pueda, que evidentemente en scada no es... :roll_eyes:)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.