Go Down

Topic: Float I2c (Read 3 times) previous topic - next topic

woody_unreal

Is there a nice simple way to Pass Float Value over I2C -to a second arduino-  (example 3.12 for Volts). All ive seen is elaborate unions and pointers ,, Seems WAY over complexe so i skipped reading further. Any thoughts/ideas /Examples/referances :) ?

woody_unreal

Wow thers a first, never had one with out some kind of responce :)

Nick Gammon

You need a union. You said you don't want to use one. Not much left to say. They are not particularly elaborate BTW.

woody_unreal

Nick Gammon , you sem to the goto for I2C ,, have your had the chance to run "unions" before ?

Nick Gammon

#4
May 08, 2012, 01:59 am Last Edit: May 08, 2012, 02:01 am by Nick Gammon Reason: 1
OK, here's how to do it. Based on the EEPROM_Anything idea I did this ...




I2C_Anything.h

Make a new tab in the IDE called "I2C_Anything.h". Put this in it:

Code: [Select]
// Written by Nick Gammon
// May 2012

#include <Arduino.h>
#include <Wire.h>

template <typename T> int I2C_writeAnything (const T& value)
 {
   const byte * p = (const byte*) &value;
   unsigned int i;
   for (i = 0; i < sizeof value; i++)
         Wire.write(*p++);
   return i;
 }  // end of I2C_writeAnything

template <typename T> int I2C_readAnything(T& value)
 {
   byte * p = (byte*) &value;
   unsigned int i;
   for (i = 0; i < sizeof value; i++)
         *p++ = Wire.read();
   return i;
 }  // end of I2C_readAnything


Now here is an example of sending a float and a long to a slave:




Master

Code: [Select]

// Written by Nick Gammon
// May 2012

#include <Wire.h>
#include "I2C_Anything.h"

const byte SLAVE_ADDRESS = 42;

void setup()
{
 Wire.begin ();
}  // end of setup

void loop()
{

long foo = 42;

for (float fnum = 1; fnum <= 10; fnum += 0.015)
   {  
   Wire.beginTransmission (SLAVE_ADDRESS);
   I2C_writeAnything (fnum);
   I2C_writeAnything (foo++);
   Wire.endTransmission ();
     
   delay (200);
   }  // end of for

}  // end of loop





And here is the slave:

Slave

Code: [Select]

// Written by Nick Gammon
// May 2012

#include <Wire.h>
#include "I2C_Anything.h"

const byte MY_ADDRESS = 42;

void setup()
{
 Wire.begin (MY_ADDRESS);
 Serial.begin (115200);
 Wire.onReceive (receiveEvent);
}  // end of setup

volatile boolean haveData = false;
volatile float fnum;
volatile long foo;

void loop()
{
 if (haveData)
   {
   Serial.print ("Received fnum = ");
   Serial.println (fnum);  
   Serial.print ("Received foo = ");
   Serial.println (foo);  
   haveData = false;  
   }  // end if haveData

}  // end of loop

// called by interrupt service routine when incoming data arrives
void receiveEvent (int howMany)
{
if (howMany >= (sizeof fnum) + (sizeof foo))
  {
  I2C_readAnything (fnum);  
  I2C_readAnything (foo);  
  haveData = true;    
  }  // end if have enough data

}  // end of receiveEvent


The template in the .h file will convert any data type (eg. float, int, long) into a pointer to a series of bytes and send (or receive) those one at a time via I2C.

Example output:

Code: [Select]

Received fnum = 6.52
Received foo = 410
Received fnum = 6.53
Received foo = 411
Received fnum = 6.55
Received foo = 412
Received fnum = 6.56
Received foo = 413
Received fnum = 6.58
Received foo = 414
Received fnum = 6.59
Received foo = 415
Received fnum = 6.61
Received foo = 416
Received fnum = 6.62
Received foo = 417
Received fnum = 6.64
Received foo = 418
Received fnum = 6.65
Received foo = 419
Received fnum = 6.67
Received foo = 420

Go Up