Mega communication problems

I’m trying to get 2 Arduino megas to communicate via XBee series 1. I know that they’re actually transmitting and receiving data (I checked using X-CTU), but I’m not getting anything when I try to print the battery voltage. It just displays zero the whole time (again, I do know that the bytes are being received). Below is the code I have for the receiver in the pair of XBees, and this is where I’m having the issue.

#include <LiquidCrystal.h>    //library for the LCD

byte incoming;    //incoming serial byte

//variables to store input values from joysticks from the remote
byte X;    //Joystick horizontal movement
byte Y;    //Joystick vertical movement

//variables to store analog input values
int Fresist_L1 = 100;            //Force resistor #1 in left leg; analog pin 0
int Fresist_L2 = 0;            //Force resistor #2 in left leg; analog pin 1
int Fresist_L3 = 0;            //Force resistor #3 in left leg; analog pin 2
int Fresist_R1 = 145;            //Force resistor #1 in right leg; analog pin 3
int Fresist_R2 = 0;            //Force resistor #2 in right leg; analog pin 4
int Fresist_R3 = 0;            //Force resistor #3 in right leg; analog pin 5

//variables to store digital input values
int lcdSw;                   //switch to cycle lcd screens
int PresSw;                  //pump status?

//Internal variables
int CenterSw;               //switch used in conjuction with joysticks to center legs
int BloodSw;                //switch to control the "blood pump"
byte connection;            //show if MATT is connected
int screen = 0;             //variable to store screen selection of LCD
long minutesD = 1;          //Set minutes til death after testing
long secondsD = 2;          //Set seconds til death after testing
int Eminutes, Eseconds;     //Elapsed time
int minsD, secsD;           //Time until death
int pumpStartTime=0;        //time the pump is turned on
int count = 0;
int Dmins = 1;              //minutes until MATT dies
int Dsecs = 2;              //seconds until MATT dies
long totalSeconds;
int serial_count = 0;
static unsigned long TotalFlowL = 0;    //freq of L flow sensor
static unsigned long TotalFlowR = 0;    //freq of R flow sensor
int intRemBatVolt, decRemBatVolt, RemBatVolt;

//Digital pin assignments
int Hservo = 4;        //PWM
int Vservo = 5;        //PWM
int BldPum = 25;
int LCD_RS = 26;
int LCD_EN = 27;
int LCD_D4 = 28;
int LCD_D5 = 29;
int LCD_D6 = 30;
int LCD_D7 = 31;
int LCD_Sw = 32;
int Pres_Sw = 33;

//Analog input pin assignments
int FSR_L1 = 0;
int FSR_L2 = 1;
int FSR_L3 = 2;
int FSR_R1 = 3;
int FSR_R2 = 4;
int FSR_R3 = 5;
int BatVol = 6;

//LiquidCrystal lcd( RS, Enable, D4, D5, D6, D7 )
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);

  // setup pins as input and output 
  pinMode(Hservo, OUTPUT);      //Horiz PWM control of leg
  pinMode(Vservo, OUTPUT);      //Vert PWM control of leg
  pinMode(Pres_Sw, INPUT);      //Pressure switch sensor
  pinMode(BldPum, OUTPUT);      //Blood pump control relay
  pinMode(LCD_RS, OUTPUT);      //LCD RS pin 4
  pinMode(LCD_EN, OUTPUT);      //LCD Enable pin 6
  pinMode(LCD_D4, OUTPUT);      //LCD D4 pin 11
  pinMode(LCD_D5, OUTPUT);      //LCD D5 pin 12
  pinMode(LCD_D6, OUTPUT);      //LCD D6 pin 13
  pinMode(LCD_D7, OUTPUT);      //LCD D7 pin 14

  lcd.begin(20,4);
  lcd.clear();
  Serial.flush();
}

