Wire.onRequest() with scheduler

Hi,
I am building a project that uses two arduinos and a raspberry pi, both arduinos are the slaves and the raspberry pi is the master, Arduino 1, collects data from sensors periodically from a scheduler, ( TaskScheduler/examples at master · arkhipenko/TaskScheduler · GitHub) using I2C passing the data onto the master raspberry pi who then passes the information on to second arduino which controls the actuators.

My question is, how can i get the arduino 1 to send the data to the raspberry pi in time with when the scheduler runs the code for the sensor read. Here is my code for the Sensor Arduino.

#include <DHT.h>

#include <defaults.h>
#include <global.h>
#include <Wire.h>

#include <TaskScheduler.h>

#define SLAVE_ADDRESS 0x04

void ec_pHCallback();
void temp_humidityCallback();

const int ec_pin = 1;//analog pin for the EC-pH sensor
const int temp_pin = 0;//analog pin for the Temp sensor

float temperatureC;


Task t_ec(50000, TASK_FOREVER, &ec_pHCallback);
Task t_temp(5000, TASK_FOREVER, &temp_humidityCallback);

Scheduler runner;

void ec_pHCallback() {
 //this function takes a reading from the ec sensors and sends it over CAN
}

void temp_humidityCallback() {
 //this function takes a temperature reading and sends it over CAN
int reading = analogRead(temp_pin);  

// converting that reading to voltage, for 3.3v arduino use 3.3
float voltage = reading * 5.0;
voltage /= 1024.0; 

// print out the voltage
Serial.print(voltage); Serial.println(" volts");

// now print out the temperature
temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                              //to degrees ((voltage - 500mV) times 100)
Serial.print(temperatureC); Serial.println(" degrees C");


}
void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);

 runner.init();
 Serial.println("Scheduler started");

 runner.addTask(t_ec);
 runner.addTask(t_temp);

 t_ec.enable();
 t_temp.enable();

  Wire.begin(SLAVE_ADDRESS);

// define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}

void receiveData(int howMany){
byte msgBuf[2];
  {
 for (byte i = 0; i < howMany; i++)
   {
   msgBuf[i] = Wire.read ();
   }  // end of for loop
 if(msgBuf[0] == 1) {
   Serial.println("correct ID");
   Serial.println(msgBuf[0]);
 if (msgBuf[1] == 8){
   Serial.print("message correct too");
   Serial.println(msgBuf[1]);
   digitalWrite(13, HIGH); // set the LED on
   delay(1000);
   digitalWrite(13, LOW); // set the LED off
  }
 }
 }
}

// callback for sending data
void sendData(){
 byte outBuf[1];
 outBuf[0] = 3;
 outBuf[1] = temperatureC;
 Serial.println(temperatureC);
Wire.write(outBuf, 1);
}

void loop() {
 // put your main code here, to run repeatedly:
   runner.execute();
}

Thanks Jonny

Read number 7 about code tags : http://forum.arduino.cc/index.php/topic,148850.0.html
Modify your first post or show your sketch again with the code tags.

The onReceive and onRequest handlers may not call Serial functions, and they may not use any delay(). Keep those functions as short and as fast as possible.
You can use : Wire.readBytes ( msgBuf, ) ;
The can be ‘howMany’, or sizeof ( msgBuf ), or 2.

Your outBuf has one element, but you use two elements.

A I2C Slave can not send data to the Master, the Master decides when to ask for data from a Slave.
A Slave can become (temporarily) a Master, but then a collision could occur. Or a Slave might use an interrupt signal to notify the Master and after that the Master can request data from the Slave.

Hi,

ok thanks,

So is there no way of me using the scheduler side of the arduino to notify the raspberry pi that he should request a data transfer?

Thanks Jonny

Some sensors use an interrupt signal, that is the normal way to tell a Master that data is ready.

A third option is that the Raspberry Pi polls the Arduino via I2C to check if data is ready.

A fourth option is to keep the timing in the Raspberry Pi. For example, let the Arduino read the sensors as many times as possible, and when the Raspberry Pi requests data, the newest data from the Arduino is returned.

Another way is to use both I2C interfaces on Raspberry Pi: first as a slave to Arduino 1, and second as a master to Arduino 2. That way the master/slave concept follow the data flow Ard1 --> RPi --> Ard 2