XBee module makes SPI fail?

I’m pretty sure this is a problem-between-chair-and-keyboard kind of thing so I’ll try to be brief.

I’m wiring up a simple breadboard circuit with an XBee Series 2 in a Sparkfun breakout board with a BMA180 accelerometer breakout board talking over SPI. I can talk to the BMA180 just fine over SPI (using an Arduino UNO). When I add the XBee, all SPI comms completely fail - I get nothing but zeros. The XBee powers up fine and connects to a coordinator (I have LEDs hooked up to the appropriate “debug” pins.)

I’ve added 10uF and 1uF bypass caps (electrolytics) close to pin 1 on the XBee. When I look at schematics of XBee shields from Arduino.cc or sparkfun, these seem to be the values most commonly used, although the XBee datasheet calls for a 1uf and and 8.2pf (I don’t have an 8.2pf). My bypass caps are also 50V (for the 1uF) and 25V (for the 10uF) so they’re quite probably just the wrong caps for the job.

Does decoupling sound like the problem here? I’m about to shell out for an XBee shield (which includes the caps), but I’d like to figure out if there’s some deeper issue going on here.

Incidentally, another SPI device (MPL115A1 barometer) has the same failure mode. Works great until it sits on the same power bars as the XBee.

Thanks in advance,

-hherhold

No, it does not sound like a de-coupling problem with the XBee but adding those caps is a good idea and will not hurt.

Which processor is the XBee and the Accelerometer connected to???

The problems sound like a coding problem but it could be a power issue. However if the 10uF cap didn’t help then it is more likely a code issue.

Which processor and post your code (in code tags).

Thanks for the reply!

I’m using an Arduino Uno R3. I’ve distilled down the code so that it just starts up SPI and dumps registers to Serial out. If I have the XBee connected to power and GND, I get all zeros (no SPI comm). If I disconnect VCC from the XBee and hit reset on the arduino, the registers dump perfectly.

I am an SPI noob - it’s quite possible there’s just some timing thing I should be setting up in SPI that I’m not doing and that’s what’s making it stop working, especially because two separate SPI devices exhibit the same behavior (the BMA180 accelerometer and an MPL115A1 barometer). I have not toyed with adding in delay()s here and there because I’d like to understand what’s going on before I start altering the timing in random ways.

Also, the 10uF cap I have is an electrolytic. I ordered some ceramics to try that match the data sheet (8.2pf, 1uf, 10uf) but they’re not here yet. Although for decoupling I kinda figured a cap is a cap, more or less, but I could easily be quite mistaken.

Any ideas? Thanks in advance!!!

// BMA SPI Tests

// BMA180 Pins:
// INT is UNO Pin 2
// CS is UNO Pin 7
// MOSI is UNO Pin 11
// MISO is UNO Pin 12
// SCK is UNO Pin 13

// BMA180 SPI Parameters:
// 1. Bit Order: MSB first, so setBitOrder(MSBFIRST).
// 2. Polarity: polarity = 1, phase = 0 (pp. 58), so SPI.setDataMode(SPI_MODE2) 
//        (see http://arduino.cc/en/Reference/SPI).
// NOTE: For some reason the default settings seem to work fine.

// Control Registers. Section 7.10, p.46.
#define BMA180_CTRL_REG0_ADDR 0x0D
#define BMA180_CTRL_REG0_EE_W_BIT 0x10

#define BMA180_CTRL_REG3_ADDR 0x21
#define BMA180_CTRL_REG3_ADV_INT_BIT 0x04

// Offsets. MSB is <11:4>, LSB is <3:0>. You should never have to use
// or change these as these values are set in the factory. Google for
// calibration information if you're feeling really adventurous and
// have your BMA180 mounted securely in something VERY level.
#define BMA180_OFFSET_X_MSB_ADDR     0x38
#define BMA180_OFFSET_Y_MSB_ADDR     0x39
#define BMA180_OFFSET_Z_MSB_ADDR     0x3A
#define BMA180_OFFSET_LSB1_ADDR      0x35
#define BMA180_OFFSET_LSB2_ADDR      0x36

// Also contains Mode Config.
#define BMA180_TCO_Z_ADDR 0x30

#define BMA180_BW_TCS_ADDR 0x20
// BW (Bandwidth) is high-order 4 bits.
#define BMA180_BW_MASK      0xF0
#define BMA180_BW_10HZ      0x00
#define BMA180_BW_20HZ      0x10
#define BMA180_BW_40HZ      0x20
#define BMA180_BW_75HZ      0x30
#define BMA180_BW_150HZ     0x40
#define BMA180_BW_300HZ     0x50
#define BMA180_BW_600HZ     0x60
#define BMA180_BW_1200HZ    0x70
#define BMA180_BW_HIGH_PASS 0x80
#define BMA180_BW_BAND_PASS 0x90

// Chip ID. Reading this to verify connectivity and communication with
// the device is a pretty good idea.
#define BMA180_CHIP_ID_ADDR 0x00

// Acceleration and Temperature data. MSB is <13:6>, LSB is packed 8
// bits (<5:0> 0 new_data_flag).
#define BMA180_ACC_X_LSB_ADDR    0x02
#define BMA180_ACC_X_MSB_ADDR    0x03
#define BMA180_ACC_Y_LSB_ADDR    0x04
#define BMA180_ACC_Y_MSB_ADDR    0x05
#define BMA180_ACC_Z_LSB_ADDR    0x06
#define BMA180_ACC_Z_MSB_ADDR    0x07
#define BMA180_TEMP_ADDR         0x08

