Sunday, June 26, 2016

Info on number conversions - SUCCESS updated!

Update:   The m file from the Matlab file exchange works!!!
The function is hexsingle2num.h

Here's what I typed:
hexsingle2num('401c0000')
It returned the correct answer 2.4375

To test:  I believe the api frame sends the bytes as 00 00 1C 40

So, the bytes need to be switched to put it into the new function.


Here's a really good explanation by Jack Christensen - scroll down to his second entry.
http://forum.arduino.cc/index.php?topic=211723.0

Here's a good converter that gives the same values as the BNO055 sensor and the library and the use of the C union struct.
http://www.h-schmidt.net/FloatConverter/IEEE754.html


Info on number conversions

Here's a really good explanation by Jack Christensen - scroll down to his second entry.
http://forum.arduino.cc/index.php?topic=211723.0

Here's a good converter that gives the same values as the BNO055 sensor and the library and the use of the C union struct.
http://www.h-schmidt.net/FloatConverter/IEEE754.html


Monday, June 20, 2016

Similar projects


Reference to hip, knee, ankle!
http://www.mathworks.com/matlabcentral/answers/144385-storing-arduino-serial-data-to-cell-array


Two BNO055, two xbees, two arduinos sending data to coordinator


This works!

Each arduino has code from this blog post: http://xbeematlabsiena.blogspot.com/2016/06/txbno055-arduino-code-success.html.  The name of the file is Tx_BNO055_Success_6_20_16.ino

The api packets are received by the coordinator as seen in the XCTU software.

Configuration settings are important!!!
One xbee was transmitting really fast and the other was really slow.  I wasn't sure if it was a difference in boards:  arduino uno, spark fun shield, or xbee.  I saved the xctu configuration file for my fast xbee and loaded it onto the slow xbee.  Voila - it started transmitting faster.

I'm not sure what change to the settings makes the xbee transmit faster.  It could be IC = 10 or IA = FFFFFFFF



Xbee CTU profile files

Coordinator

file name:  Coord_config_xctu_profile.xml
<?xml version="1.0" encoding="UTF-8"?>

<data>
  <profile>
    <description_file>xb24_15_4_10ed.xml</description_file>
    <settings>
      <setting command="CH">C</setting>
      <setting command="ID">3332</setting>
      <setting command="DH">0</setting>
      <setting command="DL">FFFF</setting>
      <setting command="MY">1234</setting>
      <setting command="MM">0</setting>
      <setting command="RR">0</setting>
      <setting command="RN">0</setting>
      <setting command="NT">19</setting>
      <setting command="NO">0</setting>
      <setting command="CE">1</setting>
      <setting command="SC">1FFE</setting>
      <setting command="SD">4</setting>
      <setting command="A1">0</setting>
      <setting command="A2">0</setting>
      <setting command="EE">0</setting>
      <setting command="KY"></setting>
      <setting command="NI">0x20COORDINATOR</setting>
      <setting command="PL">4</setting>
      <setting command="CA">2C</setting>
      <setting command="SM">0</setting>
      <setting command="ST">1388</setting>
      <setting command="SP">0</setting>
      <setting command="DP">3E8</setting>
      <setting command="SO">0</setting>
      <setting command="BD">3</setting>
      <setting command="NB">0</setting>
      <setting command="RO">3</setting>
      <setting command="AP">2</setting>
      <setting command="D8">0</setting>
      <setting command="D7">1</setting>
      <setting command="D6">0</setting>
      <setting command="D5">1</setting>
      <setting command="D4">0</setting>
      <setting command="D3">0</setting>
      <setting command="D2">0</setting>
      <setting command="D1">0</setting>
      <setting command="D0">0</setting>
      <setting command="PR">FF</setting>
      <setting command="IU">1</setting>
      <setting command="IT">1</setting>
      <setting command="IC">0</setting>
      <setting command="IR">0</setting>
      <setting command="P0">1</setting>
      <setting command="P1">0</setting>
      <setting command="PT">FF</setting>
      <setting command="RP">28</setting>
      <setting command="IA">FFFFFFFFFFFFFFFF</setting>
      <setting command="T0">FF</setting>
      <setting command="T1">FF</setting>
      <setting command="T2">FF</setting>
      <setting command="T3">FF</setting>
      <setting command="T4">FF</setting>
      <setting command="T5">FF</setting>
      <setting command="T6">FF</setting>
      <setting command="T7">FF</setting>
      <setting command="DD">10000</setting>
      <setting command="CT">64</setting>
      <setting command="GT">3E8</setting>
      <setting command="CC">2B</setting>
    </settings>
  </profile>
</data>
-----------------------------------------

End Device

file name:  End_device_config_xctu_profile.xml

<?xml version="1.0" encoding="UTF-8"?>

