Hardware Serial 9 bits

Hello All

I use this 9 bit library on Arduino mega 2560 to communicate with a game machine.

The game machine sends its address through the serial port every 20ms.
until the host (Arduino Mega) sends it a poll.

Once the game machine receives the poll, it must respond with the correct data. Most responses are <64 bytes

The problem I have is that once the program has started, until the arduino mega sends the poll, the RX buffer contains data that corresponds to what the game machine has sent before receiving the poll. I have tried Serial1.flush () but it does nothing, apparently it only works with TX in standby mode for TX sending.

This only happens the first time, for the rest of the polls the RX buffer contains the appropriate data.

TX -->Longitud de dataRx: 41
17:30:37.677 -> RX <--1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 11 2 66 77 42 17 8D
17:30:37.825 -> RX <--1 12 6 18 16 61 E0 1D  -->Longitud de dataRx: 8
17:30:37.978 -> RX <--1 11 2 66 77 42 17 8D  -->Longitud de dataRx: 8
17:30:38.025 -> RX <--1 12 6 18 16 61 E0 1D  -->Longitud de dataRx: 8
17:30:38.179 -> RX <--1 11 2 66 77 42 17 8D  -->Longitud de dataRx: 8
17:30:38.226 -> RX <--1 12 6 18 16 61 E0 1D  -->Longitud de dataRx: 8

Function that sends the poll and receives the response from the gaming machine