void loop() {
  screen = LCD(screen);
  //Handshake
  while (count == 0) {
    Serial.print(255, BYTE);
    Serial.print(1, BYTE);
    incoming = Serial.read();
    if (int(incoming) == 255) {
      connection = Serial.read();
      if (int(connection) == 1) {
        Serial.flush();
        count = 10;
      }
    }
  }

  //Set pump start time
  if (Serial.read() == 252) {
    BloodSw = Serial.read();
    if ((BloodSw == HIGH) && (connection == 1)) {
      if (count == 10) {
        pumpStartTime = millis();
        count = 50;
      }
    }
  }

  //Used to calculate frequency of flow sensors
  if ((millis() % 1000) == 0) {
    if (TotalFlowL == 0) {
      LzeroCount++;
    }
    else if (TotalFlowL > 0) {
      LzeroCount--;
    }
    if (TotalFlowR == 0) {
      RzeroCount++;
    }
    else if (TotalFlowR > 0) {
      RzeroCount--;
    }
    TotalFlowL = 0;
    TotalFlowR = 0;
  }

  //read incoming serial data and determine which SYNC
  if (Serial.available() > 0) {
    incoming = Serial.read();
    if (Serial.available() > 0) {
      //SYNC with remote / handshake
      if (int(incoming) == 255) {
        connection = Serial.read();
      }    

      //Left joystick/leg, horizontal direction
      if (int(incoming) == 254) {
        X = Serial.read();
        X = map(int(X), 0, 245, 0, 1023);
        analogWrite(Hservo, int(X));      
      }

      //Joystick/leg, vertial direction
      if (int(incoming) == 253) {
        Y = Serial.read();
        Y = map(int(Y), 0, 245, 0, 1023);
        analogWrite(Vservo, int(Y));
      }

      //Turn blood pump on/off
      if (int(incoming) == 252) {
        BloodSw = Serial.read();
        if (int(BloodSw) == 1) {
          digitalWrite(BldPum, HIGH);
        }
        else if (int(BloodSw) == 0) {
          digitalWrite(BldPum, LOW);
        }
      }

      //AutoMATT
      if (int(incoming) == 251) {
        AutoMATT = Serial.read();
      }

      //Remote's Battery Voltage
      if (int(incoming) == 250) {
        RemBatVolt = int(Serial.read());
        RemBatVolt = map(RemBatVolt, 0, 245, 0, 1023);
        intRemBatVolt = RemBatVolt / 83;
        decRemBatVolt = RemBatVolt % 83;
      }
    }
  }

  Fresist_L = average(Fresist_L1, Fresist_L2, Fresist_L3);
  Fresist_R = average(Fresist_R1, Fresist_R2, Fresist_R3);

  if (serial_count > 45) {
    //Sending data
    Serial.print(255, BYTE);              //Connected?
    Serial.print(1, BYTE);

    Serial.print(254, BYTE);
    Serial.print(BloodSw, BYTE);          //Blood pumping?

    Serial.print(253, BYTE);
    Serial.print(Lbloodflow, BYTE);       //Left leg bleeding?

    Serial.print(252, BYTE);
    Serial.print(Rbloodflow, BYTE);       //Right leg bleeding?

    Serial.print(251, BYTE);
    Serial.print(Vbloodflow, BYTE);       //Vein bleeding?

    //Need to know how many force sensors will be used to determine
    //how many variables/SYNCs are needed

    Serial.print(250, BYTE);
    Serial.print(Fresist_L, BYTE);       //max force in L leg

    Serial.print(249, BYTE);
    Serial.print(Fresist_R, BYTE);       //max force in R leg

    serial_count = 0;
  }
  serial_count++;
}

int average(int a, int b, int c) {
  int avg = a + b + c;
  avg = avg/3;
  return avg;
}

int LCD(int S) {
  lcdSw = digitalRead(LCD_Sw);
  //Splash Screen
  if (S == 0) {                
    lcd.setCursor(3,2);
    if (connection == 1) {
      lcd.print("  Connected  ");
    }
    else if (connection == 0) {
      lcd.print("Not Connected");
    }
    if (connection == 1) {
      lcd.clear();
      return 1;
    }
    else {
      return 0;
    }
  }
  //Battery Screen
  if (S == 1) {
    delay(60);
    lcd.setCursor(0,0);
    lcd.print("Remote Batt.: ");
    lcd.print(intRemBatVolt,DEC);
    lcd.print(".");
    lcd.print(decRemBatVolt,DEC);
    lcd.print("V");
    lcd.setCursor(0,1);
    if (lcdSw == HIGH) {
      delay(150);
      lcd.clear();
      return 2;
    }
    else {
      return 1;
    }
  }    

  //Miscellaneous Screen
  if (S == 2) {
    delay(60);
    //Display length of exercise
    LCD_printTime(Dmins, Dsecs);

    if (lcdSw == HIGH) {
      delay(150);        //allow time for button to be depressed
      lcd.clear();
      return 1;
    }
    else {
      return 2;
    }
  }


}