<data>
  <profile>
    <description_file>xb24_15_4_10ed.xml</description_file>
    <settings>
      <setting command="CH">C</setting>
      <setting command="ID">3332</setting>
      <setting command="DH">0</setting>
      <setting command="DL">1234</setting>
      <setting command="MY">5678</setting>
      <setting command="MM">0</setting>
      <setting command="RR">0</setting>
      <setting command="RN">0</setting>
      <setting command="NT">19</setting>
      <setting command="NO">0</setting>
      <setting command="CE">0</setting>
      <setting command="SC">1FFE</setting>
      <setting command="SD">4</setting>
      <setting command="A1">0</setting>
      <setting command="A2">0</setting>
      <setting command="EE">0</setting>
      <setting command="KY"></setting>
      <setting command="NI">0x20SENSOR</setting>
      <setting command="PL">4</setting>
      <setting command="CA">2C</setting>
      <setting command="SM">0</setting>
      <setting command="ST">1388</setting>
      <setting command="SP">0</setting>
      <setting command="DP">3E8</setting>
      <setting command="SO">0</setting>
      <setting command="BD">3</setting>
      <setting command="NB">0</setting>
      <setting command="RO">3</setting>
      <setting command="AP">2</setting>
      <setting command="D8">0</setting>
      <setting command="D7">1</setting>
      <setting command="D6">0</setting>
      <setting command="D5">1</setting>
      <setting command="D4">3</setting>
      <setting command="D3">0</setting>
      <setting command="D2">0</setting>
      <setting command="D1">0</setting>
      <setting command="D0">0</setting>
      <setting command="PR">FF</setting>
      <setting command="IU">1</setting>
      <setting command="IT">1</setting>
      <setting command="IC">10</setting>
      <setting command="IR">0</setting>
      <setting command="P0">1</setting>
      <setting command="P1">0</setting>
      <setting command="PT">FF</setting>
      <setting command="RP">28</setting>
      <setting command="IA">FFFFFFFFFFFFFFFF</setting>
      <setting command="T0">FF</setting>
      <setting command="T1">FF</setting>
      <setting command="T2">FF</setting>
      <setting command="T3">FF</setting>
      <setting command="T4">FF</setting>
      <setting command="T5">FF</setting>
      <setting command="T6">FF</setting>
      <setting command="T7">FF</setting>
      <setting command="DD">10000</setting>
      <setting command="CT">64</setting>
      <setting command="GT">3E8</setting>
      <setting command="CC">2B</setting>
    </settings>
  </profile>
</data>

Sunday, June 19, 2016

Next steps


MATLAB

Now that the coordinator is receiving the packets, how do we read them in Matlab?

  1. Start with the RPI Matlab code
    1. Count how many bytes to get to the data
    2. Display data values - are they hex, string, uint?
    3. Convert 4 bytes to float for x,y,z, a_x, a_y, and a_z
  2. Plot in real time

More XBEES and BNO055's

  1. Add another sensor/xbee/arduino combo
  2. Do we see multiple RX frames in the XCTU console?
  3. Interestingly, it doesn't seem to matter the DL setting on the coordinator.  That's nice as we can send a message to multiple end device xbees at once.
  4. Will our BNO055's always be close to each other?  If so, the delay in receiving the signal to start from the coordinator should be negligible.

Reading from sensor

  1. Google tells me that Series 1 xbees have a 100 byte buffer.  If we read the sensor once, we have an API packet that is 29 bytes:  5 + 24 bytes of data.  Therefore, we can only read the sensor 3 times for each API packet.  Can we squeeze one more byte in there to get 4 reads per api frame?
  2. Do we want to consider using the I/O frames instead of the TX/RX frames?  Do the I/O frames have fewer than 5 extra bytes?
  3. I have a delay of 100 ms in void loop in the arduino.  How fast can we go?
  4. Can we minimize the arduino code to decrease clock time between reads?
  5. De we really need the x,y,z values as often as accel values?

Tx_BNO055 Arduino Code Success

This code transmits the 3 position values and 3 acceleration values from a remote end device xbee in API 2 mode connected to an Arduino and sends it to a coordinator xbee connected to an explorer shield.  The data is read by XCTU.

Coordinator:
DL:  anything
MY:  1234
CE:  Coordinator(1)
AP:  API-2

End Device:
DL:  1234 (note it sends to coordinator
MY:  5678
CE: End Device(0)
AP: API-2

This is what success looks like!  Notice the 24 bytes of data to the right of the screen!  Question is whether we can convert them back into floats and get the correct values.






This code uses Andrew Rapp's xbee.h library as well as Adafruit's libraries.

/**
 * Copyright (c) 2009 Andrew Rapp. All rights reserved.
 *
 * This file is part of XBee-Arduino.
 *
 * XBee-Arduino is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * XBee-Arduino is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XBee-Arduino.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <XBee.h>

XBee xbee = XBee();
unsigned long start = millis();

// allocate two bytes for to hold a 10-bit analog reading
uint8_t payload[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };

// 16-bit addressing for Series 1: Enter address of remote XBee, typically the coordinator
Tx16Request tx = Tx16Request(0x1234, payload, sizeof(payload));
TxStatusResponse txStatus = TxStatusResponse();
//initialize BNo055
Adafruit_BNO055 bno = Adafruit_BNO055();
int x = 0;

void setup() {
  Serial.begin(9600);
  xbee.setSerial(Serial); //MAKE SURE to move the UART switch to UART when running the program.  Switch to DLine when uploading program.
   /* Initialise the BNO055 sensor */
  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
}

