Receive data from I2C and reading NFC Tag SPI

Hi guys !

I'm encountering a huge problem.

I'm working with a IMU MPU 9150, a NFC PN532 Reader and a SD Card.

On one board, i retrieve imu data and send it to the second board via I2C. I use beginTransmission, write and endTransmission to send data. It works fine.

On the second board, i retrieve data via onReceive event. It works fine too.

Retreive NFC alone works fine too.

However, when i'm trying to retrieve the NFC tag via SPI when the onReceive handler is active, it does not work. I cannot stop the I2C interruption (something like semaphore would be great).

Here is the scheme of my code :

CPU1 :
| setup()
| init imu

| loop : every 100 ms
| retrieve IMU data
| compute and fusion pose
| send data to CPU2
(this is called 6 times because I2C buffer is only 32 BYTES)
| beginTransmission(addr)
| write
| endTransmission()

CPU2 :
| setup()
| init SD and NFC board
| attach handler onReceive

| onReceive :
| while data available
| save char to string
| set boolean dataReady to true

| loop
| get NFC tag
| check flags
| if tag present, write log file
| if (dataReady)
| write log file

You'll find the code as an attachment.

Thank you very much !

CPU1.ino (14.7 KB)

CPU2.ino (8.86 KB)

However, when i'm trying to retrieve the NFC tag via SPI when the onReceive handler is active, it does not work.

Of course not. Interrupts are disabled while receiveEvent() is running.

Couldn't you have figured out a meaningful name for the function? Something that reflected the kind of data being received? Or what the data was being received from?

Adafruit_NeoPixel strip = Adafruit_NeoPixel(5, 6, NEO_GRB + NEO_KHZ800);

// Configuration values:
#define SENSOR_PIN          A3      // Analog pin which is connected to the sensor. 
#define SPEAKER_PIN         A2

You seem to have forgotten to mention these.

SENSOR_PIN is a stupid name. You didn't attach a generic sensor. You attached a SPECIFIC sensor. The name should reflect what is actually attached.

int getFlag() {
  return flags;
}

Why do you need a function to get a global variable?

You need some more Serial.print() statements in the code. The interrupts should not be interfering with the ability to read data from the SPI bus, unless you are spending too much time in the interrupt service routine.

  String toSend;
  toSend = String(quatStruct.x);
  toSend += ";";
  toSend += quatStruct.y;
  toSend += ";";
  toSend += quatStruct.z;
  toSend += ";";
  toSend += quatStruct.w;
  toSend += ";";
  Wire.beginTransmission(11);
  Wire.write(toSend.c_str());
  Wire.endTransmission();

Why is is necessary to create a String object for quatStruct.x but not quatStruct.y, quatStruct.z, or quatStruct.w? What data type is quatStruct.x? Why is it necessary to piss away resources on the String class, anyway?

Why isn't the SD card attached to the first Arduino? Sending the data to another, already busy doing completely unrelated stuff, doesn't seem smart.

You need to explain the WHOLE project.

Okay i assume names are stupid but anyway. :slight_smile:

As you can see, my ISR is very short. Just saving a char or change a boolean. However, my ISR is called 6 times because the buffer length on I2C is 32 bytes.

I use String(quatStruct) because i cannot send float through Wire.write(). So i decided to send a string. Moreover, these data are sended to be saved, not to be computed so send a string seems logic.

I can't add the SD card on the first CPU because I use TinyCircuit Board (http://tiny-circuits.com/). They have only 32Kb Flash and 2kb SRAM. When i add the SDFat lib on the CPU1, the sketch is too big and cannot be upload. If i could have just 1 CPU it would be awesome but my project is to have sensors into a glass. My boards need to be small. I cannot put a Arduino MEGA :slight_smile:

PS : i'll change some names and delete the getFlags function !

As you can see, my ISR is very short. Just saving a char or change a boolean.

void receiveEvent(int numBytes) {
  c = 0;
  while (Wire.available()) {
    c = Wire.read();
    if (c == '/') {
      dataReady = true;
    }
    else {
      data += c;
    }
  }
}

Just saving A char, huh?

The fact that memory allocation, copying, and free has to happen doesn't matter, eh? The fact that the while loop should iterate up to 32 times doesn't matter, eh?

I use String(quatStruct) because i cannot send float through Wire.write().

You most certainly can.

What you can't do is to expect sprintf() to convert the float to a string. But, dtostrf() can.