OLED SH1106 and adafruit library now working with MPU6050

Hi everyone

Firstly apologies if the title isn't descriptive enough, I don't really know whats causing my issue so its the best I could come up with.

I have a MPU 6050 connect to a Arduino Uno. I am taking gyro readings from the MPU and looking at displaying these on a 1.3" OLED.

I used a smaller 0.9" OLED with the Adafruit SSD1306 library and it worked great. I then replaced the smaller OLED with the larger 1.3" version and found a library based on the Adafruit one that supported the new SH1106 OLED. A link to the library and the display can be found below.

https://www.netram.co.za/3374-13-128x64-oled-display-blue-iic.html

I then updated my code to make provision for the new display. Its not working however and I cant seem to figure out why. When I delete some of the MPU code in the void loop and setup, the display starts working but then obviously I cant read the MPU data. Please see below my code as reference. Any advice would be much appreciated.

#include <SPI.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include <Average.h>
//#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>

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

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu(0x68);

#define OUTPUT_READABLE_YAWPITCHROLL

#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

//Calibration
float RollCalibrationReading;  // initial roll reading before calibration, this value is used for calibrtion
float RollValue;  // Roll angle
float CallibrationAdjustment; // Calibration adjustment
boolean RunCalibration = false;  // has calibration run yet

// Handstand
boolean standStatus;
int HandStandCount = 0;
//Average<long> StandArray(100);
long recordDuration;

// timing
unsigned long startMillis;
unsigned long currentMillis;
unsigned long strandStartTime;
unsigned long standDuration;
unsigned long previousMillis = 0;
const long interval = 1000;

// 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;
}

//display

#define OLED_RESET 4
Adafruit_SH1106 display(OLED_RESET);

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH  16
static const unsigned char PROGMEM logo16_glcd_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

#if (SH1106_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SH1106.h!");
#endif

void setup()
{
  startMillis = millis();

// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif

Serial.begin(9600);
  while (!Serial); // wait for Leonardo enumeration, others continue immediately

mpu.initialize();

devStatus = mpu.dmpInitialize();

mpu.setXGyroOffset(138);
  mpu.setYGyroOffset(-37);
  mpu.setZGyroOffset(41);
  mpu.setZAccelOffset(1338); // 1688 factory default for my test chip

mpu.setDMPEnabled(true);

attachInterrupt(0, dmpDataReady, RISING);
  mpuIntStatus = mpu.getIntStatus();

dmpReady = true;

packetSize = mpu.dmpGetFIFOPacketSize();

//display
display.begin(SH1106_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64)
// init done

// Show image buffer on the display hardware.
// Since the buffer is intialized with an Adafruit splashscreen
// internally, this will display the splashscreen.
display.display();
delay(1000);

// Clear the buffer.
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);

}

void loop()
{
  currentMillis = millis();

//avareage, max etc
  int minat = 0;
    int maxat = 0;

// if programming failed, don't try to do anything
  if (!dmpReady) return;

while (!mpuInterrupt && fifoCount < packetSize) {
  }

// reset interrupt flag and get INT_STATUS byte
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();

// get current FIFO count
  fifoCount = mpu.getFIFOCount();

// check for overflow (this should never happen unless our code is too inefficient)
  if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
    // reset so we can continue cleanly
    mpu.resetFIFO();
    Serial.println(F("FIFO overflow!"));

// otherwise, check for DMP data ready interrupt (this should happen frequently)
  } else if (mpuIntStatus & 0x02) {
    // wait for correct available data length, should be a VERY short wait
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

// read a packet from FIFO
    mpu.getFIFOBytes(fifoBuffer, packetSize);

// track FIFO count here in case there is > 1 packet available
    // (this lets us immediately read more without waiting for an interrupt)
    fifoCount -= packetSize;

// display Euler angles in degrees
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);

RollValue = (ypr[2] * 180 / M_PI);
  }
    TestMeasurements();
}

// ================================================================
// ===                      TEST MEAUSREMENTS                  ===
// ================================================================

void TestMeasurements() {
  //current angle after calibration

if (currentMillis - previousMillis >= interval){
  previousMillis = currentMillis;
  display.clearDisplay();

display.setCursor(0, 0);
//display.println(RollValue);
display.print(millis()/1000);
display.display();
  }
}

Most probably you run out of memory. The Adafruit library uses half of the available RAM for the screen buffer.

Hi Pylon

Thanks for the reply. I haven't run into memory issues before so this is new to me, thanks for pointing it out.

When I remove or drastically reduce the long array, it seem to work. Thing is though I need the array to get an average and a max value using the Average library. Is there a solution such as boosting the memory, saving my data to a SD card or using a alternative to an array?

Average<unsigned long> StandArray(100);

Is there a solution such as boosting the memory, saving my data to a SD card or using a alternative to an array?

Use an Arduino Mega2560 instead of the UNO, it has 4 times the RAM.

Thanks for the advise, I will look into using a MEGA instead =]