0

Trying to get the address of receiving XBee's data in the loop in API mode with escape. Sent data can be received properly. However, in order to identify XBee, I need the address in the loop. In other words I need those address1 to 7 which is in union XbEE_FRAME. How to get the address in main loop. Following is the code. Appreciate your help.

#include <SoftwareSerial.h>


struct SENSOR_DATA{
   char rpm;   // worked
  //float rpm;
  //float strain;
  //unsigned long sampling_interval;
};

boolean xbee_rx(struct SENSOR_DATA *ret) {
  union LEN_FRAME{
    byte len_array[2];
    word len;
  }lenlen;
  static int len_i = -1;

  union XbEE_FRAME{
    byte buf[25]; // 30
    struct {
      byte frame_type;
      byte frame_id;
      byte address1;
      byte address2;
      byte address3;
      byte address4;
      byte address5;
      byte address6;
      byte address7;
      byte reserved1;
      byte reserved2;
      byte recieve_options;
      struct SENSOR_DATA sensor_data;
      byte checksum;
    } frame;
  } xbee;
  static int buf_i = -1;
  static bool escape = false;
  static byte sum;

  while (Serial.available() > 0) {
    byte b = Serial.read();

    //Serial.print(b, HEX);

     //b = Serial.read();
    if (
      b != 0x7e &&
      buf_i == -1 &&
      len_i == -1
      ) {
      continue;
    } else if (b == 0x7e){
      buf_i = 0;
      lenlen.len = 0;
      len_i = 0;
      sum = 0;
      escape = false;
      continue;
    } else if (b == 0x7d){
      //Serial.print("es: ");
      //Serial.println(b,HEX);
      escape = true;
      continue;
    }

    if (escape){
      b = b ^ 0x20;
      escape = false;
    }

    if (len_i < 2){
      lenlen.len_array[1 - len_i] = b;
      len_i++;
    } else {
      xbee.buf[buf_i++] = b;
      sum += b;
    }
    if (
      len_i == 2 &&
      buf_i >= sizeof(xbee.buf)
      ){
      len_i = -1;
      buf_i = -1;
      // frame recieved !!
      if (sum == 0xff){ // check sum!
        *ret = xbee.frame.sensor_data;
        return true;
      }
    }
  }
  return false;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);   // 38400
  Serial.println("overover");
}

void loop() {
  //mySerial.println("work");
  // put your main code here, to run repeatedly:
 struct SENSOR_DATA data;
  if (xbee_rx(&data)){   
    //Serial.print(data.rpm);

     // if(b == 0x40 )  //&& b == 0xd5 && b == 0xaa && b == 0xac
  }
} 
0

Function xbee_rx() only returns the contents of struct SENSOR_DATA which doesn't include those addresses. You could instead 1) return the contents of the entire struct {...} frame which does contain them (making sure loop() 's buffer is large enough; or 2) instead of returning all of that data at all, make the union {...} xbee static so it persists after xbee_rx() exits, and return a pointer to sensor_data, with which loop() can access any member of it, such as p->address1.

Update: The caller - rather than the called-function - allocates the memory buffer and the called-function uses that memory instead of its own, effectively passing the data to the caller. Here's your code, slightly re-written, with my initialed comments. I have not tried to run it but it does compile:

#include <SoftwareSerial.h>


struct SENSOR_DATA{
   char rpm;   // worked
  //float rpm;
  //float strain;
  //unsigned long sampling_interval;
};

//-jr-: Here we define what an XbEE_FRAME is and make it a data-type
// but we don't allocate any storage. This is just information to the
// compiler:
typedef union {
    byte buf[25]; // 30
    struct {
      byte frame_type;
      byte frame_id;
      byte address1;
      byte address2;
      byte address3;
      byte address4;
      byte address5;
      byte address6;
      byte address7;
      byte reserved1;
      byte reserved2;
      byte recieve_options;
      struct SENSOR_DATA sensor_data;
      byte checksum;
    } frame;
} XbEE_FRAME;

