Float I2c

I’m making progress but the foo value is not increasing as I though it would here is the codes, might be a bit messy and a better way of doing it but it’s working(I will tidy up code in a bit) I’m doing it as building blocks as I want to measure a voltage from 4 locations and send it to one unit but first thought make sure it send float values, My ADC code works so I think it’s just the case of adding it bit by bit
Master

#include <Wire.h>
#include <I2C_anyThing.h> // Template from Nick Gammon

long fnum;   // volatile Not Need because variable will be Not be accessed during an interrupt ISR
float foo;   //  same thing.
long fnum1;
long foo1;
#define DATALEN (sizeof fnum) + (sizeof foo)
#define SLAVE_ADDRESS_1 0x58   // slave 1change this for each slave
#define SLAVE_ADDRESS_2 0x59   // slave 2

void setup() {
  Wire.begin();  // not a slave
  Serial.begin(9600); // if USB is connected to this slave and Serial monitor is on
  //we will send debug messages.
}

void debug_out( char msg[]) {
  Serial.println(msg);
  Serial.print("foo=");
  Serial.println(foo);
  Serial.print("fnum=");
  Serial.println(fnum);
  Serial.println("**************");

}

void loop() {
  slave_one();
  slave_two();
  delay(1000);
}

float slave_one() {
  Wire.requestFrom(SLAVE_ADDRESS_1, DATALEN);
  if (Wire.available() == DATALEN) {
    I2C_readAnything(fnum);
    I2C_readAnything(foo);
    debug_out("SLAVE ONE");
  }
  else debug_out("Tried to Read from Slave 1, Failed.");
}
float slave_two() {
  Wire.requestFrom(SLAVE_ADDRESS_2, DATALEN);
  if (Wire.available() == DATALEN) {
    I2C_readAnything(fnum);
    I2C_readAnything(foo);
    debug_out("SLAVE TWO");
  }
  else debug_out("Tried to Read from Slave 1, Failed.");
}

Slave_one (two is the same apart from address and values)

#include <Wire.h>
#include <I2C_anyThing.h> // Template from Nick Gammon

volatile long fnum; // volatile because variable will be accessed during an interrupt ISR
volatile float foo;  //  same thing.
volatile uint8_t newData; // flag to detect I2C activity

#define DATALEN (sizeof fnum) + (sizeof foo)

#define SLAVE_ADDRESS 0x58   // change this for each slave

void onRequestEvent(void) {
  /* Wire.write(1);
   Wire.write(2);
   Wire.write(3);
   Wire.write(4);
   Wire.write(5);
   Wire.write(6);
   Wire.write(7);
   Wire.write(8);
  */
  I2C_writeAnything(fnum);
  I2C_writeAnything(foo);
  // newData = newData | 1; // set bit 0 to mark I2C Sent data
}

void onReceiveEvent(int numbytes) {
  if (numbytes == DATALEN) { // Masters beginTransmission(SLAVE_ADDRESS);Write();endTransmission();
    // sent the correct number of bytes
    I2C_readAnything(fnum);
    I2C_readAnything(foo);
    // newData = newData | 2; // set bit 1 to mark I2C Received Data.
  }
}

void setup() {
  //newData = 0;
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(onReceiveEvent);
  Wire.onRequest(onRequestEvent);
  Serial.begin(9600); // if USB is connected to this slave and Serial monitor is on
  //we will send debug messages.
}

void loop() {

  foo = 12.36 + 0.01;
  fnum = 24;
}

Why is not the foo value increasing ?

chucktodd:
Now for one more complication. You do realize that an arduino can be both a Master and a Slave at the same time?

just add the onRequest, onReceive events to the Master Sketch, change the Wire.begin() in the Master to Wire.begin(thirdslaveaddress);add the Wire.onReceive(),onRequest(). One more thing, put the volatile prefix on fnum, and foo. They will now be access in a ISR.

Now one proviso, The master CANNOT talk to itself successfully. if you put this new sketch into multiple Arduino’s you could have them access each other.

