Get floating value from slave to master

I would liketo get floating value from a slave, but I having problem.

The slave has address as 30. value “data” as global float

I placed Wire.onRequest(passdataSLV) in set up.

placed passdataSLV() in loop.

placed void passdataSLV that containing Wire.write((byte)data).

If I check data in void passdataSLV with Serial monitor it is there.

In Master side,

begin ()

placed Wire.onRequest(passdata) in set up.

placed passdata() in loop.

added void passdata() that contains

Wire.requestFrom(30, 8);

While (Wire.available());

float dataS = Wire.read();

I don’t get the value in master.

What am I doing wrong?

Your code description is very unclear. Do us a favor and explain first what sort of language this is. It’s probably Arduino, but it’s best to confirm also which library you are using specifically. Second, please show the entire code. And insert it in between [ code ] [/ code ] tags. That makes it much easier to read and understand (and avoids the smiley icons).

And if I understand you correctly, floating point numbers cannot be sent over a serial connection directly, shown as 123.4567 or something. They will be sent as a string of bytes containing the binary representation of the value. At least, I think that something goes wrong in the re-casting of the variable type. But without the entire code I can’t offer much further help.

click on to open

************************slave side *****************
#include <Wire.h>
        

float dataS;

const int buttonPin = 9;     // Digital input of the pushbutton pin (9)

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
int ID; 

void setup()
{
//  Wire.begin(30);        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output. Serial Monitor must match.

  ID = 30;  // Preset the ID to 30. if switch is ON if command below will change it to 40.
  
  pinMode(buttonPin, INPUT);  
  buttonState = digitalRead(buttonPin); 
  if (buttonState == HIGH) 
  {     
    //Serial.println("Switch OFF");
    ID = 30;           // if switch is off make slave address as "30"
    Wire.begin(ID);
    
  } 
  else
  {
    //Serial.println("Switch ON");
    ID = 40;           // if switch is off make slave address as "40"
    Wire.begin(ID);
  }
  
  Wire.onRequest(passdataSLV);  ///  data transfer to Master
 
}


void loop()
{
  //Serial.print("ID =");  // just check the status.
  //Serial.print(ID);
  
 
  passdataSLV();
  
}

void passdataSLV()
   {
     dataS = 55; // temp data to check 
     
     Wire.write((byte)dataS);
     Serial.print("Pass=");
     Serial.println(dataS);
   }
 
*************** master side ***************************
  // Master side

#include <Wire.h>

float x1;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Wire.onRequest(passdata);
}

void loop()
{
    passdata();
}

void passdata()
{
  Wire.requestFrom(30, 8);
  
  while (Wire.available());
  {
  x1 = Wire.read();
  }

  
  Serial.print("Data received=");
  Serial.println(x1);
  delay(200);
 
}

Thank you for posting the code. This is much easier to understand.

Try changing the floats dataS and x1 into bytes or chars. See what you get.

Wire.write and Wire.read only handle single bytes. Floats are not integer bytes. They take more space, and require conversion. Unless Wire.write is used in the form of Wire.write(string) or Wire.write(data, length) can you send variables as sequences of bytes. The library has no way to send float variables. Why would you want to really? Floats are very difficult and slow to process for microcontrollers. On top of that they need much extra library code. But they love handling integers. Whatever that 55 is meant to represent, I doubt the slave arduino gets that value as a float to begin with. Probably as an integer or string somehow. So you might as well leave it in that form until you convert it at the master side.

If you really want to send floats, first convert them to a string, and send that. While Arduino doesn’t have a function named FloatToString or something build in, it does inherrit one from the avrgcc compiler: dtostrf() as part from the stdlib library

http://www.nongnu.org/avr-libc/user-man … 3ce8771d42 (avrgcc description of the function)

http://www.arduino.cc/cgi-bin/yabb2/YaB … 1205038401 (see post at end of the thread how to include it in your sketch)

Thank you for many information. I will try.

Oh I knoticed that you were asking me about 100M I2c.

That is NXP P82B96 instead of using 715.

Thanks again.

I think I am doing okay for slave that using dtostrf. but i am having problem to extract it in master side.

wire.read line gives me error "invalid conversion from “int” to “char*”.

Why it saying int? Would you please tell me commond lines to have float in x1? Thanks

// Master side

