I2C along with Serial1

I’m creating a topic for the first time, sorry if something is wrong. Also apologize for my english. Let's move on to the question (the question is more theoretical). In my project, I use the gps + gsm module with which I communicate in Serial1 and the MPU6050 with which I communicate in I2C. I want to poll the gps module for the current position and the accelerometer and, in certain cases, send data to the server. Separately, the GPS module and sending data to the server works without problems. Also separately, without any problems, I look through the values ​​of the accelerometer. But when I make the modules work together, for some reason the board freezes. Now directly the question. Can the data in Serial1 and I2C somehow mix and cause freezes, for example, in the library for mpu6050. Or should I2C with Serial1 work without problems? Maybe someone came across this? Thank you all for the answers.

I am not aware of any problem using Serial1 and I2C.

Please post your program.

Have you identified the point in the program at which it freezes?

...R

It seems to me that the hangs occur somewhere at the time of reading the accelerometer data.

void getCurrentMpuValues () {
  Serial.println(1);


  if (!dmpReady) return;

  unsigned long long currentMillis = millis();

  while (!mpuInterrupt && fifoCount < packetSize) {
    Serial.println("while");
    if (millis() - currentMillis >= 5000) {
      Serial.println("return");

      delay(1000);
      return ;
    }

    if (mpuInterrupt && fifoCount < packetSize) {
      fifoCount = mpu.getFIFOCount();
    }
  }

  Serial.println(2);

  mpuInterrupt = false;

  mpuIntStatus = mpu.getIntStatus();

  fifoCount = mpu.getFIFOCount();

  if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {
    mpu.resetFIFO();

    fifoCount = mpu.getFIFOCount();

    Serial.println(F("FIFO overflow!"));
  } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) {
    currentMillis = millis();

    while (fifoCount < packetSize) {
      Serial.println("while");
      if (millis() - currentMillis >= 5000) {
        Serial.println("return");

        delay(1000);
        return ;
      }
      Serial.println("do");
      fifoCount = mpu.getFIFOCount();
      Serial.println("posle");
    }


    Serial.println(3);

    mpu.getFIFOBytes(fifoBuffer, packetSize);

    mpu.resetFIFO();

    fifoCount -= packetSize;

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

It seems to me in this function. Took an example from the MPU6050 library.

Sam999:
It seems to me in this function.

Please post the complete program. Snippets are no use - the problem is probably somewhere else.

...R

main

#include <TinyGPS++.h>

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif

#define INTERRUPT_PIN 2

#include "MPU6050_6Axis_MotionApps_V6_12.h"

TinyGPSPlus gps;

MPU6050 mpu;

uint8_t devStatus;

volatile bool mpuInterrupt = false;

uint8_t mpuIntStatus;

bool dmpReady = false;

uint16_t packetSize;

uint16_t fifoCount;

uint8_t fifoBuffer[64];

Quaternion q;

VectorFloat gravity;

float ypr[3];

unsigned long long previousMillis = 0;

String imei = "***";

void dmpDataReady() {
  mpuInterrupt = true;
}

void setupMpu() {
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  Wire.setClock(400000);
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif

  while (!Serial);

  Serial.println(F("Initializing I2C devices..."));

  mpu.initialize();

  pinMode(INTERRUPT_PIN, INPUT);

  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  Serial.println(F("Initializing DMP..."));

  devStatus = mpu.dmpInitialize();

  if (devStatus == 0) {
    Serial.println();
    Serial.println(F("Enabling DMP..."));

    mpu.setDMPEnabled(true);

    Serial.print(F("Enabling interrupt detection (Arduino external interrupt "));
    Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
    Serial.println(F(")..."));

    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

    mpuIntStatus = mpu.getIntStatus();

    Serial.println(F("DMP ready! Waiting for first interrupt..."));

    dmpReady = true;

    packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));

    delay(1000);

    setupMpu();
  }
}

