using I2c : conflict beteween Wire and VirtualWire libraries ?

Hello all,

I try for 1 week to solve a problem with the I2C interface between my Arduino and my raspberry Pi.
I'm building a project of motion detectors in my flat.

My first Arduino is connected to a Motion sensor and when it detects something a signal is sended by a 433MHz transmitter. It works fine.

I don't want to listen the radio signal directly by the PI because it uses a lot of ressources, so I decided to give this task to another Arduino wich is connected as a slave by I2C. This one received the signal by a 433MHz : I use for that the library "VirtualWire" : it works fine and I can display the mails ont the serial monitor.

My problem is to send something to my Pi by the I2C interface. In fact I know how to send data from Arduino to raspberry pi by I2C (thanks to : https://gist.github.com/gileri/5a9285d6a1cfde142260 : the script Arduino + python work fine together) but when the Arduino is processing the radio signal (by the VirtualWire library) I think there is a conflict to send data by I2C protocol (library Wire).
The python script return "nan" while it returns the good data when I just send it by the Arduino without listening the radio signals.

If someone has an idea with this problem, I will be happy :slight_smile:

Julien

Ps: in attached my you can read my arduino script.

Ardui2RaspiV1.1.ino (1.55 KB)

The onRequest is an interrupt handler. It is not allowed to use delay() or any Serial function inside that. It should be very short.
You have a delay of 500 ms and 5 seconds and 300ms, and you retrieve the VirtualWire data there, and the Serial function is used.
The Wire.write writes 8 bytes (two float), but 'dataReceived' is only one float ?

How often is data requested via the I2C ?
Is it possible to add some kind of 'interrupt' signal ? A signal from the Arduino to indicate that new VirtualWire data has been received.

I don't have a Raspberry Pi, but I do have a seperate Arduino for VirtualWire. It receives temperature and so on from a few modules. The VirtualWire functions are used in the loop(). All received data is stored in EEPROM with a timestamp. The Master retrieves the data from the EEPROM via I2C whenever it needs to. I have added an 'interrupt' signal, in case something needs to be taken handled right away, for example opening a door. The Master reads the 'interrupt' signal (by polling) and then reads from the Slave what just was received, and can sound an alarm.

Thank you for your answer.

I put delays because I thought the Arduino had to be ready to send the data by I2C.

The master (PI) requests every second, I didn't know the OnRequest was so restrictive.
I will explore your idea to use a process with EEPROM.

I have a few modules, and every module has its own location in the EEPROM. That way I can easily add more modules without changing the sketch in the VirtualWire receiving Arduino. It was only as an example.

You don't need the EEPROM, just store it in a buffer in ram. I don't know if vw_get_message() can be called from within the onRequest handler, I have never done that.

Show us your new sketch, then I will have another look at your onRequest handler.
Polling every second is not very often, that should be no problem.

Hello,

Finally I changed my sketch (see below) thanks to Peter who made me understand that the command Wire.Onrequest was an interrupt...

It works nice now !
I do not use EEPROM because I don't need to save data.

You can see the result on my website : http://neptarium.gotgeeks.com (sorry it is in french :))

  • I manage a vivarium with some carnivorous plants : I control hygro, temperature, lightning, fans...
  • I built an arduino weather station wich is on my balcony (data are sent by a RF 433MHZ transmitter and sent by I2C to my raspberry Pi)
  • I look up my cat with motion captors.

Thanks

Julien

// this is the sketch of my arduino NANO connected to my Raspberry PI with the bus I2C : it is listening radio signals from others arduinos wich controll motion captors. Actually I'm just working with 1 motion aptor but later I will use 4-5.
// when it got a signal it analyzes it and send it to the raspberry Pi by I2C. I used a python script on the raspberry Pi to listen the I2C bus.


#include <VirtualWire.h>   // call the library for RF 433Mhz receiver
#include <Wire.h>       // call the library for I2C communication
#define SLAVE_ADDRESS 0x12  // define adress I2C (slave)
#define FLOATS_SENT 2 // define the long of floats wich will sent by I2C from the arduino to the Pi
float dataReceived;



void setup() {
  Serial.begin(9600);


  // I will flash my LEDs when radio signal signal is received : I set up the pins OUT
  pinMode(4, OUTPUT);
  pinMode(2, OUTPUT);

  // Initialise the IO and ISR : for using the 433MHz receiver
  vw_set_rx_pin(11);
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_setup(1500);	 // Bits per sec
  vw_rx_start();       // Start the receiver PLL running

// Initialise the I2C code
  Wire.begin(SLAVE_ADDRESS);
  Wire.onRequest(sendData);
}

void loop()
{
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  delay(100);

  if (vw_get_message(buf, &buflen)) //

  {
   

    delay (500);
    // I analyze the signal : 
    if (buf[1] == '1' and buf[2] == '1') // code 11 ==> someone has been detected by the motion sensor

    {
      //==> I will send to the PI the data
      // I turn the LED on while waiting the Raspberry PI interrupt the script and call for the data.
      dataReceived = 11;
      digitalWrite(4, HIGH );
      delay(3000); /// 3seconds to be sure that the Pi will call me... Maybe will I decrease this delay when I will use others motion captor.
      digitalWrite(4, LOW );
    }

    else if (buf[1] == '1' and buf[2] == '0')   // code 10 : nobody has been detected but the captor motion says it is still alive... (happens normally every 15 minutes)
    {
      dataReceived = 10;
      digitalWrite(2, HIGH );
      delay(2000);
      digitalWrite(2, LOW );
    }
  }

  else {

    dataReceived = 0; // code 0 = nothing to say

  }


}


void sendData() {

//when the python script call the slave (approx every seconds): this one sends its data

  Wire.write((byte*) &dataReceived, FLOATS_SENT * sizeof(float));
}

Your website is very nice. I see that you use http://www.highcharts.com/, they have also graphs. That is very nice, free for personal use and fully HTML5.
I have a few doubts about the sketch, but that's okay.