0

[UPDATE] Now it works fine but the as soon as I add the GY-521 module (hardware not software), it starts sending me crapy info

Project uses:

Arduino Pro Mini as brain

FTDI as a programmer

GY-521 gyro/accel

MPL3115A2 baro/altimeter

DS3231 real time clock

Micro SD card adapter to datalog

The GY-521, MPL3115A2 and the DS3231 uses I2C and they are breakout boards so they include pull-up resistors on the board. Now the GY-521 and the MPL3115A2 works fine together but as soon as I add the DS3231, it all freezzes. My code is fine and I'm sure of that.

Now my theory is that all of those pull-up resistors caused some kind of problem in the circuit. I know that normal I2C require 4.7k ohm pull-up resistors. Now I BELIEVE that the GY-521 uses 4.7k pull-up resistors, the MPL3115A2 uses 10k pull-up resistors and the DS3231 also uses 10k pull-up resistors.

I don't know if this setup could work and I would like to know if I can add some external resistors to calm the whole I2C constellation a bit. Note that I do not want to sodder anything to the breakouts nor do I want to modify them.

Here is the code:

Tab1: MAIN

  //==================================================

#include <SPI.h>                        //include the SPI library
#include <SD.h>                         //include the SD card library
#include <Wire.h>                       //include I2C library
#include "I2Cdev.h"                     //include another I2C library
#include "Wire.h"                       //include another I2C library (yes, again)
#include "MPU6050_6Axis_MotionApps20.h" //include the MPU6050 library
#include "SparkFunMPL3115A2.h"          //include the MPL3115A2 library
#include <DS3231.h>                     //include the DS3231 library

//==================================================

#define testtest           //*** COMMENT THIS LINE BEFORE UPLOADING OFFICIAL CODE TO FINAL PROJECT ***

#define chipSelect 10      //pin for the CS/SS
#define led 2              //led and/or buzzer

volatile bool mpuInterrupt = false; //just one of those bools

bool ledState     = false; //state of the led and/or buzzer
bool dmpReady     = false; //state of the mpu6050

int yprInt[3];             //gyro data in a integer because the extra precision of the float is total bullshit
int altitude;              //altitude above takeoff point in meters
int altitudeCalibration;   //calibration for the altimeter
int temperature;           //temperature in degrees Celcius

float counter = 0;         //time counter, a somewhat internal clock that starts when the module starts dataloging

uint8_t mpuIntStatus;      //holds actual interrupt status byte from MPU
uint8_t devStatus;         //return status after each device operation (0 = success, !0 = error)
uint8_t fifoBuffer[64];    //FIFO storage buffer

uint16_t packetSize;       //expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;        //count of all bytes currently in FIFO

String day;                //day of the week
String ymd;                //date: year,month,day
String hms;                //time: hour,minute,second

MPU6050 mpu;               //MPU6050 object declaration as mpu
Quaternion q;              //quaternion container
VectorFloat gravity;       //gravity vector

MPL3115A2 myPressure;      //MPL3115A2 object declaration as myPressure
DS3231  rtc(SDA, SCL);     //DS3231 object declaration as rtc

//==================================================

void setup()
{
  generalSetup();

  gyroSetup();
  baroSetup();

  dataSetup();
}

//==================================================

void loop()
{
  gyro();      //read angles
  baro();      //read altitude and temperature
  timeClock(); //read day, date, time

  dataPrint();   //serial print the information

  dataLog();   //write data in sd card

  timer();     //time delay and led flash
}

Tab2: SETUP

//==================================================

void generalSetup()
{
  Serial.begin(115200); //start serial communication
  Wire.begin();         //start I2C communication
  rtc.begin();          //start DS3231

  pinMode(led, OUTPUT); //led or buzzer; used to easily find a lost device
}

//==================================================

void dmpDataReady() {
  mpuInterrupt = true;
}

void gyroSetup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  TWBR = 24;
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif
  //while (!Serial);
  mpu.initialize();
  devStatus = mpu.dmpInitialize();
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788);

  if (devStatus == 0)
  {
    mpu.setDMPEnabled(true);
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
  }

  else
  {
    return;
  }
}

//==================================================

void baroSetup()
{
  myPressure.begin();             //start MPL3115A2 communication 
  myPressure.setModeAltimeter();
  myPressure.setOversampleRate(7);
  myPressure.enableEventFlags();
  altitudeCalibration = myPressure.readAltitude(); //read altitude
}

//==================================================

void dataSetup()
{
  if (SD.begin());
}

//==================================================

Tab3: FUNCTIONS

//==================================================

void gyro()
{
  float yprFlo[3]; //gyro data in a float

  mpu.resetFIFO();
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  fifoCount = mpu.getFIFOCount();

  if (mpuIntStatus & 0x02)
  {
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    fifoCount -= packetSize;
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(yprFlo, &q, &gravity);

    for (int i = 0; i < 3; i++)
    {
      yprFlo[i] = yprFlo[i] * 180 / M_PI; //simplify the variable for serial printing and dataloging
    }

    for (int i = 0; i < 3; i++)
    {
      yprInt[i] = yprFlo[i]; //changing the variable from a float to a int
    }
  }
}

//==================================================

void baro()
{
  altitude = myPressure.readAltitude() - altitudeCalibration; //read altitude
  temperature = myPressure.readTemp();  //read temperature
}