If you added this complexity you would need to start monitoring the results from endTransmission(), requestFrom(). your transfers might get aborted if the transaction looses arbitration. you could no longer assume the master will always suceed.

multiple Master can be on the bus at the same time. Two masters can talk to the same slave at the same time. The master that wins is the one that transfers a byte with a low bit first.

Here is a good reference on the I2C buss Philips Electronics I2C Specs

Chuck.

I did think about that but not was 100% sure about it, Now you got me worried and think may have bit of more than I can chew but the main ting is I’m having fun it seems to be working ok here a sample of the data coming in

SLAVE ONE
foo=12.37
fnum=24
**************
SLAVE TWO
foo=12.36
fnum=50
**************
SLAVE ONE
foo=12.37
fnum=24
**************
SLAVE TWO
foo=12.36
fnum=50
**************
SLAVE ONE
foo=12.37
fnum=24
**************
SLAVE TWO
foo=12.36
fnum=50
**************
SLAVE ONE
foo=12.37
fnum=24
**************
SLAVE TWO
foo=12.36
fnum=50
**************

Thanks for the link it will be interesting bedtime reading :slight_smile:

EDIT… I got it counting set foo to read 12.36 then in the loop I added foo = foo + 0.01;

Steveiboy: EDIT... I got it counting set foo to read 12.36 then in the loop I added foo = foo + 0.01;

Feels good when you figure it out :grin:

Enjoy! Chuck.


Check out my Kickstarter Project Memory Panes an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

chucktodd:
Steveiboy,

The Wire library has a problem. When the onRequestevent() is triggered (inside ISR), the code only transmits the last Wire.write() data. if your onRequestEvent() is like this:

void onRequestEvent(){

Wire.write(1);
  Wire.write(2);
  Wire.write(3);
  Wire.write(4);
  Wire.write(5);
  Wire.write(6);
  Wire.write(7);
}




and the Master's code was