//-jr-: This function expects a pointer to memory (i.e., its address)
// allocated for data of type 'XbEE_FRAME' - the union from your
// original code. Note that we don't allocate any memory for it here;
// the caller is expected to do that, and this function will use what
// the caller allocated.
boolean xbee_rx(XbEE_FRAME *pXbF) {
  union LEN_FRAME{
    byte len_array[2];
    word len;
  }lenlen;
  static int len_i = -1;


  static int buf_i = -1;
  static bool escape = false;
  static byte sum;

  while (Serial.available() > 0) {
    byte b = Serial.read();

    //Serial.print(b, HEX);

     //b = Serial.read();
    if (
      b != 0x7e &&
      buf_i == -1 &&
      len_i == -1
      ) {
      continue;
    } else if (b == 0x7e){
      buf_i = 0;
      lenlen.len = 0;
      len_i = 0;
      sum = 0;
      escape = false;
      continue;
    } else if (b == 0x7d){
      //Serial.print("es: ");
      //Serial.println(b,HEX);
      escape = true;
      continue;
    }

    if (escape){
      b = b ^ 0x20;
      escape = false;
    }

    if (len_i < 2){
      lenlen.len_array[1 - len_i] = b;
      len_i++;
    } else {
       //-jr-: Note how we changed our reference from 'xbee.buf...' to
       // 'pXbF->buf...'! The '.' style addressing is used to refer to
       // memory we can name directly, as when you allocated that union
       // here. But now we  have to refer to it by the  pointer we received -
       // its address. The '->' symbol is how you address members of a
       // union or struct through a pointer:
      pXbF->buf[buf_i++] = b;
      sum += b;
    }
    if (
      len_i == 2 &&
      buf_i >= sizeof(pXbF->buf)
      ){
      len_i = -1;
      buf_i = -1;
      // frame recieved !!
      if (sum == 0xff){ // check sum!
    //-jr-: Notice that here we don't try to return any data;
    // we don't have to. Since We did everything in memory the
    // caller owns, the caller already has the data!
        return true;
      }
    }
  }
  return false;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);   // 38400
  Serial.println("overover");
}

void loop() {
  //mySerial.println("work");
  // put your main code here, to run repeatedly:

   //-jr-: Define the entire XbEE_FRAME here and pass its address to
   // your function. The function will use _this_ local storage
   // (instead of its own) to buffer the data, so it will already
   // be here when your function returns:
   XbEE_FRAME data;     //-jr- Define the entire union here
   if (xbee_rx(&data)){    //-jr-  and pass its address to the function
      //-jr-: You can address a member such as address3 as:
      //      data.frame.address3
    //Serial.print(data.rpm);

     // if(b == 0x40 )  //&& b == 0xd5 && b == 0xaa && b == 0xac


  }
}

Update:

How to get the SENSOR_DATA sensor_data?

Use: data.frame.sensor_data.rpm (lower case).

  • SENSOR_DATA only describes the kind of contents in a struct, not any actual data in memory.
  • sensor_data is one instance of such a struct.

To go a bit further, suppose frame{} contained more than one SENSOR_DATA in it, maybe named sensor_data_a, sensor_data_b, ..., etc. Now to get the data from, say, sensor_data_a it should be clear that you need to refer to the particular instance you're interested in.

  • JRobert, I am trying method No.1 that you have suggested, though still I cant get. Could you please write the code? – zalt Jun 5 '17 at 2:32
  • Ok, got the address. But now can not get the SENSOR_DATA sensor_data. How to get the SENSOR_DATA sensor_data? – zalt Jun 8 '17 at 7:17
  • I tried to get with Serial.print(data.frame.SENSOR_DATA.rpm); but didn't work. – zalt Jun 8 '17 at 7:22
0

I don't think you can.

The structures are defined within a function so the loop() won't have access to them.

Further the parameter returned from the function xbee_rx() is of type SENSOR_DATA which is a sibling in the frame structure to the data you want to read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.