void procesarCMD(byte cmd[], int lenTx, bool crc_need)
    { 

     int periodo2=20; 
     anterior=0;  
     int x=0; 
     int i=0;
     int pos=0;
     byte verificaCRC[50]; //Array para generar/comparar el CRC
        
     //Genera CRC si lo necesita y envía el comando
     if (crc_need == true)
      {  
        computeCRC(cmd, lenTx);              
        cmd[lenTx]= globalCRC[0];//Añade el primer byte de CRC al comando
        cmd[lenTx+1]= globalCRC[1];//Añade el segundo byte de CRC al comando  
        lenTx = lenTx+2;  
      }
        
         
     
     udpSend(cmd,lenTx); //Envío trama TX
     sendCommand(cmd,lenTx);
     serEgm.flush();
     anterior = millis();  
     while(millis() < anterior + periodo2){}
     anterior = millis();
    
     
    
          
     //Lee del puerto serie la trama recibida y verifica el CRC
     int lenRx = serEgm.available();//Obtiene el tamaño de la trama recibida
     byte dataRx[lenRx];
     
     serMonitor.println("Longitud de dataRx: " + String(sizeof(dataRx))); 
     
     pos=0;
     
     while (i<lenRx)
         {  

           if (serEgm.available()>0)
            {
             dataRx[i]=serEgm.read();
             i++;
            } 
         } 

     serMonitor.print("RX <--");
  
     for (x=0;x<=lenRx-1;x++)
       {
         serMonitor.print(dataRx[x],HEX);
         serMonitor.print(" ");
         pos++;
         
         if (pos == lenRx)
          { 
            serMonitor.print("--"); 
          }
       }   

     serMonitor.flush();
             
     if (lenRx > 1)
      {
        //carga la variable con todos los bytes de la trama    
        for (x=0; x<lenRx; x++)
          { 
            verificaCRC[x] = dataRx[x];
          }

             //Envía la trama recibida a verificar CRC sin los 
             //dos últimos bytes que corresponden al CRC recibido
        computeCRC(verificaCRC, lenRx-2); 

        if (globalCRC[0] != dataRx[lenRx - 2] && globalCRC[1] != dataRx[lenRx - 1])
         {
           excepcion = "Error de CRC";
           serMonitor.println(" Error de CRC ");
           return;     
         }

        excepcion = "CRC Ok";
        serMonitor.println(" CRC Ok");

        }
        excepcion = "ACK";
        serMonitor.println(" ACK");

serEgm corresponds to Serial1 of mega2560 and serMonitor corresponds to Serial of mega 2560

I hope your help, thank you very much

You could write your own input buffer flush using Serial.available and Serial.read.
(This is how flush used to work)

Hi yKnownAsAWOL

With your suggestion it has worked for me

Before sending the poll to the gaming machine, I do what you propose

Thanks for your help

//Vacía el buffer RX
     int lenRx = serEgm.available();
     byte RxFlush[lenRx];
     while (i<lenRx)
         {  
           if (serEgm.available()>0)
            {
             RxFlush[i]=serEgm.read();
             i++;
            } 
         }
19:28:14.152 -> TX -->Longitud de dataRx: 8
19:28:14.152 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8
19:28:14.199 -> RX <--1 12 6 18 16 61 E0 1D --TX -->Longitud de dataRx: 8
19:28:14.399 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8
19:28:14.452 -> RX <--1 12 6 18 16 61 E0 1D --TX -->Longitud de dataRx: 8
19:28:14.618 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8
19:28:14.653 -> RX <--1 12 6 18 16 61 E0 1D --TX -->Longitud de dataRx: 8
19:28:14.854 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8
19:28:14.901 -> RX <--1 12 6 18 16 61 E0 1D --TX -->Longitud de dataRx: 8
19:28:15.055 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8
19:28:15.102 -> RX <--1 12 6 18 16 61 E0 1D --TX -->Longitud de dataRx: 8
19:28:15.302 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8
19:28:15.356 -> RX <--1 12 6 18 16 61 E0 1D --TX -->Longitud de dataRx: 8
19:28:15.503 -> RX <--1 11 2 66 77 42 17 8D --TX -->Longitud de dataRx: 8

You don’t have to store the flushed bytes

(void)serEgm.read();

No, we are necessary, it is the queue of the repetitive sending of the game machine as a keep alive.

The necessary data is what it responds after sending the poll with the necessary command.

After verifying that it works correctly, I have commented out all the Serial.print lines for the Arduino IDE serial monitor because I only use them for debugging.

Now I have packet loss because it is as if Serial1 works faster. I have tried putting some delay or millis () but no results.

The operation of this application consists of a main loop that sends calls to the functions that contain the configuration of each command. This function calls and sends the parameters to the function that sends the poll to the gaming machine, and in turn receives the response.

This process is repeated for each command sent, in my case ten commands.

It gives the feeling that you are not waiting to receive the data and returns to the main loop early.

If I re-enable the Serial.print for debugging everything works perfectly again.

Is it possible that Serial enables some interrupt that Serial1 needs for its purpose?

Main loop

void loop()

{

anterior = millis();
  while(millis() < anterior + periodo){ 
       comandoA0();} 
  anterior = millis(); 
  while(millis() < anterior + periodo){ 
       comando0F();} 
  anterior = millis(); 
  while(millis() < anterior + periodo){ 
       comando11();} 
  anterior = millis();
  while(millis() < anterior + periodo){ 
       comando12();}
  anterior = millis();
  while(millis() < anterior + periodo){ 
       comando2D();}
  anterior = millis();
  while(millis() < anterior + periodo){
       comandoMulti();}
  anterior = millis();
  while(millis() < anterior + periodo){ 
       comando1E();}
  anterior = millis();
  while(millis() < anterior + periodo){ 
       comando1F();}
  anterior = millis();
  while(millis() < anterior + periodo){ 
       comando1C();}
  anterior = millis();
  while(millis() < anterior + periodo){ 
       comando0E();}
  anterior = millis();

  anterior = millis();
  while(millis() < anterior + periodo){}     
  anterior = millis();

}

Functions with command configuration
These are two of the ten in total. The rest are similar

//-------------------------------------------------------------------------------
void comando11() // Comando 0x11
{
  lenTx=2;
  byte cmd[]={address,0x11};
  procesarCMD(cmd,lenTx,false);
}
//-------------------------------------------------------------------------------
void comando12() // Comando 0x12
{
  lenTx=2;
  byte cmd[]={address,0x12};
  procesarCMD(cmd,lenTx,false);
}

Function for sending and receiving data with commented Serial lines. Only those corresponding to Serial1 are operational

void procesarCMD(byte cmd[], int lenTx, bool crc_need)
    { 
     int periodo2=20; 
     anterior=0;  
     int x=0; 
     int i=0;
     int pos=0;
     byte verificaCRC[100]; //Array para generar/comparar el CRC
        
     //Genera CRC si lo necesita y envía el comando
     if (crc_need == true)
      {  
        computeCRC(cmd, lenTx);              
        cmd[lenTx]= globalCRC[0];//Añade el primer byte de CRC al comando
        cmd[lenTx+1]= globalCRC[1];//Añade el segundo byte de CRC al comando  
        lenTx = lenTx+2;  
      }
        
     //anterior = millis();     
    //serMonitor.println("Tiempo transcurrido: " + String(anterior/1000)); 

    //Vacía el buffer RX
     int lenRx = serEgm.available();
     byte RxFlush[lenRx];
     while (i<lenRx)
         {  
           if (serEgm.available()>0)
            {
             RxFlush[i]=serEgm.read();
             i++;
            } 
         }
     //--------------------------------------------------

     
     udpSend(cmd,lenTx); //Envío trama TX
     sendCommand(cmd,lenTx);
     serEgm.flush();
     anterior = millis();  
     while(millis() < anterior + periodo2){}
     anterior = millis();
     //sendCommand(cmd,lenTx);     
     
    /* serMonitor.print("TX -->");
     for (x=0;x<lenTx;x++)
         {
         serMonitor.print(cmd[x],HEX);
         serMonitor.print(" ");
         pos++;
         if (pos == lenTx)
             { 
             serMonitor.println(); 
             }
       }  */
          
     //Lee del puerto serie la trama recibida y verifica el CRC
     lenRx = serEgm.available();//Obtiene el tamaño de la trama recibida
     byte dataRx[lenRx];
     
     //serMonitor.println("Longitud de dataRx: " + String(sizeof(dataRx))); 
     
     pos = 0;
     i = 0;
     while (i<lenRx)
         {  
           if (serEgm.available()>0)
            {
             dataRx[i]=serEgm.read();
             i++;
            } 
         } 
     /*serMonitor.print("RX <--");  
      for (x=0;x<=lenRx-1;x++)
       {
         serMonitor.print(dataRx[x],HEX);
         serMonitor.print(" ");
         pos++;
         
         if (pos == lenRx)
          { 
            //serMonitor.println("--"); 
          }
       } */ 
     serMonitor.flush();             
     if (lenRx > 1)
      {
        //carga la variable con todos los bytes de la trama    
        for (x=0; x<lenRx; x++)
          { 
            verificaCRC[x] = dataRx[x];
          }
             //Envía la trama recibida a verificar CRC sin los 
             //dos últimos bytes que corresponden al CRC recibido
        computeCRC(verificaCRC, lenRx-2); 
        if (globalCRC[0] != dataRx[lenRx - 2] && globalCRC[1] != dataRx[lenRx - 1])
         {
           excepcion = "Error de CRC";
           //serMonitor.println(" Error de CRC ");
           udpSendText(excepcion);
           return;
         }
        udpSend(dataRx,lenRx); //Envio UDP trama recibida 
        excepcion = "CRC Ok";
        //serMonitor.println(" CRC Ok");
        udpSendText(excepcion);
      }
      
      if (lenRx == 1)
       {
        excepcion = "ACK";
        //serMonitor.println(" ACK");
        udpSendText(excepcion);
       }

As always, I appreciate your help

Best regards