I am struggling trying to send some data through a transceiver. All of my other values go through fine since they are of type uint8_t, however, when I am trying to send a float it comes out as 220....
This is what I am trying to do, my float value is 4828.9038
I am trying to store it in a packet whose class is this:
class CCPACKET
{
public:
/**
This provides me with an output of 220 what I run Serial.println(data[0]);
So I believe my goal is to go from my float (4828.9038) to a byte(or many bytes) and then on the receiving end, go from byte to float.
I really don't care which format/type it is in so long as that on the receiving end I can parse out 4828.9038 since I will be typing that into a text box!
Thanks in advance!
I have been searching for 2 days now and can't seem to find a decent answer anywhere. (Please let me know if I have left out vital information!)
What makes you think you can stuff a 4 byte variable into a single byte? That's like trying to park four cars into the same spot; it just doesn't work. The simplest way is to use a union:
typedef union
{
float number;
uint8_t bytes[4];
} FLOATUNION_t;
Then if you want to access both the byte array and the actual float number:
FLOATUNION_t myFloat;
myFloat.number = 123.456; // Assign a number to the float
for (int i=0; i<4; i++)
{
Serial.print(myFloat.bytes[i], HEX); // Print the hex representation of the float
Serial.print(' ');
}
There are several options. One is to convert float to a character string and send the character string. Any computer can then convert the character string back to a float, regardless of type. Another is to send the four bytes that represent the floating point variable value. For that, the "union" construct is useful, in which you can refer to the same memory space in two different ways: e.g.
union cvt {
float val;
unsigned char b[4];
} x;
Then in your code you might refer to these as in the following
Thank you everyone for your fast replies!
PeterH provided very simple code which gets the job done however using the provided code, the entire packet is set to contain the float. I am looking to send other data as well... my current packet looks like:
data.data[0] = hour;
data.data[1] = minute;
data.data[2] = seconds;
data.data[3] = milliseconds; put float here
data.data[4] = day;
data.data[5] = month;
data.data[6] = year;
and now to integrate the float how would I go about doing that and then read it on the other side?
now to integrate the float how would I go about doing that
Use the union, and copy the byte representation into your data packet. But do take a moment to read and understand the responses you've received.
Okay so, I go ahead and create the union and now I have both my float value stored in myFloat.number and the byte representation of that stored in myFloat.bytes.
Now I go ahead and add it to my packet like this:
data.data[0] = hour;
data.data[1] = minute;
data.data[2] = seconds;
data.data[3] = milliseconds;
data.data[4] = myFloat.bytes[0];
data.data[5] = myFloat.bytes[1];
data.data[6] = myFloat.bytes[2];
data.data[7] = myFloat.bytes[3];
data.data[8] = day;
data.data[9] = month;
data.data[10] = year;
Now on the receiving end, I have all my other data fine, but the myFloat.bytes are come through as: 61, 231, 150, 69. My problem is I just don't understand how to convert that back into a float on the receiving end.
Sorry this is so tasking but I think I am lacking a little comprehension here. I do appreciate the fact everyone is taking time out of their day to slow pitch this in for me!
Again, take a moment to read and understand the responses you've received.
It is not that difficult. Don't be afraid to experiment until you do understand it!
Most of us don't want to write your program for you.
optomus:
Now on the receiving end, I have all my other data fine, but the myFloat.bytes are come through as: 61, 231, 150, 69. My problem is I just don't understand how to convert that back into a float on the receiving end.
Sorry this is so tasking but I think I am lacking a little comprehension here. I do appreciate the fact everyone is taking time out of their day to slow pitch this in for me!
Alright, thanks guys, finally got through my thick skull. Thanks Arrch for spelling it out just enough!
Ended up using, on the sending end:
union
{
float misc;
unsigned char misc_byte[3];
}Misc;
Misc.misc = myValue;
There is another way to do it if you don't want to use structs.
Convert float to String, then you need your array of bytes and you pass each char of that String to the array of bytes...
I know it's not pretty but it works
Hi,
Thank you all and with your helps I could solve my problem. I wrote a below sketches to demonstrate usage of union with struct for both writing and reading from NVRAM, which worked perfectly. Hope it helps others and below is the code:-
*/ *************************************************************
Purpose:-
This is a trial program made to test the typedef union
with various data types to see if it works with
in data writing and reading from DS1307 or similar NVRAM
Author:-
Pradip Khare
Courtesy:-
Respective owner of the libraries writers, who make our programming easier
Results:-
it works perfectly check with Nano and RTC chip DS1307
Also, it is 50 times faster than writtign to EEPROM of the processor
for the same data bytes written and read
*/
#include <Wire.h>
#include "RTClib.h" // Courtsey Jeelabs- https://github.com/adafruit/RTClib
RTC_DS1307 rtc; // i2c address 0x68
// below is the data format that I need to write and read from NVRAM
struct myStruct{
boolean wasDataSaved;
char lastMode;
float VlimitVal;
float VsetVal;
float AlimitVal;
boolean wasOEnabled;
int lastCurPos;
};
typedef union{ // union to contain above structure
myStruct inSide;
byte bytes[17];
} UNION_t;
long lM1,lM2; // just to capture the time stamp in milli seconds
void setup() {
Serial.begin(9600);
rtc.begin();
UNION_t oldSet; // source
UNION_t newSet; // target
// the actual values to be written
oldSet.inSide.wasDataSaved = false;
oldSet.inSide.lastMode = 'A';
oldSet.inSide.VlimitVal = 20.00;
oldSet.inSide.VsetVal = 10.00;
oldSet.inSide.AlimitVal = 0.50;
oldSet.inSide.wasOEnabled = true;
oldSet.inSide.lastCurPos = 3;
// below dummies values in target to check the difference after NVRAM read
newSet.inSide.wasDataSaved = true;
newSet.inSide.lastMode = 0;
newSet.inSide.VlimitVal = 0.0;
newSet.inSide.VsetVal = 0.0;
newSet.inSide.AlimitVal = 0.0;
newSet.inSide.wasOEnabled = false;
newSet.inSide.lastCurPos = 0;
Serial.print("\nSize oldSet=");Serial.print(sizeof(oldSet));
Serial.print("\nOld Bytes pattern to be written from union");
for(int i=0;i<17;i++) {
Serial.print(" ");Serial.print(oldSet.bytes[i]); // Print the DEC representation of the data
}
lM1=millis();
rtc.writenvram(0, oldSet.bytes, 17); // memory write
lM2=millis();
Serial.print("\nTook ");Serial.print(lM1-lM2);Serial.print(" milliSeconds to Write.");
Serial.print("\n\nBefore Read values in source :-");
Serial.print("\nwasDataSaved="); Serial.print(oldSet.inSide.wasDataSaved);
Serial.print("\nlastMode ="); Serial.print(oldSet.inSide.lastMode);
Serial.print("\nVlimitVal ="); Serial.print(oldSet.inSide.VlimitVal);
Serial.print("\nVsetVal ="); Serial.print(oldSet.inSide.VsetVal);
Serial.print("\nAlimitVal ="); Serial.print(oldSet.inSide.AlimitVal);
Serial.print("\nwasOEnabled ="); Serial.print(oldSet.inSide.wasOEnabled);
Serial.print("\nlastCurPos ="); Serial.print(oldSet.inSide.lastCurPos);
lM1=millis();
rtc.readnvram (newSet.bytes,17, 0); // memory read
lM2=millis();
Serial.print("\nTook ");Serial.print(lM1-lM2);Serial.print(" milliSeconds to Read.");
Serial.print("\nNew Bytes");
for(int i=0;i<17;i++) {
Serial.print(" ");Serial.print(newSet.bytes[i]); // Print the hex representation of the float
}
Serial.print("\n\nFrom NVRAM actual values-");
Serial.print("\nwasDataSaved="); Serial.print(newSet.inSide.wasDataSaved);
Serial.print("\nlastMode ="); Serial.print(newSet.inSide.lastMode);
Serial.print("\nVlimitVal ="); Serial.print(newSet.inSide.VlimitVal);
Serial.print("\nVsetVal ="); Serial.print(newSet.inSide.VsetVal);
Serial.print("\nAlimitVal ="); Serial.print(newSet.inSide.AlimitVal);
Serial.print("\nwasOEnabled ="); Serial.print(newSet.inSide.wasOEnabled);
Serial.print("\nlastCurPos ="); Serial.print(newSet.inSide.lastCurPos);
}
void loop() {
// put your main code here, to run repeatedly:
}
Below is the Results when executed:-
Size oldSet=17
Old Bytes Pattern 0 65 0 0 160 65 0 0 32 65 0 0 0 63 1 3 0
Took -2 milliSeconds to Write.
Before Read:-
wasDataSaved=1
lastMode =
VlimitVal =0.00
VsetVal =0.00
AlimitVal =0.00
wasOEnabled =0
lastCurPos =0
Took -2 milliSeconds to Read.
New Bytes pattern 0 65 0 0 160 65 0 0 32 65 0 0 0 63 1 3 0