Pages: 1 [2] 3   Go Down
Author Topic: TWI/I2C - Arduino to Arduino, sending float  (Read 7188 times)
0 Members and 1 Guest are viewing this topic.
NZ
Offline Offline
Sr. Member
****
Karma: 0
Posts: 390
Turtle in a hard shell
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice work thanks.

As mentioned, what I wrote I never said was the best solution - I am not a programmer by any stretch of the imagination.
Just trying to help.

Appreciate the updated code.

Regards
James
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 127
Posts: 8521
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm a bit late to this thread but you don't need floats to work with fractional values. Use large ints and work in 10ths or 100th of the units you need, then format accordingly when you present the data to a human.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Your original code should work.

In cases like this, I typically use a low-level function to isolate the user code from the actual protocol, like this:

Code:
//send a byte with a protocol
void send_byte(unsigned char dat) {
//implement your protocol here
}

//send a word with send_byte()
void send_word(unsigned short wrd) {
  unsigned char i=sizeof(wrd);
  unsigned char *ptr=(unsigned char *) &wrd;
  while (i--) send_byte(*ptr++);
}

//send a float with send_byte()
void send_float(float flt) {
  unsigned char i=sizeof(flt);
  unsigned char *ptr = (unsigned char *) &flt;
  while (i--) send_byte(*ptr++);
}

You can pretty much expand it to cover any other data types.

It has the advantage of providing some stability to your code: if you wish to change the protocol through which the data is sent, you just change send_byte(), as everything else is built on top of it.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 2
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See: http://arduino.cc/forum/index.php?topic=104732.0

You could make a struct, put 6 floats in it and then use I2C_Anything to send the struct.


Hi,

I was asking for the code. I tried the above code and it works perfect! I just have to change few things ( master has to request slave to send).

Thank you so much!  smiley

Bye
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello.

Could someone please take a look at my code -simplified as given below-, and say what's the problem here? I am using 2 DUEs, and I am almost out of my mind! Please help me...

Additionally, I wonder if using volatile and union together like;
  • volatile union T {byte b[8]; double d;} T;,
  • union T {volatile byte b[8]; volatile double d;} T; or
  • union T {byte b[8]; double d;} volatile T;
is possible or not?

MASTER:
Code:
    #include <Wire.h>

    volatile double t, x, y;

// I2C BUS:

// Constants:
    const byte slaveAddress = 8;
    const byte dataCount = 24;

// Variables:
    union T {byte b[8]; double d;} T;
    union X {byte b[8]; double d;} X;
    union Y {byte b[8]; double d;} Y;

// Functions:
    void readPositions()
    {
      if (Wire.requestFrom(slaveAddress, dataCount) == dataCount)
      {
        for (byte i = 0; i < 8; i++)
        {
          T.b[i] = Wire.read();
          X.b[i] = Wire.read();
          Y.b[i] = Wire.read();
        }

        t = T.d; x = X.d; y = Y.d;
      }
    }

void setup()
{
  Wire.begin();
}

void loop()
{
  // Here is some code using t, x and y values...
}

SLAVE:
Code:
    #include <Wire.h>

    volatile double t, x, y;

// I2C BUS:

// Constants:
    const byte myAddress = 8;
    const byte dataCount = 24;

// Variables:
    byte* ArrayPtrT;
    byte* ArrayPtrX;
    byte* ArrayPtrY;
    byte* data;

// Functions:
    void writePositions()
    {
      ArrayPtrT = (byte*) &t;
      ArrayPtrX = (byte*) &x;
      ArrayPtrY = (byte*) &y;

      for (byte i = 0; i < 8; i++)
      {
        byte j = i * 3;
        data[j] = ArrayPtrT[i];
        data[j + 1] = ArrayPtrX[i];
        data[j + 2] = ArrayPtrY[i];
      }

      Wire.write(data, dataCount);
    }

void setup()
{
  Wire.begin(myAddress);
  Wire.onRequest(writePositions);
}

void loop()
{
  t = t + 0.1;
  x = x + 0.1;
  y = y + 0.1;
}
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18801
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Why are you going out of your mind? Does it compile? Does it work? Why not use I2C_Anything?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will try to implement I2C_Anything tomorrow. However, I want to learn how to use union, and also learn how to deal with things in bytes level...

My code is actually semi-working:

I serial-print data[0] to data[23] just before the wire.write line. It prints something like: 1,2,3,...,22,23,24

I also serial-print T.b[0] to T.b[23] + X.b[0] to X.b[23] + Y.b[0] to Y.b[23] just after wire.read commands. It should print exactly the same series, but it doesn't. It prints: 0,1,2,...,21,22,8

And if I print T.d, X.d and Y.d, I see that they are all 0.00. Sometimes, for some values I thing, they may be nan or vof...

