Send 6 float numbers via I2c from AtTiny85

Hi...
I need to transfer 6 float fields data from ATtiny85 (slave) to an Arduino Mega (master) via i2c.
Use TinywireS to post, but unfortunately I can send only one byte at a time.
I need the mega receive data quickly.
I saw the i2c_anything library but i don't know if possible use it with Attiny.
I have the Attiny and mega arduino , I have just test the i2c comunication from one to another .
Ide version 1.5.

Need help.

thanks a lot

A float has a size of 4 bytes.

Normally when you want to send a variable bigger than 1 byte you can use using the shift operator >> and a bit mask operator &.

unsigned long number = 3667098123;  // 32 bits

void setup() 
{
  Serial.begin(38400);
}

void loop() 
{  
  Serial.println(number, BIN);
  Serial.print(number >> 24 & 0xFF, BIN); Serial.print(" "); 
  Serial.print(number >> 16 & 0xFF, BIN); Serial.print(" "); 
  Serial.print(number >> 8  & 0xFF, BIN); Serial.print(" "); 
  Serial.println(number & 0xFF, BIN);
  
  delay(1000);
}

you can test this code using the serial monitor monitor.

This also works with the I2C functions.

So you would get:

unsigned long number = 3667098123;  // 32 bits
#include <TinyWireS.h>

void setup() 
{
  TinyWireS.begin();   // as master
  Serial.begin(38400);
}

void loop() 
{  
  TinyWireS.beginTransmission(0x51);           // random adress
  TinyWireS.send(number >> 24);                // 1st byte
  TinyWireS.send(number >> 16);                // 2nd byte
  TinyWireS.send(number >> 8);                 // 3rd byte
  TinyWireS.send(number);                         // 4th byte
  TinyWireS.beginTransmission();
  
  delay(1000);
}

Unlike Serial.print() Wire.write() and TinyWireS.send() will consequently send 1 single byte at the time, that would mean if you would do Wire.write(0xABCD) only 0xCD will be send. This makes the & 0xFF statement redundant for our purpose.

On the other end of the I2C bus you need also to shift the bytes correctly and you have to use the or operator |:

 unsigned long byteINC // 32 bits

if(Wire.available()) {
byteINC |= Wire.read() << 24;   // we now shift the bytes back in the other direction
byteINC |= Wire.read() << 16;   // and we OR the incoming bytes with the variabele byteINC
byteINC |= Wire.read() << 8;
byteINC |= Wire.read();            // last of the 4 bytes

I do not know if this also works with a float (32 bits) variable (I cant test this with the serial monitor)
If the IDE starts complaining about sending a float type variabele with, Wire.write() function. You can try to use the shift and bit mask operators to split the float into 4 different byte variables

Thank you.
I will try the code today and I will tell you if it's ok.
I think, that need to make a routine for receive 6 float fields..

superzaffo:
Hi...
I need to transfer 6 float fields data from ATtiny85 (slave) to an Arduino Mega (master) via i2c.
Use TinywireS to post, but unfortunately I can send only one byte at a time.
I need the mega receive data quickly.
I saw the i2c_anything library but i don't know if possible use it with Attiny.
I have the Attiny and mega arduino , I have just test the i2c comunication from one to another .
Ide version 1.5.

Need help.

thanks a lot

you have a problem, The TinyWireS library only has a 16byte buffer. 6 floats at 4 bytes each is 24 bytes, too big.

you are going to have to either

  • send each float, one at a time
  • send two blocks of three floats

I recommend the second.

Setup your code for the ATtiny as:

static volatile uint8_t numFloat=0;
static volatile float F[6];

void onRequestEvent(){
uint8_t * b; // pointer to access byte of float
TinyWireS.send(numFloat); // identify starting float for this transmission
b=(uint8_t*)*F[numFloat]; // pointer to first float to send
for(uint8_t i=0;i<12;i++){
  TinyWireS.send(b[i]);           // send each byte of float
  }
if(numFloat==0) numFloat =3;
else numFloat=0;
}

the 'master' code in the Mega is:

float F[6];

void readFloatsFromTiny(){
uint8_t index=0;
uint8_t * b; // pointer to use to access Float bytes

Wire.reqestFrom(tinySlaveID,13); // ident + 3x4
if(Wire.Available()==13){ // read them
  index = Wire.read();   
  b=(uint8_t*)&F[index];
  for(index=0;index<12;index++){
    b[index]=Wire.read();
    }
  }
// got to do it twice because of the limitations of TinyWireS

Wire.reqestFrom(tinySlaveID,13); // ident + 3x4
if(Wire.Available()==13){ // read them
  index = Wire.read();   
  b=(uint8_t*)&F[index];
  for(index=0;index<12;index++){
    b[index]=Wire.read();
    }
  }
}

I don't have a tiny so I hope it works! :slight_smile:

Chuck.

Opps... chucktodd .. this is new for me.
Is possible to increase memory in the tinyWire buffer ?
Anyway.. I will try your code...
Thank you..

I have a Idea.. I don't know if is bad o good idea, but is possible to write a float data in a external eeprom with Tiny and read the data with mega ? All with I2C bus.
Tiny->eeprom->Mega.

superzaffo:
I have a Idea.. I don't know if is bad o good idea, but is possible to write a float data in a external eeprom with Tiny and read the data with mega ? All with I2C bus.
Tiny->eeprom->Mega.

I wouldn't recommend it, most EEPROMS have a 1ms to 10ms write cycle, with a write endurance of 100k to 1M cycles. if you updated the EEPROM 100 times a second, 60 seconds a minute, 60 minutes and hour. You would exhaust the EEPROM is 2:46:40. So less than 3 hours!

The data in the EEPROM is always stale, by the time the Tiny has completed the write and the EEPROM has updated it's self the tiny could have new values.
And then there is the collision/retry logic. after how many retry's does the Mega Halt because of stale values? Is the Tiny locked up, or is the EEPROM just slow? too many possibilities.

Chuck.

Use a shared FRAM instead - SRAM writing speeds, EEPROM nonvolatilty.
High-endurance 100 trillion (10^14) read/writes!

Higher capacity also available if needed - check for 5V power if using with Uno or Mega

Thank you, goood solution...
You think that I need to attention for the locking data in the SRAM ?
For example, when the Tiny write, arduino mega canno't read in the same time ?

superzaffo:
Thank you, goood solution...
You think that I need to attention for the locking data in the SRAM ?
For example, when the Tiny write, arduino mega canno't read in the same time ?

true,

with two I2C masters on the same bus you will have to code for failures /collisions. The Wire.endTransmission() can return error codes, but Wire.requestFrom() will only return 0 as an error.

you will have to put code around these calls to retry or handle the collision error.

Chuck.