Double Bytes Markers

Hi,

For save pictures i'm trying to use FF D8 as start markers and FF D9 as end markers, i use the structure of the Robin2 work (Serial Input Basics - updated - Introductory Tutorials - Arduino Forum) for the exercise:

const byte numBytes = 32;
byte receivedBytes[numBytes];
byte numReceived = 0;

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvBytesWithStartEndMarkers();
    showNewData();
}

void recvBytesWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
 //   byte startMarker = 0x3C;
 //   byte endMarker = 0x3E;
      byte startMarker1 = 0xFF;
      byte startMarker2 = 0xD8;

      byte endMarker1 = 0xFF;
      byte endMarker2 = 0xD9;
    byte rb;
   

    while (Serial.available() > 0 && newData == false) {
        rb = Serial.read();

        if (recvInProgress == true) {
            if (rb != endMarker) {
                receivedBytes[ndx] = rb;
                ndx++;
                if (ndx >= numBytes) {
                    ndx = numBytes - 1;
                }
            }
            else {
                receivedBytes[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                numReceived = ndx;  // save the number for use when printing
                ndx = 0;
                newData = true;
            }
        }

        else if (rb == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in (HEX values)... ");
        for (byte n = 0; n < numReceived; n++) {
            Serial.print(receivedBytes[n], HEX);
            Serial.print(' ');
        }
        Serial.println();
        newData = false;
    }
}

I've tried to use the same technic we can find in this code but with no succes.
http://chynehome.com/web/wp-content/uploads/2015/08/Wifi_Cam_FTP_6.txt but with no succes

Maybe it's possible to do buffer with two byte and compare it with the end/start markers, like that byte startMarker[] = {0xFF, 0xD8}, or i was thinking about a two step solution, if it detect the first markers, it start an new comparaison operator for the second marker like that:

//Start marker
else if (rb == startMarker1) {
      if (rb == startMarker2) {
            recvInProgress = true;
  }
 }

I read many topics for find a close case with no succes :/, can you help me for that pls ?

Thank !

I agree with @Delta_G. I think this will do the trick - but not tested.

const byte numBytes = 32;
byte receivedBytes[numBytes];
byte numReceived = 0;

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {
    recvBytesWithStartEndMarkers();
    showNewData();
}

void recvBytesWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
//   byte startMarker = 0x3C;
//   byte endMarker = 0x3E;
    byte startMarker1 = 0xFF;
    byte startMarker2 = 0xD8;

    byte endMarker1 = 0xFF;
    byte endMarker2 = 0xD9;
    
    byte latestByte;
    byte previousByte = '0'; // any non marker value
    

    while (Serial.available() > 0 && newData == false) {
        previousByte = latestByte;
        latestByte = Serial.read();

        if (recvInProgress == true) {
            if ! (latestByte == endMarker2 && previousByte == endMarker1) {
                receivedBytes[ndx] = latestByte;
                ndx++;
                if (ndx >= numBytes) {
                    ndx = numBytes - 1;
                }
            }
            else {
                receivedBytes[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                numReceived = ndx;  // save the number for use when printing
                ndx = 0;
                newData = true;
            }
        }

        else if (latestBye == startMarker2 && previousByte == startMarker1 ) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in (HEX values)... ");
        for (byte n = 0; n < numReceived; n++) {
            Serial.print(receivedBytes[n], HEX);
            Serial.print(' ');
        }
        Serial.println();
        newData = false;
    }
}

I would like to hear if it works as it will be useful to keep a link to it.

Of course your chosen marker combination may occur in the image data :frowning:

The only way to avoid that is to process the image data and use some combination of bytes to represent the marker bytes. Or send the size of the image as part of the preamble.

...R

Hi,

thx! It's simpler than i thought but it works only when i print the values of previousByte and latestByte.

Here is the code:

const byte numBytes = 32;
byte receivedBytes[numBytes];
byte numReceived = 0;

boolean newData = false;

void setup() {
    Serial.begin(115200);
    Serial1.begin(115200);
    Serial.println("<Arduino is ready>");
    Serial1.println("<Arduino is ready>");
}

void loop() {
    recvBytesWithStartEndMarkers();
    showNewData();
}

void recvBytesWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    
    byte startMarker1 = 0xFF;
    byte startMarker2 = 0xD8;

    byte endMarker1 = 0xFF;
    byte endMarker2 = 0xD9;
    
    byte latestByte;
    byte previousByte = 0xB1; // any non marker value
    

    while (Serial1.available() > 0 && newData == false) {
        previousByte = latestByte;
        latestByte = Serial1.read();

        if (recvInProgress == true) {
            if (latestByte != endMarker2 && previousByte != endMarker1) {
                receivedBytes[ndx] = latestByte;
                ndx++;
                if (ndx >= numBytes) {
                    ndx = numBytes - 1;
                }
            }
            else {
                receivedBytes[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                numReceived = ndx;  // save the number for use when printing
                ndx = 0;
                newData = true;
            }
        }

        else if (latestByte == startMarker2 && previousByte == startMarker1 ) {
            recvInProgress = true;
        }
        //Serial.print("LatestByte: ");
        //Serial.println(latestByte, HEX);
        //Serial.print("previousByte: ");
        //Serial.println(previousByte, HEX);
        
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in (HEX values)... ");
        for (byte n = 0; n < numReceived; n++) {
            Serial.print(receivedBytes[n], HEX);
            Serial.print(' ');
        }
        Serial.println();
        newData = false;
    }
}

it was not working at the begining so i added few lines for know what's happen with latestByte and previousByte:

else if (latestByte == startMarker2 && previousByte == startMarker1 ) {
            recvInProgress = true;
        }
        Serial.print("LatestByte: ");
        Serial.println(latestByte, HEX);
        Serial.print("previousByte: ");
        Serial.println(previousByte, HEX);

It show the good value exept "previousByte" shows "0" more than 1 time so we can't be sure it will take the first byte(FF). I just added random bytes before the header FF D8 and it works.
But when i remove the Serial.print lines the sketch doesn't work anymore it's like there is a problem with the latestByte/previousByte.

I think it's impossible to have the FF D8 and FF D9 combination in the data exepte for the header and footer, i've checked with other jpg images and it seems to be true. So it's a good point.

For finish, the markers have to be in the array so i've found a "dirty" solution but it work, how i could impove this ?

while (Serial1.available() > 0 && newData == false) {
        previousByte = latestByte;
        latestByte = Serial1.read();

        if (recvInProgress == true) {
            if (latestByte != endMarker2 && previousByte != endMarker1) {
                receivedBytes[ndx] = latestByte;
                ndx++;
            }
            else {
                
                receivedBytes[ndx++] = latestByte;
                receivedBytes[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                numReceived = ndx;  // save the number for use when printing
                ndx = 0;
                newData = true;
            }
        }

        else if (latestByte == startMarker2 && previousByte == startMarker1 ) {
            receivedBytes[ndx++] = startMarker1;
            receivedBytes[ndx++] = startMarker2;
            recvInProgress = true;
        }

Ps: i use an arduino mega and i send with Hterm the bytes: 46 E0 FF D8 20 4A 46 E0 10 FF D9

I seen your challenge and thought of using a union and shifting the byte over like this then checking the int version for the matching hex value that way you can easily spot the start and end with a simple if statement.

union bytesIntUnion {
  char c[2];
  int i;
};
bool Reading = false;
bytesIntUnion BIUnion;
void setup() {
  Serial.begin(115200); //

}

void loop() {
  // put your main code here, to run repeatedly:
  while (Serial.available() > 0) {
    BIUnion.c[1] = BIUnion.c[0];
    BIUnion.c[0] = Serial.read();

      //Reversed operation 
      //BIUnion.c[0] = BIUnion.c[1];
      //BIUnion.c[1] = Serial.read();


    if (BIUnion.i == 0xFFD9) {
      Serial.print("found 0xFFD9");
      Reading = false;
    }

    if(Reading){
         Serial.print(BIUnion.c[0]);
    }

    if (BIUnion.i == 0xFFD8) {
      Serial.print("found 0xFFD8");
      Reading = true
    }
  }
}

Z

Excellent Zhomesclice !
Now it's works but i was thinking to upload on the SPIFFS memory, it works but only about 1/10 of the data :/.
Save directly at 115200 to the SPIFFS is a bad idea ?
I use a ES8285 module and i tested with the 8266FtpServer to save a 30kB picture and it take around 1-2 sec (also to the SPIFFS) so it's fast but maybe i should use the ram to store temporarly the image before write in the SPIFFS, if yes, how to do that ?

void CamRD()
{ 
  if(SaveRD == true) {
   File logF = SPIFFS.open("/picture.JPG", "a"); 
   while (swSer.available() > 0) {
    BIUnion.c[1] = BIUnion.c[0];
    BIUnion.c[0] = swSer.read();


    if (BIUnion.i == 0xFFD9) {
      logF.print(cEnd);
      server.send(200, "text/plain", "The picture has been taken !");   
      Serial.print("found 0xFFD9");
      Reading = false;
      SaveRD = false;
      logF.close();
    
    }

    if(Reading){
         logF.print(BIUnion.c[0]);       
    }

    if (BIUnion.i == 0xFFD8) {
      Serial.print("found 0xFFD8");
      Reading = true;
    }
  }
}
}

Thx !