Go Down

Topic: Merging two XBee receivers into a single serial/usb stream? (Read 1 time) previous topic - next topic

kriista

I'm working on a sensor project that has two 9DOF boards with built-in arduinos, each sending data from an XBee to an XBee receiver (so 2 transmitters and 2 receivers). I initially was trying 2 transmitters to 1 receiver but ended up with all sorts of problems with buffer overflow and the serial stream getting all mashed up.

At the moment I'm just using one 'pair' and the XBee receiver is plugged into an XBee usb explorer. Rather than using two XBee explorers I'd like to just have an Arduino on the receive side with 2 XBees plugged into it.

So to do this, do I need to use a Mega since it has more than one hardware serial port? (So each XBee would plug into an independent hardware serial port). Or can I do this with a regular Arduino?

And then in terms of the software, would it just be a sketch on the receiving Arduino that weaves the two streams into one? If so, how would I keep each stream "intact" so that the parsing on my computer doesn't get broken by out of order stuff.

PaulS

Quote
So to do this, do I need to use a Mega since it has more than one hardware serial port?

No, you could use a UNO and SoftwareSerial. Though, the Mega is not that much more, and hardware serial is more reliable.

Quote
If so, how would I keep each stream "intact" so that the parsing on my computer doesn't get broken by out of order stuff.

Start and end of markers around each packet. Each XBee would need to read from one hardware serial (or software serial) port, and then write to the PC-based hardware serial port when the port is not in use.

kriista

I've got a spare Mega on hand so I can just use that.

In terms of the packets, would I need to put those markers in, or are the XBees doing that anyways (in which case I would just parse/split them on the Mega)?

At the moment I'm doing a serial call-response so each sensor/arduino is sending a clump of 20 bytes (9 sensors at 2 bytes each, then 2 more bytes for two switches), and then that's getting split in Max/MSP based on the 20 byte chunk, rather than having the actual packet or sensor bytes tagged.

This is my sensor/arduino code:

Code: [Select]
// i2c Arduino Library
#include <Wire.h>

// 0011110b, i2c 7bit address of HMC5883
#define address 0x1E

// Define sensor variables
int AccX;
int AccY;
int AccZ;
int GyroX;
int GyroY;
int GyroZ;
int SW1 = 9;
int SW2 = 10;

#define aX A0
#define aY A1
#define aZ A2
#define gX A6
#define gY A7
#define gZ A3

// Incoming serial byte
int inByte = 0;

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  // Start serial port at 57600 bps:
  Serial.begin(57600);
 
  // Set incoming switch mode
  pinMode(SW1,INPUT);
  pinMode(SW2,INPUT);
 
  // Start i2c communication
  Wire.begin();
 
  // Put the HMC5883 IC into the correct operating mode
  Wire.beginTransmission(address); //open communication with HMC5883
  Wire.write(0x02); //select mode register
  Wire.write(0x00); //continuous measurement mode
  Wire.endTransmission();
 
  // Send a byte to establish contact until receiver responds
  establishContact(); 
}

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  // Define variables for magnetometer
  int MagX,MagY,MagZ;

  // Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
 
  // If we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    inByte = Serial.read();
   
    AccX = analogRead(aX);
    AccY = analogRead(aY);
    AccZ = analogRead(aZ);
    GyroX = analogRead(gX);
    GyroY = analogRead(gY);
    GyroZ = analogRead(gZ);
   
  // Read data from each axis of magnetometer, 2 registers per axis
  Wire.requestFrom(address, 6);
  if(6<=Wire.available()){
    MagX = Wire.read()<<8; // X msb
    MagX |= Wire.read(); // X lsb
    MagZ = Wire.read()<<8; // Z msb
    MagZ |= Wire.read(); // Z lsb
    MagY = Wire.read()<<8; // Y msb
    MagY |= Wire.read(); // Y lsb
  }
 
  // Send sensor data out
 
  // Accelerometer X 
  Serial.write(highByte(AccX));
  Serial.write(lowByte(AccX));
 
  // Accelerometer Y
  Serial.write(highByte(AccY));
  Serial.write(lowByte(AccY));
 
  // Accelerometer Z
  Serial.write(highByte(AccZ));
  Serial.write(lowByte(AccZ));
 
  // Gyroscope X
  Serial.write(highByte(GyroX));
  Serial.write(lowByte(GyroX));
 
  // Gyroscope Y
  Serial.write(highByte(GyroY));
  Serial.write(lowByte(GyroY));
 
  // Gyroscope Z
  Serial.write(highByte(GyroZ));
  Serial.write(lowByte(GyroZ));
 
  // Magnetometer X
  Serial.write(highByte(MagX));
  Serial.write(lowByte(MagX));
 
  // Magnetometer Y
  Serial.write(highByte(MagY));
  Serial.write(lowByte(MagY));
 
  // Magnetometer Z
  Serial.write(highByte(MagZ));
  Serial.write(lowByte(MagZ));
 
  // Switch 1
  Serial.write(digitalRead(SW1));
 
  // Switch 2
  Serial.write(digitalRead(SW2));
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.write('A');   // send a capital A
    delay(300);
  }
}

PaulS

Quote
In terms of the packets, would I need to put those markers in, or are the XBees doing that anyways (in which case I would just parse/split them on the Mega)?

The XBees may or may not packetize the data, depending on whether or not you are using API mode packeting is done) or not (no packeting is done). The code you posted does not use API mode, so you need to delimit the packets.

kriista

Right, should I do that at source (the arduino attached to the sensors) or when combining the streams in the Mega?
I'm worried about data rates/latency if I have to chub up the packets leaving the sensors again (I'm currently using a call-response method between the sensor arduino and the computer as I was getting wicked buffer locking up problems just sending data willy nilly).

PaulS

Quote
I'm worried about data rates/latency if I have to chub up the packets leaving the sensors again

You need something as simple as
Code: [Select]
Serial.print("<");
// Existing prints
Serial.print(">");


Quote
I'm currently using a call-response method between the sensor arduino and the computer as I was getting wicked buffer locking up problems just sending data willy nilly

You are only sending two extra characters - one at the start and one at the end. Should have no real impact on transmission speed, complexity, etc.

kriista

Ah that makes more sense. I was picturing sticking a header/footer onto each byte, but I guess the receiving Arduino would get a clump of data, then send that whole clump out before reading/sensor the other clump of data (rather than reading/sending each byte as it comes).

Go Up