void loop() {
  union flintbyte { //this is a C construct to convert float to 4 bytes
float ff; //to gain access to bytes of float
unsigned int ii; //to gain access to bytes of int
unsigned char cc[4]; //as many as needed to cover the largest other element
} fib;


   // start transmitting after a startup delay.  Note: this will rollover to 0 eventually so not best way to handle
    if (millis() - start > 15000) {
      // break down 10-bit reading into two bytes and place in payload
//      pin5 = analogRead(5);
//      payload[0] = pin5 >> 8 & 0xff;
//      payload[1] = pin5 & 0xff;
   
        imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);
        imu::Vector<3> acc = bno.getVector(Adafruit_BNO055::VECTOR_ACCELEROMETER);
        /*This way works!
        x=(int)(euler.x()*100);
        payload[0] = x >> 8 & 0xff;
        payload[1] = x & 0xff;
        Serial.print(euler.x());
        Serial.print("   ");
        Serial.print(pin5);
        Serial.print("   ");
        Serial.print(payload[0],HEX);
        Serial.print("   ");
        Serial.println(payload[1],HEX);
         xbee.send(tx);
         */
     
         fib.ff=euler.x();
         payload[3] = fib.cc[3];
         payload[2] = fib.cc[2];
         payload[1] = fib.cc[2];
         payload[0] = fib.cc[0];
         fib.ff=euler.y();
         payload[7] = fib.cc[3];
         payload[6] = fib.cc[2];
         payload[5] = fib.cc[2];
         payload[4] = fib.cc[0];      
         fib.ff=euler.z();
         payload[11] = fib.cc[3];
         payload[10] = fib.cc[2];
         payload[9] = fib.cc[2];
         payload[8] = fib.cc[0];
         fib.ff=acc.x();
         payload[15] = fib.cc[3];
         payload[14] = fib.cc[2];
         payload[13] = fib.cc[2];
         payload[12] = fib.cc[0];
          fib.ff=acc.y();
         payload[19] = fib.cc[3];
         payload[18] = fib.cc[2];
         payload[17] = fib.cc[2];
         payload[16] = fib.cc[0];
         fib.ff=acc.z();
         payload[23] = fib.cc[3];
         payload[22] = fib.cc[2];
         payload[21] = fib.cc[2];
         payload[20] = fib.cc[0];        
//         Serial.print(fib.ff);Serial.print('=');
//         Serial.print(fib.cc[3],HEX);Serial.print(','); //print the bytes, 3F,9D,70,A4
//         Serial.print(fib.cc[2],HEX);Serial.print(',');
//         Serial.print(fib.cc[1],HEX);Serial.print(',');
//         Serial.println(fib.cc[0],HEX);
//         fib.cc[0] ^= 1; //toggle LSB of mantissa in IEEE754
//         Serial.println(fib.ff);Serial.print(',');
//         //Serial.println((fib.ff-1.23)*1000000.0); //difference is 1.2e-7
         xbee.send(tx);
    }

    // after sending a tx request, we expect a status response
    // wait up to 5 seconds for the status response
    if (xbee.readPacket(5000)) {
        // got a response!

        // should be a znet tx status            
    if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {
      xbee.getResponse().getTxStatusResponse(txStatus);
   
      // get the delivery status, the fifth byte
           if (txStatus.getStatus() == SUCCESS) {
            // success.  time to celebrate

           }
        }    
    } else if (xbee.getResponse().isError()) {
      //nss.print("Error reading packet.  Error code: ");
      //nss.println(xbee.getResponse().getErrorCode());
      // or flash error led
    }
 
    delay(100);
}

Code for sending x value from BNo055 from end device to coordinator

This works!  I get an RX packet on XCTU.  But, converting from float to bytes isn't working.  Next thing to figure out.


#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <XBee.h>
//#include <SoftwareSerial.h>

XBee xbee = XBee();

unsigned long start = millis();

// allocate two bytes
uint8_t payload[] = { 0, 0 };

// 16-bit addressing: Enter address of remote XBee, typically the coordinator
Tx16Request tx = Tx16Request(0x1234, payload, sizeof(payload));

TxStatusResponse txStatus = TxStatusResponse();
Adafruit_BNO055 bno = Adafruit_BNO055();
int x = 0;

