Arduino Leonardo Unable to Pull Data from MPU6050 sensor and displaying it to LCD screen

Hello,

I am creating a project at the moment that uses an Arduino Leonardo, MPU6050 accelerometer and an XC4630 tft LCD display to create an attitude indicator.

I have a few problems that I cannot find solutions to:

  1. The LCD screen is unable to print the roll values that the MPU6050 measures. I have tested the MPU6050 and the LCD screen individually, both work fine. The MPU6050 is able to measure and output the pitch and roll on the serial monitor, and the LCD screen is able to print text, numbers, and fill screen perfectly. The problem is when I try to run them together in the same sketch, I find that the MPU6050 is displaying on the serial monitor but the LCD screen remains white.
  2. The sketch uses around 97% memory when I compile the the code separately and when I try to run them together, I exceed the sketch memory. I was wondering if there is a way to reduce sketch memory usage or should I just buy an arduino UNO board instead?

Here is the code that I have so far, I am using the Adafruit TFT library and the MPU6050 library.

#include <Adafruit_TFTLCD.h>
#include <Adafruit_GFX.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>

// Assign human-readable names to some common 16-bit color values:
#define YELLOW  0xFFE0
#define RED      0xF800
#define WHITE   0xFFFF
#define BROWN      0x5140 //0x5960
#define SKY_BLUE   0x02B5 //0x0318 //0x039B //0x34BF

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

Adafruit_MPU6050 mpu;

void setup() {
  // put your setup code here, to run once:

  //set Digital Pin 10 as 5V to power MPU6050
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  tft.reset();
  uint16_t identifier = tft.readID();
  tft.begin(identifier);
  
  tft.fillRect(0,0,240,160, SKY_BLUE);
  tft.fillRect(0,160,240,320, BROWN);
  
  Serial.begin(9600);

  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  Serial.println("");
  delay(100);
  
  
}
void loop() {
  // put your main code here, to run repeatedly:

  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  float grav = sqrt(a.acceleration.x*a.acceleration.x + a.acceleration.y*a.acceleration.y + a.acceleration.z*a.acceleration.z);
  
  float pitch = asin(a.acceleration.x/grav);
  float roll = atan(a.acceleration.y/grav);

   Serial.print("Pitch: ");
      Serial.print(pitch*180/M_PI);
  Serial.print(", Roll: ");
      Serial.print(roll*180/M_PI);
  printOnScreen(roll*180/M_PI);
  Serial.println("");
  delay(100);

  updateHorizon(roll);  

}

//This function takes in a roll angle in radians and draws a line of that angle from the center of the screen in both directions, 
//to form the diagonal horizon line when the MPU6050 is banked
void drawHorizon (float pitch, float roll) {

  tft.drawLine(0, 160-(160*sin(roll)), 240, 160+(160*sin(roll)), WHITE);

}

//This function takes in a roll angle in radians, draws the new horizon line and fills in the colour of the sky/ground in the area underneath or above
//the banked horizon line 
void updateHorizon (float roll) {

   tft.drawLine(0, 160-(160*sin(roll)), 240, 160+(160*sin(roll)), WHITE);

   if (roll>0) {
    tft.fillTriangle(120, 160, 0, 160, 0, 160-(160*sin(roll)), BROWN);
    tft.fillTriangle(120, 160, 240, 160, 240, 160+(160*sin(roll)), SKY_BLUE);
   } else if (roll<0) {
     tft.fillTriangle(120, 160, 0, 160, 0, 160-(160*sin(roll)), SKY_BLUE);
    tft.fillTriangle(120, 160, 240, 160, 240, 160+(160*sin(roll)), BROWN);
   } else {
     tft.fillRect(0,0,240,160, SKY_BLUE);
    tft.fillRect(0,160,240,320, BROWN);
   }
   
}

As for the wiring, I have cables running everywhere and cannot get a clear picture of it all. If there is a program to make a wiring diagram please let me know where I can find that. For now, I have the LCD_RST ->A4, LCD_CS->A3, LCD_RS->A2, LCD_WR->A1, LCD_RD->A0. Then I've got the LCD_D1~LCD_D7 connected to Digital 2~10.

For the MPU6050 I have it connected to 5V and GND, and the SCL and SDA pins connected together.

Where's the function printOnScreen?

Sorry, this was a function that I made using other functions in the library:

void printOnScreen (float roll) {
tft.setCursor(120, 160); //I set the cursor in the centre of the screen to see if the message would print  
tft.setTextColor(BROWN);
tft.setTextSize(2);
tft.print(roll);
}

Regarding the first problem, I need more details about what doesn't works.

This code without debug messages takes 88% of flash memory and 91% with debug messages.

#include <Adafruit_TFTLCD.h>
#include <Adafruit_GFX.h>
#include "Wire.h"
#include <MPU6050_light.h> // https://github.com/rfetick/MPU6050_light/archive/refs/heads/master.zip
#include <Adafruit_Sensor.h>

//#define DEBUG // uncomment do enable debug messages

