LowPowerLab Forum

Hardware support => General topics => Topic started by: THE_01011010 on May 31, 2017, 01:40:44 PM

Title: Data struct float payload issues
Post by: THE_01011010 on May 31, 2017, 01:40:44 PM
Hi All,

I've tried to find a solution, but so far all in vain. Have read the following forum posts (and others) but still can't figure out what I'm doing wrong...
https://lowpowerlab.com/forum/moteino/data-struct-for-sendingreceiving-(solved)/
and https://lowpowerlab.com/forum/moteino/multiple-payloads/

Problem: When I send my struct payload with a float variable, I'm unable to read out the value on the receiver. The data gets transmitted correctly, payload length match on sender and receiver, however I'm struggling to extract the float value.  With a workaround - at least I would consider this as such - I've managed to build the float value, but I feel like I'm missing something.

HW: Moteino R4, RFM69HW

Here is my struct:

typedef struct sensorData_t {
  byte nid; /*node id*/
  float h; /* temperature */
  float t; /* humidity */
};

typedef union MO_Packet_t {
  sensorData_t sensor;
  byte MOPacket[sizeof(sensorData_t)];
};
MO_Packet_t packetinfo;


Then I fill in my data:

packetinfo.sensor.nid = NODEID;   
packetinfo.sensor.h = H;
packetinfo.sensor.t = C;


Finally, I send it with:

radio.sendWithRetry(GATEWAYID, (const void*)(packetinfo.MOPacket), sizeof(sensorData_t)))


On the receiver end, I extract the data with:

packetinfo= *(MO_Packet_t*)radio.DATA;


...and get the float value with this workaround:

    float wka; /* workaround var... */
       
    union ft {
      byte b[4]; /* byte array size... */
      float val;
    } x;

    /* 4 bytes to float... for example Humidity data */
    x.b[0] = radio.DATA[3];
    x.b[1] = radio.DATA[4];
    x.b[2] = radio.DATA[5];
    x.b[3] = radio.DATA[6];

    wka = x.val;


This would produce the correct float amount, for example: 23.44 in C

However, I would like to read the float value using: (packetinfo.sensor.t) instead of pointing to a specific byte in the package. If I do that, than I would get 0.00 in this case... which is incorrect. Ideally I would like to keep the packages modular, and therefore the workaround is less than ideal..

What am I doing wrong? Any pointers on what I should read etc would be appreciated. I have some experience with coding, but pointers, casting and C is something that I'm getting used to.
Title: Re: Data struct float payload issues
Post by: TomWS on June 01, 2017, 02:12:38 PM
Quote from: THE_01011010 on May 31, 2017, 01:40:44 PM
HW: Moteino R4, RFM69HW
On both ends of the link?
Title: Re: Data struct float payload issues
Post by: THE_01011010 on June 01, 2017, 05:57:54 PM
AFAIK the radio modules are the same, although from different suppliers - should I compare them in case one is HW and the other is HCW or something like that? Both of them are on the same FREQ etc. Could a difference like that cause an issue like this?

The sender is a Moteino, and the receiver is running the same RF lib on an ESP Huzzah. I don't suspect the Huzzah to be the root of the problem...or could that be the case?

Over the weekend I'll try it without the Huzzah.. using 2 identical Motes.
Title: Re: Data struct float payload issues
Post by: TomWS on June 01, 2017, 06:18:32 PM
Quote from: THE_01011010 on June 01, 2017, 05:57:54 PM
The sender is a Moteino, and the receiver is running the same RF lib on an ESP Huzzah. I don't suspect the Huzzah to be the root of the problem...or could that be the case?
The ESP8266 is EXACTLY the problem.  It will not accept a primitive data value that is not aligned on its natural boundary and also forces structs on a 32 bit word boundary so a struct within a struct needs to be aligned to a 4 byte boundary.  There are a number of ways to correct this.  The easiest is to either put your larger primitives in the struct first or make sure you have a multiple of smaller primitives that adds up to a 4 byte boundary for your larger primitives.

For example, (without reexamining your code) if you have a couple of uint8_t values, one 16 bit int and put these first in the struct, then put the float as the very next element in the struct, this 'could' work.  I say 'cold' because after you solve the alignment problem you need to make sure both compilers (Moteino and ESP) use the same IEEE floating point type - that you can get it to work suggests that they are, but it's something you need to diligently confirm whenever you're exchanging binary data between two different processors.  You also need to be aware of possible differences in 'endianess' between the processors. 

The general solution, which you have discovered, is to exchange the data as a collection of bytes, for which you KNOW the ordering, and, at the far end, simply reconstruct the larger primitives out of the component bytes.  In this case, alignment is not an issue and, if you order properly at each endpoint, you'll successfully exchange data between any processors.  Finally, there is always the fallback to text encoded data exchange which is almost always foolproof and, for these processors and limited data ranges, isn't all that inefficient.

Tom
Title: Re: Data struct float payload issues
Post by: THE_01011010 on June 02, 2017, 01:36:24 PM
Thank you so much TomWS! I really appreciate all the info and help. Now I have a much better understanding of how this works. Unfortunately it shows that I have a limited amount of knowledge in this areas, but will do my best to improve.

Thanks again, and I think in the long run will move over to some type of text/json encode.

As a last question/long shot - although very off topic and not mote related- is there a book that you would highly recommend reading in this area, especially C related?
Title: Re: Data struct float payload issues
Post by: Felix on June 02, 2017, 01:39:36 PM
Quote from: THE_01011010 on June 02, 2017, 01:36:24 PM
As a last question/long shot - although very off topic and not mote related- is there a book that you would highly recommend reading in this area, especially C related?

Books? Paper? What is that?  :o
JK but if you want a quick great C/C++ reference site here is one: http://www.cplusplus.com/reference/
Title: Re: Data struct float payload issues
Post by: jra on June 02, 2017, 02:56:43 PM
Quote from: THE_01011010 on June 02, 2017, 01:36:24 PM
As a last question/long shot - although very off topic and not mote related- is there a book that you would highly recommend reading in this area, especially C related?
https://www.amazon.com/Programming-Language-Brian-W-Kernighan/dp/0131103628
The classics never go out of style, I still have my 1st edition purchased c.1979.  The 2nd edition covers ANSI C instead of plain old K&R C.  Just bear in mind that C != C++ and arduino is really C++ at heart although simple cavemen like myself get away with treating it as if it were C.
Title: Re: Data struct float payload issues
Post by: TomWS on June 02, 2017, 04:45:31 PM
Environments like Arduino coddle you into a false sense of comfort if you dare tread outside the original platforms it was built on.  While the IDE has been continually updated (over and over again, on an hourly basis it seems) the updates are moving to platforms that don't perfectly fit the original model, ie a very forgiving but limited platform.  Moving to ARM and ESP type processors require an understanding beyond the simple Arduino tutorials.

Fortunately there are plenty of resources on the web (DAGS is your friend) and the information is there as long as you realize that a platform like ESP or SAM is NOT going to behave like an AVR processor.

BTW, I concur with the continuing value of K&R, but it probably wouldn't have helped much in this case... 
Tom
Title: Re: Data struct float payload issues
Post by: THE_01011010 on June 05, 2017, 04:23:41 PM
Thanks for all the input from everyone, much appreciated.