modbus_read_registers - ERROR conexión expiró

0

Estamos utilizando la biblioteca libmodbus para leer los valores de registro del medidor de energía EM6400 que admite Modbus sobre RTU. Estamos enfrentando los siguientes dos problemas.

1) Estamos enfrentando un problema con Modbus_read_registers API, esta API devuelve -1 y el mensaje de error es "ERROR Connection tim out out: select". Después de depurar la biblioteca, encontramos que este problema se debe al eco de los bytes de solicitud en el mensaje de respuesta. La llamada a la API read () en _modbus_rtu_recv devuelve los bytes de solicitud primero seguidos por los bytes de respuesta. Como resultado, length_to_read se calcula en compute_data_length_after_meta () en función de los bytes de solicitud en lugar de los bytes de respuesta (que contienen el número de bytes leídos) y se produce un problema de tiempo de espera de conexión. Intentamos utilizar las versiones de libmodbus 3.0.6 y 3.1.2, pero ocurre lo mismo en ambas versiones.

2) modbus_rtu_set_serial_mode (ctx, MODBUS_RTU_RS485) devuelve ‘BAD file descriptor’.

Por favor, confirme si falta alguna llamada a la API o si algún parámetro no está configurado correctamente. Por favor, sugiera cualquier puntero para resolver estos problemas.

Nuestro código de muestra para leer el valor de registro es el siguiente.

int main()
{
    modbus_t *ctx;
    uint16_t tab_reg[2] = {0,0};
    float avgVLL = -1;;
    // EMValue *pemVal = new EMValue;
    int res = 0;
    int rc;
    int i;
    struct timeval response_timeout;
    uint32_t tv_sec = 0;
    uint32_t tv_usec = 0;
    response_timeout.tv_sec = 5;
    response_timeout.tv_usec = 0;

    ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'E', 8, 1);
    if (NULL == ctx)
    {
                    printf("Unable to create libmodbus context\n");
                    res = 1;
    }
    else
    {
        printf("created libmodbus context\n");
        modbus_set_debug(ctx, TRUE);
        //modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK |MODBUS_ERROR_RECOVERY_PROTOCOL);
        rc = modbus_set_slave(ctx, 1);
        printf("modbus_set_slave return: %d\n",rc);
        if (rc != 0)
        {
            printf("modbus_set_slave: %s \n",modbus_strerror(errno));
        }

        /* Commented - Giving 'Bad File Descriptor' issue
        rc = modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
        printf("modbus_rtu_set_serial_mode: %d \n",rc);

        if (rc != 0)
        {
            printf("modbus_rtu_set_serial_mode: %s \n",modbus_strerror(errno));
        }
        */

        // This code is for version 3.0.6
        modbus_get_response_timeout(ctx, &response_timeout); 
        printf("Default response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );

        response_timeout.tv_sec = 60;
        response_timeout.tv_usec = 0;

        modbus_set_response_timeout(ctx, &response_timeout); 
        modbus_get_response_timeout(ctx, &response_timeout); 
        printf("Set response timeout:%ld sec %ld usec \n", response_timeout.tv_sec, response_timeout.tv_usec );


        /* This code is for version 3.1.2
        modbus_get_response_timeout(ctx, &tv_sec, &tv_usec); 
        printf("Default response timeout:%d sec %d usec \n",tv_sec,tv_usec );

        tv_sec = 60;
        tv_usec = 0;

        modbus_set_response_timeout(ctx, tv_sec,tv_usec); 
        modbus_get_response_timeout(ctx, &tv_sec, &tv_usec); 
        printf("Set response timeout:%d sec %d usec \n",tv_sec,tv_usec );
        */

        rc = modbus_connect(ctx);
        printf("modbus_connect: %d \n",rc);

        if (rc == -1) {
            printf("Connection failed: %s\n", modbus_strerror(errno));
            res = 1;
        }

        rc = modbus_read_registers(ctx, 3908, 2, tab_reg);
        printf("modbus_read_registers: %d \n",rc);

        if (rc == -1) {
            printf("Read registers failed:  %s\n", modbus_strerror(errno));
            res = 1;
        }

        for (i=0; i < 2; i++) {
            printf("reg[%d]=%d (0x%X)\n", i, tab_reg[i], tab_reg[i]);
        }

        avgVLL = modbus_get_float(tab_reg);

        printf("Average Line to Line Voltage = %f\n", avgVLL);

        modbus_close(ctx);
        modbus_free(ctx);
    }
}



Output of this sample is as follows:
created libmodbus context
modbus_set_slave return: 0
modbus_rtu_set_serial_mode: -1 
modbus_rtu_set_serial_mode: Bad file descriptor 
Default response timeout:0 sec 500000 usec 
Set response timeout:60 sec 0 usec 
Opening /dev/ttyUSB0 at 19200 bauds (E, 8, 1)
modbus_connect: 0 
[01][03][0F][44][00][02][87][0A]
Waiting for a confirmation...
ERROR Connection timed out: select
<01><03><0F><44><00><02><87><0A><01><03><04><C4><5F><43><D4><C6><7E>modbus_read_registers: -1 
Read registers failed:  Connection timed out
reg[0]=0 (0x0)
reg[1]=0 (0x0)
Average Line to Line Voltage = 0.000000
    
pregunta Singhal

2 respuestas

1

Supongo que algo está mal con la conexión, me refiero al hardware de RS485 o el controlador del dispositivo. No debe recibir mientras transmite, esto se hace con el pin RTS y el interruptor electrónico dentro del transceptor rs485. También el puerto utilizará halfduplex. Rastrear cómo la señal de TX llega a RX.

    
respondido por el Marko Buršič
1

"Descriptor de archivo incorrecto" no es uno de los valores de retorno para la función modbus_rtu_set_serial_mode (consulte aquí ). Es un error devuelto por ioctl () y probablemente indica que no tiene los privilegios adecuados para modificar las comunicaciones en / dev / ttyUSB0. Como eso sucede, todas las llamadas a los registros de lectura / escritura tendrán un tiempo de espera debido a que el modo es incorrecto y su esclavo modbus no puede interpretar los comandos o dar una respuesta adecuada. Asegúrese de tener acceso a / dev / ttyUSB0 y, de no ser así, cambie los permisos en el sistema de archivos o ejecute su programa como usuario con el acceso adecuado a / dev / ttyUSB0.

    
respondido por el Cheibriados

Lea otras preguntas en las etiquetas