#define BMA180_NEW_ACCEL_DATA_BIT   0x01

// Range. Section 7.7.1, p. 27.
// Range is 3 bits, ranging from 1g to 16g. The value is stored in the
// offset_lsb1 register, in the high 3 bits of the lower nibble:
// 0x35 ->   | offset_x<3:0> (lsb) | range<2:0> | smp_skip |
#define BMA180_RANGE_1G          ( 0x00 << 1 )
#define BMA180_RANGE_1_5G        ( 0x01 << 1 )
#define BMA180_RANGE_2G          ( 0x02 << 1 )
#define BMA180_RANGE_3G          ( 0x03 << 1 )
#define BMA180_RANGE_4G          ( 0x04 << 1 )
#define BMA180_RANGE_8G          ( 0x05 << 1 )
#define BMA180_RANGE_16G         ( 0x06 << 1 )
#define BMA180_RANGE_MASK        0x0E

#include <SPI.h>


#define BMA180_INT_PIN  2
#define BMA180_CS_PIN   7

void readFromBMA180( byte startAddress, int numBytesToRead, byte* receiveBuf )
{
  digitalWrite( BMA180_CS_PIN, LOW );
  
  // Bitwise-OR in the R/W bit, bit 8. Datasheet p. 59.
  // 1 = Read, 0 = Write.
  SPI.transfer( startAddress | 0x80 );
  
  for (int i = 0; i < numBytesToRead; i++ )
  {
    receiveBuf[ i ] = SPI.transfer( 0x00 );
  }
  digitalWrite( BMA180_CS_PIN, HIGH );
}

void writeTo( byte registerAddress, byte value )
{
  digitalWrite( BMA180_CS_PIN, LOW );
  
  // Bitwise-AND down the R/W bit, bit 8. Datasheet p. 59.
  // 1 = Read, 0 = Write.
  SPI.transfer( registerAddress & 0xEF );
  SPI.transfer( value );
  
  digitalWrite( BMA180_CS_PIN, HIGH );
}

  
// Some of these are reserved. We just read them all anyway.
byte BMA180RegisterCache[ 0x60 ];  

void dumpRegisterCacheToSerial( )
{
  for ( int i = 0x5F; i > 0x1F; i-- )
  {
    Serial.print( " 0x" ); Serial.print( i, HEX ); Serial.print( "   | " );    // Register Address
    Serial.print( BMA180RegisterCache[ i ], HEX ); Serial.print( "\t| ");  // Value in Hex );
    Serial.println( BMA180RegisterCache[ i ], BIN );
  }   
  for ( int i = 0x10; i > -1; i-- )
  {
    Serial.print( " 0x" ); Serial.print( i, HEX ); Serial.print( "   | " );    // Register Address
    Serial.print( BMA180RegisterCache[ i ], HEX ); Serial.print( "\t| ");  // Value in Hex );
    Serial.println( BMA180RegisterCache[ i ], BIN );
  }
}

void setup()
{
  Serial.begin( 9600 );
  
// Don't seem to need these?? Odd...  
//  SPI.setClockDivider( SPI_CLOCK_DIV2 );
//  SPI.setBitOrder(MSBFIRST);
//  SPI.setDataMode(SPI_MODE0);

  SPI.begin();
  
  pinMode( BMA180_INT_PIN, INPUT );
  pinMode( BMA180_CS_PIN, OUTPUT );
  
  Serial.println( "Start..." );
  
  byte chipID;
  
  readFromBMA180( 0x00, 1, &chipID );
  Serial.println( chipID, HEX ); 
  
  // Update register cache.
  readFromBMA180( 0x00, 0x60, BMA180RegisterCache );  
  dumpRegisterCacheToSerial( );
  
}

void loop()
{
}

Are you connecting the XBee power to +3.3V??? It is a 3.3V device and will not work on 5V.

What is the VCC Voltage you are using?

If the VCC is 3.3V then it is possible that the XBee is drawing too much current and the UNO is not really working.

Measure the VCC with a DVM.

The XBee draws more current when transmitting. This is a sub-millisecond duration. So a DVM might not show that the XBee’s 3.3V load, if regulated down from a source in common to the SPI and CPU devices, might droop during the XBee’s brief transmissions. This is especially true for the XBees with HPA/LAN like the XBee Pro where the transmitter current is higher yet, though brief.

I’m using the 3.3V from the Uno. I have checked it with a DVM and it’s 3.3.

I do have a Sparkfun “power stick” voltage regulator I could use to power the breadboard separate from the Uno. Meaning, I could power the Uno via USB and the breadboard with its own regulator. I’m assuming I should set up a common ground when I do this.

As far as the XBee transmit using up power, the XBee is currently not doing anything. It’s associated with a coordinator but then just sitting there. I believe there are packets that fly back and forth to maintain the link periodically, but I would think that this would then be more of an intermittent problem where SPI would function but not all the time. What I’m seeing, however, is if the XBee is plugged in, SPI completely dies.

Thanks to all for your comments and suggestions. I’m still kinda stumped - any ideas?

(My caps are still en route from Digikey. Once they arrive I’ll plug them in and see if they fix it.)

So this might be a fix.

It appears to be a power issue - if I use the 3.3V power stick to power my breadboard, SPI works fine.

After double-checking the XBee datasheet and the Uno specs, the max current draw from the 3.3V out on the Uno is 50 mA. The XBee draws 40 mA, which, while under 50, is still more than I would have thought. It appears the 3.3V out on the Uno was never really intended to power more than one or maybe two small devices.