Author Topic: data struct for sending/receiving? [Solved]  (Read 7826 times)

Hank

  • Newbie
  • *
  • Posts: 5
data struct for sending/receiving? [Solved]
« on: August 17, 2013, 08:58:35 PM »
Hi All,

I have been using a struct in my Jeenode sketch and I am wondering if anyone can help to get a similar mechanism working for the Moteino RFM69 library. It helped me  lot with preserving the data types of transmitted values. I first saw it on "Steve's blog" at http://www.trease.eu/?p=1038. It has worked well on the JN and helped a noob such as myself with deconstructing radio data and using it as variables in sketches.

The code in the sending sketch goes like this:

typedef struct {      
     int            nodeid;      // sending node ID
     float          data_1;      
     float          data_2;
     float          data_3;
     float          data_4;
} Payload;
Payload data;

int a = data.data_1;
int b - data.data_2;
int c = data.data_3;

//then in loop(), ...

rf12_sendStart(0, &data, sizeof data);

-----------------------------------------------------------------------------
Then the code in the receiving sketch went like this:

// Payload data structure
typedef struct {             // Message data structure, same on sending and receiving motes
     int             nodeid;      // sending node ID
     float          data_1;      // data types
     float          data_2;
     int             data_3;
} Payload;
Payload data;                         //instance of Payload

void loop() {

  if (rf12_recvDone()) {
    if (rf12_crc == 0) {

data=*(Payload*) rf12_data;               //apparently fills the data struct with data from rf12_data buffer, can do same for RFM69?

      Serial.print(data.nodeid);
      Serial.print(",");
      Serial.print(data.data_1);
      Serial.print(",");
      Serial.print(data.data_2);
      Serial.print(",");     
      Serial.print(data.data_3);

I don't really understand magic in the line "data=*(Payload*) rf12_data;" other than it somehow fills the data struct with data from the rf12 data buffer. Can this line be modified to work with the RFM69 library? I  simply replaced  "rf12_data" with "radio.DATA", but no luck. If anyone can point me in the right direction, I'd appreciate it.
« Last Edit: August 17, 2013, 11:01:36 PM by Hank »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 5939
  • Country: us
    • LowPowerLab
Re: data struct for sending/receiving?
« Reply #1 on: August 17, 2013, 10:11:18 PM »
Hey Hank,
Thanks for bringing this up. I always meant to show how this can be done but always forgot to post it.
You were on the right track, except the payload array is a bit different in the RFM69 than the payload in Jeelib.
You're basically dealing with different data types and different kinds of type casting between them. Pointers are involved so you have to understand pointers a little bit to be able to get out of the fog alive :)
I added struct examples in the RFM69 repository, so here are sender and receiver examples that are ready to go (just edit your frequency, nodeid, network id etc):

https://github.com/LowPowerLab/RFM69/blob/master/Examples/Struct_send/Struct_send.ino
https://github.com/LowPowerLab/RFM69/blob/master/Examples/Struct_receive/Struct_receive.ino

My payloads are (const void*) so you have to cast them back and forth a little different:

dumping to radio.DATA:
Code: [Select]
(const void*)(&theData)
extracting from radio.DATA:
Code: [Select]
theData = *(Payload*)radio.DATA
get the size of your struct (to pass to send functions as payloadLength):
Code: [Select]
sizeof(Payload)

I hope this makes sense and is not too confusing, but as long as you are in c++ land you will innevitably encounter pointers and casting between different data types including pointer variables.
There are tons of resources on the web/youtube about pointers so I'll let you explore if you want to.

Enjoy!  8)

Hank

  • Newbie
  • *
  • Posts: 5
Re: data struct for sending/receiving?
« Reply #2 on: August 17, 2013, 11:00:40 PM »
Thank you soooo much ... I can't tell you how much

Amazing. I posted the question, got up to feed the dogs, came back to the puter and you have already read the post, developed code, and posted it .... on Saturday evening. And, to top it off, it works beautifully. Now that's magic to me .... and I am actually beginning (just beginning) to understand .... thanks for explanation as well ....

I look forward to returning the favor someday ... now on to reading up on pointers, casting, recasting  (that should take me a while) and ordering some more rfm69s.

kiwisincebirth

  • Jr. Member
  • **
  • Posts: 69
Re: data struct for sending/receiving? [Solved]
« Reply #3 on: September 21, 2014, 06:27:13 AM »
Another Tip for defining structures, specifically to use less space in the message. The example below shows a structure that uses only 4 bytes, not the 7 bytes you would expect. The 3,5,4,20 define the number of bits assigned to each element in the structure so only 32 bits (4 bytes) are used. This comes in handy for low power where every byte transmitted cost precious battery power.

// The MESSAGE being Sent over wireless
struct Message {
  byte operation  :  3 ;   // P for Publish / S-set G-get value
  byte locationID :  5 ;   // Defines a Location In House
  byte measure    :  4 ;   // What are we measuring
  long value      : 20 ;   // The value we observed
} message;

The limitation of course is that you don't get the full range of values e.g the long is in the range +/- 524,288.

ColinR

  • Full Member
  • ***
  • Posts: 176
Re: data struct for sending/receiving? [Solved]
« Reply #4 on: September 22, 2014, 02:05:58 PM »
This is the second post I've read of yours, both of which are super-helpful.

Cheers,
Colin
CuPID Controls :: Open Source browser-based sensor and device control
Interfaceinnovations.org/cupidcontrols.html
cupidcontrols.com