Why is SoftwareSerial causing arduino to reboot?

I’m trying to design an RC controller using an Arduino and an XBee Series 2 Pro. I have the hardware serial running for debug information and I want the XBee to be connected to a soft serial on pins 8 and 9.

My arduino keeps restarting, or at least the setup function keeps looping, every time I try to send data through the XBee. If I modify the code so the XBee runs on the hard serial, the program works, but I would rather not have that setup because then to load new code onto the arduino I have to open the controller and disconnect the XBee. I’ve never had a problem using SoftwareSerial for XBees before.

I tried changing the pins that the soft serial runs on and that makes no difference, nor does unplugging the power to the XBee but leaving the serial connections in. I also tried to write another pin high to make sure there’s enough current, and that didn’t cause a restart.

My arduino is connected to the XBee, 4 potentiometers, and 1 switch.

#include <XBee.h>
#include <SoftwareSerial.h>

#define NOTE_A3  220
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_D4  294
#define NOTE_E4  330

#define THR_JOYSTICK A0
#define YAW_JOYSTICK A1
#define RL_JOYSTICK A2
#define FB_JOYSTICK A3
#define POT A4
#define TOGGLE 4
#define SPEAKER_PIN 3
//#define WAKE_PIN 10

#define YAW_MIN 0
#define YAW_OFFSET 386
#define YAW_MAX 815

#define RL_MIN 0
#define RL_OFFSET 359
#define RL_MAX 800

#define FB_MIN 0
#define FB_OFFSET 355
#define FB_MAX 795

#define THR_MIN 0
#define THR_OFFSET 0
#define THR_MAX 754

const int ESC_MIN = 764;
const int ESC_OFFSET = 1500;
const int ESC_MAX = 2000;

XBee xbee = XBee();
SoftwareSerial nss(13,12);
uint8_t payload[10];
// SH + SL Address of receiving XBee
XBeeAddress64 addr64 = XBeeAddress64(0x0013a200, 0x40c67584);
ZBTxRequest packet = ZBTxRequest(addr64, payload, sizeof(payload));
ZBTxStatusResponse txStatus = ZBTxStatusResponse();

void setup() {
  //start serials
  Serial.begin(9600);
  nss.begin(9600);
  xbee.setSerial(nss);

  //pin modes
  pinMode(THR_JOYSTICK,INPUT);
  pinMode(YAW_JOYSTICK,INPUT);
  pinMode(RL_JOYSTICK,INPUT);
  pinMode(FB_JOYSTICK,INPUT);
  pinMode(POT,INPUT);
  pinMode(TOGGLE,INPUT);
  pinMode(SPEAKER_PIN,OUTPUT);

  //delay to allow inputs to settle
  delay(1000);

  //the speaker will need a total resistance of at least 125 Ohm
  //so if it's an 8 Ohm speaker, an additional 117 is needed etc...

   //calibrate THR
  int first = millis();
  tone(SPEAKER_PIN,NOTE_A3);
  int reading = analogRead(THR_JOYSTICK);
  while(reading > THR_OFFSET + 5 || reading < THR_OFFSET - 5) {
    delay(20);
    reading = analogRead(THR_JOYSTICK);
  }
  int dif = 200 - millis() + first;
  if(dif <= 200 && dif >= 0) {
    delay(dif);
  }

  //calibrate YAW
  first = millis();
  tone(SPEAKER_PIN,NOTE_B3);
  reading = analogRead(YAW_JOYSTICK);
  while(reading > YAW_OFFSET + 5 || reading < YAW_OFFSET - 5) {
    delay(20);
    reading = analogRead(YAW_JOYSTICK);
  }
  dif = 200 - millis() + first;
  if(dif <= 200 && dif >= 0) {
    delay(dif);
  }

  //calibrate FB
  first = millis();
  tone(SPEAKER_PIN,NOTE_C4);
  reading = analogRead(FB_JOYSTICK);
  while(reading > FB_OFFSET + 5 || reading < FB_OFFSET - 5) {
    delay(20);
    reading = analogRead(FB_JOYSTICK);
  }
  dif = 200 - millis() + first;
  if(dif <= 200 && dif >= 0) {
    delay(dif);
  }

  //calibrate RL
  first = millis();
  tone(SPEAKER_PIN,NOTE_D4);
  reading = analogRead(RL_JOYSTICK);
  while(reading > RL_OFFSET + 5 || reading < RL_OFFSET - 5) {
    delay(20);
    reading = analogRead(RL_JOYSTICK);
  }
  dif = 200 - millis() + first;
  if(dif <= 200 && dif >= 0) {
    delay(dif);
  }

  //done
  tone(SPEAKER_PIN,NOTE_E4);
  delay(200);
  noTone(SPEAKER_PIN);
  delay(15);
  tone(SPEAKER_PIN,NOTE_E4);
  delay(200);
  noTone(SPEAKER_PIN);
  delay(15);
  tone(SPEAKER_PIN,NOTE_E4);
  delay(350);
  noTone(SPEAKER_PIN);
}

