Thursday, March 7, 2013

Two XBee Modules Communicate at High Data Rates with a Single Receiver

I now made two head mounted XBee modules with sniff and accelerometer monitoring for a total of 4 ADC channels each.  Each module alone sends a sample from each channel at 1000 / 4 = 250 Hz.  Each 4 sample packet is 16 bytes in length so the XBee is sending 16*250 = 4000 bytes per second or 32 Kbps.

With two modules, I was not sure if the receiving XBee was going to be able to handle twice the data (though the stated RF data rate is 250 Kbps).  A further concern was that my receiving XBee is communicating with an Arduino at 115.2 Kbps so with data from a single remote XBee, we are already one third of the way there.

Surprisingly, everything worked together immediately after a slight tweak of the Arduino code (below).

I can now have two animals with the magnetically connected sensors running around while I monitor sniffing and movement.  The total data rate into the receiving XBee is now 64 Kbps.  In principle I should only be limited by the serial port speed.

Each XBee has a further 2 on-board ADCs which I am planning to use soon.

Next: Adding an on-board amplifier for recording bio-potentials (EMG, LFP, etc).

Two XBee sensor modules and one receiver module hooked up to an Arduino which outputs a total of 8 DAC channels.
Here is the Arduino code:


#include <Wire.h>

#define BUFFER_LEN 64

// constants
#define START_DELIMITER 0x7E
#define API_ID          0x83

// source addresses of two XBee modules
#define SRC1            0x4321
#define SRC2            0x4322

#define PACKET_LEN      0x10
#define N_SAMPLES       0x01

#define MCP4725_ID      0b01100000  

int DAC_BUS_PINS[] = {13,12,11,9,8,7,6,5};
int N_DAC = 4;

int i, j;

byte buffer[BUFFER_LEN];
byte L12[2];
byte dac_bits[2];

int dac_off = 0;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(115200);
  Wire.begin();
  
  
  for (i=0;i<(N_DAC*2);i++)
  {
    pinMode(DAC_BUS_PINS[i],OUTPUT);
    digitalWrite(DAC_BUS_PINS[i],LOW);
  }
  
  dac_bits[0] = 0;
  dac_bits[1] = 0;
}

// the loop routine runs over and over again forever:
void loop() {
  
  int len, addr;
  unsigned char firstByte;
    
  int value, X, Y, Z;
  word adc_val;

  if (Serial.available()) {
  
    firstByte = Serial.read();

    if (firstByte==START_DELIMITER) // start of a packet
    {
      Serial.readBytes((char*)L12,2);
      len = word(L12[0],L12[1]);

      if (len==PACKET_LEN) { // check for API packet of right length
        
        Serial.readBytes((char*)buffer,len);  
               
        addr = (int)word(buffer[1],buffer[2]);
        (addr==SRC2) ? dac_off = 4 : dac_off = 0;
        
       
        //      [ sniff |   X   |   Y   |   Z   ]
        //buffer[  8, 9, 10, 11,  12,13,  14,15 ]
                        
        // DAC Communication
        for (j=0;j<N_DAC;j++)
        {
          // adc value
          value=word(buffer[(j*2)+8],buffer[(j*2)+9]);
          //value=word(buffer[8],buffer[9]);
          adc_val = value*4;
   
          digitalWrite(DAC_BUS_PINS[j+dac_off],HIGH); // address a DAC chip [0b1100011]
          Wire.beginTransmission(99); //99
          Wire.write(0b01000000); // write dac register command [c2 c1 c0 x x pd1 pd0 x]  for write dac c2 = 0, c1 = 1, c0 = 0
          for (i=0;i<8;i++) bitWrite(dac_bits[0],i,bitRead(adc_val,i+4)); // shift bits around for making i2c compatible
          for (i=0;i<4;i++) bitWrite(dac_bits[1],i+4,bitRead(adc_val,i));
          Wire.write(dac_bits[0]);
          Wire.write(dac_bits[1]);
          Wire.endTransmission();
          digitalWrite(DAC_BUS_PINS[j+dac_off],LOW); // null DAC address to [0b1100010]
        } 
        // END DAC Communication  
      }          
    }
  }
  
}

No comments:

Post a Comment