Wire.requestFrom(slave,7);
  while(Wire.available()){
    Serial.print(Wire.read(),HEX);
    Serial.print(’ ');
    }




the Monitor would print:

7 FF FF FF FF FF FF

Not what you expected right?

I changed the code in my library to fix this and another Issue.


C:\Program Files\Arduino\hardware\arduino\avr\libraries\Wire\utility\twi.c


/*

  • Function twi_transmit
  • Desc    fills slave tx buffer with data
    *          must be called in slave tx event callback
  • Input    data: pointer to byte array
    *          length: number of bytes in array
  • Output  1 length too long for buffer
    *          2 not slave transmitter
    *          0 ok
    /
    uint8_t twi_transmit(const uint8_t
    data, uint8_t length)
    {
      uint8_t i;

// ensure data will fit into buffer
  //if(TWI_BUFFER_LENGTH < length){ // original
  if(TWI_BUFFER_LENGTH < (length+twi_txBufferLength)){ //chuck 15JUN2015
    return 1;
  }
 
  // ensure we are currently a slave transmitter
  if(TWI_STX != twi_state){
    return 2;
  }
 
  // set length and copy data into tx buffer
  //twi_txBufferLength = length; original
  for(i = 0; i < length; ++i){
  //  twi_txBuffer[i] = data[i]; original
    twi_txBuffer[twi_txBufferLength++] = data[i]; //chuck 15Jun2015
    }
  return 0;
}






Appended are my update twi.c and two test Sketches that work. 

Chuck.


---


Check out my Kickstarter Project [Memory Panes](https://www.kickstarter.com/projects/1052400055/mega2560-expansion-ram-arduino-compatible-xmem) an expansion RAM Shield for Mega2560's. It adds 1MB of RAM for those projects where 8KB is not enough.

i’m the new, how to do with your library and the twi file. Thanks

I’ve started to play around again with this again, Not sure what’s happened as the last time it was working but now I just get it displaying -1 and nan on the LCD and serial port, I’ve done nothing to the code since it was working last time other than reloaded it into the board’s. I’m only using one slave at the moment and highlighted out slave two if/when I get it working I will see about adding 3 other slaves.
I’m using version 1.67 and replaced the twi.c file as I did the last time to get it working when I add the same issue with the previous version of the IDE
Master code

#include <Wire.h>
#include <I2C_anyThing.h> // Template from Nick Gammon
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

float fnum;   // volatile Not Need because variable will be Not be accessed during an interrupt ISR
long foo;   //  same thing.
float fnum1;
float foo1;
#define DATALEN (sizeof fnum) + (sizeof foo)
#define SLAVE_ADDRESS_1 0x58   // slave 1change this for each slave
#define SLAVE_ADDRESS_2 0x59   // slave 2

void setup() {
  Wire.begin();  // not a slave
  Serial.begin(9600); // if USB is connected to this slave and Serial monitor is on
  lcd.begin (20,4); // for 16 x 2 LCD module
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.clear();
  //we will send debug messages.
}

void debug_out( char msg[]) {
  Serial.println(msg);
  Serial.print("foo=");
  Serial.println(foo);
  Serial.print("fnum=");
  Serial.println(fnum);
  Serial.println("**************");
lcd.setCursor(0, 0);
lcd.print(foo);
  lcd.print("  ");
  lcd.setCursor(0, 1);
  lcd.print(fnum);
  lcd.print("  ");

}
void debug_out1( char msg1[]) {
  Serial.println(msg1);
  Serial.print("foo=");
  Serial.println(foo1);
  Serial.print("fnum=");
  Serial.println(fnum1);
  Serial.println("**************");
lcd.setCursor(0, 2);
lcd.print(foo1);
  lcd.print("  ");
  lcd.setCursor(0, 3);
  lcd.print(fnum1);
  lcd.print("  ");

}
void loop() {
  slave_one();
 // slave_two();
 delay(200);
}

float slave_one() {
  Wire.requestFrom(SLAVE_ADDRESS_1, DATALEN);
  if (Wire.available() == DATALEN) {
    I2C_readAnything(fnum);
    I2C_readAnything(foo);
    debug_out("SLAVE ONE");
  }
  else debug_out("Tried to Read from Slave 1, Failed.");
}
float slave_two() {
  Wire.requestFrom(SLAVE_ADDRESS_2, DATALEN);
  if (Wire.available() == DATALEN) {
    I2C_readAnything(fnum1);
    I2C_readAnything(foo1);
    debug_out1("SLAVE TWO");
  }
  else debug_out1("Tried to Read from Slave 2, Failed.");
}

Slave code

#include <Wire.h>
#include <I2C_anyThing.h> // Template from Nick Gammon
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
float vout = 0.0;
int inputPin = A0;
volatile float fnum; // volatile because variable will be accessed during an interrupt ISR
volatile long foo;  //  same thing.
volatile uint8_t newData; // flag to detect I2C activity
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
#define DATALEN (sizeof fnum) + (sizeof foo)

#define SLAVE_ADDRESS 0x58   // change this for each slave

void onRequestEvent(void) {
  /*	Wire.write(1);
  	Wire.write(2);
  	Wire.write(3);
  	Wire.write(4);
  	Wire.write(5);
  	Wire.write(6);
  	Wire.write(7);
  	Wire.write(8);
  */
  I2C_writeAnything(fnum);
  I2C_writeAnything(foo);
   newData = newData | 1; // set bit 0 to mark I2C Sent data
}

void onReceiveEvent(int numbytes) {
  if (numbytes == DATALEN) { // Masters beginTransmission(SLAVE_ADDRESS);Write();endTransmission();
    // sent the correct number of bytes
    I2C_readAnything(fnum);
    I2C_readAnything(foo);
     newData = newData | 2; // set bit 1 to mark I2C Received Data.
  }
}

void setup() {
  newData = 0;
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(onReceiveEvent);
  Wire.onRequest(onRequestEvent);
  Serial.begin(9600); // if USB is connected to this slave and Serial monitor is on
  //we will send debug messages.
  for (int thisReading = 0; thisReading < numReadings; thisReading++)
    readings[thisReading] = 0;
}