void setup() {
  Serial.begin(9600);
  xbee.setSerial(Serial); //MAKE SURE to move the UART switch to UART when running the program.  Switch to DLine when uploading program.
   /* Initialise the sensor */
  if(!bno.begin())
  {
    /* There was a problem detecting the BNO055 ... check your connections */
    Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
}

void loop() {
 
   // start transmitting after a startup delay.  Note: this will rollover to 0 eventually so not best way to handle
    if (millis() - start > 15000) {
      // break down 10-bit reading into two bytes and place in payload
     
        imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);

  //This calculation of multiplying by 100 and then converting to an int doesn't seem to work or I don't  
 //understand the results!
        x=(int)(euler.x()*100);
        payload[0] = x >> 8 & 0xff;
        payload[1] = x & 0xff;
     
        //Serial.print(x);
        Serial.print("   ");
        Serial.print(payload[0],HEX);
        Serial.print("   ");
        Serial.println(payload[1],HEX);
         xbee.send(tx);
    }
 
    // after sending a tx request, we expect a status response
    // wait up to 5 seconds for the status response
    if (xbee.readPacket(5000)) {
        // got a response!

        // should be a znet tx status            
    if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {
      xbee.getResponse().getTxStatusResponse(txStatus);
   
      // get the delivery status, the fifth byte
           if (txStatus.getStatus() == SUCCESS) {
            // success.  time to celebrate
               // or flash status led

           }
        }    
    } else if (xbee.getResponse().isError()) {
      //nss.print("Error reading packet.  Error code: ");
      //nss.println(xbee.getResponse().getErrorCode());
      // or flash error led
    }
   
    delay(1000);
}

Ideas for sending the BNO055 data through xbees

It's not straightforward to send the BNO055 data from the end device xbee to the coordinator xbee.

1.  The position and acceleration data output from R_Plotrawdata3_test.ino are float.  In the arduino ide a float is 4 bytes.  The API packets require bytes, not float values.

2.  There are two ways to send the data:
     a.  Multiply the float data by 10000 and convert to an int, then convert to two bytes in the arduino code.  Then convert back in the receiving code.
     b.  Use the C union structure.  Here's an example - note that this structure uses 7 bytes, we'd only use 4 bytes, but it's good to see if you want other info included.  Also note that they are using Andrew Rapp's xbee library for series 2 xbees when they make the call with ZBTxRequest.  We'd change that to the series 1 call.:
typedef union {
typedef struct{
  uint16_t t_count;   //2 byte
  byte    year; //1 byte
  float   myfloat; //4 byte
} LOG_DATA_STRUCTURE;
    LOG_DATA_STRUCTURE vals;
uint8_t xbeePl[7]; //7 bytes same a vals
} MYPACKET;

// declare a variable type MYPACKET
MYPACKET exbee;

...

exbee.vals.t_count = x;
exbee.vals.year = y;
exbee.vals.myfloat = z;
ZBTxRequest zbTx = ZBTxRequest(addr64, exbee.xbeePl, sizeof(exbee.xbeePl));
ZBTxStatusResponse txStatus = ZBTxStatusResponse();
xbee.send(zbTx);

3.  The BNO055.cpp library converts the 6 bytes of data that it receives from the BNO055 to float.  How can we get these bytes before the conversion?  Seems silly to have the code convert to float and back to bytes, taking extra processor time.  To do:  learn more about the BNO055 libraries.  Maybe we can get the 6 byte data before it is converted in the getVector() function.  Here's the function from the BNO055.cpp library:

/**************************************************************************/
/*!
    @brief  Gets a vector reading from the specified source
*/
/**************************************************************************/
imu::Vector<3> Adafruit_BNO055::getVector(adafruit_vector_type_t vector_type)
{
  imu::Vector<3> xyz;
  uint8_t buffer[6];
  memset (buffer, 0, 6);

  int16_t x, y, z;
  x = y = z = 0;

  /* Read vector data (6 bytes) */
  readLen((adafruit_bno055_reg_t)vector_type, buffer, 6);

  x = ((int16_t)buffer[0]) | (((int16_t)buffer[1]) << 8);
  y = ((int16_t)buffer[2]) | (((int16_t)buffer[3]) << 8);
  z = ((int16_t)buffer[4]) | (((int16_t)buffer[5]) << 8);

  /* Convert the value to an appropriate range (section 3.6.4) */
  /* and assign the value to the Vector type */
  switch(vector_type)
  {
    case VECTOR_MAGNETOMETER:
      /* 1uT = 16 LSB */
      xyz[0] = ((double)x)/16.0;
      xyz[1] = ((double)y)/16.0;
      xyz[2] = ((double)z)/16.0;
      break;
    case VECTOR_GYROSCOPE:
      /* 1rps = 900 LSB */
      xyz[0] = ((double)x)/900.0;
      xyz[1] = ((double)y)/900.0;
      xyz[2] = ((double)z)/900.0;
      break;
    case VECTOR_EULER:
      /* 1 degree = 16 LSB */
      xyz[0] = ((double)x)/16.0;
      xyz[1] = ((double)y)/16.0;
      xyz[2] = ((double)z)/16.0;
      break;
    case VECTOR_ACCELEROMETER:
    case VECTOR_LINEARACCEL:
    case VECTOR_GRAVITY:
      /* 1m/s^2 = 100 LSB */
      xyz[0] = ((double)x)/100.0;
      xyz[1] = ((double)y)/100.0;
      xyz[2] = ((double)z)/100.0;
      break;
  }

  return xyz;
}

