RS-485(Automatically)

Hello @ashok.tx Sir,

Regards: RS-485 in Colibri VF50.

I want to know how to implement RS-485(Automatically) in Colibri(VF50) .
Response ASAP please.

H/W -Colibri VF50.
OS- Linux
Tool- Eclipse.

Hi @Mohd

Welcome to toradex community.

I want to know how to implement RS-485(Automatically) in Colibri(VF50).

What exactly does it mean? enabling rs485 from devicetree? if yes, Please have a look at this article.

Sample code and reference
https://community.toradex.com/t/how-to-define-rs485-in-device-tree/4710/4

I already enable RS-485 .

/* Enable RS485 mode: */
    rs485conf.flags |= SER_RS485_ENABLED;

    /* or, set logical level for RTS pin equal to 0 when sending: */
    rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);

    /* Set logical level for RTS pin equal to 1 after sending: */
    rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;

    /* Enable receiver during sending, required for i.MX devices */
    rs485conf.flags |= SER_RS485_RX_DURING_TX;

But I dont understand how to enable it in the device tree by setting linux,rs485-enabled-at-boot-time , rs485-rts-active-low and rs485-rx-during-tx property.

How to change in this structure?

&uart2 {
    status = "okay";
    linux,rs485-enabled-at-boot-time;
    rs485-rts-active-low;
    rs485-rx-during-tx;
}

In which file it is located?

I don’t want to enable Receiver while Transmitting.
I trying to implement RS-485 in HALF DUPLEX mode.

My ticket number for this request is: Ticket#2022062210000129

Hi @Mohd

Have you seen this reference link?
There are two ways to enable Rs485 communication. One is from Devicetree and the other is from userspace.

In which file it is located?

Clone the Linux kernel and alter the Devicetree file arch/arm/boot/dts/vf-colibri.dtsi,build and update to existing Linux image.

For building and updating the device tree, please have a look at this article

I already used user space way to enable Rs485 communication.
Please check my UART2 initialization code where I do mistake?

int Uart2CommInit()
{
    /*------------------------------- Opening the Serial Port -------------------------------*/
										/* ttyUSB0 is the FT232 based USB2SERIAL Converter   */
										/* O_RDWR Read/Write access to serial port           */
										/* O_NOCTTY - No terminal will control the process   */
										/* O_NDELAY -Non Blocking Mode,Does not care about-  */
										/* -the status of DCD line,Open() returns immediatly */
	memset(&rs485conf, 0, sizeof(struct serial_rs485));

	uart2FD = open("/dev/ttyLP2",O_RDWR | O_NOCTTY | O_NDELAY);
	if(uart2FD == -1)
	{
		printf("Error! in Opening ttyUART 2  \r");
		return -1;
	}
	if (ioctl (uart2FD, TIOCGRS485, &rs485conf) < 0)
	{
			/* Error handling. See errno. */
		printf("ERROR ! in Setting attributes ttyUART 2\r\n");
	}
	/* Enable RS485 mode: */
	rs485conf.flags |= SER_RS485_ENABLED;

	/* Set logical level for RTS pin equal to 1 when sending: */
	rs485conf.flags |= SER_RS485_RTS_ON_SEND;
	/* Set logical level for RTS pin equal to 1 after sending: */
	rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
	/* Set rts delay before send, if needed: */
	rs485conf.delay_rts_before_send = 100;
	/* Set rts delay after send, if needed: */
	rs485conf.delay_rts_after_send = 100;

	/*---------- Setting the Attributes of the serial port using termios structure --------- */

	tcgetattr(uart2FD, &SerialPortSettings);    /* Get the current attributes of the Serial port */

	cfmakeraw(&SerialPortSettings);
	SerialPortSettings.c_cflag &= ~PARENB;   /* Disables the Parity Enable bit(PARENB),So No Parity   */
	SerialPortSettings.c_cflag &= ~CSTOPB;   /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
	SerialPortSettings.c_cflag &= ~CSIZE;     /* Clears the mask for setting the data size             */
	SerialPortSettings.c_cflag |=  CS8;      /* Set the data bits = 8                                 */
	SerialPortSettings.c_cflag &= ~CRTSCTS;       /* No Hardware flow Control                         */
	SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines       */
	SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  /* Non Cannonical mode             */
	SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);          /* Disable XON/XOFF flow control both i/p and o/p */
	SerialPortSettings.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
	SerialPortSettings.c_oflag &= ~OPOST; /*No Output Processing*/
	SerialPortSettings.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
	SerialPortSettings.c_cc[VTIME] = 100;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
	SerialPortSettings.c_cc[VMIN] = 0;

	cfsetispeed(&SerialPortSettings,B115200); /* Set Read  Speed as B115200        B230400               */
	cfsetospeed(&SerialPortSettings,B115200); /* Set Write Speed as B115200                       */

	if((tcsetattr(uart2FD, TCSANOW, &SerialPortSettings)) != 0)
	{ /* Set the attributes to the termios structure*/
		printf("ERROR ! in Setting attributes ttyUART 2\r\n");
		return -2;
	}
	else
	{
		//printf("\n  BaudRate = 19200 \n  StopBits = 1 \n  Parity   = none\n");
	}
	tcflush(uart2FD, TCIFLUSH);
	tcflush(uart2FD, TCOFLUSH);
	return 0;
}