// Assign human-readable names to some common 16-bit color values:
#define YELLOW  0xFFE0
#define RED      0xF800
#define WHITE   0xFFFF
#define BROWN      0x5140 // 0x5960
#define SKY_BLUE   0x02B5 // 0x0318 //0x039B //0x34BF

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS A3         // Chip Select goes to Analog 3
#define LCD_CD A2         // Command/Data goes to Analog 2
#define LCD_WR A1         // LCD Write goes to Analog 1
#define LCD_RD A0         // LCD Read goes to Analog 0

#define LCD_RESET A4      // Can alternately just connect to Arduino's reset pin

#define UPDATE_INTERVAL 1 // Time in seconds.

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

MPU6050 mpu(Wire);

unsigned long updateMillis = 0;

#ifdef DEBUG
  #define LOG(...) Serial.print(__VA_ARGS__)
  #define LOGLN(...) Serial.println(__VA_ARGS__)
#else
  #define LOG(...)
  #define LOGLN(...)
#endif

void updateHorizon (float roll);
void drawHorizon (float pitch, float roll);
void printOnScreen (float roll);

void setup()
{
  #ifdef DEBUG
    Serial.begin(9600);
    while (!Serial)
    {
    }
  #endif

  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);

  tft.reset();
  uint16_t identifier = tft.readID();
  tft.begin(identifier);

  tft.fillRect(0,0,240,160, SKY_BLUE);
  tft.fillRect(0,160,240,320, BROWN);

  Wire.begin();

  byte status = mpu.begin();

  if (status != 0)
  {
    return;
  }
}

void loop()
{
  if((millis() - updateMillis) > (UPDATE_INTERVAL * 1000UL))
  {
    mpu.update();

    LOG(F("TEMPERATURE: "));
    LOGLN(mpu.getTemp());
    LOG(F("ACCELERO  X: "));
    LOG(mpu.getAccX());
    LOG("\tY: ");
    LOG(mpu.getAccY());
    LOG("\tZ: ");
    LOGLN(mpu.getAccZ());

    LOG(F("GYRO      X: "));
    LOG(mpu.getGyroX());
    LOG("\tY: ");
    LOG(mpu.getGyroY());
    LOG("\tZ: ");
    LOGLN(mpu.getGyroZ());

    LOG(F("ACC ANGLE X: "));
    LOG(mpu.getAccAngleX());
    LOG("\tY: ");
    LOGLN(mpu.getAccAngleY());

    LOG(F("ANGLE     X: "));
    LOG(mpu.getAngleX());
    LOG("\tY: ");
    LOG(mpu.getAngleY());
    LOG("\tZ: ");
    LOGLN(mpu.getAngleZ());
    LOGLN(F("=====================================================\n"));

    float grav = sqrt(mpu.getAccX() * mpu.getAccX() + mpu.getAccY() * mpu.getAccY() + mpu.getAccZ() * mpu.getAccZ());
    float roll = atan(mpu.getAccY() / grav);

    printOnScreen(roll * 180 / M_PI);

    updateHorizon(roll);
    updateMillis = millis();
  }
}

void printOnScreen (float roll)
{
  tft.setCursor(120, 160); // I set the cursor in the centre of the screen to see if the message would print
  tft.setTextColor(BROWN);
  tft.setTextSize(2);
  tft.print(roll);
}


// This function takes in a roll angle in radians and draws a line of that angle from the center of the screen in both directions,
// to form the diagonal horizon line when the MPU6050 is banked
void drawHorizon (float pitch, float roll)
{

  tft.drawLine(0, 160 - (160 * sin(roll)), 240, 160 + (160 * sin(roll)), WHITE);

}

// This function takes in a roll angle in radians, draws the new horizon line and fills in the colour of the sky/ground in the area underneath or above
// the banked horizon line
void updateHorizon (float roll)
{

  tft.drawLine(0, 160 - (160 * sin(roll)), 240, 160 + (160 * sin(roll)), WHITE);

  if (roll > 0)
  {
    tft.fillTriangle(120, 160, 0, 160, 0, 160 - (160 * sin(roll)), BROWN);
    tft.fillTriangle(120, 160, 240, 160, 240, 160 + (160 * sin(roll)), SKY_BLUE);
  }
  else if (roll < 0)
  {
    tft.fillTriangle(120, 160, 0, 160, 0, 160 - (160 * sin(roll)), SKY_BLUE);
    tft.fillTriangle(120, 160, 240, 160, 240, 160 + (160 * sin(roll)), BROWN);
  }
  else
  {
    tft.fillRect(0,0,240,160, SKY_BLUE);
    tft.fillRect(0,160,240,320, BROWN);
  }

}

Update:

I have decided to switch boards to the Arduino UNO and have found more success as I can finally print out the values from the MPU6050 onto the LCD screen. I am not entirely sure but I think the reasoning is this:

The Leonardo has its SCL and SDA pins hard wired to digital 2 and digital 3. SCL and SDA are connected to the MPU6050 and D2 and D3 are connected to the LCD screen. I believe the issue was when I was trying to pull data from the MPU6050, because the LCD was connected to the same data line as the MPU6050, it was unable to do anything with the retrieved values. The UNO has its SCL and SDA pins hard wired to Analog 4 and Analog 5, which does not clash with the required pins of the LCD, which allowed the retrieved data to transmit through the bus line.