//==================================================

void dataPrint() //serial print all the data
{
  Serial.print(day);
  Serial.print(" ");
  Serial.print(ymd);
  Serial.print(" -- ");
  Serial.print(hms);
  Serial.print(", ");
  Serial.print(counter);
  Serial.print(", ");
  Serial.print(yprInt[0]);
  Serial.print(", ");
  Serial.print(yprInt[1]);
  Serial.print(", ");
  Serial.print(yprInt[2]);
  Serial.print(", ");
  Serial.print(altitude);
  Serial.print(" ,");
  Serial.print(temperature);
  Serial.println();
}

//==================================================

void dataLog()//wirte all the data in a note file on the sd card
{
  if (altitude > 1) //if the device is higher then 1m, then we sstart recording everything
  {
    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (dataFile)
    {
      dataFile.print(day);
      dataFile.print(" ");
      dataFile.print(ymd);
      dataFile.print(" -- ");
      dataFile.print(hms);
      dataFile.print(", ");
      dataFile.print(counter);
      dataFile.print(", ");
      dataFile.print(yprInt[0]);
      dataFile.print(", ");
      dataFile.print(yprInt[1]);
      dataFile.print(", ");
      dataFile.print(yprInt[2]);
      dataFile.print(", ");
      dataFile.print(altitude);
      dataFile.print(" ,");
      dataFile.print(temperature);
      dataFile.println();
      dataFile.close();
    }
  }
}

//==================================================

void timeClock()
{
  day = rtc.getDOWStr();
  ymd = rtc.getDateStr();
  hms = rtc.getTimeStr();
}

//==================================================

void timer()
{
  counter = counter + 0.5;

  #ifndef testtest
  ledState = !ledState;
  digitalWrite(led, ledState);
  #endif

  delay(500);
}

//==================================================
  • If the problem is a general one caused by pullup resistors, having one of the boards connected without trying to talk to it will still cause problems talking to the others. You can also test the pullup theory by adding some additional ones in parallel - if it still works with one of the boards replaced by another set of 2.2K resistors, it's probably not a resistor problem. An address problem would not affect other devices with unique addresses. Strictly speaking different boards could have different susceptibility to excessively stiff bus pull-up from multiple resistors in parallel. – Chris Stratton Oct 7 '16 at 18:19
  • In your ISR function dmpDataReady you are setting mpuInterrupt = true; - that variable should be declared volatile. – Nick Gammon Oct 8 '16 at 21:44
  • as soon as I add the DS3231, it all freezzes - can you clarify something? Are you adding the hardware and it freezes, or are you changing the code and also adding the hardware? – Nick Gammon Oct 8 '16 at 23:14
  • Software doesn't change. I havent tested the volatile yet but I know that in the example sketch they did use a volatile for that one. That might be the problem. When I add the DS3231 in the sense of the hardware. The program runs the MPL3115A2 + GY-521 = FINE. MPL3115A2 + DS3231 = FINE. GY-521 + DS3231 = PROBLEM. This is speaking of hardware. – Dat Ha Oct 8 '16 at 23:19
  • You can't properly perform the tests you claim to have without changing the software - leaving in software which tries to talk to a chip that isn't there will cause problems, at minimum a slowdown if there is a timeout implemented, but it isn't clear that there is, in which case the program may hang. – Chris Stratton Oct 9 '16 at 3:16
1

In fact the MPU-6050 on the GY521 and the DS3231 both use I2C address 0x68. Had you looked at the source of the header files you included for each, this would have been apparent.

By consulting the data sheet for each chip you will likely find a way to either change the I2C address by changing a configuration pin, or else to potentially enable/disable the chip by changing one with a GPIO. This will, however, likely require surgical modification of the carrier board.

You could also move whichever device you expect to access least to a distinct "soft" I2C bus bit-banged on other GPIO pins. No endorsment is implied, but the the first such library that came up in a web search was:

http://playground.arduino.cc/Main/SoftwareI2CLibrary

you can likely find other options for yourself, or can potentially create your own.

There are also other chips in the family of the MPU-6050 which speak SPI instead of or as well as I2C, however these tend to be more expensive.

2

According to my calculations the total pull-up is:

1 / (1/10 + 1/10 + 1/4.7) = 2.423 k

As I show on my page about I2C a 2.2 k pull-up resistor gives a reasonably good signal:

2.2k pullup

Thus I don't think the resistors are the issue. And I don't see how adding more would "calm the whole I2C constellation a bit".

  • Alright, I'll have to test it again. Thanks! – Dat Ha Oct 7 '16 at 0:44
  • I think there is a clash between the DS3231 and the GY-521. If I remove either of them, the code will work fine with the MPL3115A2. But if they run toghetter, with or without the MPL3115A2, the program will not have the predicted end result. If you want, I could include the code in an edit of my question. – Dat Ha Oct 7 '16 at 2:34
  • Adding the code to your question would be helpful. – Nick Gammon Oct 7 '16 at 6:37
  • The code has been added! – Dat Ha Oct 7 '16 at 10:50
  • The GY-521 has 2k2 or 10k pullups according to the Arduino Playground. playground.arduino.cc/Main/MPU-6050 – Mikael Patel Oct 7 '16 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.