Thursday, 13 February 2014

Minimizing timing impact of Diagnostic use of Serial.print function in Arduino

While developing routines for my rover, especially diagnostic routines to identify sensor errors or conflicts, I have been using the Serial.print() function.   

I've found it very useful over the past several months. 
However, like all high level functions, it comes at a cost... timing...  

I decided to see how much of a cost, and if there was anything I could do to reduce this cost.  

Here are my results....


This is a typical diagnostic report for my distance ranging module.  There are four Sharp Infrared Distance Sensors (one on each of front/rear/left/right)  and there are two MaxBotix Ultrasound modules on a servo 180 degrees from one another.  In this example, these give me Frontleft, Front, FrontRight, RearRight, Rear, RearLeft.

      Serial.print("StartTime with separate Serial.print statements = "); 
      Serial.println(test=millis()); 

         Serial.print("Front: ");  Serial.print(rangefront[midpoint]); 
         Serial.print("  Rear: ");  Serial.print(rangerear[midpoint]);  
         Serial.print("  Left: ");  Serial.print(rangeleft[midpoint]); 
         Serial.print("  Right: ");  Serial.print(rangeright[midpoint]);

         Serial.print("    Front Sonar: ");  Serial.print(FrontSonar[midpoint]/58); 
         Serial.print("  Rear Sonar: ");  Serial.print(RearSonar[midpoint]/58);  

         Serial.print("FrontLeft: ");  Serial.print(FrontLeft); 
         Serial.print("  FrontRight: ");  Serial.print(FrontRight);  
         Serial.print("  Front: ");  Serial.print(Front); 
         Serial.print("  RearLeft: ");  Serial.print(RearLeft); 
         Serial.print("  RearRight: ");  Serial.print(RearRight);  
         Serial.print("  Rear: ");  Serial.println(Rear); 

      Serial.print("EndTime with separate Serial.print statements = "); 
      Serial.println(millis()-test); 
On an 8Mhz Arduino Pro Mini, this snippit takes 17ms to generate and send this report.

But what if I used string concatenation, and only sent ONE string our Serial like this?
      Serial.print("StartTime with one Serial.print statement and concat strings = "); 
      Serial.println(test=millis()); 
        
         // Assemble the string first, then print it once.
         
         response = "";     // Flush previous message.
         response += "  Front: ";      response += rangefront[midpoint];  
         response += "  Rear: ";     response += rangerear[midpoint]; 
         response += "  Left: ";     response += rangeleft[midpoint];   
         response += "  Right: ";    response += rangeright[midpoint]; 

         response += "  Front Sonar: ";  response += FrontSonar[midpoint]/58; 
         response += "  Rear Sonar: ";  response += RearSonar[midpoint]/58;  

         response += "  FrontLeft: ";  response += FrontLeft; 
         response += "  FrontRight: ";  response += FrontRight;  
         response += "  Front: ";    response += Front; 
         response += "  RearLeft: "; response += RearLeft; 
         response += "  RearRight: ";  response += RearRight;  
         response += "  Rear: ";     response += Rear; 

         Serial.println(response);

      Serial.print("EndTime with one Serial.print statement and concat strings = "); 
      Serial.println(millis()-test); 
 On an 8Mhz Arduino Pro Mini, this snippit only takes 6ms to generate and send this report.
And before you ask why I don't just serially concatenate in one statement... the Arduino IDE doesn't seem to support that, at least not for mixed data types.

Can I do any better?  What if I reduces the TEXT portion to just comma separators, and only sent ONE string our Serial like this?

      Serial.print("StartTime with no filler and concat strings = "); 
      Serial.println(test=millis()); 
        
         // Assemble the string first, then print it once.
         
         response = "";     // Flush previous message.
         response += rangefront[midpoint];  response += ", ";    
         response += rangerear[midpoint];  response += ", "; 
         response += rangeleft[midpoint];   response += ", ";    
         response += rangeright[midpoint]; response += ", "; 

         response += FrontSonar[midpoint]/58; response += ", ";  
         response += RearSonar[midpoint]/58;   response += ", "; 

         response += FrontLeft; response += ", ";  
         response += FrontRight; response += ", ";    
         response += Front;  response += ", ";  
         response += RearLeft; response += ", ";  
         response += RearRight;  response += ", ";   
         response += Rear; 

         Serial.println(response);

      Serial.print("EndTime with no filler and concat strings = "); 
      Serial.println(millis()-test); 
 On an 8Mhz Arduino Pro Mini, this snippit now only takes between 3-4ms to generate and send this report.

This is a significant improvement, and reduces the overall impact diagnostics has on my loop timing....

Hope you find this helpful...

No comments:

Post a Comment