Hi friends!
I am trying to communicate two Arduinos using I2C. The aim of my project is to send two variables (“pitch” and “roll”) from an Arduino Nano 33 IoT to other Arduino. The code is working, BUT I don’t know why, every few seconds is stopping. In other words, if you watch the ”Monitor serie” o “serial plotter” from the “slave” which is receiving the values, you will see the results but I2C "hangs".
I have used the library I2C_Anything.h from I2C Gammon to send floats from Arduino Nano 33 IoT to Arduino UNO. Please, do you have any idea?
MASTER
#include <Wire.h>
#include <Arduino_LSM6DS3.h>
#include <I2C_Anything.h>
#include <MadgwickAHRS.h>
Madgwick filter;
const float sensorRate = 104.00;
const byte I2C_SLAVE_ADDR = 0x60;
void setup()
{
Wire.begin();
// Wire.onRequest(requestEvent);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU");
// stop here if you can't access the IMU:
while (true);
}
// start the filter to run at the sample rate:
filter.begin(sensorRate);
}
void loop()
{
float xAcc, yAcc, zAcc;
float xGyro, yGyro, zGyro;
float roll, pitch;
// check if the IMU is ready to read:
if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
// read accelerometer & gyrometer:
IMU.readAcceleration(xAcc, yAcc, zAcc);
IMU.readGyroscope(xGyro, yGyro, zGyro);
// update the filter, which computes orientation:
filter.updateIMU(xGyro, yGyro, zGyro, xAcc, yAcc, zAcc);
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
Wire.beginTransmission(I2C_SLAVE_ADDR);
I2C_writeAnything (roll);
I2C_writeAnything (pitch);
Wire.endTransmission();
}
}
Try to remove the Serial functions from receiveEvent(). That is a interrupt handler and should be as short and as fast as possible.
The Arduino Nano 33 IOT uses a 3.3V ARM M0+ processor and it has therefor a 3.3V I2C bus.
The Arduino Uno uses a 5V ATmega328P microcontroller and it has therefor a 5V I2C bus.
How did you connect the 3.3V I2C bus to a 5V I2C bus ?
How long are your wires ? Do you use pullup resistors ? Did you connect the GNDs ?
josepramon:
I am trying to communicate two Arduinos using I2C. The aim of my project is to send two variables (“pitch” and “roll”) from an Arduino Nano 33 IoT to other Arduino.
You could slow down the loop() with a delay() or use a flag.
When sending too much serial data, the buffer in the Serial library will be completely filled and that could slow down the sketch.
Now it is time to read the tutorial by Robin2 Look at the flag "bool newRxData" in the Slave code.
Set the flag in receiveEvent() and read the flag in the loop(). When the data is used, then reset the flag.
Do you use a breadboard ? You can try to relocate everthing to other pins, because breadboards have often bad contacts.
According to the schematic, the Nano 33 IOT has 4k7 pullup resistors to 3.3V for SDA and SCL.
The Arduino Uno has internal pullup resistors of 30k or 50k to 5V.
The I2C should work (a little) and hopefully nothing gets damaged, but I still prefer a I2C level shifter between the 5V Uno and the 3.3V Nano 33 IoT.
Thank you very much!
Koepel , you have all reason. When I am only sending integers, works fine. Moreover, it affects the Master IDE, and this is the part that hangs the program:
I am not using breadboard, both Arduino’s are connected directly without it.
I read a lot of documentation, but I will read carefully the documentation from Robin2. I have a lot of questions because I have never used a flag.
Anyway I have used a delay and millis() into the void loop() of master and slave and it not works.
Thanks
I don't know why those four lines hangs the program. In a normal situation it should work. If the Slave blocks the I2C bus, then perhaps the Wire.endTransmission() might halt. Since the Arduino Uno does not get the signals it needs according to the datasheet, something might go wrong.
I have a board with a M0+ SAMD processor and I have a Arduino Uno, but I will not try it without level shifter because I don't want to damage something.
Then you will have a 5V I2C bus and a 3.3V I2C bus. Connect all 3.3V things to the 3.3V bus and all the 5V things to the 5V bus, regardless if they are Slave or Master.
The I2C level shifter is not a digital component and not a amplifier, it's just a simple mosfet. If the SDA or SCL is pulled down, it needs to pull down both the 5V side and the 3.3V side. With many modules you have to be careful to have not too many pullup.
I was wondering if you got the Nano and Nano 33 IoT talking with each other over I2C. I have been working this issue for quite some time and have finally learned I am able to reliably exchange integer data using the Nano 33 IoT (Master) and the Nano (Slave). I do use a level shifter similar to the one above. I was able to move data using both interrupts on the slave for over 12 hours. I have not tried floats (or other numerical data types. I have done character well) but now I feel I need to give it a try.
But...When I made the Nano 33 IoT the Slave and the Nano the Master it failed (data stopped and SDA and SCL lines went to zero volts on scope) quickly in about 15-30 seconds. I tried three different programs - two of the examples and one of my own.
Similarly, I have not been able to use two Nano 33 IoT's as Slaves and Masters to communicate on I2C. I get similar results and it fails quickly.
Surprisingly, I have been able to use the SEED XAIO (Slave) and the Nano 33 IoT (Master) in which it works reliably just like the Nano and Nano 33 IoT. But, in this circumstance again, I was not able to use the Nano 33 IoT as a Slave.
My conclusion so far has been the Nano 33 IoT does not work well as a Slave. I do not have a strong programming background but would like to use the Nano 33 IoT's together with the I2C. Something in the way interrupts are managed by the wire library?????
Many suggestions to help you out have been offered in the forum. Only additional suggestion I have is to try only sending roll (do not send pitch). Keep in mind also that sizes for storage on the Nano 33 IoT and the Nano may be different. A good example of this is the int data type. On the Nano this is a 2 byte variable. On the Nano 33 IoT this is a 4 byte variable.
I included my example Slave and Master sketch files.
Thanks you very much. I tried a lot of things and ideas and I have arrived at the same conclusion. Arduino nano not work well as slave and the communication between different Arduino models give problems.
Thanks you very much!!