void getCurrentMpuValues () {
  Serial.println(1);


  if (!dmpReady) return;

  unsigned long long currentMillis = millis();

  while (!mpuInterrupt && fifoCount < packetSize) {
    Serial.println("while");
    if (millis() - currentMillis >= 5000) {
      Serial.println("return");

      delay(1000);
      return ;
    }

    if (mpuInterrupt && fifoCount < packetSize) {
      fifoCount = mpu.getFIFOCount();
    }
  }

  Serial.println(2);

  mpuInterrupt = false;

  mpuIntStatus = mpu.getIntStatus();

  fifoCount = mpu.getFIFOCount();

  if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {
    mpu.resetFIFO();

    fifoCount = mpu.getFIFOCount();

    Serial.println(F("FIFO overflow!"));
  } else if (mpuIntStatus & _BV(MPU6050_INTERRUPT_DMP_INT_BIT)) {
    currentMillis = millis();

    while (fifoCount < packetSize) {
      Serial.println("while");
      if (millis() - currentMillis >= 5000) {
        Serial.println("return");

        delay(1000);
        return ;
      }
      Serial.println("do");
      fifoCount = mpu.getFIFOCount();
      Serial.println("posle");
    }


    Serial.println(3);

    mpu.getFIFOBytes(fifoBuffer, packetSize);

    mpu.resetFIFO();

    fifoCount -= packetSize;

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

void setup() {
  delay(5000);

  Serial.println("Setup");

  setupMpu();

  Serial.begin(115200);
  Serial1.begin(115200);

  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(8, OUTPUT);

  digitalWrite(5, HIGH);
  digitalWrite(4, LOW);
  digitalWrite(8, HIGH);

  delay(3000);

  digitalWrite(8, LOW);

  Serial.println("A7 Power ON!");



  Serial.flush();
  Serial1.flush();

  configure();

  connectToServer("***", "8084");

  Serial.println("Setup end");
}

void commandProcessing (String command) {
  Serial.println("CommandProcessing");

  if (command == "F") {
    sendData("{" + imei + "|" + String(gps.location.lat(), 6) + "|" + String(gps.location.lng(), 6) + "|" + String(gps.course.deg(), 2) + "|" + String(gps.speed.kmph(), 2) + "|N|F}");
  } else if (command == "M") {
    sendData("{" + imei + "|" + String(gps.location.lat(), 6) + "|" + String(gps.location.lng(), 6) + "|" + String(gps.course.deg(), 2) + "|" + String(gps.speed.kmph(), 2) + "}");
  }

  Serial.println("CommandProcessing end");
}

void loop() {
  String serialPortData = "";

  while (Serial1.available()) {
    int incomingByte = Serial1.read();

    gps.encode(incomingByte);

    serialPortData += String((char)incomingByte);
  }

  if ((serialPortData.indexOf("{") != -1) && (serialPortData.indexOf("}") != -1)) {
    serialPortData.remove(0, serialPortData.indexOf("{") + 1);
    serialPortData.remove(serialPortData.indexOf("}"));

    serialPortData.trim();

    commandProcessing(serialPortData);
  }

//    getCurrentMpuValues();

  unsigned long long currentMillis = millis();

  if (gps.speed.kmph() > 5) {
    if (currentMillis - previousMillis >= 5000) {
      previousMillis = currentMillis;

      sendData("{" + imei + "|" + String(gps.location.lat(), 6) + "|" + String(gps.location.lng(), 6) + "|" + String(gps.course.deg(), 2) + "|" + String(gps.speed.kmph(), 2) + "}");
    }
  } else {
    if (currentMillis - previousMillis >= 30000) {
      previousMillis = currentMillis;

      sendData("{" + imei + "|" + String(gps.location.lat(), 6) + "|" + String(gps.location.lng(), 6) + "|" + String(gps.course.deg(), 2) + "|" + String(gps.speed.kmph(), 2) + "}");
    }
  }

  getCurrentMpuValues();
}

functions

String getSerialPortData (char* stopPhrases[]) {
  unsigned long long currentMillis = millis();

  String serialPortData = "";

  while (true) {
 
      if (millis() - currentMillis >= 5000) {
        return "TIMEOUT";
      }
    

    if (Serial1.available()) {
      serialPortData += String((char)Serial1.read());
    }

    bool isBreak = false;

    for (int i = 0; i < 3; i++) {
      String stopPhrase = stopPhrases[i];

      if (stopPhrase == "") {
        continue;
      } else if (serialPortData.endsWith(stopPhrases[i])) {
        isBreak = true;

        break;
      }
    }

    if (isBreak) {
      break;
    }
  }

  return serialPortData;
}

void configure() {
  Serial.println("Configure");

  Serial1.println("AT+GPS=1");

  char* stopPhrases[] = {"OK", "ERROR"};

  getSerialPortData(stopPhrases);

  Serial1.println("AT+AGPS=1");

  getSerialPortData(stopPhrases);

  Serial1.println("AT+GPSRD=1");

  getSerialPortData(stopPhrases);

  Serial.println("Configure end");
}

void resetAllTCPConnections() {
  Serial.println("ResetAllTCPConnections");

  Serial1.println("AT+CIPSHUT");

  char* stopPhrases[] = {"OK", "ERROR"};

  getSerialPortData(stopPhrases);

  Serial.println("ResetAllTCPConnections end");
}

void connectToServer (String host, String port) {
  Serial.println("ConnectToServer");

  resetAllTCPConnections();

  Serial1.println("AT+CIPSTART=\"TCP\"," + host + "," + port);

  char* stopPhrases[] = {"CONNECT OK", "ERROR"};

  getSerialPortData(stopPhrases);

  Serial.println("ConnectToServer end");
}

void sendData(String data) {
  Serial.println("SendData");

  Serial1.println("AT+CIPSEND=" + String(data.length()));

  char* stopPhrases[] = {"ERROR", ">", "OK"};

  String serialPortData = getSerialPortData(stopPhrases);

  if (serialPortData.endsWith("ERROR") || serialPortData == "TIMEOUT") {
    connectToServer("***", "8084");

    return;
  }

  Serial1.println(data);

  getSerialPortData(stopPhrases);

  Serial.println("SendData end");
}

do not scold much)))

Why are there two pieces of code in Reply #5?

What Arduino board are you using?

It is not a good idea to use the String (capital S) class on an Arduino as it can cause memory corruption in the small memory on an Arduino. This can happen after the program has been running perfectly for some time. Just use cstrings - char arrays terminated with '\0' (NULL).

...R

Using the Leonardo board. The program was divided into 2 parts, some functions were taken out in a separate file.

It looks like your MPU library is using I2C in the background but I'm afraid I'm not familiar with the MPU library.

My strong suspicion is that the problem is due to your use of the String class causing memory corruption.

...R

Robin2:
It looks like your MPU library is using I2C in the background but I'm afraid I'm not familiar with the MPU library.

My strong suspicion is that the problem is due to your use of the String class causing memory corruption.

...R

Why then can the program work if you exclude everything related to mpu6050?

Sam999:
Why then can the program work if you exclude everything related to mpu6050?

I don't know. Maybe adding the MPU code is the straw that breaks the camel's back - i.e. reduces free memory so much that the String class no longer has room to mess about.

All I can suggest is trying a re-written program that does not use the String class.

...R