Search code examples
cavratmegars485

Cannot establish proper RS485 communication


I was trying serial communication using ATmega32. First i used RS232, using USB-to-RS232 to establish receive and transmit using serial terminal(in my case tera term). Whatever i send from serial terminal Atmega32 echo it back.

for eg. i send Hello\r and i receive 'Hello\r'

It is working fine.

Then i used RS485, using USB-to-RS485 to establish communication with ATmega32 but i only get 1st character in return.

for eg. if i send Hello i get back H. if i send planets i get only p in return.

Here is the code:

void Delay(int ms)
{
    int i;
    for (i=0;i<ms;i++)
    _delay_ms(1);

}

void UART_Init(unsigned int baud)
{
    UBRRH = (unsigned char)(baud >> 8);
    UBRRL = (unsigned char)baud;

    UCSRB = (1<<RXEN)  | (1<<TXEN) | (1<<RXCIE);
    UCSRC = (1<<URSEL) | (3<<UCSZ0);
}

void UART_Transmit(unsigned char data)
{
    UDR = data;
    while ( !( UCSRA & (1<<UDRE) ) );
}


void USART_Transmit_String( char *string)
{
    while (*string != 0)
    UART_Transmit(*string++);
}


void Clear_Buffer(char *string)
{
    while (*string != '\0')
    {
        *string = 0;
        string++;
    }
}

ISR(USART_RXC_vect)
{
    uartBuff[datapos] = UDR;
    if (uartBuff[datapos] == '\r')
    {
        eos = 1;
    }
    datapos++;
    if (datapos > SIZE)
    {
        datapos = 0;
        Clear_Buffer(uartBuff);
    }
}

int main(void)
{
    _delay_ms(1000);
    UART_Init(103);
    sei();
    LED_Enable();
    LED_High();
    Delay(100);
    LED_Low();
    Delay(100);

    RE_DE_Enable();
    RE_DE_High();
    USART_Transmit_String("Hello World");
    UART_Transmit(0x0d);
    UART_Transmit('\n');
    Delay(1000);
    datapos = 0;
    eos = 0;
    RE_DE_Low();
    while (1) 
    {
        if (strstr(uartBuff,"led on\r"))
        {
            LED_High();
        }
        if (strstr(uartBuff,"led off\r"))
        {
            LED_Low();
        }

        if (eos == 1)
        {
            RE_DE_High();
            uartBuff[datapos] = '\0';
            USART_Transmit_String("\r\n");
            USART_Transmit_String(uartBuff);
            USART_Transmit_String("\r\n");
            Clear_Buffer(uartBuff);
            datapos = 0;
            eos = 0;
            RE_DE_Low();
        }

    }
}

Why this type of abnormality?

How to rectify this error?

Any suggestions will be helpful.

Thanks in advance


Solution

  • Getting a bit confused on who is transmitting what in reviewing this post so have the following comments:

    1) simplify the Atmel code to only stream out "Hello World %d" + CR and keep incrementing the line #. For now, keep com speed @ 9600 baud. Does this traffic from the Atmel to the USB RS485 dongle get received with 100% success? Do not continue till this does.

    2) Which RS485 transceiver are you using in this design for the Atmel side? There is a lot of garbage on the market and not all transceivers are created equal.

    3) Which USB RS485 dongle are you using? As per (2), only few are reliable. If using the clear FTDI USB RS485 dongle then review very carefully on which RS485 transceiver is embossed inside the plastic. FTDI has admitted they put out some flaky dongle cables based on the Sipex transceiver. From our brief review, believe the design was at fault and not the transceiver. However, regardless, now that the dongle is sealed, the same buggy dongle cannot be corrected.

    We build some solid adapters but do not wish to turn this into an ad so let us see if we can debug your case. Post more details to continue.

    Wish to add that on your RS485 receiver pin, be sure there is a local pull-up resistor to +3v3. This is required to have a high state on the Atmel receive of the UART when the RS485 receiver is DISABLED. That is, when the RS485 receiver is disabled, the RX pin is high-z. A value of 10k is known to be good and the value is not critical but the pull-up is recommended.

    Update

    I think I understand the point of view of your project. Please correct if I am wrong. Are you attempting to use Teraterm + USB RS485 dongle to send out text to the Atmel over RS485 and wish to have the Atmel send back the data to your Teraterm? If yes, then the results are logical if you are typing this data in Teraterm. Please confirm this setup.

    That is, are you typing "Hello world" and expecting to receive this text back?

    The issue with this idea is that the PC is sending out the data faster than you can type. Instead, review on how you can use Teraterm to send out in a macro form the entire string in a block. Only this method will work for your idea. When you are typing, Teraterm is sending out (aka flushing the tx buffer) the "H" over the RS485 interface, etc. so you will not receive the entire string in a single block receive.

    Consider a macro with Teraterm to send out "Planets", etc. in a single send. The key point is not delay between each character that you wish to send.