Serial overflow buffering problem

Hello,

I am reading data from a bunch of xbees, checking and cleaning the data, then sending them off to another program (labview) to do stuff and things.

Labview will read and interpret the data great for a couple of hours to days, then all of a sudden I no longer read any data. That is until I hit the reset button on the arduino.

After some investigation I have a couple of ideas, but nothing seems to work yet. I have tried Serial.flush(), overflow, and stream.flush().

Am I overloading the buffer on the arduino? I send the data to labview immediately after it is checked and cleaned. I have no idea why my arduino is freezing.

Thank you.

Code is below, as well as uploaded

/*

    //////////////////
    // Introduction //
    //////////////////

*/


///////////////
// Libraries //
///////////////
#include <SoftwareSerial.h>

///////////////
// Variables //
///////////////
// Xbee Variables //
int packageLength;  // How large is the package incoming from the Xbee radios
int ID;
boolean proceed = true;
byte checkSumCalc = 0;
byte xbeeByte[30]; // Was 26, lets see if this works.
byte xbeeOut[36]; // For sending commands to gates

//byte discardSum = 0;
byte lengthMSB = 0;
byte lengthLSB = 0;
byte frameType = 0;
byte frameID = 0;

// Serial Available Variables //
byte addy5; // 1st byte of address information
byte addy6;
byte addy7;
byte addy8; // 4th byte of address information
byte save;  // 0x0 = do not save until a 0x2 is read
byte port;  // Which port/digital IO pin on the xbee to command
byte value; // Do you want it high(0x5)(off) or low(0x4)(on) because the arduino reads low as on. May need to change this
char pin;   //  this is a char produced from the port byte. 

/////////////////////////////////
// Communications declarations //
/////////////////////////////////
const int XB_RX = 2;            // XBee's RX (Din) pin *Different pins from Analog in
const int XB_TX = 3;            // XBee's TX (Dout) pin
const int XBEE_BAUD = 9600;     // Your XBee's baud (9600 is default)
const int SERIAL_BAUD = 19200;   // Baud rate for computer communication (make sure it is same for "serial monitor"
SoftwareSerial xB(XB_RX, XB_TX);// Setting up the channels for communication with the zigbee via sparkfun redboard


///////////
// Setup //
///////////
// Setup is the beginning of the program to initialize all pins
// communications, and declarations. This will run only once.
void setup() {
  Serial.begin(SERIAL_BAUD);  // Sets the baud rate for communication via terminal monitor on computer
  xB.begin(XBEE_BAUD);        // Sets the baud rate for communication with the Coordinator receiving Xbee radio
}


//////////
// Loop //
//////////
// This loop will run continuously until batteries run out, or the sun dies.
// Here we will run a few subroutines. One will be to read the sonar, BV and PV.
// Another one will be to send out data through the zigbee radio.
void loop() {

  if (xB.available()) {
    xbeeByte[0] = (int)0;
    xbAvailable();
    proceed = true;
  }

  if (Serial.available()) {
    serialAvailable();
  }

  if (xB.overflow()) {
    Serial.println("Software serial overflow");
  }
}


void xbAvailable() {


  // This section prints out all xb bytes for diagnostics purposes
  
  /*
    for (int i = 0; i < 35; i++) { // reset xbeeByte to 0 and = length to get checksum
    xbeeByte[i] = xB.read();
    Serial.print(xbeeByte[i]); Serial.print(",");
    delay(1);
    }
    Serial.println("End of line biotch");
    delay(10);
  */




  if (xB.available() >=  12 && proceed == true) { // If available # of bytes is greater than 21 proceed

    proceed = false;

    if ((xbeeByte[0] = xB.read()) == 0x7E) {
      for (int i = 1; i < 3; i++) { // reset xbeeByte to 0 and = length to get checksum
        xbeeByte[i] = xB.read();
        delay(1);
      }

      lengthMSB = xbeeByte[1];
      lengthLSB = xbeeByte[2];

      for (int i = 3; i < lengthLSB + 4; i++) { // reset xbeeByte to 0 and = length to get checksum
        xbeeByte[i] = xB.read();
        delay(1);
      }

      frameType = xbeeByte[3];
      frameID = xbeeByte[4];

      checkSumCalc = 0;
      if (frameType == 0x90 || frameType == 0x92) {   //0x90 = 144
        for (int i = 3; i < lengthLSB + 3; i++) {
          checkSumCalc += xbeeByte[i];
          delay(10);
        }

        byte checkSumByte = lengthLSB + 3;
        byte checkSum = xbeeByte[checkSumByte]; // lengthLSB + 3


        checkSumCalc &= 0xFF;
        checkSumCalc = 0xFF - checkSumCalc;

        if (checkSum == checkSumCalc && xbeeByte[lengthLSB + 2] == 69) {
          for (int i = 0; i < lengthLSB + 4; i++) {
            Serial.print(xbeeByte[i]); Serial.print(",");
          }
          Serial.println("");
          delay(1);
        }

        else if (checkSum == checkSumCalc && xbeeByte[2] == 18) {
          for (int i = 0; i < lengthLSB + 4; i++) {
            Serial.print(xbeeByte[i]); Serial.print(",");
          }
          Serial.println("");
          delay(1);
          Serial.flush();

        }
      }
    }
  }
}