I don't understand what the problem here is...
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18801
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    byte* data;

      for (byte i = 0; i < 8; i++)
      {
        byte j = i * 3;
        data[j] = ArrayPtrT[i];
        data[j + 1] = ArrayPtrX[i];
        data[j + 2] = ArrayPtrY[i];
      }

You haven't allocated any memory for data, therefore you are corrupting memory. Try:

Code:
    byte data [dataCount];

Also your sending and receiving ends are non-symmetrical which is confusing.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for your quick reply. I will try this asap. But what do you mean by saying non-symmetrical ends?
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 485
Posts: 18801
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

This to read:

Code:
for (byte i = 0; i < 8; i++)
        {
          T.b[i] = Wire.read();
          X.b[i] = Wire.read();
          Y.b[i] = Wire.read();
        }

This to write:

Code:
      ArrayPtrT = (byte*) &t;
      ArrayPtrX = (byte*) &x;
      ArrayPtrY = (byte*) &y;

      for (byte i = 0; i < 8; i++)
      {
        byte j = i * 3;
        data[j] = ArrayPtrT[i];
        data[j + 1] = ArrayPtrX[i];
        data[j + 2] = ArrayPtrY[i];
      }

      Wire.write(data, dataCount);

One uses a union, the other uses pointers. Why not do both the same way? And look at I2C_Anything.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I've done all you said. It is still not working correctly. I am now going to use I2C_Anything, but I still wonder what the problem here is?

I have now:

Master:
Code:
// I2C BUS:

// Constants:
    const byte slaveAddress = 8;
    const byte dataCount = 24;

// Variables:
    union T {byte b[8]; double d;} T;
    union X {byte b[8]; double d;} X;
    union Y {byte b[8]; double d;} Y;

// Functions:
    void readPositions() // Requests coordinates (x and y) and the heading angle (theta) from the slave.
    {
      if (Wire.requestFrom(slaveAddress, dataCount) == dataCount)
      {
        for (byte i = 0; i < 8; i++)
        {
          T.b[i] = Wire.read(); Serial.print(T.b[i]); Serial.print(",");
          X.b[i] = Wire.read(); Serial.print(X.b[i]); Serial.print(",");
          Y.b[i] = Wire.read(); Serial.print(Y.b[i]); Serial.println();
        }
        Serial.println();

        t = T.d; x = X.d; y = Y.d;

        // Serial.print(t); Serial.print(",");
        // Serial.print(x); Serial.print(",");
        // Serial.print(y); Serial.println();
      }
    }

Slave:
Code:
// I2C BUS:

// Constants:
    const byte myAddress = 8;
    const byte dataCount = 24; // [bytes] Max:32

// Variables:
    union T {byte b[8]; double d;} T;
    union X {byte b[8]; double d;} X;
    union Y {byte b[8]; double d;} Y;
    byte data[dataCount];

// Functions:
    void writePositions() // The function that executes whenever data is requested by master.
    {
      T.d = t; X.d = x; Y.d = y;

      for (byte i = 0; i < 8; i++)
      {
        byte j = i * 3;
        data[j]     = T.b[i]; Serial.print(data[j]); Serial.print(",");
        data[j + 1] = X.b[i]; Serial.print(data[j + 1]); Serial.print(",");
        data[j + 2] = Y.b[i]; Serial.print(data[j + 2]); Serial.println();
      }
      Serial.println();

      Wire.write(data, sizeof data);

      // Serial.print(t); Serial.print(",");
      // Serial.print(x); Serial.print(",");
      // Serial.print(y); Serial.println();
    }

Outputs are:

Slave:
249,17,126
186,201,27
131,71,189
155,55,202
120,75,69
31,153,120
25,165,245
64,191,62

Master:
64,249,17
126
,186,201
27
,131,71
189
,155,55
202
,120,75
69
,31,153
120
,25,165
245
,64,255
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    union T {byte b[8]; double d;} T;
Psst. A double on the Arduino is 4 bytes, not 8.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
    union T {byte b[8]; double d;} T;
Psst. A double on the Arduino is 4 bytes, not 8.

http://arduino.cc/en/Reference/Double => "On the Arduino Due, doubles have 8-byte (64 bit) precision."
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 614
Posts: 49365
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
On the Arduino Due,
Then why in the hell are you NOT in the Due section?

And why does your post title say FLOAT?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 12
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
On the Arduino Due,
Then why in the hell are you NOT in the Due section?

And why does your post title say FLOAT?

I am sorry about that, I am new here. I've just googled my problem and found this topic; I don't think that floats and doubles matter for this I2C stuff. But, it's OK; I will find the DUE section and write there. Thank you.
Logged

Pages: 1 [2] 3   Go Up
Jump to: