[resolved] why is Serial for arrays from Mega to Mega (and back) so slow?

I tried this following code, but unfortunately I find no documentation or help files in the Playground or IDE help to make it work fast.
I'm sending byte arrays[48] from 1 Mega to another, and for simulation reasons then change some values, and send them back, and so on.
But I get only 1 send/receive/sendback cycle in 1-2seconds.

For data transmission control byte[0] is 0xff, byte[1] contains a coded checksum byte, the rest is data.

What am I doing wrong? This is what I tried (please don't worry about the TFT part but I have to use different TFTs to work with it):

/*     Tx  master 
       ver 0004   
       IDE 1.6.5
 */

#include <SPI.h>
#include <SD.h>
#include <UTFTQD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9340.h>

#define  clock()  millis()


//=====================================================================================
// TFT LCD
//=====================================================================================
#define   UTFT_SmallFont     8 // UTFT 8x10
#define   UTFT_MediumFont   12 // UTFT ++ 
#define   UTFT_BigFont      18 // UTFT +++ 
#define   _SmallFont_        1 // 9341 6x9
#define   _MediumFont_       2 // 9341 12x16
#define   _BigFont_          3 // 9341 18x23

int16_t  LCDmaxX , LCDmaxY ;                // display size
int16_t  _curx_, _cury_,                    // last x,y cursor pos on TFT screen
         _maxx_, _maxy_;                    // max. x,y cursor pos on TFT screen       
char     wspace[128];                       // line of white space


// set LCD TFT type
int16_t  LCDTYPE   =   -1;

#define  _LCD1602_    1  // LCD1602  Hitachi HD44780 driver <LiquidCrystal.h> 
                           // http://www.arduino.cc/en/Tutorial/LiquidCrystal   //
#define  _SERLCD_     2  // Sparkfun serLCD 16x2  
                           // http://playground.arduino.cc/Code/SerLCD   //
#define  _UTFT_       4  // Henning Karlsen UTFT 2.2-2.4" 220x176 - 320x240 lib
                           // http://henningkarlsen.com/electronics/library.php?id=51   //
#define _ILI9341_     8  // https://github.com/adafruit/Adafruit_ILI9340
                           // https://github.com/adafruit/Adafruit-GFX-Library //
                           
                           
//--------------------------------------------------------------------------------------------------
#define  UTFT_cs      52    // <<<<<<<< adjust!

//UTFT   qdUTFT(Model, SDA=MOSI,  SCL, CS,         RESET,  RS)    // Due: 3 exposed SS pins: 4,10,52
  UTFT   qdUTFT(QD220A,   A2,     A1,  A5,         A4,     A3);   // adjust model parameter and pins!
//UTFT   qdUTFT(QD220A,   50,     49,  UTFT_cs,  0,     51);   // A0->Vc (LED), A4->BoardReset
 extern  uint8_t SmallFont[];
//--------------------------------------------------------------------------------------------------
#define    tft_cs     50
#define    tft_dc     49
#define    tft_rst     0
Adafruit_ILI9340   tft = Adafruit_ILI9340(tft_cs, tft_dc, tft_rst);

//--------------------------------------------------------------------------------------------------

int16_t  fontwi= 8;  // default
int16_t  fonthi=10;  // default


void putfonttype(uint8_t fsize) {
  if(LCDTYPE==_UTFT_)  { fontwi= qdUTFT.getFontXsize(); fonthi=qdUTFT.getFontYsize(); }
  else
  if(fsize==_SmallFont_)     { fontwi= 6; fonthi=9; }  // 5x7 + overhead ?
  else
  if(fsize==_MediumFont_)    { fontwi=12; fonthi=16; } // ?
  else
  if(fsize==_BigFont_)       { fontwi=18; fonthi=23; } // ?
  
  _maxx_ = LCDmaxX / fontwi;    // max number of letters x>>
  _maxy_ = LCDmaxY / fonthi;    // max number of letters y^^ 
  memset(wspace, ' ', _maxx_);  // line of white space
  wspace[_maxx_]='\0';
}



void setlcdorient(int8_t orient) {
  if(LCDTYPE==_ILI9341_) {
      tft.setRotation(orient);
      LCDmaxX=tft.width();
      LCDmaxY=tft.height();        
   }
}

void lcdcls()  {                                                         
   if(LCDTYPE==_UTFT_)      { qdUTFT.clrScr();                }  
   if(LCDTYPE==_ILI9341_)   { tft.fillScreen(ILI9340_BLACK);  }
   _curx_ =0;  _cury_ =0;
}

void curlf()   {                                                        
   _curx_=0; 
   if( _cury_ <=(LCDmaxY-10) ) _cury_+=fonthi; 
   else _cury_=0;   
   if(LCDTYPE==_ILI9341_)   {tft.setCursor(0, _cury_); }  
}



void curxy(int16_t  x,  int16_t  y) {
   _curx_ = x;
   _cury_ = y; 
   if(LCDTYPE==_ILI9341_)   {tft.setCursor(x, y); }
}


void lcdprintxy(int16_t x, int16_t y, char * str) {
   if(LCDTYPE==_UTFT_)     { qdUTFT.print(str,x,y); _curx_=x+strlen(str)*fontwi; _cury_=y; }
   else if(LCDTYPE==_ILI9341_)  { 
      tft.setCursor(x,y);  tft.print(str); 
      _curx_=tft.getCursorX(); _cury_=tft.getCursorY(); 
   }
}


void lcdprint(char * str) {
    if(LCDTYPE==_UTFT_)     { qdUTFT.print(str, _curx_, _cury_); _curx_=_curx_+strlen(str)*fontwi; }
    else if(LCDTYPE==_ILI9341_)  { 
       tft.setCursor(_curx_, _cury_); tft.print(str); 
       _curx_=tft.getCursorX(); _cury_=tft.getCursorY(); 
    }
}


void initlcd(uint8_t orient) { // 0,2==Portrait  1,3==Landscape
   if(LCDTYPE==_UTFT_) {
      qdUTFT.InitLCD();
      LCDmaxX=qdUTFT.getDisplayXSize();
      LCDmaxY=qdUTFT.getDisplayYSize();
      qdUTFT.setFont(SmallFont);
      putfonttype(UTFT_SmallFont);
      fontwi=qdUTFT.getFontXsize();
      fonthi=qdUTFT.getFontYsize();
   }
   else
   if(LCDTYPE==_ILI9341_) {
      tft.begin();
      setlcdorient(orient);       
      tft.setTextSize(_SmallFont_);
      putfonttype(_SmallFont_);
   }   
}  






//=====================================================================================
//=====================================================================================

const  uint8_t  bwidth=48;
uint8_t  bsync=255; 
uint8_t  val[bwidth];
uint8_t  inval[bwidth];

//=====================================================================================
const uint32_t UARTclock=38400;

void setup() {
   char sbuf[128];   
   int32_t  i=0;
         
   // Serial
   Serial.begin(115200);      // USB terminal
   
   Serial1.begin(UARTclock);                    // RX-TX UART
   while(Serial1.available())  Serial1.read();  // clear output buffer
   Serial1.setTimeout(1000);
   
   
   // TFT LCD
   LCDTYPE = _UTFT_;
   initlcd(1);   
   sprintf(sbuf, "LCD=%d wi%d x hi%d",LCDTYPE,LCDmaxX,LCDmaxY);
   lcdcls(); lcdprint(sbuf);
   
   
   sprintf(sbuf, "setup(): done.");
   curlf(); curlf(); lcdprint(sbuf);
   
   lcdcls();
   
   sprintf(sbuf, "Tx master, BAUD= %ld", UARTclock );
   lcdprintxy(0, 0, sbuf);

}


//=====================================================================================
//=====================================================================================


uint8_t checksum(uint8_t array[]) {
  int32_t  sum=0;
  for(int i=2; i<bwidth; ++i) sum+=(array[i]);
  return (sum & 0x00ff);  
}  


//=====================================================================================

void displayvalues(int line, char * caption, uint8_t array[]) {
  int cnt;
  char sbuf[128];
  
  sprintf(sbuf, "%s cks=%-4d", caption, array[1]);
  lcdprintxy(0, line, sbuf);  
  //Serial.println(sbuf);
  for(cnt=0; cnt<8; ++cnt) {
    sprintf(sbuf, "%3d ", array[cnt]);      // print on TFT
    lcdprintxy(cnt*3*8, line+10, sbuf);
    //Serial.print(sbuf);                      // Print value to the Serial Monitor
  }    
  //Serial.println(); 
  
}  


//=====================================================================================
//=====================================================================================

void loop()
{
  char     sbuf[128];     
  static   int cnt=0;  
  uint8_t  ibuf[bwidth], chk;
  uint32_t xtime;
 
  //   send to Rx slave Arduino
  
  //Serial.println();  
  chk=(byte)checksum(val);
  val[1]=chk;  
  val[0]=bsync;
  for(cnt=0; cnt<bwidth; ++cnt) {        
     Serial1.write(val[cnt]);        // Send value to the Rx Arduino        
  }         
  Serial1.flush();                    // clear output buffer
  displayvalues(20, "Transmitted...: ", val);

  
  //     Receive from Rx slave Arduino
  
  cnt=0; 
  memset(ibuf, 0, sizeof(ibuf));  
    
  while(!Serial1.available() ) {                  // wait for data to come
     if( clock()-xtime >2000)  break;
  }
  if(Serial1.available() )  {
     Serial1.readBytes(ibuf, bwidth);            // Get them.
  }
  while(Serial1.available())  Serial1.read();    // clear input buffer
    
  if( ibuf[0]==bsync ) {                         // byte 0 == syncbyte ?
     displayvalues(60, "Received...:", ibuf);
     chk=(byte)checksum(ibuf);                      
     if( (byte)chk == (byte)ibuf[1] ) {          // chksum ok? <<<<<<<<<<< outcomment ?
        memcpy(inval, ibuf, sizeof(ibuf));
        //displayvalues(100, "checked...:", inval);
     
        // change invalues to send back!
        memcpy(val, inval, sizeof(val));         // copy inbuf to outbuf
        val[0]=bsync;  
        val[4]+=1;                               // change [4] to send back 
     }
  } 
 
}

//=====================================================================================
//=====================================================================================
/*     Rx  slave      
       ver 0004 
       IDE 1.6.5
 */
 




#include <SPI.h>
#include <SD.h>
#include <UTFTQD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9340.h>


#define  clock()  millis()


// *SNIP*





//=====================================================================================
//=====================================================================================

const    uint8_t  bwidth=48;
uint8_t  bsync=255; 
uint8_t  val[bwidth];
uint8_t  inval[bwidth];


//=====================================================================================
const uint32_t UARTclock=38400;

void setup() {
   char sbuf[128];   
   int32_t  i=0;
         
   // Serial
   Serial.begin(115200);   // USB terminal
 
   Serial1.begin(UARTclock);                    // RX-TX UART
   while(Serial1.available())  Serial1.read();  // clear output buffer
   Serial1.setTimeout(1000);
   
   // GPIO pins default = INPUT_PULLUP, 13 for LED13
   Serial.println();
   Serial.println("GPIO pin mode default: INPUT_PULLUP");
   for ( i= 2; (i<=13); ++i)  pinMode(i, INPUT_PULLUP); 
   pinMode(13, OUTPUT);
   for ( i=22; (i<=53); ++i)  pinMode(i, INPUT_PULLUP); 
   
   
   // TFT LCD
   Serial.println();
   LCDTYPE = _UTFT_;
   Serial.print("init LCD..."); 
   initlcd(1);   
   Serial.println(" done.");   lcdcls();
   sprintf(sbuf, "LCD=%d wi%d x hi%d",LCDTYPE,LCDmaxX,LCDmaxY);
   Serial.println(sbuf); 
   Serial.println();
   lcdcls(); lcdprint(sbuf);
   
   sprintf(sbuf, "setup(): done.");
   Serial.println(); Serial.println(sbuf);   
   curlf(); curlf(); lcdprint(sbuf);

   lcdcls();
   
   sprintf(sbuf, "Rx slave, BAUD= %ld", UARTclock );;
   lcdprintxy(0, 0, sbuf);


}


//=====================================================================================
//=====================================================================================


uint8_t checksum(uint8_t array[]) {
  uint32_t  sum=0;
  for(int i=2; i<bwidth; ++i) sum+=(array[i]);
  return (sum & 0x00ff);  
}  


//=====================================================================================

void displayvalues(int line, char * caption, uint8_t array[]) {
  int cnt;
  char sbuf[128];
  
  sprintf(sbuf, "%s cks=%-4d", caption, array[1]);
  lcdprintxy(0, line, sbuf);  
  //Serial.println(sbuf);
  for(cnt=0; cnt<8; ++cnt) {
    sprintf(sbuf, "%3d ", array[cnt]);      // print on TFT
    lcdprintxy(cnt*3*8, line+10, sbuf);
    //Serial.print(sbuf);                      // Print value to the Serial Monitor
  }    
  //Serial.println();  
  
}  




//=====================================================================================


void loop(){
  char     sbuf[128];     
  static   int cnt=0; 
  uint8_t  ibuf[bwidth], chk;
  uint32_t xtime;
 
  
  cnt=0; 
  memset(ibuf, 0, sizeof(ibuf)); 
  xtime=clock();  
  while(!Serial1.available() ) {                  // wait for data to come
     if( clock()-xtime >2000)  break;
  }                     
  if(Serial1.available() )   {
     Serial1.readBytes(ibuf, bwidth);             // Get them.
  }
  while(Serial1.available())  Serial1.read();     // clear input buffer
  
  if( ibuf[0]==bsync ) {                          // byte 0 == syncbyte ?
     displayvalues(20, "Received...:", ibuf);
     chk=(byte)checksum(ibuf);
     if( (byte)chk == (byte)ibuf[1] ) {        // chksum ok? <<<<<<<<<<< outcomment ?
        //displayvalues(60, "checked...:", ibuf);
        memcpy(inval, ibuf, sizeof(ibuf));
        // change values to send back!
        memcpy(val, inval, sizeof(val));          // copy inbuf to outbuf
        val[0]=bsync;   
        val[6]+=1;                                // change [6] to send back 
     }     
  }    
  
  // array send back to master:
  
  //Serial.println();  
  chk=(byte)checksum(val);
  val[1]=chk;  
  for(cnt=0; cnt<bwidth; ++cnt) {        
     Serial1.write(val[cnt]);         // Send value to the Rx Arduino        
  } 
  Serial1.flush();                    // clear output buffer
  displayvalues(100, "back to master...:", val);
      
  
}


//=====================================================================================
//=====================================================================================

ArthurD:
I tried this following code, but unfortunately I find no documentation or help files in the Playground or IDE help to make it work fast.
I’m sending byte arrays[48] from 1 Mega to another, and for simulation reasons then change some values, and send them back, and so on.
But I get only 1 send/receive/sendback cycle in 1-2seconds.

For data transmission control byte[0] is 0xff, byte[1] contains a coded checksum byte, the rest is data.

What am I doing wrong? This is what I tried:

I did not see any glaring errors, but I think a different communication protocol would be better.

Can you guarantee that 0xff will never be a value in the buffer? only the sync byte?

here is some code that will work in either case, and will actually sync on 0xff.

#define BUFSIZE 48
bool checksum(uint8_t buf[]){ // this should actually test the checksume of the block

return (buf[1]==27); // my random compile fix
}

bool addToBuffer( uint8_t buf[], uint8_t *cnt, uint16_t timeout){
bool inSync = *cnt>0;
unsigned long start=millis();
do{
  if(Serial1.available()){ // grab new char, test for sync char, if so start adding to buffer
    buf[*cnt] = (uint8_t)Serial1.read();
    if(inSync) *cnt++;
    else{
     if(buf[*cnt]==0xFF){
       inSync = true;
       *cnt++;
       }
     }
    }
  }while((*cnt<BUFSIZE)&&(millis()-start<timeout));
return (*cnt==BUFSIZE);
}

bool receive(uint8_t * buf, uint16_t timeout){

uint8_t cnt=0; // count of received bytes.
bool inSync=false;
unsigned long start=millis();
uint8_t * p;  // pointer into buf for reSync operation
bool done=false;

do{
  done = addToBuffer(buf,&cnt,timeout); // if this return false, a timeout has occured, and the while will exit.
  if(done){ // do checksum test of buffer;
    done=checksum(buf);
    if(!done){// checksum failed, scan buffer for next sync char 
       p = (uint8_t*)memchr(buf,0xff,BUFSIZE);
       if(p){ // found next sync char, shift buffer content, refill buffer
         cnt = BUFSIZE -(p-buf); // count of characters to salvage from this failure
         memcpy(buf,p,cnt); //cnt is now where the next character from Serial is stored!
         }
       else cnt=0; // whole buffer is garbage
       }
    }
    
  }while(!done&&(millis()-start<timeout));

return done; // if done then buf[] contains a valid buffer, else a timeout occurred 
}

Call bool success=receive( buffer, timeout); if success then buffer contains a valid block of data.
if not, a timeout has occured.

Chuck.

Chuck,
thank you for your input.
Unfortunately, I don’t understand your code at all and how to integrate it into mine.
I also don’t understand pointer operations like, e.g.
*cnt++;

I just understand
cnt++;

I am just a simple Arduino Sketch user with VERY limited and poor C experience.

About my 0xff and my chksum - if there is a byte 0xff at position [ 0] and the following byte [ 1] equals the valid chksum then I supposed the array to be valid, too

So how would your algorithm look like and work with my loop() ?
Just a simple, quick sending and then a simple quick receiving, feat. your simple error/validity check!

void loop()
{
 char     sbuf[128];     
 static   int cnt=0; 
 uint8_t  ibuf[bwidth], chk;
 uint32_t xtime;

 //   send to Rx slave Arduino

 //Serial.println(); 
 chk=(byte)checksum(val);
 val[1]=chk; 
 val[0]=bsync;
 for(cnt=0; cnt<bwidth; ++cnt) {       
    Serial1.write(val[cnt]);        // Send value to the Rx Arduino       
 }         
 Serial1.flush();                    // clear output buffer
 displayvalues(20, "Transmitted...: ", val);


 //     Receive from Rx slave Arduino

 cnt=0;
 memset(ibuf, 0, sizeof(ibuf)); 
  
 while(!Serial1.available() ) {                  // wait for data to come
    if( clock()-xtime >2000)  break;
 }
 if(Serial1.available() )  {
    Serial1.readBytes(ibuf, bwidth);            // Get them.
 }
 while(Serial1.available())  Serial1.read();    // clear input buffer
  

    displayvalues(60, "Received...:", ibuf);
    chk=(byte)checksum(ibuf);                     

       memcpy(inval, ibuf, sizeof(ibuf));
       //displayvalues(100, "checked...:", inval);
    
       // change invalues to send back!
       memcpy(val, inval, sizeof(val));         // copy inbuf to outbuf
       val[4]+=1;                               // change [4] to send back


}

I tried to implement your code, but now it blocks completely, nothing is transmitted or received:

// master:


const  uint8_t  bwidth=48;
uint8_t  bsync=255; 
uint8_t  val[bwidth];
uint8_t  inval[bwidth];

//=====================================================================================
const uint32_t UARTclock=38400;

void setup() {
   char sbuf[128];   
   int32_t  i=0;
         
   // Serial
   Serial.begin(115200);      // USB terminal
   
   Serial1.begin(UARTclock);                    // RX-TX UART
   while(Serial1.available())  Serial1.read();  // clear output buffer
   Serial1.setTimeout(1000);
   
   
   // TFT LCD
   LCDTYPE = _UTFT_;
   initlcd(1);   
   sprintf(sbuf, "LCD=%d wi%d x hi%d",LCDTYPE,LCDmaxX,LCDmaxY);
   lcdcls(); lcdprint(sbuf);
   
   
   sprintf(sbuf, "setup(): done.");
   curlf(); curlf(); lcdprint(sbuf);
   
   lcdcls();
   
   sprintf(sbuf, "Tx master, BAUD= %ld", UARTclock );
   lcdprintxy(0, 0, sbuf);

}


//=====================================================================================
//=====================================================================================

bool checksum(uint8_t buf[]){ // this should actually test the checksume of the block

return (buf[1]==27); // my random compile fix
}

//=====================================================================================

bool addToBuffer( uint8_t buf[], uint8_t *cnt, uint16_t timeout){
bool inSync = *cnt>0;
unsigned long start=millis();
do{
  if(Serial1.available()){ // grab new char, test for sync char, if so start adding to buffer
    buf[*cnt] = (uint8_t)Serial1.read();
    if(inSync) *cnt++;
    else{
     if(buf[*cnt]==0xFF){
       inSync = true;
       *cnt++;
       }
     }
    }
  }while((*cnt<bwidth)&&(millis()-start<timeout));
return (*cnt==bwidth);
}


//=====================================================================================

bool receive(uint8_t * buf, uint16_t timeout){

uint8_t cnt=0; // count of received bytes.
bool inSync=false;
unsigned long start=millis();
uint8_t * p;  // pointer into buf for reSync operation
bool done=false;

do{
  done = addToBuffer(buf,&cnt,timeout); // if this return false, a timeout has occured, and the while will exit.
  if(done){ // do checksum test of buffer;
    done=checksum(buf);
    if(!done){// checksum failed, scan buffer for next sync char
       p = (uint8_t*)memchr(buf,0xff,bwidth);
       if(p){ // found next sync char, shift buffer content, refill buffer
         cnt = bwidth -(p-buf); // count of characters to salvage from this failure
         memcpy(buf,p,cnt); //cnt is now where the next character from Serial is stored!
         }
       else cnt=0; // whole buffer is garbage
       }
    }
    
  }while(!done&&(millis()-start<timeout));

return done; // if done then buf[] contains a valid buffer, else a timeout occurred
}


//=====================================================================================
//=====================================================================================

void displayvalues(int line, char * caption, uint8_t array[]) {
  int cnt;
  char sbuf[128];
  
  sprintf(sbuf, "%s cks=%-4d", caption, array[1]);
  lcdprintxy(0, line, sbuf);  
  //Serial.println(sbuf);
  for(cnt=0; cnt<8; ++cnt) {
    sprintf(sbuf, "%3d ", array[cnt]);      // print on TFT
    lcdprintxy(cnt*3*8, line+10, sbuf);
    //Serial.print(sbuf);                      // Print value to the Serial Monitor
  }    
  //Serial.println(); 
  
}  

//=====================================================================================
//=====================================================================================

void loop()
{  
  char     sbuf[128],  resOK;     
  static   int cnt=0;  
  uint8_t  ibuf[bwidth], chk;
  uint32_t xtime;
 
  //   send to Rx slave Arduino
  
  //Serial.println();  

  val[0]=bsync;
  for(cnt=0; cnt<bwidth; ++cnt) {        
     Serial1.write(val[cnt]);        // Send value to the Rx Arduino        
  }         
  Serial1.flush();                    // clear output buffer
  displayvalues(20, "Transmitted...: ", val);

  
  //     Receive from Rx slave Arduino

  memset(ibuf, 0, sizeof(ibuf));  
    
  resOK = receive ( ibuf, 1000);
    
  if( resOK ) {                         // byte 0 == syncbyte ?
     displayvalues(60, "Received...:", ibuf);
     chk=(byte)checksum(ibuf);                      

        memcpy(inval, ibuf, sizeof(ibuf));
        //displayvalues(100, "checked...:", inval);
     
        // change invalues to send back!
        memcpy(val, inval, sizeof(val));         // copy inbuf to outbuf
        val[4]+=1;                               // change [4] to send back 
  } 
 
}
// slave:

 
const  uint8_t  bwidth=48;
uint8_t  bsync=255; 
uint8_t  val[bwidth];
uint8_t  inval[bwidth];

//=====================================================================================
const uint32_t UARTclock=38400;

void setup() {
   char sbuf[128];   
   int32_t  i=0;
         
   // Serial
   Serial.begin(115200);      // USB terminal
   
   Serial1.begin(UARTclock);                    // RX-TX UART
   while(Serial1.available())  Serial1.read();  // clear output buffer
   Serial1.setTimeout(1000);
   
   
   // TFT LCD
   LCDTYPE = _UTFT_;
   initlcd(1);   
   sprintf(sbuf, "LCD=%d wi%d x hi%d",LCDTYPE,LCDmaxX,LCDmaxY);
   lcdcls(); lcdprint(sbuf);
   
   
   sprintf(sbuf, "setup(): done.");
   curlf(); curlf(); lcdprint(sbuf);
   
   lcdcls();
   
   sprintf(sbuf, "Tx master, BAUD= %ld", UARTclock );
   lcdprintxy(0, 0, sbuf);

}


//=====================================================================================
//=====================================================================================

bool checksum(uint8_t buf[]){ // this should actually test the checksume of the block

return (buf[1]==27); // my random compile fix
}

//=====================================================================================

bool addToBuffer( uint8_t buf[], uint8_t *cnt, uint16_t timeout){
bool inSync = *cnt>0;
unsigned long start=millis();
do{
  if(Serial1.available()){ // grab new char, test for sync char, if so start adding to buffer
    buf[*cnt] = (uint8_t)Serial1.read();
    if(inSync) *cnt++;
    else{
     if(buf[*cnt]==0xFF){
       inSync = true;
       *cnt++;
       }
     }
    }
  }while((*cnt<bwidth)&&(millis()-start<timeout));
return (*cnt==bwidth);
}


//=====================================================================================

bool receive(uint8_t * buf, uint16_t timeout){

uint8_t cnt=0; // count of received bytes.
bool inSync=false;
unsigned long start=millis();
uint8_t * p;  // pointer into buf for reSync operation
bool done=false;

do{
  done = addToBuffer(buf,&cnt,timeout); // if this return false, a timeout has occured, and the while will exit.
  if(done){ // do checksum test of buffer;
    done=checksum(buf);
    if(!done){// checksum failed, scan buffer for next sync char
       p = (uint8_t*)memchr(buf,0xff,bwidth);
       if(p){ // found next sync char, shift buffer content, refill buffer
         cnt = bwidth -(p-buf); // count of characters to salvage from this failure
         memcpy(buf,p,cnt); //cnt is now where the next character from Serial is stored!
         }
       else cnt=0; // whole buffer is garbage
       }
    }
    
  }while(!done&&(millis()-start<timeout));

return done; // if done then buf[] contains a valid buffer, else a timeout occurred
}


//=====================================================================================
//=====================================================================================

void displayvalues(int line, char * caption, uint8_t array[]) {
  int cnt;
  char sbuf[128];
  
  sprintf(sbuf, "%s cks=%-4d", caption, array[1]);
  lcdprintxy(0, line, sbuf);  
  //Serial.println(sbuf);
  for(cnt=0; cnt<8; ++cnt) {
    sprintf(sbuf, "%3d ", array[cnt]);      // print on TFT
    lcdprintxy(cnt*3*8, line+10, sbuf);
    //Serial.print(sbuf);                      // Print value to the Serial Monitor
  }    
  //Serial.println(); 
  
}  

//=====================================================================================
//=====================================================================================

void loop()
{  
  char     sbuf[128],  resOK;     
  static   int cnt=0;  
  uint8_t  ibuf[bwidth], chk;
  uint32_t xtime;
 
  //   send to Rx slave Arduino
  
  //Serial.println();  

  val[0]=bsync;
  for(cnt=0; cnt<bwidth; ++cnt) {        
     Serial1.write(val[cnt]);        // Send value to the Rx Arduino        
  }         
  Serial1.flush();                    // clear output buffer
  displayvalues(20, "Transmitted...: ", val);

  
  //     Receive from Rx slave Arduino

  memset(ibuf, 0, sizeof(ibuf));  
    
  resOK = receive ( ibuf, 1000);
    
  if( resOK ) {                         // byte 0 == syncbyte ?
     displayvalues(60, "Received...:", ibuf);
     chk=(byte)checksum(ibuf);                      

        memcpy(inval, ibuf, sizeof(ibuf));
        //displayvalues(100, "checked...:", inval);
     
        // change invalues to send back!
        memcpy(val, inval, sizeof(val));         // copy inbuf to outbuf
        val[4]+=1;                               // change [4] to send back 
  } 
 
}

yep, ArthurD, I make a mistake, in the addToBuffer()

instead of *cnt++, I should have used *cnt +=1; The first was incrementing the address pointed to by cnt,
The second updates the value pointer to by cnt. An important differance,

and in my resync routing I forgot to skip passed the current sync value at position 0.

I expected you to actually use the checkSum value. my hardcoded =27 would almost never be correct.

uint8_t calcCheckSum(uint8_t array[]) {
  int32_t  sum=0;
  for(int i=2; i<bwidth; ++i) sum+=(array[i]);
  return (sum & 0x00ff); 
} 

bool checkSum(uint8_t array[]){
return (calcCheckSum(array)==array[1]);
}

// ================================================================

bool addToBuffer( uint8_t buf[], uint8_t *cnt, uint16_t timeout){
bool inSync = *cnt>0;
unsigned long start=millis();
while((*cnt<bwidth)&&(millis()-start<timeout)){
  if(Serial.available()){ // grab new char, test for sync char, if so start adding to buffer
    buf[*cnt] = (uint8_t)Serial.read();
    if(inSync) *cnt += 1;  // my origional *cnt++ was updating the pointer address, not
                           // the pointed to value
    else{
     if(buf[*cnt]==0xFF){
       inSync = true;
       *cnt +=1;
       }
     }
    }
  }
return (*cnt==bwidth);
}

//=====================================================================================

bool receive(uint8_t * buf, uint16_t timeout, uint8_t *cnt){ // by passing cnt in and out,
// i can timeout and still save a partial buffer, so a resync costs less (less data lost)

bool inSync=false;
unsigned long start=millis();
uint8_t * p;  // pointer into buf for reSync operation
bool done=false;

do{
  done = addToBuffer(buf,cnt,timeout); // if this return false, a timeout has occured, and the while will exit.
  if(done){ // do checksum test of buffer;
    done=checkSum(buf);
    if(!done){// checksum failed, scan buffer for next sync char
       p = (uint8_t*)memchr((buf+1),0xff,(bwidth-1)); //forgot to skip the current sync at 0
       
       
       if(p){ // found next sync char, shift buffer content, refill buffer
         *cnt = bwidth -(p-buf); // count of characters to salvage from this failure
         memcpy(buf,p,*cnt); //cnt is now where the next character from Serial is stored!
         }
       else *cnt=0; // whole buffer is garbage
       }
    }
    
  }while(!done&&(millis()-start<timeout));

return done; // if done then buf[] contains a valid buffer, else a timeout occurred
}

Attached are to sketchs that bounce a buffer back an forth. If you connected to Ardunios (I used UNO’s) and watch the Serial monitor you can see them send back and forth. if you jumper tx->rx and disconnect is some times you will see the resync.

Chuck.

arraySend.zip (4.61 KB)

Chuck,
thank you very much for your reply!
I just don’t understand how to call the new receive() in my own code …?

uint8_t checksum(uint8_t array[]) {
  int32_t  sum=0;
  for(int i=2; i<bwidth; ++i) sum+=(array[i]);
  return (sum & 0x00ff);  
}  

void loop()
{  
  char     sbuf[128],  resOK;     
  static   int cnt=0;  
  uint8_t  ibuf[bwidth], chk;
  uint32_t xtime;
 
  //   send to Rx slave Arduino
  
  val[0]=bsync;
  val[1]=(byte)checksum(val);
  for(cnt=0; cnt<bwidth; ++cnt) {        
     Serial1.write(val[cnt]);        // Send value to the Rx Arduino        
  }         
  Serial1.flush();                    // clear output buffer
  displayvalues(20, "Transmitted...: ", val);
  
  //     Receive from Rx slave Arduino

  memset(ibuf, 0, sizeof(ibuf));      
  resOK = receive ( ibuf, 1000, ?????? );   // ????????????????????????????????????
    
  if( resOK ) {                         // byte 0 == syncbyte ?
     displayvalues(60, "Received...:", ibuf);                          
     if( checksum(ibuf) == ibuf[1] ) {
        memcpy(inval, ibuf, sizeof(ibuf));
        //displayvalues(100, "checked...:", inval);     
        // change invalues to send back!
        memcpy(val, inval, sizeof(val));         // copy inbuf to outbuf
        val[4]+=1;                               // change [4] to send back 
     }
  }  
}

ps, where are the effing code tags in the editor window?!

ArthurD:
Chuck,
thank you very much for your reply!
I just don’t understand how to call the new receive() in my own code …?

Here is what you need to add to your code.

void loop()
{  
// changes 

  static uint8_t bufCount =0;  //<---- variable to contain current data in ibuf, to allow multiple timeout failures


  resOK = receive ( ibuf, 1000, bufCount );  // <----------
    
  if( resOK ) {                         // byte 0 == syncbyte ?
    bufCount = 0; // <--------- empty buffer for next receive
     displayvalues(60, "Received...:", ibuf);                          
     if( checksum(ibuf) == ibuf[1] ) { // don't really need this, if resOK==true, checkSum has matched.
        memcpy(inval, ibuf, sizeof(ibuf));
        //displayvalues(100, "checked...:", inval);     
        // change invalues to send back!
        memcpy(val, inval, sizeof(val));         // copy inbuf to outbuf
        val[4]+=1;                               // change [4] to send back 
     }
  }  
}

ArthurD:
ps, where are the effing code tags in the editor window?!

look for </>, first icon above the smiley faces.

Chuck.

update:

instead of changing my sourcecode by your functions I now took your attached file and added my lcdprint function.

and:

GOOD NEWS!

The transmission works perfect and quick!

Thank you very much for your efforts!

:slight_smile: