Pages: [1]   Go Down
Author Topic: Is it possible to clear the Serial Buffer?  (Read 848 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everyone,

First apologize if someone ask something similar to this before but I couldn't find anything similar.

I am working on a project which is basically a datalogger who write all the sensors information in a SD CARD every some 'x' controlled time.

Arduino only will send the information in case to one of the sensor values exceed the limits values or in case that an external device (via LabView via ZigBee technology) ask for it.

My main idea it was something similar to this:

switch(var)

{

case 'a':

send_data();

case 'b':

change_delay();

case 'c':

change_limits()

}


...and so on.

The point is that I am able to ask for it and it works the first time, but when I ask for more than one option sometimes doesn't work.

I think the problem probably it will be fixed if I could clear the Serial buffer every time after I use the serial port but until this moment I haven't been able to figure out how to do it.

If it's possible I would like if someone can tell me how to do it or if is not I would really appreciate some other idea to control it.

Thanks a lot for advance.

Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 200
Posts: 12773
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


I am having trouble understanding the role of the Arduino.  Are you trying to clear the receive buffer or the send buffer?

Quote
The point is that I am able to ask for it and it works the first time, but when I ask for more than one option sometimes doesn't work.

I suspect you have jumped to a "solution" before diagnosing the problem.  I suggest you post more details about the problem.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I suggest you post more details about the problem.
And ALL of your code.
Logged

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

Here is the code.  

I am trying to clear the receive serial data.

My problem it is that my program don't always answer to the commands I send from the other XBee terminal.

Code:
#include <SHT1x.h> //SHT15 Library
#include <SD.h> //SD Library
#include <Wire.h> //I2C Library
#include <DS3231.h> //RTC Library

#define dataPin  3
#define clockPin 2

SHT1x sht1x(dataPin, clockPin);
DS3231 RTC; //Create the R8025 object
File logFile; //Create the logFile object

int d= 5000; //DELAY TIME
int limit_x = 0; //ALARM limit_S
int limit_y = 0;
int limit_z = 0;
int limit_t = 50;
int limit_h = 100;
int inByte;


void setup () {
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();

  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);

  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");



}


void loop () {




  //CASE
  if (Serial.available() > 0) {
    int inByte = Serial.read();

    switch (inByte) {
    case 'a':   
      sentdata();
      break;
    case 'b':   
      ConfigTime();
      break;
    case 'c':   
      d=wait();
      break;
    case 'x':   
      limit_x= climit_x();
      break;
    case 'y':   
      limit_y= climit_y();
      break;
    case 'z':   
      limit_z= climit_z();
      break;
    case 't':   
      limit_t= climit_t();
      break;
    case 'h':   
      limit_h= climit_h();
      break;

    }
    //ADXL     
    int angle_x = getx();
    int angle_y = gety();
    int angle_z = getz();

    String adxl = (' ') + String(angle_x, DEC) + (' ') + String(angle_y, DEC) + (' ') + String(angle_z, DEC) ;


    //SHT15

    int temp_c;
    int humidity;

    temp_c = sht1x.readTemperatureC();
    humidity = sht1x.readHumidity();

    String sht =  (' ') + String(temp_c) + (' ') + String(humidity) ;


    //CLOCK
    DateTime now = RTC.now();

    String dateString = String(now.year()) + ('/') + String(now.month()) + ('/') + String(now.date()) + (' ')
      + String(now.hour()) + (':')  + String(now.minute()) + (':') + String(now.second());


    //SD

    File logFile = SD.open("LOG.csv", FILE_WRITE);
    if (logFile) {

      String dataString = dateString  + adxl + sht;

      logFile.println(dataString);
      delay(d);
      logFile.close();
    }

    else {
      // if the file didn't open, print an error:
      Serial.println("error opening test.txt");
    }

    //ALARM!

    if (angle_x>limit_x ||angle_y>limit_y ||angle_z>limit_z || temp_c>limit_t || humidity>limit_h)
    {
      alarm();
    };

  }

}


int getx(){

  const int analogInPin = 7;  // Analog input pin that the potentiometer is attached to
  float sensorValue = 0;     
  int angle_x = 0;
  int sample[20];
  int i, j, temp;

  for(i=0; i < 20; i++)                   // take 20 sample readings
  { 

    sensorValue = analogRead(analogInPin);  // read the analog in value:   

    sample[i] = 0.75*( 510 - sensorValue);     //  considering 510 is value at Horizantal position

  }



  for(i=0; i < 20; i++)            // BUBBLE SORTINHG puts readings in ascending order     
      for(j=0; j < 20; j++)
    {

      if( sample[j] > sample[j+1])
      {   
        temp = sample[j];
        sample[j] = sample[j+1];
        sample[j+1] = temp;           
      }

    }   


  for ( i=5; i <= 15; i++)      // sum of angle values eleminating first five and last five

    angle_x = angle_x + sample[i];    // inconsistance readings
  angle_x= angle_x/10;            // Average of angle

  return angle_x;

}


int gety(){


  const int analogInPin = 6;  // Analog input pin that the potentiometer is attached to
  float sensorValue = 0;     
  int angle_y = 0;
  int sample[20];
  int i, j, temp;



  for(i=0; i < 20; i++)                   // take 20 sample readings
  { 

    sensorValue = analogRead(analogInPin);  // read the analog in value:   

    sample[i] = 0.75*( 510 - sensorValue);     //  considering 510 is value at y position

  }



  for(i=0; i < 20; i++)            // BUBBLE SORTINHG puts readings in ascending order     
      for(j=0; j < 20; j++)
    {

      if( sample[j] > sample[j+1])
      {   
        temp = sample[j];
        sample[j] = sample[j+1];
        sample[j+1] = temp;           
      }

    }   


  for ( i=5; i <= 15; i++)      // sum of angle values eleminating first five and last five

    angle_y = angle_y + sample[i];    // inconsistance readings
  angle_y= angle_y/10;            // Average of angle

  return angle_y;




int getz(){



  const int analogInPin = 3;  // Analog input pin that the potentiometer is attached to
  float sensorValue = 0;     
  int angle_z = 0;
  int sample[20];
  int i, j, temp;

  for(i=0; i < 20; i++)                   // take 20 sample readings
  { 

    sensorValue = analogRead(analogInPin);  // read the analog in value:   

    sample[i] = 0.75*( 420 - sensorValue);     //  considering 420 is value at y position

  }



  for(i=0; i < 20; i++)            // BUBBLE SORTINHG puts readings in ascending order     
      for(j=0; j < 20; j++)
    {

      if( sample[j] > sample[j+1])
      {   
        temp = sample[j];
        sample[j] = sample[j+1];
        sample[j+1] = temp;           
      }

    }   


  for ( i=5; i <= 15; i++)      // sum of angle values eleminating first five and last five

    angle_z = angle_z + sample[i];    // inconsistance readings
  angle_z= angle_z/10;

  return angle_z;
}



void sentdata() {

  logFile = SD.open("LOG.csv");
  while (logFile.available())
  {
    Serial.write(logFile.read());
  }

}

void ConfigTime() {


  DateTime dt = Serial.read();
  RTC.adjust(dt); //Adjust date-time as defined 'dt' above

}

int wait() {

  int d=Serial.read();
  return d;

}

void alarm() {
  Serial.println("WARNING");

}

int climit_x() {

  int x=Serial.read();
  return x;


}

int climit_y() {

  int y=Serial.read();
  return y;


}

int climit_z() {

  int z=Serial.read();
  return z;


}

int climit_t() {

  int t=Serial.read();
  return t;


}

int climit_h() {

  int h=Serial.read();
  return h;


}


« Last Edit: January 27, 2013, 03:05:46 pm by danmala » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'd suggest that you get rid of the String class. None of the stuff you are doing requires String objects. You can use more than one statement to write data to the file. And should.

I'd also suggest that you learn what Tools + Auto Format does, and use it before posting code. I can't read code that jumps all over the place.
Logged

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

I'll try what you say about the strings.

Also I've edited the previous post with my code with the automatic format.

Thank you.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also I've edited the previous post with my code with the automatic format.
Now, if you could do something about all the blank lines, that would be good. Also, every for loop should have curly braces, even if it contains only one statement. It just makes it much clearer that you intend to repeat just the one statement, as opposed to looking like a mistake.

Code:
  DateTime dt = Serial.read();
  RTC.adjust(dt); //Adjust date-time as defined 'dt' above
You can't stuff a DateTime value in one byte. Serial.read() only reads one byte.

What does the sending code look like? There are plenty of statements that appear to be trying to read an int from the serial port. The Serial.read() function only returns one byte/character from the serial port. If those functions are correctly reading one binary byte from the serial port, the return type of the function should be int.

The biggest problem, though, is that none of those functions check to see if there is actually any data to read, before they read.
Logged

SF Bay Area (USA)
Offline Offline
Tesla Member
***
Karma: 124
Posts: 6652
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
if I could clear the Serial buffer
Code:
void clear_serial_buffer() {
  while (Serial.read() >= 0)  // read characters until there aren't any (-1)
      ;  // but don't do anything else
}
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's nice to provide code that implements OPs explicit request, but, it isn't clear that OP needs to clear the serial buffer. Actually reading all the data in the serial buffer properly is a much better idea. In my humble opinion.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


The problem with (every form of) serial.clear() is that the buffer is only clear just after the inner loop is finished.
Before the next instruction is executed new bytes can arrive.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Left Coast, CA (USA)
Offline Offline
Brattain Member
*****
Karma: 361
Posts: 17263
Measurement changes behavior
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I agree, 'clearing the serial buffer(s) is usually a case of the creator of the sketch not understanding the serial protocol (or lack of same) being used or not using proper program flow structure in their sketch. It's a "I'm confused here and I need a get out jail card so I know from where to start again", kind of thing. A crutch, that probably does much more harm then the problem trying to be addressed.

Lefty
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
A crutch, that probably does much more harm then the problem trying to be addressed.
That's why I always refer to it as "throwing away random amounts of unread data". Never a good idea, in my opinion.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 200
Posts: 12773
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


I spent years dealing with serial communications.  In that time I encountered two situations that warranted clearing a receive buffer...

We often worked with simple radios.  The receiver was always on.  The receiver picked up atmospheric noise and turned it into a continuous stream of garbage.  The proper sequence to exchange data was: turn on the carrier, wait a few milliseconds, clear the receive buffer, transmit, turn off the carrier, sift through incoming data for a proper response.

Receive buffer overrun.  If data continues to be stored after the ring buffer is full, valid data typically becomes corrupt.  This problem is best solved by fixing the reading / parsing code or adding enough CPU time to handle the quantity of data.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Receive buffer overrun. 
Depends very much on how the internal buffer is implemented. IMHO the preferred implementation is to stop adding chars when the buffer is full.
That way the data in the buffer can contain complete packets. It is a waste to flush these before checking them (Checking is often faster than receiving).
Overwriting destroys data which is imho worse that ignoring.

In my arduino UNO I patched hardware serial to count the "overflow bytes", to see if overrun occurs. It adds only a few bytes to the HardwareSerial.cpp implementation. Posted it as an improvement for future. See details - https://github.com/arduino/Arduino/issues/637 -

That said, different application might need different strategies for handling overflow. (no silver bullet)
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pages: [1]   Go Up
Jump to: