Serial Communication performance after adding TFT code

Hi
Have a function that :
//sending comand to serial device
//wait for data incoming with delay(with millis)
//recive data
//pars the data

This function reapeat every 100ms
And its working great
How ever if i adding a tft screen it look like the print text command create delays that cause the data recived to miss data
So when the screen working some times there is no communication with the serial device....
My Q is how the screen efect the cycle time or the timing if i dont use delays at my programs at all.....??

The Serial funtions operate via interrupts. There is no point in introducing delays.
TFT operations tend to be in the foreground. A lot of traffic. No delays.

Because the Serial function are handled with interrupts, the TFT drawing will hardly notice the Serial traffic in the background.

Just bear this in mind when designing your program.

David.

Im sorry but i dont understand can you make it more simple :slight_smile:
Is that meaning that there it not supposed to efect on each other?

Here is a sketch that sends a message via Serial every 100ms.
If you link digital #0, #1 pins, Serial will receive this message.

Observe the pointer as it goes round the circle. If the CPU is busy, it will rotate slower.

You will not notice any “slowdown” when Serial prints the message.
Nor when Serial receives the message.
This is because Serial handles the traffic via interrupts.

You will notice a slowdown when the received message is “parsed” i.e. printed on the TFT screen.

Note that Serial @ 9600 baud can TX <= 96 chars and RX <= 96 chars in a 100ms period.
The Serial interrupt buffers are only 64 bytes on a Uno. So it is wise to send < 64 bytes in one message.

I have built the sketch for MCUFRIEND shields. If you lift the shield 1mm from the socket, you can “short” the TX and RX pins safely. (remove any short before Uploading via Bootloader)
It will build for an Adafruit_ILI9341 display if you alter the #if 0 to #if 1

#if 0
#include <Adafruit_ILI9341.h>
Adafruit_ILI9341 tft(10, 9, 8);
#define ID
#else
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#define ID tft.readID()
#endif

#define TFT_WHITE 0xFFFF
#define TFT_BLACK 0x0000
#define TFT_BLUE  0x001F
#define TFT_RED   0xF800

char buf[100];
int x, y, radius, parse = 0;

void setup()
{
    Serial.begin(9600);
    tft.begin(ID);
    tft.setRotation(1);            //LANDSCAPE
    x = tft.width() / 2;
    y = tft.height() / 2;
    radius = 60;                   //bigger radius will slow down
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_WHITE);   //text colour
    tft.drawCircle(x, y, radius + 1, TFT_WHITE);
    tft.setCursor(0, tft.height() - 10);
    tft.print("short pins 0,1 to receive Serial. print when red");
}

void loop()
{
    static uint32_t t;
    static float angle = 0;
    static int i = 0, cnt = 0;
    if (millis() - t > 100) {      //send message every 100ms via interrupts
        t = millis();
        Serial.println("This is a long message that is safely less than 64 characters");
        if (++cnt > 10) {          //change parse mode every second
            cnt = 0;
            parse = !parse;
            tft.fillRect(0, 0, tft.width(), 16, TFT_BLACK);
        }
    }
    while (Serial.available()) {   //receive reply into buffer via interrupts
        char c = Serial.read();
        buf[i++] = c;
        if (c == '\n' || i > 98) { //process buffer when full sentence
            buf[i] = '\0';
            if (parse) {           //only display when pointer is red
                tft.setCursor(0, 0);
                tft.fillRect(0, 0, tft.width(), 16, TFT_BLACK);
                tft.print(buf);
            }
            i = 0;
        }
    }
    tft.drawLine(x, y, x + int(radius * sin(angle)), y + int(radius * cos(angle)), TFT_BLACK);
    angle += 0.02;
    tft.drawLine(x, y, x + int(radius * sin(angle)), y + int(radius * cos(angle)), parse ? TFT_RED : TFT_BLUE);
}

Yes, the TFT does “slow it down” but only because GFX printing text is quite a complex operation. The rotating line also complex for a TFT. I have deliberately chosen f-p maths.

You should never put delays into a loop unless you have designed it that way.

David.

Thanks David
I was manage to stable the program by printing data to screen only when there is a change
Like...
If (currentTemp != oldTemp
Print to screen......
Old Temp= current

I noted that the printing contiuselly to screen it causing
The slowdown you mentiond
Un like the fill rect comand for example that not make any difference when exequte in the cycle

Any way i will post the serial function i was using
Tomarrow and i will be very much appriciate if someone with your coding skills can advice how to improve the function
Thanks alot for your support and explenation it help me

void CommunicationCheck()
 {

    switch (ticState)
     {
      
    case SEND_NEW_COMMAND:    
     
         sendCommandToTic();
         CommTimer.startTimer(ComDelayTime);
         ticState= GET_DATA_FROM_BUFFER;
        
         #if debugTic
            showParsedData();
         #endif       


    case GET_DATA_FROM_BUFFER:
    
        if (CommTimer.isTimerReady()) // delay with millis (100ms)
          {
             if (Serial1.available() > 0 )
               {
                 char rc = Serial1.read();        
                 receivedChars[index] = rc;
                 index++;
                   if (index >= numChars)
                   index = numChars - 1;
               }              
              else
               {
                 receivedChars[index] = '\0'; // terminate the string
                 index = 0;
            
                ticState = PARSE_DATA;
               }
        } 
          break;
          
      case PARSE_DATA: 

               Command = String(receivedChars); // get the command 
                 
                 if (Command.substring(0,9) == "read-temp")
                 {  
                    TIC.Communication = true;                  
                    String tempString = Command.substring(13,17);
                    float tempF = tempString.toFloat();
                    TIC.Temp = tempF /10; 
                     
                    ticState=SEND_FALSE_COMMAND; //finish parsing go to next state
                 }
                else if  (Command.substring(0,11) == "read-floats")
                 {
                     TIC.Communication = true;
                     String tempString =  Command.substring(16,26);                
                     tempString.toCharArray(copy,12);
                     parseDataFloats();
                     ticState = SEND_FALSE_COMMAND;                
                  }                 
                else
                  {             
                    TIC.Communication = false;
                    TIC.Temp         = 0.0;
                    TIC.HighFloat    ="NA";
                    TIC.MediumFloat  ="NA";
                    TIC.LowFloat     ="NA";
                    
                    ticState = SEND_NEW_COMMAND; 
                  }
                break;



     case SEND_FALSE_COMMAND:
          
             Serial1.print("sendingDummy\r"); // after every command need to send false data and ignore the return value
             CommTimer.startTimer(ComDelayTime);         
             ticState  = EMPTY_BUFFER;
                   
          break;

          
     case EMPTY_BUFFER:
          
          if (CommTimer.isTimerReady())
            {          
              if (Serial1.available()>0)         
                char drainBuff = Serial1.read();             
               else
                ticState= SEND_NEW_COMMAND;     
             }
              break;                
           }    
         }              
              
 void parseDataFloats() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(copy," ");      // get the first part - the string
    int intFrom1 = atoi(strtokIndx);     // convert this part to an integer
       if (intFrom1!= 0)
           TIC.LowFloat = "Down";
           else
            TIC.LowFloat = "Up";
       
    strtokIndx = strtok(NULL, " "); // this continues where the previous call left off
    int intFrom2 = atoi(strtokIndx);     // convert this part to an integer
      if (intFrom2!= 0)
           TIC.MediumFloat = "Down";
           else
            TIC.MediumFloat = "Up";
            
    strtokIndx = strtok(NULL, " ");
    int intFrom3 = atoi(strtokIndx);    
        if (intFrom3!= 0)
           TIC.HighFloat = "Down";
           else
            TIC.HighFloat = "Up";
}       
         
void showParsedData() {
  
    Serial.print("Communication Status:= ");
    Serial.print(TIC.Communication);
    Serial.print("     Tic Temp :=");
    Serial.print(TIC.Temp);
    Serial.print("     float_Low :=");
    Serial.print(TIC.LowFloat);
    Serial.print("     float_Medium:=");
    Serial.print(TIC.MediumFloat);
    Serial.print("    float_High:=");
    Serial.println(TIC.HighFloat);
}

   void sendCommandToTic()
   {
    if (ChangeCommand == 0)
     {
      Serial1.print("read-floats .s\r"); 
      ChangeCommand +=1;
     }
     else if (ChangeCommand == 1)
     {
      Serial1.print("read-temp .s\r"); 
      ChangeCommand = 0;
     }
   }

Your original post was about TFT code losing Serial traffic.

My point was that Serial is handled via interrupts. You should never lose any data providing you access Serial before the interrupt RX buffers fill up. And you can send TX data with virtually no cost to your program performance.

Yes, TFT code tends to be costly. However you can alleviate some foreground cost by using DMA.

I do not see any reference to TFT in your code snippet.

I suggest that you read Serial1 in a while loop rather than a simple if.
The Serial.available() and Serial.read() are cheap operations. There are no delays.

I suggest that you choose to either work with char arrays or with String class.
String on an Arduino is fairly slow and bloated. But better than it used to be.
There are equivalent C library functions for most things that the String class can do.

As a general rule. Only update a TFT screen when necessary.
Avoid delays in loop(). Check if a peripheral is ready or data is available. If busy, go off and do something else. It will probably be ready by the next time you check.

David.

Thanks for the advice....
Noted!