#include <Wire.h>

float x1;
char* S1;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  Wire.onRequest(passdata);
}

void loop()
{
    passdata();
}

void passdata()
{
  Wire.requestFrom(30, 8);
  
  while (Wire.available());
  {
    
   S1 = Wire.read();

   x1 = atof(S1);
  


  Serial.print("Data received=");
  Serial.println(x1);
  delay(200);
  
  }

  
  
 
}

pmcuser:
I think I am doing okay for slave that using dtostrf. but i am having problem to extract it in master side.

wire.read line gives me error "invalid conversion from “int” to “char*”.

Why it saying int? Would you please tell me commond lines to have float in x1? Thanks

With
char* S1;

you defined S1 as a pointer to a char. Which means S1 is now a integer-value that contains the adress of a char. (or it is a reserved space for an adress, but not yet assigned a value to it)

While this is sufficient to reference the start of a string variable, it is not enough as you have not defined the maximum size of the character string. (or else filling it with too large strings might cause buffer overruns) For that your would need to define it with:

char S1[9]=""; // reserve 8 characters for the float-string + 1 binary zero as termination marker. And make it empty.

The above reserves the space for the 8-character string variable, and assigns it an empty value.

Then with (your code)

...
   S1 = Wire.read();
...

you assigned a byte value (the type that Wire.read() returns) to S1. A pointer to a memory location is larger in size than a single byte, so the compiler doesn’t allow this. It doesn’t match sizes.

Writing it as:

S1[0]= Wire.read();

would have compiled succesfully. But S1[1], pointing to the second character of the string, would still be susceptible for buffer overruns. (There are plenty of warnings though, about other code in other libraries. And defining S1 as char S1[9]=“”; would have solved those warnings.)

Use the above change only to see which individual bytes are sent from your slave program. (Atleast I think it will, as I don’t have my own slave sending it to test) It is not enough to get a propper float value into x1. But should help to learn what is needed further. The sent bytes need to be concatenated into a string somehow, one after the other. Now you are just replacing them one OVER the other.

My suggestion for void Passdata():

void passdata()
{
  // make sure the following is already declared globally:
   // char S1[9]="";

  Wire.requestFrom(30, 8);
  
  int index=0; // character position index;
  while (Wire.available());
  {
    
   S1[index] = Wire.read();
   Serial.print("Data byte received= ");
   Serial.println(S1[index]);
   index++; // increment character index
  }
  S1[9]=0; // place zero-termination marker in string to make sure.

  
  Serial.print("Full string received: ");
  Serial.println(S1);
  
  x1 = atof(S1);
 
  Serial.print("Full float (converted 8 characte string): ");
  Serial.println(x1);
  delay(200);
 
}

I hope this works as desired. As said, I can’t test the result.

This did not do anything. Monitor was no action.

I found Nick’s I2C anything that read and write.

This works great for one slave to Master.

Now I added one more slave that will send same data as other one.

with this code, I am judging ID from data from slaves and assign S1 and S2.

The problem is that it works for short time and stops due to communication mix.

What is the best way to have clean separation for data transfer?

Also many times, i have to push reset on slave 328 to get start too. I don’t want to have that.

What do I need?

Thanks for help.

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

void setup()
{

  Wire.onReceive(getdata);   // contact to get ID and data from Slave
  
  delay (1000);
  Serial.println("Ready");
}

volatile boolean haveData = false;
volatile float Sd, S1, S2;
volatile int Sensor;

void loop()
{
  if (haveData)
 {
  getdata(haveData);   // 
 
  S1 = 0;
  haveData = false;
 }
}

void getdata(int howMany)
{

  if (howMany >= (sizeof Sd) + (sizeof Sensor))
  {
    I2C_readAnything (Sd);
    I2C_readAnything (Sensor);
    
    if (Sensor == 30)
    {
     S1 = Sd;
     Serial.print ("Sensor1 =");
     Serial.print (Sensor);
     Serial.print ("  ang=");
     Serial.println(S1);
     
     haveData = true;
     delay(300);
    }
     if (Sensor == 40)
    {
     S2 = Sd;
     Serial.print ("Sensor2 =");
     Serial.print (Sensor);
     Serial.print ("  ang=");
     Serial.println(S2);
     
     haveData = true;
     delay(300);
    }

  }

}