///*
void serialAvailable() {

  addy5 = Serial.parseInt();
  addy6 = Serial.parseInt();
  addy7 = Serial.parseInt();
  addy8 = Serial.parseInt();
  save = Serial.parseInt(); // Write all data to xbee yet? 2 = yes, 0 = no
  port = Serial.parseInt();  // Which digital pin to write to?
  value = Serial.parseInt(); // Which value? 0/4 = low, 1/5 = high

  if (save == 0) {
    save = 0x0;
  }
  else if (save == 1) {
    save = 0x2;
  }

  if (value == 0) {
    value = 0x4;
  }
  else if (value == 1) { // 5 = high? But we want it low for now to make it move in that direction. 
    value = 0x5;
  }

  switch (port) {
    case 0:
      pin = '0';
      break;
    case 1:
      pin = '1';
      break;
    case 2:
      pin = '2';
      break;
    case 3:
      pin = '3';
      break;
    case 4:
      pin = '4';
      break;
    case 5:
      pin = '5';
      break;
    case 6:
      pin = '6';
      break;
  }

  command(save, pin, value);

}


void command(byte save, char pin, byte value ) {

  xB.write((byte)0x7E);
  xB.write((byte)0x0);
  xB.write((byte)0x10);
  xB.write((byte)0x17);
  xB.write((byte)0x0);  // Frame ID
  xB.write((byte)0x00); // first byte
  xB.write((byte)0x13); // 2
  xB.write((byte)0xA2); // 3
  xB.write((byte)0x00); // 4
  xB.write(addy5); // 5
  xB.write(addy6); // 6
  xB.write(addy7); // 7
  xB.write(addy8);// 8
  xB.write((byte)0xFF); // "10"67
  xB.write((byte)0xFE);// 10"66"
  xB.write(save);
  xB.write('D');
  xB.write(pin);
  xB.write(value);
  long sum = 0x17 + 0x13 + 0xA2 + addy5 + addy6 + addy7 + addy8 + 0xFF + 0xFE + save + 'D' + pin + value;
  xB.write((byte)0xFF - (sum & 0xFF));
  delay(1);
}

A1_xbAvailable.ino (1.93 KB)

A2_serialAvailable.ino (1.69 KB)

arduino_forum_question.ino (2.48 KB)

    xbeeByte[0] = (int)0;

Why are you casting the 0 to an int to store in a byte?

      for (int i = 1; i < 3; i++) { // reset xbeeByte to 0 and = length to get checksum
        xbeeByte[i] = xB.read();
        delay(1);
      }

12 (or more) bytes are in the buffer waiting to be read. Why are you delay()ing?

  if (save == 0) {
    save = 0x0;
  }

If save is 0, set save to 0. Why?

  save = Serial.parseInt(); // Write all data to xbee yet? 2 = yes, 0 = no
  else if (save == 1) {
    save = 0x2;
  }

So, the comment is wrong, or the code is. What value means that data should be written to the XBee? Why don’t you just send that value?

  switch (port) {
    case 0:
      pin = '0';
      break;
    case 1:
      pin = '1';
      break;
    case 2:
      pin = '2';
      break;
    case 3:
      pin = '3';
      break;
    case 4:
      pin = '4';
      break;
    case 5:
      pin = '5';
      break;
    case 6:
      pin = '6';
      break;
  }

or

   pin = port + '0';

Which is easier to type and maintain?

You are overly fond of useless delay()s. I can’t see a reason for your code to have ANY delay()s.

Hi, I too am concerned about my usage of delays. Unfortunately when I remove a few of them, the program gets completely hung up and doesn't work. So I have had to insert delay(1) here and there. I don't know why.

Why are you casting the 0 to an int to store in a byte?

I don't know why I did that. Brain fart.

12 (or more) bytes are in the buffer waiting to be read. Why are you delay()ing?

I don't know. Ill get rid of it and see if it helps.

If save is 0, set save to 0. Why?

redundancy for my brain to handle hex to dec. I like to have that in there just so I know I am printing/reading hex. Yes I know 0x0 = 0.

So, the comment is wrong, or the code is. What value means that data should be written to the XBee? Why don't you just send that value?

I want to send multiple commands to the xbee, but I need all of them read by the other arduino at once. So I send digital pins 0-5 high or low, and the last transmission I command the xbee to change the pins all at once with a 0x02 command. Otherwise I can't transfer data fast enough and the arduino reads a whole bunch of incorrect data.

pin = port + '0';

I was wondering about this. Are byte and char similar enough that I can just add 1 + '0' and get '1'? That would be awesome, thank you for this!

Thank you for your response.

I just removed the delays, and now I don’t get any serial data printed. Once I put them back in all at delay(1);, the data prints fine again…I don’t know how to get around that.

Are byte and char similar enough that I can just add 1 + '0' and get '1'?

Yes.

Sounds ike a race condition between xbee and code.
Is there an xbee library function to poll that says the xbee has finished what it’s doing? aka done / not busy?

lastchancename:
Sounds ike a race condition between xbee and code.
Is there an xbee library function to poll that says the xbee has finished what it’s doing? aka done / not busy?

There is an XBee library that would handle all the stuff OP is manually doing.

I see no advantage in trying to force the data into an API frame, when the XBee can be put in AT mode, and send strings.

I finally got it all working, but require the delay(1) after each transmission. Also had to add Serial.flush to a different section.

The reason I need to send out API packets is because I have many many many xbee radios set up across my area, and need to communicate specifically with one, and turn on certain digital pins. I have yet to see a way to do this in AT.

There are likely easier ways to crack a nut than using a hammer - perhaps a proven library.

But if the hammer works, and you don't have money/time to buy a cracker, might as well use it.

QVC