Here's a site that talks about it specifically for the arduino and xbee and the xbee.h library:
http://forum.arduino.cc/index.php?topic=123432.0

4.  The BNO055 has a UART mode.  Can remove the arduino on the end device and send API packets with the serial data?  Then we can run the BNO055 library on an arduino attached to the coordinator and host computer.

BNO055 library and miscellaneous info

BNo055 data sheet from Bosch:
https://cdn-shop.adafruit.com/datasheets/BST_BNO055_DS000_12.pdf

Small wearable bno055 nano board

Check this post for a new library with better calibration.

Saturday, June 18, 2016

BNO055, xbee, and serial port conflicts

When I add the code from R_Plotrawdata3_test.ino to the file receive_xbee_working_6_17_16.ino, the code stops working I believe because there's a conflict with the serial ports.

UPDATE:  I got this working by keeping this in void setup

 xbee.setSerial(Serial)

Upload the code while shield button is in Dline position.  Once upload is complete change switch to UART.

I'd really like to have the xbee use a softwareSerial so that the hardware serial is open for debugging.  But I can't figure out how to do it.  In the example code in void setup they initialize the serial as
xbee.setSerial(Serial)

I tried to do initialize a softwareSerial port:

SoftwareSerial xb(2, 3); // RX, TX

then in void setup, I tried
xbee.setSerial(xb)
as well as 
xbee.setSerial(SoftwareSerial)

And neither one worked.

Here's a post on using different serial ports. But the problem is I don't understand how setSerial works.  From looking at the xbee.h library, it looks like it's a pointer to the serial, so maybe &xb or *xb works.  I'll ask Graziano! 

https://community.particle.io/t/arduino-core-softwareserial-and-serial1/9058


From what I've read, the BNO055 defaults to the hardware serial port on digital pins 0 and 1 on the arduino uno.

I'm not sure how to change them.  But this link talks about reading two BNO055's on the same arduino.  They change one sensor to 0x28 and the other to 0x29.  I'm not sure how this works.

http://www.timothyjmeo.com/downloads/code-repository/utility-sketches/_16_Read_Two_BNO055_Sensors.ino

Here are some links to check out:
https://forums.adafruit.com/viewtopic.php?f=19&t=92598

My code didn't work and by that I mean that my debugging messages weren't sent to the serial port.  Maybe this is because the BNO055 is using the serial port.  Next, I will add code to correctly calculate the checksum to send a packet over xbee and see if/what I get in XCTU.

Things to consider:
1.  The api packet sends bytes.  How do I convert floats to bytes?
    - one way is to figure out how much the values change, then multiply the change by a number to make an int.  Then convert at the receiving end.

Here's one example.  Working code is included in the post.

2.  Is it possible to read from the BNO055, then close bno.begin() and then do everything else?



Sending from coordinator, receiving by end device, and sending back to coordinator working!

Same simple 01 TX message as previous post.  Setting are the same and given in the code below.

Here's the Arduino code.  New code to send back a message is at the bottom.

/*****************************************************************
XBEE_receive_ex.ino

Set up a software serial port to pass data between an XBee Shield
and the serial monitor.

Hardware Hookup:
  The XBee Shield makes all of the connections you'll need
  between Arduino and XBee. If you have the shield make
  sure the SWITCH IS IN THE "DLINE" POSITION. That will connect
  the XBee's DOUT and DIN pins to Arduino pins 2 and 3.
 
 
  End Device + arduino
  DL = 1234
  MY = 5678
  API = 2
  CE = 0
 
  Receives this example rx signal from the transmission signal sent by coordinator
 
  Coordinator + explorer shield
  DL = 5678
  MY = 1234
  API = 2
  CE = 1
 
*****************************************************************/
// We'll use SoftwareSerial to communicate with the XBee:
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX
int incomingByte = 0;
int PacketArray[11] = {1,1,1,1,1,1,1,1,1,1,1}; // to store the validated xbee packet
int data = 0;
byte packetRX[] = {0x7E, 0x00, 0x07, 0x01, 0x01, 0x12, 0x34, 0x00, 0x03, 0xff, 0xB5};

