Comunicação multimaster i2c entre Arduinos – Programa 3

Este é um  programa exemplo da implementação da comunicação i2c entre Arduinos em que ambos são master.

Este é o terceiro de três programas que exploraram o uso do interface i2c com mais que um Arduino master.

Este exemplo adiciona a leitura de um MPU6050 controlado pelo Arduino 1 que não funciona, ou não é estavel quando existem muitas mensagens no bus i2c .

A estabilidade apenas se verifica para intervalos de tempo muito elevados entre comunicações iniciadas pelo do Arduino 2.

Arduino 1

Programa semelhante ao do teste anterior, mas que inclui a leitura do MPU6050.

#include <Wire.h>

#define I2C_NODE_ADDR 0x04
byte receiveArray[32];
byte *arrayPtr = receiveArray;

#define TIMER_INTERVAL 5
unsigned long timerTime;

#define I2C_SLAVE_ADDR 0x2

#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
MPU6050 mpu; //MPU6050 mpu(0x69); //use for AD0 high
#define INTERRUPT_PIN 2 // use pin 2 on Arduino Uno & most boards
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
#define MPU_TIMER_INTERVAL 5
unsigned long mpuUpdateTimer;

byte requestCounter = 0;
unsigned long loopTimeStart;

void setup() {
Serial.begin(115200);
Serial.print("start..");
Wire.begin(I2C_NODE_ADDR);
Wire.onReceive(dataReceive);
Wire.onRequest(dataRequest);
Serial.println(".");

setupMpu ();
mpuUpdateTimer = millis() + MPU_TIMER_INTERVAL;

timerTime = millis() + TIMER_INTERVAL;
loopTimeStart = millis();
}

void loop() {
static byte counter = 0; 
if(millis() > timerTime) {
timerTime = millis() + TIMER_INTERVAL;
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write(I2C_NODE_ADDR);
Wire.write(" Hello ");
Wire.write(I2C_SLAVE_ADDR + 48);
Wire.write(" From ");
Wire.write(I2C_NODE_ADDR + 48);
Wire.write('\0');
Wire.write(" ");
Wire.write(counter + 48);
Wire.endTransmission();
counter++; if(counter == 10) counter = 0;
}
// BOF: MPU6050

if(millis() >= mpuUpdateTimer) {
mpuUpdateTimer = millis() + MPU_TIMER_INTERVAL;

// do only for MPU interrupt or extra packet(s) available
if(!(!mpuInterrupt && fifoCount < packetSize)) {
getMpuRead();
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
}
}
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI); Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI); Serial.print("\t");
Serial.print(ypr[2] * 180/M_PI); Serial.print("\t");

Serial.print(requestCounter); Serial.print("\t");
int i;
for(i = 0; i < 32; i++) {
Serial.print((char)receiveArray[i]);
}
Serial.print("\t");

Serial.print(millis() - loopTimeStart); Serial.print("\t");
loopTimeStart = millis();

Serial.println("");
}

void dataRequest() {
requestCounter++;
Wire.write(requestCounter);
}

void dataReceive(int byteCount) {
byte *ptr = receiveArray; 
while(Wire.available()) {
byte b = Wire.read();
*ptr = b;
ptr++;
}
}

void setupMpu () {
mpu.initialize();
pinMode(INTERRUPT_PIN, INPUT);
if(!mpu.testConnection()) Serial.println(F("MPU6050 connection failed"));
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
if (devStatus == 0) {
mpu.setDMPEnabled(true);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
if (!dmpReady) return;
}

void getMpuRead() {
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
} else if (mpuIntStatus & 0x02) {
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
}
}

 

Arduino 2

Usa o mesmo programa do teste anterior

#include <Wire.h>

#define I2C_SLAVE_ADDR 0x4
#define I2C_NODE_ADDR 0x2

void setup() {
Serial.begin(115200);
Wire.begin(I2C_NODE_ADDR);
Wire.onReceive(onReceiveFunc);
}

void loop() {
static byte counter = 0; 
delay(1);
Wire.beginTransmission(I2C_SLAVE_ADDR);
Wire.write(I2C_NODE_ADDR);
Wire.write(" Hello ");
Wire.write(I2C_SLAVE_ADDR + 48);
Wire.write(" From ");
Wire.write(I2C_NODE_ADDR + 48);
Wire.write('\0');
Wire.write(" ");
Wire.write(counter + 48);
Wire.endTransmission();
counter++; if(counter == 10) counter = 0;
}

void onReceiveFunc(int howMany) {
while (Wire.available() > 0) {
char c = Wire.read();
Serial.print(c);
}
Serial.println();
}