void loop() {
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(inputPin);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings)
    // ...wrap around to the beginning:
    readIndex = 0;

  // calculate the average:
  vout = total / numReadings;
  foo = (vout * 5.0) / 1024.0; // see text
  fnum = 12;
  delay(200);
}

Steveiboy:
I’ve started to play around again with this again, Not sure what’s happened as the last time it was working but now I just get it displaying -1 and nan on the LCD and serial port, I’ve done nothing to the code since it was working last time other than reloaded it into the board’s. I’m only using one slave at the moment and highlighted out slave two if/when I get it working I will see about adding 3 other slaves.
I’m using version 1.67 and replaced the twi.c file as I did the last time to get it working when I add the same issue with the previous version of the IDE
Master code

#include <Wire.h>

#include <I2C_anyThing.h> // Template from Nick Gammon
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

float fnum;   // volatile Not Need because variable will be Not be accessed during an interrupt ISR
long foo;   //  same thing.
float fnum1;
float foo1;
#define DATALEN (sizeof fnum) + (sizeof foo)
#define SLAVE_ADDRESS_1 0x58   // slave 1change this for each slave
#define SLAVE_ADDRESS_2 0x59   // slave 2

void setup() {
 Wire.begin();  // not a slave
 Serial.begin(9600); // if USB is connected to this slave and Serial monitor is on
 lcd.begin (20,4); // for 16 x 2 LCD module
 lcd.setBacklightPin(3, POSITIVE);
 lcd.setBacklight(HIGH);
 lcd.clear();
 //we will send debug messages.
}