My uart2 is working fine without RS485.
For RS485 I only use UART2 (Tx, Rx and RTS ) Pins .
Please tell me what should I do next ?

In your init code, you need to write the rs485conf structure changes using the ioctl:
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
printf(“Error: TIOCSRS485 ioctl not supported.\n”);
}
That was in the link provided by ashok.

Your init code also shouldn’t be setting both SER_RS485_RTS_ON_SEND and SER_RS485_RTS_AFTER_SEND. You’ll need to set one or the other depending on your circuit.

Look around for some more example code concerning rs485 setup and use…there should be examples out there you can reference.

Hello Dave,

Thanks for your response.

Please look into the image below.

image.png

Which PINS are used for RS485 interfacing with the Colibri VF50 module?

Currently I am using only 3 Pins of UARTB(Rx,Tx & RTS).

Please find the attachment and check my code once again .

I don’t understand why the code is not working?
UART_RS485.txt (4.0 KB)

Now my code is working with RS485 but facing data loss issue .
UART_RS485.txt (4.7 KB)

What does “data loss issue” exactly mean? You’re trying to transmit a large amount and only a small amount is received? You’re trying to receive a large amount and only a small amount is received? There are gaps in the middle of either the tx or rx data?

Since you’re using rs485 tx/rx control, you don’t need the SerialPortSettings.c_cflag &= ~CRTSCTS. I doubt that’s causing any problems, but it’s just not right.

You’re setting the VTIME piece of your serial port settings to 10 seconds (100)? That seems a bit large. You should read Understanding UNIX termios VMIN and VTIME.

I don’t know why you’re using tcflush before every write and read?

You really need to think about your system i/o design and set your timing parameters up to work that way.

Hello Dave,

Thanks for your response.
My code is stuck while performing read() operation if data is not available to read.
That’s why setting the VTIME piece of your serial port settings to 10 seconds.
Yes I am trying to transmit a large amount(1500 bytes+) and only a small amount is received and also trying to receive a large amount and only a small amount is received.
Yes gaps in the middle of either the tx or rx data is 1000 mili seconds(1 sec) on both ends(Colibri VF50 and PC(USR TCP));

	while(1)
	{
		memset(RecvBuff,0,sizeof(RecvBuff));
		WriteToUart2(buff, sizeof(buff));
		usleep(1000000); //1000 mili seconds
//		usleep(100000); //100 mili seconds

		ReadFromUart2(RecvBuff, sizeof(buff));
//		sleep(1);

		printf("Response : %s\r\n", RecvBuff);
		memset(RecvBuff,0,1500);
//		sleep(1);

	}

Thanks yes you are right no need to use SerialPortSettings.c_cflag &= ~CRTSCTS .
I am not using this right now.
Now you please look into my code.
UART_RS485.txt (4.6 KB)

@ritesh.tx
please look into this sir.

Can you move the baud rate down to something very slow and see if the problem persists?

Do you have DMA enabled in the device tree for that board?

I assume you’ll have to describe what kernel version you’re using, etc. in order for the toradex folks to come to your aid.

Maybe you can step back to using a development board and connecting 2 serial ports together via rs232 and getting your code working first on the linux platform only? Then move to rs485 and then to connecting to an external machine?

Hello Dave,

I will do test on low baud rate?

In past we are using UART on RS232 which are working.
But now need to implement RS485 on Half duplex Mode.
I have no idea how to check DMA mode is enable or disable?
Please look into the attached image for my Toradex VF50 kernel version.

Data loss means is :
■:When I trying to receive a large amount of data example.
DATA[1500] = {“ABCD…XYZ”};

I received total 1500 bytes but data is

{YZABCD…X}

I hope this example helps you for understanding.

I would think the YZ at the beginning of the received data is actually that last 2 bytes sent from the other side during the previous transmission. When you first start your applications, just do a single transfer of data from the pc side to the linux side without doing any writes from the linux side and see what u get. If you only get 1498 bytes, then the pc side is turning RTS off too soon. Btw, rs485 usb modules are notoriously bad when using windows. You might need to get the scope out to look at the RTS line timing.

Hi @Mohd

Is dose @DaveM’s Answer helpful? did you test it?

Thanks, @DaveM.

Hello Dave,
Single transfer of data are working both side.
And also test with different different baud rate but not working.

On PC side I transmit a packet after 1000 ms interval and receive packet successfully.
On Linux side I transmit a packet and give 1000 ms delay after transmission and then call a receive function.(Received complete bytes but data is not in sequence).