Pages: [1]   Go Down
Author Topic: reading serial data with timeouts  (Read 917 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

arduino UNO R3 and IDE 1.01
here is what i have so far, and what i would like it to do. but not sure how to go about it, the length of amount of serial data is not known for each burst of data, and there is no way to tell the program. what i do know is that if i dont recieve data any data within 40ms then i want program to continue then while it is reading data i want to wait up to 6ms to revieve the next byte. if 7ms passes then i want to break the read and send info to server.

Code:
      byte serav  = Serial.available();
       byte seravcount = 0;
       byte lprtemp[200];
      
       //here i would like to start to wait for data for up to 40ms then continue program (with reading serial port)if nothing is recieved but i want to start reading serial port as soon as its available(even if its only been 5ms)
       if (serav > 0) {
         while (Serial.available())
         {
           seravcount = seravcount +1;
           lprtemp[seravcount] = Serial.read();
// if serial is no longer availble i want to wait up to 6ms to see if more will come, if 7ms passes without any serial being available then i want to exit the while
          }
        
         }
//server is a ethernet/tcp link to a pc (this is working
         server.write(seravcount);
         for (byte x = 1; x < seravcount+1 ;x++)
         server.write(lprtemp[x]);
i hope this makes sense
here is the way it should work
server requests data
wait for data up to 40ms /if 40ms passes with no serial input then will have program contine and send a message to server stating that
if serial data present at anytime up to 40 ms start reading it
as each byte is read wait up to 6ms for the next byte (exit the read if 7ms passes since last byte.

i do not want to use things like delay (6) since i could lose info that way if data is actually coming in alot faster. the device i am reading (i cannot change) can sned it bytes as slow as 5ms apart.

thanks in advance

Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 27
Posts: 1188
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You need to use the same technique as the 'Blink without delay' example.

Before you start checking if a characetr is available on the serial port, you store the current value of millis(). You then loop waiting for a character until either a character arrives or the new current millis() value is bigger than the timeout.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks i used a variation of blink without delay, i still had to put a couple delay(1) in and will try to use they delaymicro in a revison, its been running for about 12 hours so far without a hitch

Code:
delay(10);
      byte seravcount = 0;
      byte lprtemp[200];
      byte datafound1 = 0;
      byte bytefound1 = 0;
      unsigned long currentMicros = micros();
      delay(1);
      while (micros() - currentMicros < 100000)
      {
        if (Serial.available() >0)
        {
          datafound1 = 1;
          bytefound1 = 1;
          seravcount = seravcount +1;
          lprtemp[seravcount] = Serial.read();
          break;
        }
      }
      delay(1);
      while (bytefound1 == 1)
      {
        currentMicros = micros();
       
        while(micros() - currentMicros < 6000)
        {
          if (Serial.available() > 0)
          {
            seravcount = seravcount +1;
            lprtemp[seravcount] = Serial.read();
            currentMicros = micros();
            delay(1);
            break;
          }
          else
          {
            bytefound1 = 0;
          }
        }
      }
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46255
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
i used a variation of blink without delay, i still had to put a couple delay(1) in
No. You absolutely did NOT need the delay() in the loop to read the serial data. You DO need to add start and end of packet markers to your packets, rather than diddling around hoping that the whole packet gets there in time.

Then, you read the data as fast as it arrives (no delay()), and only do something when the end of the packet arrives. Like so:
Code:
#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 77
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I cannot add start and stop markers to the incomng data since i have no control, the protocol states that i response must be given within 40ms or there is no response and that the time between each byte will not excedd 5ms. there is however a crc added to end that i can check and if its invalid i can reissue command
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So how is you code?  If you will be using the h/w serial, what I do is use the flexitimer2 library and serial.event.

At each serial.event, at the start I stop flexitimer2 from running.  After the new byte has arrive,  I run flexitimer2.  So as long as new data keeps arriving within the set timeout for flexitimer2, flexitemer2 will never run the function its supposed to run.  If no new data has arrived and timeouts, flexitimer2 then runs the the specified function.

In my specified function, i just raise a flag to indicate that I should already read the buffer.  Hope this helps.  I posted the code in my favorite local forum as my code is related to specifc local product.  In the code, the flexitimer2 is alyastmr2.  Its a modified flexitimer2 tha supports the particular cpu I am using.

http://www.elab.ph/forum/index.php?topic=37118.0
Logged

Pages: [1]   Go Up
Jump to: