PSOC to PSOC UART Comm

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
CaDu_3933941
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Hi all,

I am working on developing an RC car for which I need a controller and a receiver. This of course means the communication is through radio. The way it works is by sending multiple packets of data between each radio device.

I am sending a total of 10 bytes of data, the first 3 being start bytes being three chars: 's', 't', 'r' which signal the start of the message. The following bytes are anything from the steering angle to the motor speed of the rc car (along with a few other commands).

The problem I am having is the following: I a, sending 10 bytes of data and on the receiver side, everything seems fine, however, sometimes wrong bytes will begin to be written to the wrong byte on the receiver side. For the transmitter, I am using the UART_PutArray() command in order to send multiple bytes, and on the receiver side, I am using an interrupt on each byte received using the handler to unpack the bytes and assign them to the right index o the receiver buffer. Any help on this is appreciated.

I am attaching both projects to this comment..

0 Likes
1 Solution
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

CaDu,

There might be issue with communication protocol.  In your case, Rx port is waiting for the prefix "str", and then it has to count exact number of bytes to elapse (10) or wait for a timeout (if not enough bytes received). This is not very robust and may lead to potential data loss. For example, consider that one byte in the packet has been lost so Rx counts next "str" prefix as a valid byte "s". As a result, the first message will be corrupted, and the second one will get lost (only "tr" remains, which is not valid prefix).

Typically with UART communication, the Rx port waits for a termination character, which indicates the end of the message (typ. 0x0A or 0x0D - 'line feed' or 'carriage return', or both). This immediately signals that some complete command is received and needs to be processed immediately (no timeout or byte count needed). Anything received afterward the termination character belongs to the next message. So the good way for UART control would be to send a packet (does not have to be a fixed length), which looks like this:

prefix, byte1,....byteN, checksum, termination char

You can find example of such UART_Rx here:

Re: UART string reception garbage value

The demo project uses custom circular buffer to receive the data. Once the Termination character is received, it fires the interrupt and starts processing accumulated message. The command prefix is optional, it is indicates that the valid message is received and can carry additional information. I recommend adding a checksum to the message for higher reliability (no checksum used in the demo). Typically a simple sum of all bytes in the message is used as quick check, trimmed to one (least significant) byte.

/odissey1

View solution in original post

5 Replies
NoriTan
Employee
Employee
25 sign-ins 5 questions asked 10 sign-ins

I assumed that your are saying about the "UART" instance in the "RC_receiver" project.

You are setting the RX buffer size to 10 as following snapshot.

GS004763.png

In this case, an internal ISR is defined, a software FIFO is configured, and the received data will be consumed in the internal ISR.

Please try to set the RX buffer size to "4" not to use the internal ISR with the software FIFO.

Regards,

Noriaki

0 Likes

I figured the buffer size had to be bigger than the expected number of bytes.

0 Likes

I still seem to be getting the same error. I made two new test projects with a transmitter sending a basic message and a receiver unpacking the data.

Transmitter:

/* ========================================

*

* Copyright YOUR COMPANY, THE YEAR

* All Rights Reserved

* UNPUBLISHED, LICENSED SOFTWARE.

*

* CONFIDENTIAL AND PROPRIETARY INFORMATION

* WHICH IS THE PROPERTY OF your company.

*

* ========================================

*/

#include "project.h"

#define MSG_LENGTH 8

volatile uint8_t Data_In=0;

uint8_t i=0;

const uint8_t MSG_STR[MSG_LENGTH]={'a', 'b', 'c','d', 'e', 'f', 'g', 'h'};

//CY_ISR(TX_Handler){

//   

//    UART_WriteTxData(MSG_STR);

//    i++;

//    if (i>=MSG_LENGTH) i = 0;

//   

//   

//    TX_ISR_ClearPending();

//   

//   

//}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    UART_Start();

    UART_Terminal_Start();

    TX_ISR_Start();

//    TX_ISR_StartEx(TX_Handler);

    for(;;)

    {

       

        //UART_WriteTxData(3);

        //UART_WriteTxData(4);

//        if(UART_TX_STS_FIFO_EMPTY){

//            UART_PutArray(MSG_STR,4);

//        }

//        if(UART_TX_STS_COMPLETE){

//            UART_WriteTxData(MSG_STR);

//            i++;

//            if (i>=MSG_LENGTH) i = 0;

//            TX_ISR_ClearPending();   

//        }

        UART_PutArray(MSG_STR,4);

        Data_In=UART_ReadRxData();

        UART_Terminal_WriteTxData(Data_In);

    }

}

/* [] END OF FILE */

Receiver:

/* ========================================

*

* Copyright YOUR COMPANY, THE YEAR

* All Rights Reserved

* UNPUBLISHED, LICENSED SOFTWARE.

*

* CONFIDENTIAL AND PROPRIETARY INFORMATION

* WHICH IS THE PROPERTY OF your company.

*

* ========================================

*/