void loop() {
  int POTReading = analogRead(POT);
  int toggle = digitalRead(TOGGLE);

  int throttleValue = mapLimit(analogRead(THR_JOYSTICK) - THR_OFFSET,THR_MIN,THR_MAX - THR_OFFSET,0,ESC_OFFSET);
  int yawValue = mapLimit(analogRead(YAW_JOYSTICK),YAW_MIN,YAW_MAX,ESC_OFFSET-ESC_MAX,ESC_MAX - ESC_OFFSET);
  int rightLeftValue = mapLimit(analogRead(RL_JOYSTICK) - RL_OFFSET,RL_MIN,RL_MAX - RL_OFFSET,0,ESC_MAX - ESC_OFFSET);
  int frontBackValue = mapLimit(analogRead(FB_JOYSTICK) - FB_OFFSET,FB_MIN,FB_MAX - FB_OFFSET,0,ESC_MAX - ESC_OFFSET);
  int potValue = analogRead(POT);
  int toggleValue = digitalRead(toggle);

  //throttle
  payload[0] = throttleValue >> 8 & 0xff;
  payload[1] = throttleValue & 0xff;
  //yaw
  payload[2] = yawValue >> 8 & 0xff;
  payload[3] = yawValue & 0xff;
  //RL
  payload[4] = rightLeftValue >> 8 & 0xff;
  payload[5] = rightLeftValue & 0xff;
  //FB
  payload[6] = frontBackValue >> 8 & 0xff;
  payload[7] = frontBackValue & 0xff;
  //Pot
  payload[8] = potValue >> 8 & 0xff;
  payload[9] = potValue & 0xff;
  //toggle
  payload[10] = (byte) toggleValue;

  //wake XBee
  //digitalWrite(WAKE_PIN,LOW);
  xbee.send(packet);
   if(xbee.readPacket(500)) {
     if(xbee.getResponse().getApiId() == ZB_TX_STATUS_RESPONSE) {
       xbee.getResponse().getZBTxStatusResponse(txStatus);
       if(txStatus.getDeliveryStatus() != SUCCESS) {
         //the remote XBee didn't ACK
         tone(SPEAKER_PIN,NOTE_C4,100); 
       }
     }  
   } else {
     //error or something
     tone(SPEAKER_PIN,NOTE_E4);
     noTone(SPEAKER_PIN);
     tone(SPEAKER_PIN,NOTE_E4,50);  
   }

    //sleep XBee
    //digitalWrite(WAKE_PIN,HIGH);
    delay(100);
}

int mapLimit(int val, int fromLow, int fromHigh, int toLow, int toHigh) {
  int result = map(val,fromLow,fromHigh,toLow,toHigh);
  if(result > toHigh) {
    result = toHigh;
  } else if(result < -toHigh) {
    result = -toHigh;
  }
  return result;
}

Restarting is almost always a power issue. Post a diagram of your wiring.

I also tried to write another pin high to make sure there's enough current, and that didn't cause a restart.

Enough current for what? You should not need to draw any significant amount of power from a digital pin.

I attached an LED to the pin and the arduino was able to support it. I just did a bit more debugging. If I unplug everything from the arduino except the XBee, it still fails, but the example XBee transmit sketch works if I do that.

uint8_t payload[10];

How many elements can this array hold?

  payload[10] = (byte) toggleValue;

Writing beyond the end of the array, and then blaming SoftwareSerial. is not being responsible.

Yeah I realized that yesterday. I guess I just thought an index out of bounds exception wouldn't cause a crash so I didn't think my indexes could have been wrong. Thanks guys

In C and in C++, this does NOT cause an exception. C and C++ expect that you know what you are doing, and happily write beyond the bounds of the array. This can cause a crash. There is no exception to cause a crash.