Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request for RTS signal management in Modbus RTU on VxWorks 7 using RS485/Rs422 device and for a patch for _modbus_rtu_send #785

Open
Francy3 opened this issue Jan 8, 2025 · 0 comments

Comments

@Francy3
Copy link

Francy3 commented Jan 8, 2025

libmodbus version

3.1.10

OS and/or distribution

VxWorks 7

Environment

processor 6600HLE; Intel 32-bit

Description

Hello @stephane !

I am using the Modbus RTU protocol from libmodbus 3.1.10 on VxWorks 7.

  1. I need to set the RTS signal on an RS485/RS422 serial device in order to send and receive RTU data.

Unfortunately, the approach provided by the library does not allow for effective control of the RTS signal. After monitoring the RTS signal of the serial port with an oscilloscope, I can confirm that the RTS signal does not change when using flags in the function _modbus_rtu_ioctl_rts. The only way I have observed the RTS value changing is by directly writing to the hardware register of the desired port via a sysOutByte operation.

Could you provide an implementation to handle the RTS signal when using an RS485 device with Modbus RTU without sysOutByte operation?

  1. Request for a single function capable of managing RS422/RS485/RS232 transmission, and removing of echoed transmitted bytes in RS485 as described in this issue

I would like to ask if it is possible to refactor static ssize_t modbus_rtu_send(modbus_t* ctx, const uint8* req, int req_length) in order to handle data transmission in RS485 and RS232/RS422.
Now, _modbus_rtu_send is not complete because it is designed for RS232 transmission only. To support RS485 transmission, I need to modify this method based on a previous patch found here.
Furthermore, I have fixed the handling of RTS enabling/disabling around the write operation to successfully transmit in both RS232/RS422 and RS485.

It would be great if you could integrate the patch from the link and provide a single function for sending RTU data in RS232/RS485/RS422.

Thank you in advance!

Actual behavior if applicable

  1. I need to set the RTS signal on an RS485 serial device in order to send and receive RTU data.
static void _modbus_rtu_ioctl_rts(modbus_t* ctx, int on)
{
 modbus_rtu_t* ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
 
 if (on)
 {
     if(strcmp((const char*)ctx_rtu->device, "/ttyS0") == 0)
     {
         if (ctx->debug)
         {
             printf("enable RTS ttyS0\n");
         }
         sysOutByte(0x3fc, 0xa);
     }
     else if(strcmp((const char*)ctx_rtu->device, "/ttyS1")==0)
     {
         if (ctx->debug)
         {
             printf("enable RTS ttyS1\n");
         }
         sysOutByte(0x2fc, 0xa);
     }
    
 }
 else
 {
     if (strcmp((const char*)ctx_rtu->device, "/ttyS0") == 0)
     {
         if (ctx->debug)
         {
             printf("disable RTS ttyS0\n");
         }    
         sysOutByte(0x3fc, 0x8);
     }
     else if (strcmp((const char*)ctx_rtu->device, "/ttyS1") == 0)
     {
         if (ctx->debug)
         {
             printf("disable RTS ttyS1\n");
         }  
         sysOutByte(0x2fc, 0x8);
     }
    
 }

}

Expected behavior or suggestion

  1. I need to set the RTS signal on an RS485 serial device in order to send and receive RTU data.
    RTS must be enabled every time the master needs to transmit data. Once the master has transmitted, RTS must be disabled to receive the response from the slave.

  2. It would be great a unique function for transmitting data in RS232/RS422/RS485.
    For managing communication in RS485 is necessary the modify proposed here

Steps to reproduce the behavior (commands or source code)

  1. I need to set the RTS signal on an RS485 serial device in order to send and receive RTU data.
static void _modbus_rtu_ioctl_rts(modbus_t* ctx, int on)
{
	printf("modbus_rts_ioctl_rts\n");
	int fd = ctx->s;
	uint flags = 0;
	int nRet = 0;
	
	nRet = ioctl(fd, TIOCMGET, &flags);
	
	printf("ioctl nret = %d, errno %s, getted flags: 0x%X\n", nRet, strerror(errno), flags);
	if (on) {
		flags |= TIOCM_RTS;
	}
	else {
		flags &= ~TIOCM_RTS;
	}
	nRet = ioctl(fd, TIOCMSET, &flags);
	
	if (nRet == -1)
	{
		printf("ioctl Error nRet = %d, errno %s\n", nRet, strerror(errno));
	}
	else
	{
		printf("ioctl nRet = %d, setted flags: 0x%X\n", nRet, flags);
	}
}

  1. Request for a single function capable of managing RS422/RS485/RS232 transmission and removing of echoed transmitted bytes in RS485 as described here
static ssize_t _modbus_rtu_write_n_read(modbus_t* ctx, const uint8_t* req, int req_length)
{
    modbus_rtu_t* ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
    ssize_t w, r, i;
    uint8_t rb[req_length];

    // Transmit
    w = write(ctx->s, req, req_length);

    timespec tNanoSleepAfterWrite = { 0, (ctx_rtu->onebyte_time * req_length + ctx_rtu->rts_delay) * 1000 };
    nanosleep( & tNanoSleepAfterWrite, 0);

    ctx_rtu->set_rts(ctx, ctx_rtu->rts != MODBUS_RTU_RTS_UP);

    // Read back written bytes if hw has echo
    r = 0;
    while (r < w)
    {
        r += read(ctx->s, rb + r, w - r);
    }

    if (ctx->debug)
    {
        for (i = 0; i < r; ++i)
            printf("|%02X|", rb[i]);
        printf("\n");
    }

    return w;
}

static ssize_t _modbus_rtu_send_rs232_rs422(modbus_t* ctx, const uint8* req, int req_length)
{
    modbus_rtu_t* ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
    if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE)
    {
        ssize_t size;
        int nRTS = ctx_rtu->rts == MODBUS_RTU_RTS_UP;
        
	ctx_rtu->set_rts(ctx, nRTS);

        timespec tNanoSleepBeforeWrite = { 0, ctx_rtu->rts_delay * 1000 };
        nanosleep(&tNanoSleepBeforeWrite,0);

        size = write(ctx->s, (char*)req, req_length);

        return size;
    }
    else
    {
        return write(ctx->s, (char*)req, req_length);
    }
}

static ssize_t _modbus_rtu_send_rs485(modbus_t* ctx, const uint8* req, int req_length)
{
    modbus_rtu_t* ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
    if (ctx_rtu->rts != MODBUS_RTU_RTS_NONE)
    {
        ssize_t size;

        int nRTS = ctx_rtu->rts == MODBUS_RTU_RTS_UP;
        ctx_rtu->set_rts(ctx, nRTS);
    
        timespec tNanoSleepBeforeWrite = { 0, ctx_rtu->rts_delay * 1000 };
        nanosleep(&tNanoSleepBeforeWrite,0);
               
        size = _modbus_rtu_write_n_read(ctx, req, req_length);
      
        return size;
    }
    else
    {
        return _modbus_rtu_write_n_read(ctx, req, req_length);
     }
}

libmodbus output with debug mode enabled

  1. I need to set the RTS signal on an RS485 serial device in order to send and receive RTU data.
    In this case the ioctl function return -1 and the errno is ENOTSUP.
@Francy3 Francy3 changed the title Request for RTS signal management in Modbus RTU on VxWorks 7 using RS485 device Request for RTS signal management in Modbus RTU on VxWorks 7 using RS485/Rs422 device and for a patch for _modbus_rtu_send Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant