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(); }