void setup()
{
  // Set up both ports at 9600 baud. This value is most important
  // for the XBee. Make sure the baud rate matches the config
  // setting of your XBee.
  XBee.begin(9600);
  Serial.begin(9600);
}

void loop()
{
Serial.println(XBee.available()); //prints # bytes in transmitted message
if (XBee.available()>10) //needs 11 bytes to proceed - this is the xbee soft serial port
  {
    incomingByte = XBee.read(); //read the first byte
    Serial.println(incomingByte);  //print the first byte to the serial monitor
    if (incomingByte == 0x7E){
      PacketArray[0]=0x7E; //this is the start of the frame
      for(int i=1; i<11; i++) {  // for the next 10 bytes, do the following
       PacketArray[i] = XBee.read(); //set each byte to a spot in the vector
       Serial.print(i); //print the array location
       Serial.print(" "); //print a space
       Serial.print(PacketArray[i]); // print the value of the byte
       Serial.print("  "); //print a space
       delay(100); // try different values
        }
        Serial.println(" "); //add a line break
        if (PacketArray[4] == 0x12 & PacketArray[5] == 0x34 & PacketArray[9] ==255 ){ // there are two byte of data, this is the second one
          Serial.println("ON"); // if the second byte is 0xFF or 255, print this.
          data = PacketArray[9] + PacketArray[8]*256
  //NEW PART
          if (data == 1023)
          {
           for (int counter = 0;counter<11;counter++)
           {
             Serial.print(packetRX[counter]);
             Serial.print("  ");
             XBee.write(packetRX[counter]);
           }
           Serial.println();
          }
        }  
      }
  }
  /*The coordinator sends a Tx status reply that is 7 bytes long.
  7e 00 03 89 01 00 75
  7E is the start of the packet
  00 03 is the # of bytes after the first 3 and before the checksum (last byte)
  89 is the frame type which is 89 (TX (Transmit) Status)
  01 is the frame ID (could be anything - doesn't mean anything
  00 is the status of the message - 00 means success
  75 is the checksum
  The following code clears this message from the XBee serial buffer  */
  if (XBee.available()>0)
  {
    while(XBee.available()>0)
    {
      Serial.println(XBee.read());
    }
  }
    delay(2000);//delay of 2 seconds between each iteration of void loop
   
} //end void loop

The code checks to see that the data is HIGH (1023), and if so, it sends a packet back.
I created a hard-coded packet
{0x7E, 0x00, 0x07, 0x01, 0x01, 0x12, 0x34, 0x00, 0x03, 0xff, 0xB5};
The code loops through this packet and prints to the serial monitor for debugging and the xbee.

I put each packet into XCTU's frame interpreter to illustrate.
    transmitted frame from end device             received frame coordinator
                






Friday, June 17, 2016

About the serial ports

A few things I've learned:
1.  The Arduino Uno only has 1 hard serial port.

2.  The Mega has more.

3.  Most people use the SoftSerial Library to create a software serial port for the xbee.  The Sparkfun xbee shield assumes that you'll be using it like this.  When the switch is in DLine mode, the xbee serial port is on pins D2 and D3.  Make sure that the code is set this way!

4.  All information received and transmitted by the xbee will go through the soft serial port.

5.  Use the hard serial port for debugging and printing to the serial monitor.

Here are parts of code as examples of how to use the serial ports

#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX

void setup()
{
  // Set up both ports at 9600 baud. This value is most important
  // for the XBee. Make sure the baud rate matches the config
  // setting of your XBee.
  XBee.begin(9600);
  Serial.begin(9600);
}

void loop()
{
Serial.println(XBee.available()); //prints # bytes in transmitted message
if (XBee.available()>10) //needs 11 bytes to proceed - this is the xbee soft serial port
  {
    incomingByte = XBee.read(); //read the first byte from xbee soft serial
    Serial.println(incomingByte);  //print the first byte to the hard serial port (i.e.serial monitor)
  }

}


Receiving a packet from xbee explorer with remote xbee and parsing packet on arduino

An coordinator xbee on the little explorer shield plugged directly into the computer sends an  API transmission frame to the end device which is an xbee in API mode connected to an arduino.

Here's info on the transmission sent through XCTU:


The frame is sent by clicking on Send Selected Frame.

Here is the frame.  Note that it is frame type 0x01 - Tx(Transmit) Request: 16-bit address.  Also note that in the RF data entry, the hex number sent is 0x03 0xFF.  This is equivalent to 1023 or HIGH.  This is simulating  a pin that is high until a circuit is created to push a button and the value of digital pin on the xbee will be used for this purpose.