void debug_out( char msg) {
 Serial.println(msg);
 Serial.print(“foo=”);
 Serial.println(foo);
 Serial.print(“fnum=”);
 Serial.println(fnum);
 Serial.println("**************");
lcd.setCursor(0, 0);
lcd.print(foo);
 lcd.print("  “);
 lcd.setCursor(0, 1);
 lcd.print(fnum);
 lcd.print(”  ");

}
void debug_out1( char msg1) {
 Serial.println(msg1);
 Serial.print(“foo=”);
 Serial.println(foo1);
 Serial.print(“fnum=”);
 Serial.println(fnum1);
 Serial.println("**************");
lcd.setCursor(0, 2);
lcd.print(foo1);
 lcd.print("  “);
 lcd.setCursor(0, 3);
 lcd.print(fnum1);
 lcd.print(”  ");

}
void loop() {
 slave_one();
// slave_two();
delay(200);
}

float slave_one() {
 Wire.requestFrom(SLAVE_ADDRESS_1, DATALEN);
 if (Wire.available() == DATALEN) {
   I2C_readAnything(fnum);
   I2C_readAnything(foo);
   debug_out(“SLAVE ONE”);
 }
 else debug_out(“Tried to Read from Slave 1, Failed.”);
}
float slave_two() {
 Wire.requestFrom(SLAVE_ADDRESS_2, DATALEN);
 if (Wire.available() == DATALEN) {
   I2C_readAnything(fnum1);
   I2C_readAnything(foo1);
   debug_out1(“SLAVE TWO”);
 }
 else debug_out1(“Tried to Read from Slave 2, Failed.”);
}



Slave code


#include <Wire.h>
#include <I2C_anyThing.h> // Template from Nick Gammon
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
float vout = 0.0;
int inputPin = A0;
volatile float fnum; // volatile because variable will be accessed during an interrupt ISR
volatile long foo;  //  same thing.
volatile uint8_t newData; // flag to detect I2C activity
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
#define DATALEN (sizeof fnum) + (sizeof foo)

#define SLAVE_ADDRESS 0x58   // change this for each slave

void onRequestEvent(void) {
 /* Wire.write(1);
  Wire.write(2);
  Wire.write(3);
  Wire.write(4);
  Wire.write(5);
  Wire.write(6);
  Wire.write(7);
  Wire.write(8);
 */
 I2C_writeAnything(fnum);
 I2C_writeAnything(foo);
  newData = newData | 1; // set bit 0 to mark I2C Sent data
}

void onReceiveEvent(int numbytes) {
 if (numbytes == DATALEN) { // Masters beginTransmission(SLAVE_ADDRESS);Write();endTransmission();
   // sent the correct number of bytes
   I2C_readAnything(fnum);
   I2C_readAnything(foo);
    newData = newData | 2; // set bit 1 to mark I2C Received Data.
 }
}

void setup() {
 newData = 0;
 Wire.begin(SLAVE_ADDRESS);
 Wire.onReceive(onReceiveEvent);
 Wire.onRequest(onRequestEvent);
 Serial.begin(9600); // if USB is connected to this slave and Serial monitor is on
 //we will send debug messages.
 for (int thisReading = 0; thisReading < numReadings; thisReading++)
   readings[thisReading] = 0;
}

void loop() {
 // subtract the last reading:
 total = total - readings[readIndex];
 // read from the sensor:
 readings[readIndex] = analogRead(inputPin);
 // add the reading to the total:
 total = total + readings[readIndex];
 // advance to the next position in the array:
 readIndex = readIndex + 1;

// if we’re at the end of the array…
 if (readIndex >= numReadings)
   // …wrap around to the beginning:
   readIndex = 0;

// calculate the average:
 vout = total / numReadings;
 foo = (vout * 5.0) / 1024.0; // see text
 fnum = 12;
 delay(200);
}

Steveiboy,
I haven’t looked at any of the newer Arduino’s past 1.65, you should install the newest version and compare my version of twi.c with the ‘new’ library, all of my edits are commented, you should be able to see the differences.

Also,I changed Wire.h, Wire.cpp, and twi.c. if you just updated twi.c I can see where this problem would rear it’s head. In the Wire.write() is were the buffer count is overwritten if the write() is during a onRequest() event.

Instead of overwriting twi.c inside of the Arduino environment, just use the Arduino Environment to install whole modified Wire library.

Sketch\include Library\add .Zip Library…

That way, you can easily remove it by just deleting the whole subdirectory.

The Arduino environment will create a directory {sketchesFolder}\libraries\Wire

My {sketchesFolder} happens to be “C:\Users\User\Documents\Arduino”.

When you have My wire library install, any sketch that uses Wire will display this warning when it is compiled:

Multiple libraries were found for "Wire.h"
 Used: C:\Users\user\Documents\Arduino\libraries\Wire
 Not used: C:\Program Files\Arduino\hardware\arduino\avr\libraries\Wire

Your locations may be different, mine are under 32bit Win7.

Chuck.

Something has changed from version 1.60 to 1.67,1.69, Chuck I've tried what you said with 1.67 and 1.69 installed your files but both programs will not complie I get errors, I deleted the library and they complie. I uninstalled 1.69 and re-installed 1.60 copied only the twi file over and everything is working like it was before. Strange, I will re-install 1.69 tomorrow and copy the errors as I could not understand the errors. I think it's something to do with the I2Canything library As its late here I will continue tomorrow Thanks for your help Steve

Steveiboy:
Something has changed from version 1.60 to 1.67,1.69,
Chuck I’ve tried what you said with 1.67 and 1.69 installed your files but both programs will not complie I get errors, I deleted the library and they complie. I uninstalled 1.69 and re-installed 1.60 copied only the twi file over and everything is working like it was before. Strange, I will re-install 1.69 tomorrow and copy the errors as I could not understand the errors. I think it’s something to do with the I2Canything library
As its late here I will continue tomorrow
Thanks for your help
Steve

Steve,

Look in my Wire.h, I included Nick Gannons I2C_anything. You probably don’t need to re include his templates.

Chuck.

chucktodd: Steve,

Look in my Wire.h, I included Nick Gannons I2C_anything. You probably don't need to re include his templates.

Chuck.

Hi Chuck Sorry for the delay and late reply, I had some time and got back onto this project and I've managed to get it working the way you said, The new errors where caused by including the I2C_writeanything still been there I removed this and it now compiles and is working I will add the 3 other salves later and see how it goes

thanks for your help