#include "project.h"

#define MSG_LENGTH 8

#define LED_ADDR 0x20

uint8_t a=0;

uint8_t b=0;

uint8_t c=0;

uint8_t d=0;

uint8_t e,f,g,h;

uint8_t I2C_DataWrite[2];

char MSG_In[MSG_LENGTH];

char dummy;

uint8_t buffer;

int i =0;

CY_ISR(RX_Handler){

   

    MSG_In=UART_Radio_GetByte();

    i++;

//    if(MSG_In==a){

//        i=0;

//    }

   

    if(i>= MSG_LENGTH) i = 0;

    RX_ISR_ClearPending();

}

int main(void)

{

    CyGlobalIntEnable; /* Enable global interrupts. */

    UART_Radio_Start();

    RX_ISR_Start();

    I2C_Start();

    I2C_EnableInt();

   

    I2C_DataWrite[0]=0x00;

    I2C_DataWrite[1]=0x00;

   

    I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

    while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

   

    I2C_DataWrite[0]=0x0c;

    I2C_DataWrite[1]=0xFF;

   

    I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

    while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

   

    I2C_DataWrite[0]=0x0d;

    I2C_DataWrite[1]=0xFF;

   

   

  

    RX_ISR_StartEx(RX_Handler);

    for(;;)

    {

       

        a=MSG_In[0];

        b=MSG_In[1];

        c=MSG_In[2];

        d=MSG_In[3];

        e=MSG_In[4];

        f=MSG_In[5];

        g=MSG_In[6];

        h=MSG_In[7];

        if(a=='a'){

            I2C_DataWrite[0]=0x02;

            I2C_DataWrite[1]=0xFF;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        } 

       

        else{

            I2C_DataWrite[0]=0x02;

            I2C_DataWrite[1]=0x00;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        if(b=='b'){

            I2C_DataWrite[0]=0x03;

            I2C_DataWrite[1]=0xFF;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        else{

            I2C_DataWrite[0]=0x0;

            I2C_DataWrite[1]=0x00;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        if(c=='c'){

            I2C_DataWrite[0]=0x04;

            I2C_DataWrite[1]=0xFF;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        else{

            I2C_DataWrite[0]=0x04;

            I2C_DataWrite[1]=0x00;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        if(c=='c'){

            I2C_DataWrite[0]=0x05;

            I2C_DataWrite[1]=0xFF;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        else{

            I2C_DataWrite[0]=0x05;

            I2C_DataWrite[1]=0x00;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

       

        if(UART_Radio_RX_STS_OVERRUN){

            I2C_DataWrite[0]=0x06;

            I2C_DataWrite[1]=0xFF;

               

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

           

           

        }

       

        else{

            I2C_DataWrite[0]=0x06;

            I2C_DataWrite[1]=0x00;

           

            I2C_MasterWriteBuf(LED_ADDR, I2C_DataWrite, 2, I2C_MODE_COMPLETE_XFER);

            while(I2C_MasterStatus()!=I2C_MSTAT_WR_CMPLT);

        }

        UART_Radio_WriteTxData(a);

        buffer = UART_Radio_GetRxBufferSize();

            

    }

}

/* [] END OF FILE */

0 Likes

CaDu,

You indicated that you are waiting for the 's', 't', 'r' sequence to start the data gathering of 7 bytes of data sequence.

What would happen if any of your 7 bytes f data are 's', 't', or 'r'?   Would that force your UART sequence to restart?

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted

CaDu,

There might be issue with communication protocol.  In your case, Rx port is waiting for the prefix "str", and then it has to count exact number of bytes to elapse (10) or wait for a timeout (if not enough bytes received). This is not very robust and may lead to potential data loss. For example, consider that one byte in the packet has been lost so Rx counts next "str" prefix as a valid byte "s". As a result, the first message will be corrupted, and the second one will get lost (only "tr" remains, which is not valid prefix).

Typically with UART communication, the Rx port waits for a termination character, which indicates the end of the message (typ. 0x0A or 0x0D - 'line feed' or 'carriage return', or both). This immediately signals that some complete command is received and needs to be processed immediately (no timeout or byte count needed). Anything received afterward the termination character belongs to the next message. So the good way for UART control would be to send a packet (does not have to be a fixed length), which looks like this:

prefix, byte1,....byteN, checksum, termination char

You can find example of such UART_Rx here:

Re: UART string reception garbage value

The demo project uses custom circular buffer to receive the data. Once the Termination character is received, it fires the interrupt and starts processing accumulated message. The command prefix is optional, it is indicates that the valid message is received and can carry additional information. I recommend adding a checksum to the message for higher reliability (no checksum used in the demo). Typically a simple sum of all bytes in the message is used as quick check, trimmed to one (least significant) byte.

/odissey1