Go Down

Topic: Atmega328p-pu RX "freezing" (Read 1 time) previous topic - next topic

etridas

Hi everyone,

So I have a project where I am communicating with a custom Arduino setup (ala Duemilanove with the FT232R as my UART Communication).  I am using LabVIEW to send messages to the uC via packets 15 bytes long (header byte, ID, four bytes for floating point representation, some extra NULL bytes for future use and finally a checksum).  When sending single packets over the software/firmware work great.  The problem I have is that sometimes I send these packets over in very quick succession.  I noticed that when sending say 5 packets simultaneously I will often freeze the RX of the uC.  My FT232R still tells me that the data is getting there and I still receive feedback messages (i.e. TX is still functioning) but the firmware does not respond to any new packets.

I know that there is a limited buffer size that's defined in the HardwareSerial library.  I've tried increasing this value to no avail.  I did notice that decreasing the baud rate seemed to have an effect on an older computer but when testing with a faster PC the problem persisted.  I'm not sure about the mechanics of the interrupts that are used to handle incoming UART traffic but my thought is that I might just be sending the information over too fast, clogging this up and causing the RX to shut down.

Does anyone have any experience with this or can tell me what my issue might be?

Thanks,

Eric

P.S.  I wasn't sure where to post this but I thought uC's was probably the best place... Mod's move it if necessary.  Thanks :)

strykeroz

Hi Eric

Can you please post your code in CODE tags to share what you've got on the microcontroller side?

Cheers ! Geoff
"There is no problem so bad you can't make it worse" - retired astronaut Chris Hadfield

etridas

We have a function "checkForCommand()" that runs each loop cycle:

Code: [Select]
int checkForCommand(void)
{
  int bufferBytes = Serial.available();
 
  if(bufferBytes >= COMMANDLENGTH)
  {
    // New Command Ready, Process It 
    // Build Command From Serial Buffer
    if (bufferBytes % COMMANDLENGTH == 0)  //checks to see if command is multiple of command length
    {
      for(int i=0; i<COMMANDLENGTH; i++) //if it is, read the bytes into the currentCommand array
      {
        currentCommand[i] = Serial.read();       
      }     
      processCommand(currentCommand); //then process the array and return a 1 indicating successful completion
      return 1;
    }
    else //if it is not a multiple of 15
    {
      for(int i=0; i<Serial.available(); i++) //flush through all of the bytes
      {
        Serial.read(); //by reading through each byte individually and not assigning it to anything
      }
    }
  }
  else
  {
    return 0;
  }
}

strykeroz

Hi

This looks like it would spend a lot of time discarding serial buffer data when the buffer isn't a multiple of commandlength.  As an alternative why not drop out of the function if the buffer is shorter than 15, and then come back and process 15 at a time leaving the remainder in the buffer for next time once you've processed down to less than 15?

As an additional check, is there a known shape to these command strings so you can further verify the 15 bytes are valid?

Geoff
"There is no problem so bad you can't make it worse" - retired astronaut Chris Hadfield

etridas

Hi Geoff,

Thanks for your quick replies.

We actually do drop out of the function if the number of available bytes is less than 15 (I didn't mention that the constant COMMANDLENGTH is 15, I apologize):

Code: [Select]
  if(bufferBytes >= COMMANDLENGTH)
  {
    // New Command Ready, Process It


My initial thought was to do what you suggested by using this if statement and exiting the function until there were at least 15 bytes in the buffer.  I included the flushing of the buffer to ensure that if I received a bad packet that somehow had say 14 bytes that it would just flush completely and ensure that I could read a full 15 byte packet next time we received one.  I suppose that if this function was executed half-way through receiving a packet that we could inadvertently flush part of a good packet... Something I had yet to consider.  Any thoughts on that?

Also, I'm not exactly sure what you mean by "shape" of the command but we do have some validation criteria when we perform the "processCommand" function (the first byte is a "header byte" of value 255 and the last byte is a checksum that is checked in the "checksum_Test" function).  The following is the first few lines of code from the "processCommand" function:

Code: [Select]
// Processes a given command
void processCommand(unsigned char command[])
{
  unsigned char newNumericalObjectStatus[] = {command[5], command[4], command[3], command[2]}; //reverses the order of the byte array so that it can be properly converted from the array to a float
  // Determine Command
  if(command[0] == 0xFF && checksum_Test(command) == 0)
  {
    switch(command[1])
    {
      case 0x00:     // Sync Packet
        Serial.print("sync");
        Serial.flush();     
        isSynced = true;  //sets isSynced flag to true so that commands within main loop will run
        break;


Thanks again,

Eric

strykeroz

Sorry, the word "shape" probably wasn't helpful :)

What you've described though will help you out.  You can do some additional validation in your checkforcommand() by doing a non-invasive inspection of the first character (using peek()) and read & discard until the first character in your serial buffer is a possible "header byte" 255 then continue to process only when you have 15 bytes in the queue.  If you do the validation in the checkforcommand() I'd expect you'll discard fewer good packets (though of course if 255 is valid and frequent data inside a packet that would change things).

Geoff
"There is no problem so bad you can't make it worse" - retired astronaut Chris Hadfield

Go Up