void LCD_printTime(int Dmins, int Dsecs) {
  totalSeconds = (millis() - pumpStartTime)/1000;
  long Eminutes = floor(totalSeconds/60);
  long Eseconds = floor(totalSeconds - (Eminutes*60));
  //print values to lcd
  lcd.setCursor(0,0);
  lcd.print("Time Elapsed: ");
  lcd.print(Eminutes);
  lcd.print(":");
  if (Eseconds < 10) {
    lcd.print(0);
  }
  lcd.print(Eseconds);
  //Time until death
  long totalSeconds_Death = (Dmins*60) + Dsecs - totalSeconds;
  lcd.setCursor(0,1);
  lcd.print("Dead In: ");
  int Dminutes = floor(totalSeconds_Death/60);
  int Dseconds = floor(totalSeconds_Death - (Dminutes*60));
  if ((Dminutes < 1) && (Dseconds < 0)) {
    lcd.print("-");
    totalSeconds_Death = (-1)*totalSeconds_Death;
    Dminutes = floor(totalSeconds_Death/60);
    Dseconds = floor(totalSeconds_Death - (Dminutes*60));
  }

  //Print values to lcd
  lcd.print(Dminutes);
  lcd.print(":");
  if (Dseconds < 10) {
    lcd.print(0);
  }
  lcd.print(Dseconds);
}

Any suggestions? My guess was that the XBee receiving buffer was filling up too quickly and the bytes were being dropped, but that doesn’t seem to be the case.

I see several Serial.read() calls, but no Serial.available() call. You are trying to read data that you do not know is available to read.

You are flushing the serial buffer in at least two places. This is not a call that you should be making, unless you know what it is doing, and have very good reason to be doing so.

Do you know that you are receiving a 250?

I see several Serial.read() calls, but no Serial.available() call. You are trying to read data that you do not know is available to read.

I didn't think it was necessary. I could be wrong. I thought that because I knew data was being transmitted continuously, I could just read in data continuously. Please let me know if that is wrong.

You are flushing the serial buffer in at least two places. This is not a call that you should be making, unless you know what it is doing, and have very good reason to be doing so.

The serial flushes were being used to remove all erroneous and left-over data. One I called in the setup to clear whatever might be remaining in the buffer, and the other was called after a connection between the two XBees had been verified, so I wanted to make sure that the buffer was empty in order to begin receiving relevant data.

Do you know that you are receiving a 250?

Yes, I do know that I am receiving a 250. At least, I know that the XBee is receiving a 250. I verified that using the terminal in X-CTU.

I did forget to mention that I do sometimes receive (correct) values for the voltage, but I never know when it will be or how often.

I didn't think it was necessary. I could be wrong. I thought that because I knew data was being transmitted continuously, I could just read in data continuously. Please let me know if that is wrong.

That is indeed wrong. Serial data, even continuously sent is very much slower then the average software loop. So while you might occasionally luckily read a valid character you will also 'receive' many junk characters if you don't first check data.available before each read statement to make sure there is a valid complete character in the receive buffer ready to be read.

Lefty

I do actually have Serial.available() checks before I do read values for most of the Serial.read(). I did, however, add it to the code at the beginning of the loop:

  while (count == 0) {
    Serial.print(255, BYTE);
    Serial.print(1, BYTE);
    if (Serial.available() > 0) {
      incoming = Serial.read();
    }
    if (int(incoming) == 255) {
      if (Serial.available() > 0) {
        connection = Serial.read();
      }
      if (int(connection) == 1) {
//        Serial.flush();
        count = 10;
      }
    }
  }

and I also moved

if ((BloodSw == HIGH) && (connection == 1)) {
      if (count == 10) {
        pumpStartTime = millis();
        count = 50;
      }
    }

to the section where I was reading in values so that the code now reads:

...
//Turn blood pump on/off
      if (int(incoming) == 252) {
        BloodSw = Serial.read();
        if (int(BloodSw) == 1) {
          digitalWrite(BldPum, HIGH);
        }
        else if (int(BloodSw) == 0) {
          digitalWrite(BldPum, LOW);
        }
        //Set Pump start time
        if ((BloodSw == HIGH) && (connection == 1)) {
          if (count == 10) {
            pumpStartTime = millis();
            count = 50;
          }
        }
      }
...

do you see any other places where I might've made a mistake?

Well, I just uploaded and tested those changes, and I think that fixed my problem. Thanks so much for your help!

Just one thing, for future reference:

if (int(incoming) == 255)
if (int(connection) == 1)

The variables incoming and connection are declared as byte, and are being compared to byte sized values. There is no reason to convert the byte to an int before comparing it.

Thank you for the extra help!