Here's the arduino code for the remote end device:
/*****************************************************************
XBEE_receive_ex.ino

Set up a software serial port to pass data between an XBee Shield
and the serial monitor.

Hardware Hookup:
  The XBee Shield makes all of the connections you'll need
  between Arduino and XBee. If you have the shield make
  sure the SWITCH IS IN THE "DLINE" POSITION. That will connect
  the XBee's DOUT and DIN pins to Arduino pins 2 and 3.
  
  
  End Device + arduino
  DL = 1234
  MY = 5678
  API = 2
  CE = 0
  
  Receives this example rx signal from the transmission signal sent by coordinator
  
  Coordinator + explorer shield
  DL = 5678
  MY = 1234
  API = 2
  CE = 1
  
*****************************************************************/
// We'll use SoftwareSerial to communicate with the XBee:
#include <SoftwareSerial.h>
// XBee's DOUT (TX) is connected to pin 2 (Arduino's Software RX)
// XBee's DIN (RX) is connected to pin 3 (Arduino's Software TX)
SoftwareSerial XBee(2, 3); // RX, TX
int incomingByte = 0;
int PacketArray[11] = {1,1,1,1,1,1,1,1,1,1,1}; // to store the validated xbee packet
int data = 0;
void setup()
{
  // Set up both ports at 9600 baud. This value is most important
  // for the XBee. Make sure the baud rate matches the config
  // setting of your XBee.
  XBee.begin(9600);
  Serial.begin(9600);
}

void loop()
{
Serial.println(XBee.available()); //prints # bytes in transmitted message
if (XBee.available()>10) //needs 11 bytes to proceed
  { 
    incomingByte = XBee.read(); //read the first byte
    Serial.println(incomingByte);  //print the first byte to the serial monitor
    if (incomingByte == 0x7E){
      PacketArray[0]=0x7E; //this is the start of the frame
      for(int i=1; i<11; i++) {  // for the next 10 bytes, do the following
       PacketArray[i] = XBee.read(); //set each byte to a spot in the vector
       Serial.print(i); //print the array location
       Serial.print(" "); //print a space
       Serial.print(PacketArray[i]); // print the value of the byte
       Serial.print("  "); //print a space
       delay(100); // try different values
        }
        Serial.println(" "); //add a line break
        if (PacketArray[4] == 0x12 & PacketArray[5] == 0x34 & PacketArray[9] ==255 ){ // there are two byte of data, this is the second one
          Serial.println("ON"); // if the second byte is 0xFF or 255, print this.
          data = PacketArray[9] + PacketArray[8]*256;
          Serial.println(data);
      
    }
        
        
      }
  } 
    delay(5000);//delay of 5 seconds between each iteration of void loop
}


******************************************************************

The remote xbee receives a frame of frame type 0x81.  In Hex, the received packet is:
0x7e 0x00  0x07  0x81  0x12  0x34  0x37  0x00  0x03  0xff 0xff  

I used XCTU's frame generator to plug these numbers in to see if I could replicate the frame and here's what that looks like. Notice that the frame type is 0x81 because it's a RX(Receive)Packet: 16-bit address.  Note that the checksum values match.  Also, interestingly, the RSSI value is given which is the strength of the signal (40 max in Hex, I think).  This packet is 7 bytes, it's a rx packet, it was sent by the xbee with a MY address of 1234, the signal strength is 37, there are no options, there are two bytes of data that equal 1023 decimal, and the checksum value is 255.

Here's what I see on the serial monitor.
The zeros show me XBee.available() = 0, so nothing is being transmitted.

When I send the selected packet on the coordinator's xbee (blue in the console), I get a transmission status response (red in the console) and it show that the remote xbee received it (Status 00(Success)).

The code reads the first byte as the start delimiter of the frame.  Then reads in the rest of the packet and stores all 11 bytes in an array and prints each value in the array (along with the array index) to the serial monitor.   Then the code checks the address to make sure the packet was sent by the coordinator.  It also checks to see that the last data byte is equal to 0xFF (or 255 decimal).  If so, then it prints "ON" and it adds the two data bytes and prints the result to the serial monitor.  Notice that they are equal to 1023 (HIGH).  Then it goes back to monitoring for another packet and you know this because it's printing zeros which means that there are no packets available to be read.

Next:
1.  Add to program and send a return packet with data measured from the arduino pins and printed to the xbee serial port.


Hex, dec, bytes, bits,

Good ASCII to decimal converter:  https://www.branah.com/ascii-converter

Understanding hexadecimal, decimal, binary, bytes, and bits

http://www.swarthmore.edu/NatSci/echeeve1/Ref/BinaryMath/NumSys.html

Scroll down to
Hexadecimal, Octal, Bits, Bytes and Words


To convert two hexadecimal bytes to decimal,

 data_dec = data[9] + data[8]*256; where data[9] is the LSB and data[8] is the MSBt.

For example,

0x03 0xFF in two hex bytes equals 1023.  0x03 is the MSB and 0xFF is the LSB.

Try it out:
data = 0xFF+0x03*256

0x03 is read first so it is the MSB and FF is read second and it is the LSB.

Friday, June 10, 2016

How to parse data from digital and analog pins

Experiment 14- The Hands-On Xbee Lab Manual

How to configure XMTR (remote xbee):
DL - 1234
MY - 5678
AP - 1-API enabled
IA-I/O - FFFF
D7 - 3-DI
D6 - 3-DI
D5 - 2-ADC
D4 - 2ADC
D3 - DO LOW
D2 - DO LOW
D1 - DO HIGH
D0 - DO HIGH

How to configure XMTR (connected to computer:
DL - 5678
MY - 1234
AP - 1-API enabled
IA-I/O - FFFF
D7 - 3-DI
D6 - 3-DI
D5 - 2-ADC
D4 - 2ADC
D3 - DO LOW
D2 - DO LOW
D1 - DO HIGH
D0 - DO HIGH

Two examples to collect data on pins from a remote XMTR xbee:




Example 1:
In the API packet to send from RCVR to XMTR, the API command is "IS" which means Force Sample.

ASCII text values for IS are I = 0x49 and S = 0x53

On the XMTR xbee pins, connect D7 and D6 to ground.  Here's the value for each of the pins:
D7 - 0V(set by connecting it to ground)
D6 - 0V(set by connecting it to ground)
D5 - 0V (nothing connected to it)  Question - is there a pull down resistor on D3 and D4 to make the pin value 0V?
D4 - 0V(nothing connected to it)
D3 - 0V (set by xbee config)
D2 - 0V (set by xbee config)
D1 - 5V (set by xbee config)
D0 - 5V (set by xbee config)



Example 2:
On the XMTR xbee pins, connect D7 and D6 to ground.  Here's the value for each of the pins:
D7 - 5V(set by connecting it to ground)
D6 - 6V(set by connecting it to ground)
D5 - 1.65V (nothing connected to it)  Question - is there a pull down resistor on D3 and D4 to make the pin value 0V?
D4 - 1.34V(nothing connected to it)
D3 - 0V (set by xbee config)
D2 - 0V (set by xbee config)
D1 - 5V (set by xbee config)
D0 - 5V (set by xbee config)

PCB Manufacturing

I've used expresspcb in the past with good results to make boards.  It looks like we can make 4 layer boards for about $80.  Here is the link:

https://www.expresspcb.com/

How to use API Packets to Control Remote I/O Lines

Book:  The Hands-On XBee Lab Manual

Experiment 12  Using XBEE connected to the USB-XBEE connector plugged into the computer, turned LEDS on and off on the remote XBEE.

Configuration setting on the xbee:
End Device - coordinator (RCVR)
Serial High - SH 0013A200
Serial Low - SL  408A47F9
Scan channels - SC 1FFE

End Device (XMTR)
SH 0013A200
SL  408A47E5
Scan channels SC 1FFE



Coordinator - RCVR
Step 1:  Plug in receiver (coordinator) and click on default to reset xbee settings
Step 2:  Change these settings
DL-1234
MY - 5678
AP - API enabled-1
IA-I/O settings - FFFF

XMTR - end device
Step 1:  Plug in receiver (coordinator) and click on default to reset xbee settings
Step 2:  Change these settings
DL-5678
MY - 1234
AP - API enabled-1
IA-I/O settings - FFFF

Note that both xbees are in API mode

AT commands
D2 turn on
7E 00 10 17 01 00 13 A2 00 40 8A 47 E5 FF FE 02 44 32 05 C2
D3 turn on

To send an AT remote command from the receiver, click on the first xbee and then click on Open.
Your window should look like this:


Create API frames by clicking on the plus sign to the right of the Send Frames window.

You can paste an API packet into the space or create one by clicking on edit frame.  You can paste an API frame into the window and then edit or start from scratch.


To create a frame, select the type of frame that you want.  In this case we want to create a Remote AT command.  


This is what my receiver (connected to computer) frames will send to my remote transmitter to turn on the LED and then turn it off.  If we want to run on two LEDs, we need to send the same API frame to a different pin.  To turn on pin D3, change D2 to D3 for the on and off API frames.  Note that the parameter value is 05 for on (pin HIGH) and 04 for off (pin LOW) and that this needs to be in HEX!!!
                                     LED connected to pin D2 is on                           LED connected to pin D2 is off
        


If the LEDs are not turning on and off as expected, look at the remote command response frame that you get back from the remote transmitter by clicking on it in the console.  On the right, scroll down and you'll see that you'll get an error that says that the parameter that you send (the value for the pin) is invalid.  I created the error by writing a parameter of "05" is ascii instead of hex.









Sunday, June 5, 2016

Reading API frames

The XCTU tool Frame Interpreter is very helpful in deciphering an API frame.

Here's a link to reading an API frame.  It's also a great example of using a command to change the state of the pin with a command from the coordinator that signals the end device to transmit data.
http://www.labviewing.com/sampling-data-from-xbee-radio-in-change-detection-mode/