Using peek() to wait??

Would placing "Serial1.peek()==0x01" be valid before using "Serial1.readBytes()"??

I believe I'm having a timing issue where Serial1.readBytes() is reading unwanted bytes sent before the desired "0x01" byte and throwing a subsequent string creation off by at least 3 bytes. This event occurs in about 30 places in my code and wanted to ask before committing to the keyboard banging. :slight_smile:

I haven't found anything here that says what arguments are valid after peek().

I would not use either.

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

...R

peasoup:
Would placing "Serial1.peek()==0x01" be valid before using "Serial1.readBytes()"??

I believe I'm having a timing issue where Serial1.readBytes() is reading unwanted bytes sent before the desired "0x01" byte and throwing a subsequent string creation off by at least 3 bytes. This event occurs in about 30 places in my code and wanted to ask before committing to the keyboard banging. :slight_smile:

I haven't found anything here that says what arguments are valid after peek().

peek() takes no arguments it just returns the next byte in the serial buffer without remove it from the serial buffer. If you use "Serial1.peek()==0x01" as a test and never actually read the serial buffer you could find yourself in an infinite loop.

Robin2:
I would not use either.

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

...R

I have read through those examples several times and tried to make them feasible for my situation. They would work if I had more control over the incoming message. I cannot set the number of bytes to receive (replies vary in length) or search for/add an ending marker (because I didn't create the device sending the data).

There are other bytes flowing that do not apply to the response I'm looking for and need to be "ignored". The only variable that is certain is the beginning byte that starts the message and why I questioned if peek() with a specific argument will "look", or "wait", for the first byte to equal "0x01" before allowing readBytes() to start. I'm using readBytes() to capture the complete message no matter what length the device decides to send and then manipulate those bytes for further processing.

Can you give some example data plus a description of the protocol? Or a link to the specifications/user manual of the sending device.

I would just read till I receive 0x01 and next start saving the data.

Is there a guarantee that 0x01 does not occur anywhere else in the stream?

There are other bytes flowing that do not apply to the response I'm looking for and need to be "ignored".

Then read the serial input when a byte becomes available() and ignore it if it is not what you are looking for. Repeat until you find the start of message marker and proceed from there

sterretje:
Can you give some example data plus a description of the protocol? Or a link to the specifications/user manual of the sending device.

I would just read till I receive 0x01 and next start saving the data.

Is there a guarantee that 0x01 does not occur anywhere else in the stream?

Unfortunately there is NO guarantee that 0x01 will not appear in the received message. I didn't post any my code since I didn't feel is was relevant on how to find that first byte in the message by ignoring the "garbage" before it.

UKHeliBob:
Then read the serial input when a byte becomes available() and ignore it if it is not what you are looking for. Repeat until you find the start of message marker and proceed from there

I will look for available() and see how I can use that.

I was focusing on peek() because it "looks" at the byte without reading and thought I could compare that to the byte 0x01 and then allow readBytes() to actually capture the message.

peasoup:
Unfortunately there is NO guarantee that 0x01 will not appear in the received message. I didn't post any my code since I didn't feel is was relevant on how to find that first byte in the message by ignoring the "garbage" before it.

I will look for available() and see how I can use that.

I was focusing on peek() because it "looks" at the byte without reading and thought I could compare that to the byte 0x01 and then allow readBytes() to actually capture the message.

So is the data framed at all? Usually data is framed so you can find the beginning and end of the frame. Sometimes byte-stuffing is used.

peasoup:
I cannot set the number of bytes to receive (replies vary in length) or search for/add an ending marker (because I didn't create the device sending the data).

If you have no way of knowing when a message ends, you cannot parse the message, pure and simple...

Any documentation of the messages? - there will be a procedure for determining the message boundaries
if its a well formed protocol.

I suspect the messages include a length field - if so you'll have to parse it on the fly.

MarkT:
If you have no way of knowing when a message ends, you cannot parse the message, pure and simple...

Any documentation of the messages? - there will be a procedure for determining the message boundaries
if its a well formed protocol.

I suspect the messages include a length field - if so you'll have to parse it on the fly.

My next guess will be to go thru the possible 100+ messages that will be incoming, determine the longest message that could exist, then create a buffer to read the bytes from there? But then I think about it and I'll be at the same predicament of finding the first byte that is valid with a value of 0x01 out of that buffer. Frustrating.

My next guess will be to go thru the possible 100+ messages that will be incoming, determine the longest message that could exist, then create a buffer to read the bytes from there?

What kind of device is sending 100+ unsolicited messages?

Or is there an ask and receive protocol?

Can you please provide us with more information about the sender!

cattledog:
Can you please provide us with more information about the sender!

This is essential.

...R

waiting for 0x01 is useless if it can appear both as a start point or in the data. how would you know which is which ?

11 messages (12 with this one) and still no clue about the sender process, and the kind of data stream... there is no point discussing this further until we gain clarity on that.

I had stepped away and did some yard work to clear my mind. Lemme check/try the replies, then I'll be back.

Thanks

I hadn't revealed the send/receive process because on another board to do repairs, when you ask for help building what I am (knowing well that others have succeeded), they clam up and you can't get anything else from them. I received ONE reply for 5 messages I posted looking for a clue to get me past a road block. This makes one "gun shy" to be overly specific on details because people tend to scatter like cockroaches if you ask a "secret" question they might get ahead of them on. So, what is my mysterious project? I'm trying to setup a Mega that will act as a casino server. It currently can operate on it's own successfully printing, redeeming, and handling redundant commands in the background. So yeah, I'm one of those "slot machine" guys. The Mega performs as expected on the "base" model program.

I wanted more from my $40 expense and squeeze the blood out of it.

I started programming it to handle every possible command that I can throw at my slot machine via a web interface. Stopping after each new one, uploading, and testing until that process was successful and then squeeze a little more. I've even backed out the last 3 new additions and this phenomenon still exists. Why? I've got no frickin' clue. Is the new Ethernet.server I've added causing the buffer build up? I don't know that either.

Details about the data. Yes, it is a send/response system. I send a code then get a reply with the data I've requested. And it ALWAYS will begin with the HEX code for the number 1, always. The same command response can very possibly be a different length from the last time that it was sent. I have the Mega requesting status at the correct moment that there is no way a buffer can build up in the machine. Can I slow the status requests down? I've tried and I'll get errors in the data stream because the machine wants to "ping" the Mega to make sure it's still there before the Mega can send another message letting it know the link is still good.

I still haven't got to the point others have reached and I've only introduced the Webserver from my "base" fulling-working standalone, point. I've re-read my code 3-4 times to make sure I'm not sending a new command within 200ms of the last and would cause a buffer overrun on the machine The slot machine has yet to throw that certain exception code indicating that it's throwing away data. I'm doing something right there.

I don't know where the extra data is coming from or why they started. They happen with/without a browser connected. That's the reason for this threads subject, if I can use peek() == 0x01 (or even just 1) to find the beginning of the message before I readBytes(). Why do I ask? Because Serial1.peek() >=0 works to tell me when the slot machine is pinging the the Mega and the Mega can start comms. If I use "if(Serial1.available() > 0), then the Mega is constantly reading Serial1 and looking for a signal because Serial1 is available.

Code I use at the beginning of setup():

  if (Serial1.peek() >= 0)
  {
    if (Serial1.available() > 0)
    {
      i = 0;
      SASEvent = 0;
      UCSR1B = 0b10011101;    //Turn 9-bit On
      Serial1.write(0x80);
      delay(20);
      Serial1.write(0x81);
      delay(5);
      UCSR1B = 0b10011100;    //Turn 9-bit OFF
      delay(5);
      SASEvent = Serial1.read();

Code I thought would work to help me find 0x01:

  if (Serial1.peek() == 0x01)
  {
    Serial1.readBytes(CashOut, sizeof(CashOut));
  }
  else
  {
    Serial1.read();
  }

This is the message the Mega is sending:

01 58 01 00 00 00 00 00 00 00 00 XX XX <-- XX XX is the CRC16(Kermit) value of the previous 11 bytes

This is the message the slot machine is acknowledging back:

01 58 01 00 00 00 01 57 00 00 00 XX XX <-- The '57' is left over from the command prior that initiated the "58" command.
and should be:
01 58 01 00 00 00 00 00 00 01 00 XX XX <-- Denotes that $1.00 has been cashed out

The Mega would never send a "58" without successfully receiving a "57".

You can't dictate anything about the input stream, so peeking ahead in the input buffer is pointless. It would be generally useful if there was a way to "unread" but it's hard to imagine exactly how that would operate. Just read it in a parse it normally to separate the things you want from those you don't. Seeing a 0x01 or whatever in the RX stream means the same thing whether it is processed in the system buffer, or in the program line buffer. Thus it can be properly processed in either way, and doing it in the line (program assigned) buffer is much easier. Or even better, sometimes you can keep discarding input characters "up front" and then only put valid data in the buffer.

aarg:
You can't dictate anything about the input stream, so peeking ahead in the input buffer is pointless. It would be generally useful if there was a way to "unread" but it's hard to imagine exactly how that would operate. Just read it in a parse it normally to separate the things you want from those you don't. Seeing a 0x01 or whatever in the RX stream means the same thing whether it is processed in the system buffer, or in the program line buffer. Thus it can be properly processed in either way, and doing it in the line (program assigned) buffer is much easier. Or even better, sometimes you can keep discarding input characters "up front" and then only put valid data in the buffer.

I will attempt this and let you know how it works out.

Thanks.

I don’t really get what you do there

 if (Serial1.peek() >= 0)
  {
    if (Serial1.available() > 0)
    {
      i = 0;
      SASEvent = 0;
      UCSR1B = 0b10011101;    //Turn 9-bit On
      Serial1.write(0x80);
      delay(20);
      Serial1.write(0x81);
      delay(5);
      UCSR1B = 0b10011100;    //Turn 9-bit OFF
      delay(5);
      SASEvent = Serial1.read();

First off, if peek() returns anything postive or 0 it means there’s at least one byte waiting, so you are 100% sure that Serial1.available() is > 0 there is no need to test for that.

Then what’s about the 9 bit stuff and the huge delays? If the communication is not 8N1 what is it? (Usually it’s symmetric, and you would not receive properly if you are not set up properly)

At what baud rate are you communicating? At 112500 bauds for example The delays for 25ms you have is enough time to receive more than 280 bytes and the incoming buffer can only keep 64....so what are the delays for?

if (Serial1.peek() >= 0)

Can someone please explain to me why there is a need to do this when Serial.available() will do effect do the same thing ?

If Serial.peek() returns greater than 0 then there is something to read in the serial buffer
If Serial.available() returns greater than 0 then there is something to read in the serial buffer